You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ansible如何按key存在性、group_names过滤字典并保留指定键

Ansible 组件配置过滤实现

需求梳理

已定义的components变量如下:

components:
  comp_one:
    name: first_component
    remote_server_path: "/tmp/path/one"
    binaries:
      - test
      - test_two

  comp_two:
    name: second_component
    remote_server_path: "/tmp/path/two"
    binaries:
      - ed_test
      - ed_test_2

  comp_three:
    name: third_component
    remote_server_path: "/tmp/path/three"

需要实现三个处理逻辑:

  • 过滤掉components下不存在binaries键的子项(如示例中的comp_three)
  • 以Ansible内置变量group_names(当前主机所属的主机组列表)为基准,过滤每个组件的binaries列表,仅保留同时存在于group_names中的条目
  • 每个保留的子项仅保留remote_server_path和过滤后的binaries两个键,移除其余冗余字段

参考hosts.yaml配置:

---
all:
  children:
    kubernetes_dev:
      children:
        ed_test:
          hosts:
            host_one:
              ansible_host: XXX.XXX.XXX.XXX
              ansible_ssh_user: ansible
        test_two:
          hosts:
            host_one:
              ansible_host: XXX.XXX.XXX.XXX
              ansible_ssh_user: ansible
        test:
          hosts:
            host_one:
              ansible_host: XXX.XXX.XXX.XXX
              ansible_ssh_user: ansible

预期输出为:

comp_one:
  remote_server_path: "/tmp/path/one"
  binaries:
    - test
    - test_two

comp_two:
  remote_server_path: "/tmp/path/two"
  binaries:
    - ed_test

目前已实现无binaries键项的过滤,但未完成binaries列表过滤和字段裁剪。

实现方案

直接通过Jinja2逻辑一次性完成所有处理,不需要拆分多步任务,可读性和执行效率更高,输出完全匹配预期:

- name: 生成并输出处理完成的组件配置
  ansible.builtin.debug:
    var: final_components
  vars:
    final_components: >-
      {% set result = {} %}
      {% for comp_key, comp_val in components.items() %}
        {% if comp_val.binaries is defined %}
          {% set _ = result.update({
            comp_key: {
              'remote_server_path': comp_val.remote_server_path,
              'binaries': comp_val.binaries | intersect(group_names)
            }
          }) %}
        {% endif %}
      {% endfor %}
      {{ result }}

逻辑说明

  • 遍历components字典时直接跳过不存在binaries键的项,完成第一层过滤
  • intersect(group_names)是Ansible内置的列表交集过滤器,会自动保留binaries列表中同时存在于当前主机group_names里的条目;示例中父组kubernetes_dev不在任何binaries列表中,不会对结果产生干扰
  • 构建新的组件值时仅写入remote_server_path和过滤后的binaries字段,自动丢弃name等冗余字段
  • 最终生成的result是标准字典结构,可以直接在后续任务中引用

如果偏好纯过滤器链的写法(无显式循环),也可以使用如下版本,效果完全一致:

- name: 生成并输出处理完成的组件配置
  ansible.builtin.debug:
    var: final_components
  vars:
    valid_comps: "{{ components | dict2items | selectattr('value.binaries', 'defined') | list }}"
    comp_kv: "{{ valid_comps | map(attribute='key') | list }}"
    comp_vals: "{{ valid_comps | map(attribute='value') | map('json_query', '{\"remote_server_path\": remote_server_path, \"binaries\": binaries}') | list }}"
    final_components: "{{ dict(comp_kv | zip(comp_vals)) | combine({'*': {'binaries': item.binaries | intersect(group_names)}}, recursive=True) }}"

内容的提问来源于stack exchange,提问作者Ares

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 03:12:18