Ansible遍历嵌套字典保留各级键名的实现方法
实现方法
不需要修改原始数据结构,也不需要单独创建任务文件实现嵌套循环,以下两种原生Ansible写法可直接满足需求:
方法1:过滤器组合实现单层循环(最简洁)
通过dict2items+subelements过滤器一次性将两层嵌套字典打平为单循环列表,完全匹配你的使用预期:
- name: 处理所有分组下的虚拟机 ansible.builtin.debug: # 替换为你的实际任务模块 msg: vms: "{{ item.1.value }}" group: "{{ item.1.key }}" cluster: "{{ item.0.key }}" loop: "{{ all_vms | dict2items | subelements('value | dict2items') }}"
循环中每个item是包含两个元素的元组:
item.0对应第一层集群的键值对,item.0.key为集群名item.1对应当前集群下分组的键值对,item.1.key为分组名,item.1.value为该分组下的虚拟机列表
如果觉得item.0/item.1可读性差,可以通过临时变量优化写法:
- name: 处理所有分组下的虚拟机 ansible.builtin.debug: msg: vms: "{{ group_item.value }}" group: "{{ group_item.key }}" cluster: "{{ cluster_item.key }}" loop: "{{ all_vms | dict2items | subelements('value | dict2items') }}" loop_control: loop_var: __tmp vars: cluster_item: "{{ __tmp.0 }}" group_item: "{{ __tmp.1 }}"
方法2:Jinja2原生组装扁平列表(无额外过滤器依赖)
如果不想依赖subelements过滤器,可以直接通过Jinja2语法在循环定义处遍历两层结构,组装成所需的扁平列表,不需要修改原始数据:
- name: 处理所有分组下的虚拟机 ansible.builtin.debug: msg: vms: "{{ entry.vms }}" group: "{{ entry.group }}" cluster: "{{ entry.cluster }}" loop: >- {%- set flat_list = [] -%} {%- for cluster_name, groups in all_vms.items() -%} {%- for group_name, vm_list in groups.items() -%} {%- set _ = flat_list.append({ 'cluster': cluster_name, 'group': group_name, 'vms': vm_list }) -%} {%- endfor -%} {%- endfor -%} {{ flat_list }}
补充说明
你之前尝试的block嵌套循环写法不生效,是因为Ansible的block级循环不会自动将外层循环变量透传给块内任务,这也是为什么嵌套循环通常需要配合include_tasks拆分任务文件。上述两种方法都绕开了这个限制,直接通过单层循环拿到所有层级的键名,没有冗余代码。
你之前提到的json_query方案也可以实现,只需调整JMESPath表达式即可,但可读性远低于上述原生写法,不推荐使用。
内容的提问来源于stack exchange,提问作者wfaulk
相关产品推荐
相关产品推荐

