如何在Ansible中匹配两个字典值并规范输出格式?
Ansible字典匹配结果格式优化问题
现有字典数据
small_d 字典
"small_d": { "cluster-c8836": [ "aaaa-111", "bbbb-222", "cccc-222" ] }
big_d 字典
"big_d": { "2cc5b2fbe6c6": [ "dddd-asda", "aaaa-111", "ddd-2411", "bbbb-222", "dddd-76543", "cccc-222", "dddd-66666" ], "0a722267a5bd": [ "dddd-2468" ] }
需求说明
遍历small_d中的所有节点ID,检查每个节点是否存在于big_d的某个列表中,最终输出big_d的键及其对应的匹配节点列表,预期格式如下:
"2cc5b2fbe6c6": ["aaaa-111", "bbbb-222", "cccc-222"]
尝试的Jinja2模板代码
- name: try Jinja2 filtering set_fact: worth_a_try: | {% for cluster_id, node_ids in small_d.items() %} {% for node_id in node_ids %} {% for group_id, member_ids in big_d.items() %} {% if node_id in member_ids %} - {{group_id}}: {{node_id}} {% endif %} {% endfor %} {% endfor %} {% endfor %} - debug: var=worth_a_try
当前输出结果
上述代码得到的输出为多个独立字典条目,不符合预期格式:
"worth_a_try|from_yaml": [ { "2cc5b2fbe6c6": "aaaa-111" }, { "2cc5b2fbe6c6": "bbbb-222" }, { "2cc5b2fbe6c6": "cccc-222" } ]
优化方案
方案1:Jinja2构建字典后输出
通过初始化空字典,将匹配到的节点ID逐一添加到对应分组的列表中,最后统一输出完整字典:
- name: 生成匹配结果字典 set_fact: matched_result: | {% set result = {} %} {% for _, node_ids in small_d.items() %} {% for node_id in node_ids %} {% for group_id, member_ids in big_d.items() %} {% if node_id in member_ids %} {% if group_id not in result %} {% set _ = result.__setitem__(group_id, []) %} {% endif %} {% set _ = result[group_id].append(node_id) %} {% endif %} {% endfor %} {% endfor %} {% endfor %} {{ result | to_nice_yaml }} - debug: var: matched_result | from_yaml
方案2:使用Ansible过滤器实现(更简洁)
利用Ansible内置过滤器,通过字典推导式直接生成目标结果:
- name: 用过滤器生成匹配结果 set_fact: matched_result: >- {{ big_d | dict2items | selectattr('value', 'intersect', small_d.values() | flatten) | map('combine', {'value': item.value | intersect(small_d.values() | flatten)}) | items2dict }} - debug: var: matched_result
两种方案最终都能得到符合预期的输出格式:
"matched_result": { "2cc5b2fbe6c6": [ "aaaa-111", "bbbb-222", "cccc-222" ] }
内容的提问来源于stack exchange,提问作者piercjs
相关产品推荐
相关产品推荐

