You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ansible中遍历子元素的子元素并保留所有父层数据?

Ansible多层嵌套遍历(数据中心→集群→主机)

现有如下嵌套数据结构,需要遍历每个主机,同时保留数据中心、集群的父级信息:

datacenters:
  - name: Datacenter1
    clusters:
      - name: ClusterA
        hosts:
          - 192.168.0.1
          - 192.168.0.2
      - name: ClusterB
        hosts:
          - 192.168.1.1
          - 192.168.1.2
  - name: Datacenter2
    clusters:
      - name: ClusterC
        hosts:
          - 192.168.2.1
          - 192.168.2.2

直接嵌套subelements会报错,因为第一次subelements('clusters')返回的是(数据中心对象, 集群对象)的元组,第二次subelements('hosts')会错误地尝试从元组中找hosts键,自然失败。

下面是几种可行的解决方案:

方法一:嵌套loop(最直观)

用两层遍历嵌套,外层处理数据中心→集群,内层处理集群→主机,每个层级的变量都能直接访问:

- name: 遍历所有主机并输出父级信息
  debug:
    msg: "Datacenter: {{ dc.name }}, Cluster: {{ cluster.name }}, Host: {{ host }}"
  loop: "{{ cluster.hosts }}"
  loop_control:
    loop_var: host
  vars:
    cluster: "{{ item.1 }}"
    dc: "{{ item.0 }}"
  loop: "{{ datacenters | subelements('clusters') }}"
  loop_control:
    loop_var: item

或者用with_subelements的更清晰写法(Ansible 2.5+支持):

- name: 遍历所有主机并输出父级信息
  debug:
    msg: "Datacenter: {{ dc.name }}, Cluster: {{ cluster.name }}, Host: {{ host }}"
  loop: "{{ cluster.hosts }}"
  loop_control:
    loop_var: host
  with_subelements:
    - "{{ datacenters }}"
    - clusters
  loop_control:
    loop_var: cluster
    parent_var: dc

方法二:subelements结合map重构结构

先把第一次subelements的元组转换成字典,让第二次subelements能正确识别主机列表:

- name: 遍历所有主机并输出父级信息
  debug:
    msg: "Datacenter: {{ item.0.dc.name }}, Cluster: {{ item.0.cluster.name }}, Host: {{ item.1 }}"
  loop: "{{ datacenters | subelements('clusters') | map('community.general.dict', key=['dc', 'cluster']) | subelements('cluster.hosts') }}"

这里map('community.general.dict', key=['dc', 'cluster'])把(数据中心对象, 集群对象)的元组转成{dc: 数据中心对象, cluster: 集群对象}的字典,第二次subelements就能从cluster.hosts里拿到主机列表。

方法三:用json_query扁平化数据

直接用json_query把所有主机和父级信息提取成扁平化列表,再遍历:

- name: 遍历所有主机并输出父级信息
  debug:
    msg: "Datacenter: {{ item.dc }}, Cluster: {{ item.cluster }}, Host: {{ item.host }}"
  loop: "{{ datacenters | json_query('[].{dc: name, clusters: clusters[].{cluster: name, hosts: hosts[]}}') | json_query('[].clusters[] | {dc: @.dc, cluster: @.cluster, host: @.hosts}') }}"

两次json_query先提取数据中心和集群的关联信息,再把每个主机展开成独立条目,每个条目包含dc、cluster、host三个字段。

方法四:预生成扁平化列表

先通过set_fact把所有主机的完整信息提前生成一个列表,后续直接遍历这个列表:

- name: 生成包含父级信息的主机列表
  set_fact:
    all_hosts_with_parent: "{{ all_hosts_with_parent | default([]) + [{'dc': dc.name, 'cluster': cluster.name, 'host': host}] }}"
  loop: "{{ cluster.hosts }}"
  loop_control:
    loop_var: host
  vars:
    cluster: "{{ item.1 }}"
    dc: "{{ item.0 }}"
  loop: "{{ datacenters | subelements('clusters') }}"

- name: 遍历预生成的主机列表
  debug:
    msg: "Datacenter: {{ item.dc }}, Cluster: {{ item.cluster }}, Host: {{ item.host }}"
  loop: "{{ all_hosts_with_parent }}"

内容的提问来源于stack exchange,提问作者stackprotector

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 19:10:33