Ansible如何使用嵌套循环匹配两个用户列表并设置包含状态的新事实
Ansible 合并两个用户列表实现方案
可以实现需求,不需要写复杂的嵌套循环,使用Ansible自带的过滤器即可快速完成匹配,以下是可直接运行的实现代码:
方案1:单循环+过滤器实现(适合小数据量)
- name: 合并用户角色与账号锁定状态生成新事实 set_fact: my_new_list: "{{ my_new_list | default([]) + [ item | combine({'isLockedOut': matched_status.isLockedOut | default('Name Does not Match')}) ] }}" cacheable: yes loop: "{{ username_and_role }}" vars: # 从状态列表中筛选和当前遍历用户Name一致的条目 matched_status: "{{ username_and_status | selectattr('Name', 'equalto', item.Name) | first | default({}) }}"
输出示例
最终生成的my_new_list格式如下:
[ { "Name": "Jack", "Role": "Admin User", "isLockedOut": "no" }, { "Name": "Tom", "Role": "Buyer", "isLockedOut": "no" }, { "Name": "Jill", "Role": "Seller", "isLockedOut": "no" } ]
方案2:预生成字典匹配(适合大数据量,性能更高)
如果两个列表数据量较大,可以先把状态列表转为以Name为key的字典,再做匹配,避免每次循环都遍历整个状态列表:
- name: 预生成账号状态查询字典 set_fact: status_dict: "{{ status_dict | default({}) | combine({item.Name: item.isLockedOut}) }}" loop: "{{ username_and_status }}" - name: 合并生成新的用户事实 set_fact: my_new_list: "{{ my_new_list | default([]) + [ item | combine({'isLockedOut': status_dict[item.Name] | default('Name Does not Match')}) ] }}" cacheable: yes loop: "{{ username_and_role }}"
原代码错误原因
- 同时使用
with_items和loop参数,二者是Ansible循环的不同写法,会产生参数冲突,只能保留一个 - 没有对
my_new_list做累加处理,每次循环都会覆盖之前的结果,不会追加新条目 - 匹配逻辑中
username变量未定义,也没有实现从username_and_status中筛选对应Name条目的逻辑
内容的提问来源于stack exchange,提问作者Hary Aprianto Ginting
相关产品推荐
相关产品推荐

