如何从Ansible嵌套字典中列出设备及关联vhost
Ansible嵌套字典提取设备及关联vhost解决方案
问题背景
通过特定Ansible集合收集服务器facts,得到不可修改的嵌套字典结构(无列表)。当前使用Ansible 2.10,非必要不升级至2.14。结构中vtds、device为固定键名,但vtds的子键名随服务器变化。需完成两个任务:
- 提取所有设备的列表;
- 生成设备与关联vhost的对应关系列表。
此前尝试subelements('value.vtds')失败,原因是vtds为字典而非列表,现有方案未覆盖未知子键的场景。
兼容Ansible 2.10的解决方案Playbook
--- - name: 提取嵌套字典中的设备及vhost关联关系 hosts: all gather_facts: false vars: mapping: vscsi: vhost1: info: azerty vtds: AZER_TY_125: status: UP device: disk1 AZER_TY_456: status: UP device: disk2 vhost2: info: azerty vtds: QWER_TY_123: status: UP device: disk2 QWER_TY_456: status: DOWN device: disk3 vhost3: info: azerty vtds: QWER_TI_123: status: DOWN device: disk4 tasks: # 任务1:生成所有设备的全量列表,如需去重可追加 | unique - name: 列出所有设备 ansible.builtin.debug: msg: "所有设备: {{ all_devices }}" vars: all_devices: "{{ mapping.vscsi | dict2items | map(attribute='value.vtds') | map('dict2items') | flatten | map(attribute='value.device') | list }}" # 任务2-1:生成vhost到对应设备的映射 - name: 列出vhost及其关联设备 ansible.builtin.debug: msg: "Vhost: {{ item.key }} | 关联设备: {{ item.value.vtds | dict2items | map(attribute='value.device') | list }}" loop: "{{ mapping.vscsi | dict2items }}" # 任务2-2:生成设备到对应vhost的映射(处理同一设备关联多个vhost的场景) - name: 构建设备-vhost映射 ansible.builtin.set_fact: device_vhost_map: "{{ device_vhost_map | default({}) | combine({ item.device: (device_vhost_map[item.device] | default([])) + [item.vhost] }, recursive=True) }}" loop: "{{ mapping.vscsi | dict2items | json_query('[].{vhost: key, device: value.vtds | dict2items | [].value.device}') | json_query('[].{vhost: vhost, device: device[]}') }}" - name: 打印设备到vhost的映射结果 ansible.builtin.debug: msg: "{{ device_vhost_map }}"
关键逻辑说明
dict2items:将未知键的字典转换为[{key: ..., value: ...}]格式的列表,实现动态遍历;map(attribute='xxx'):从列表元素中提取指定属性值,用于批量获取device字段;flatten:将多维列表转换为一维列表,合并所有设备条目;combine:合并字典并累加同一设备对应的vhost列表,构建双向映射;json_query:通过JMESPath语法展开嵌套结构,生成vhost与device的一一对应条目。
内容的提问来源于stack exchange,提问作者Amel Carmal
相关产品推荐
相关产品推荐

