遍历子元素的子元素

Loop through subelements of subelements

提问人:stackprotector 提问时间:11/17/2022 更新时间:11/17/2022 访问量:1059

问:

我在 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

loop: '{{ datacenters | subelements(''clusters'') }}'

这将使我能够访问数据,如下所示:

'Datacenter: {{ item.0.name }}, Cluster: {{ item.1.name }}'

我希望能够像这样扩展这个概念:

loop: '{{ datacenters | subelements(''clusters'') | subelements(''hosts'') }}'

并且能够像这样访问数据:

'Datacenter: {{ item.0.name }}, Cluster: {{ item.1.name }}, Host: {{ item.2 }}'

但这不起作用,我收到以下错误消息:

Unexpected templating type error occurred on ({{ datacenters | subelements('clusters') | subelements('hosts') }}): the key hosts should point to a dictionary, got ...(the result of the first layer)

我找到了这个问题,它解决了类似的问题,但依赖于在所有嵌套级别上具有不同的字典键,而我没有,因为数据中心和集群具有相同的键。name

那么,如何在 Ansible 中迭代子元素的子元素呢?

循环 ansible 嵌套 嵌套列表 ansible-2.x

评论


答:

3赞 Zeitounator 11/17/2022 #1

有点牵强,但以下剧本将实现您的目标:

 ---
 - hosts: localhost
   gather_facts: false
 
   vars:
     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
 
     # Get the list of datacenters
     _dcs: "{{ datacenters | map(attribute='name') }}"
     # Get the corresponding list of clusters with subelements on hosts
     _clusters: "{{ datacenters | map(attribute='clusters') | map('subelements', 'hosts') }}"
     # Recreate a list with the sublisted hosts per clusters and create subelements on that final result
     _overall: "{{ dict(_dcs | zip(_clusters)) | dict2items(key_name='datacenter', value_name='clusters') | subelements('clusters') }}"
 
   tasks:
     - name: Loop on the result
       debug:
         msg:
           - "DC: {{ item.0.datacenter }}"
           - "Cluster: {{ item.1.0.name }}"
           - "Host: {{ item.1.1 }}"
       loop: "{{ _overall }}"
       loop_control:
         label: "{{ item.0.datacenter }} - {{ item.1.0.name }}"

这给出了:

PLAY [localhost] **************************************************************************************************************************************************

TASK [Loop on the result] *****************************************************************************************************************************************
ok: [localhost] => (item=Datacenter1 - ClusterA) => {
    "msg": [
        "DC: Datacenter1",
        "Cluster: ClusterA",
        "Host: 192.168.0.1"
    ]
}
ok: [localhost] => (item=Datacenter1 - ClusterA) => {
    "msg": [
        "DC: Datacenter1",
        "Cluster: ClusterA",
        "Host: 192.168.0.2"
    ]
}
ok: [localhost] => (item=Datacenter1 - ClusterB) => {
    "msg": [
        "DC: Datacenter1",
        "Cluster: ClusterB",
        "Host: 192.168.1.1"
    ]
}
ok: [localhost] => (item=Datacenter1 - ClusterB) => {
    "msg": [
        "DC: Datacenter1",
        "Cluster: ClusterB",
        "Host: 192.168.1.2"
    ]
}
ok: [localhost] => (item=Datacenter2 - ClusterC) => {
    "msg": [
        "DC: Datacenter2",
        "Cluster: ClusterC",
        "Host: 192.168.2.1"
    ]
}
ok: [localhost] => (item=Datacenter2 - ClusterC) => {
    "msg": [
        "DC: Datacenter2",
        "Cluster: ClusterC",
        "Host: 192.168.2.2"
    ]
}

PLAY RECAP ********************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0