Ansible循环时修改自定义Fact中字典列表的值
解决Ansible自定义Fact修改问题
核心逻辑
Ansible的自定义Fact是不可直接修改的,必须通过set_fact重新构建完整的Fact结构——遍历原Fact的每个字典项,完成API查询和值修改后,将处理后的项整合为新列表,再赋值回原Fact变量。
假设你的自定义Fact结构
示例结构参考:
custom_devices: - name: device_a bt_device: "sw3" extra_info: "foo" - name: device_b bt_device: "sw2" extra_info: "bar"
完整解决方案代码
1. 带API查询的完整处理流程
- name: 遍历并修改自定义Fact中的bt_device字段 vars: updated_device_list: [] block: - name: 调用API获取每个设备的目标值 uri: url: "https://your-api-endpoint/query?bt={{ item.bt_device }}" method: GET return_content: true register: api_results loop: "{{ custom_devices }}" loop_control: label: "{{ item.name }}" - name: 构建更新后的设备列表 set_fact: updated_device_list: "{{ updated_device_list + [ item.item | combine({'bt_device': (item.json.target_device | default(item.item.bt_device))}) ] }}" loop: "{{ api_results.results }}" loop_control: index_var: idx - name: 覆盖原自定义Fact set_fact: custom_devices: "{{ updated_device_list }}" - name: 验证修改结果 debug: var: custom_devices
2. 固定值替换的简化场景(无需API)
如果只是把特定值(比如sw3替换为fp3),可以直接用过滤器完成:
- name: 批量替换自定义Fact中的bt_device值 set_fact: custom_devices: "{{ custom_devices | map('combine', {'bt_device': item.bt_device | replace('sw3', 'fp3')}) | list }}" loop: "{{ custom_devices }}"
关键说明
- 不可直接修改原Fact:Ansible的Fact变量是只读的,必须通过
set_fact重新赋值才能更新。 - combine过滤器:用
combine方法保留原字典的所有属性,只替换bt_device字段,避免丢失其他配置。 - API结果匹配:通过
loop.index0关联原循环的设备项和API返回结果,确保每个设备的修改对应正确。 - 默认值兜底:用
default过滤器保证如果API查询失败,原bt_device值不会丢失。
内容的提问来源于stack exchange,提问作者user2088608
相关产品推荐
相关产品推荐

