使用Ansible循环遍历列表字典时的错误排查与解决
解决Ansible loop遍历dict2items+subelements结果时的变量未定义错误
你这个问题其实很典型——loop参数里多嵌套了一层列表结构,导致Ansible遍历的对象完全不符合你的预期。
先来看你的错误写法:
loop: - "{{ machine_roles | dict2items(key_name='role', value_name='machine') | subelements('machine') }}"
这里你用-把过滤后的结果包装成了一个新的单元素列表,也就是说,loop实际遍历的是[ [你的目标列表] ],而非直接遍历你的目标列表。这就导致每次循环的item是整个大列表,而不是列表里的[ {role: ...}, "master1"]这样的子元素,自然会报错说list object has no attribute 'role'。
你的调试结果其实已经给出了正确的数据结构:
[ [ { "machine": [ "master1", "master2" ], "role": "masters" }, "master1" ], [ { "machine": [ "master1", "master2" ], "role": "masters" }, "master2" ], [ { "machine": [ "worker1", "worker2" ], "role": "workers" }, "worker1" ], [ { "machine": [ "worker1", "worker2" ], "role": "workers" }, "worker2" ] ]
这个结构本身就是可以直接给loop的列表,不需要再套一层。
正确的Playbook写法
把loop里的-去掉,直接引用过滤后的结果即可:
- hosts: localhost connection: local vars: machine_roles: masters: ["master1","master2"] workers: ["worker1","worker2"] tasks: - name: 遍历角色与节点 debug: msg: "{{ item.0.role}} --- {{ item.1 }}" loop: "{{ machine_roles | dict2items(key_name='role', value_name='machine') | subelements('machine') }}"
运行结果验证
执行这个修正后的Playbook,就会得到你期望的输出:
TASK [遍历角色与节点] ********************************************************************* ok: [localhost] => (item=[{'role': 'masters', 'machine': ['master1', 'master2']}, 'master1']) => { "msg": "masters --- master1" } ok: [localhost] => (item=[{'role': 'masters', 'machine': ['master1', 'master2']}, 'master2']) => { "msg": "masters --- master2" } ok: [localhost] => (item=[{'role': 'workers', 'machine': ['worker1', 'worker2']}, 'worker1']) => { "msg": "workers --- worker1" } ok: [localhost] => (item=[{'role': 'workers', 'machine': ['worker1', 'worker2']}, 'worker2']) => { "msg": "workers --- worker2" }
简单来说,loop参数接受的是一个列表,当你用- "{{ ... }}"时,相当于给它传了一个包含目标列表的列表,完全打乱了遍历逻辑,去掉那层多余的列表包裹就解决问题了。
内容的提问来源于stack exchange,提问作者Eurydice
相关产品推荐
相关产品推荐

