loops - 在 Ansible 中迭代嵌套字典,保留键名称

标签 loops data-structures ansible nested nested-loops

我有一个如下所示的数据结构:

all_vms:
  clusterA:
    group1:
      - vm-01
      - vm-02
    group2:
      - vm-03
      - vm-04
  clusterB:
    group1:
      - vm-05
      - vm-06

事先不知道键名。集群之间可能存在共享的“组”键名称。

我想循环遍历该数据结构并对每个数组运行一个任务,但我需要它们所包含的键的名称。循环任务看起来像这样:

- task:
     vms: "{{ item.value }}"
     group: "{{ item.key }}"
     cluster: "{{ item.parentkey }}"
  loop: "{{ all_vms | ??? }}"

这将展开为:

- task:
    vms:
      - vm-01
      - vm-02
    group: group1
    cluster: clusterA
- task:
    vms:
      - vm-03
      - vm-04
    group: group2
    cluster: clusterA
- task:
    vms:
      - vm-05
      - vm-06
    group: group3
    cluster: clusterB

我无法更改主簇/组结构,但我可以更改当前数组元素的结构。我考虑过将键复制为值,如下所示:

all_vms:
  clusterA:
    group1:
      cluster: "clusterA"
      group: "group1"
      vms:
        - vm-01
        - vm-02
    group2:
      cluster: "clusterA"
      group: "group2"
      vms:
        - vm-03
        - vm-04
  clusterB:
    group1:
      cluster: "clusterB"
      group: "group1"
      vms:
        - vm-05
        - vm-06

宁愿不这样做,因为这很糟糕,但我可以。但我什至无法找到一种方法将这些内容弹出到数组中。 (编辑:实际上,我认为在发布后就发现了这一点:all_vms | json_query('*.* | []')。我想如果没有办法使用更整洁的数据结构。)

或者如果我可以使用 @!#$% 嵌套循环,如果 ansible 允许的话:

- block:
  - task:
      vms: "{{ item.value }}"
      group: "{{ item.key }}"
      cluster: "{{ cluster.key }}"
    loop: "{{ cluster.value | dict2items }}"
  loop: "{{ all_vms | dict2items }}"
  loop_control:
    loop_var: cluster

(是的,我可以使用 include_tasks 来做到这一点,但是必须为嵌套循环使用单独的文件只是荒谬。)

有什么想法可以迭代这个数据结构,而不必求助于单独的文件来执行嵌套循环吗?

最佳答案

这是解决方案 using several combinations of filters directly in Ansible / Jinja

它将第一级键和值与 zip 过滤器结合起来,以便获得已知的子元素名称 - 1 - 然后我们可以在其上使用 子元素

由于映射到第一级值的 dict2items,可以访问第二级键/值对。

任务最终是

- set_fact:
    tasks: "{{ tasks | default([]) + [_task] }}"
  loop: >-
    {{
      all_vms.keys()
      | zip(all_vms.values() | map('dict2items'))
      | subelements([1])
    }}
  loop_control:
    label: "{{ item.0.0 }} — {{ item.1.key }}"
  vars:
    _task:
      task:
        vms: "{{ item.1.value }}"
        group: "{{ item.1.key }}"
        cluster: "{{ item.0.0 }}"

鉴于剧本:

- hosts: localhost
  gather_facts: no

  tasks:
    - set_fact:
        tasks: "{{ tasks | default([]) + [_task] }}"
      loop: >-
        {{
          all_vms.keys()
          | zip(all_vms.values() | map('dict2items'))
          | subelements([1])
        }}
      loop_control:
        label: "{{ item.0.0 }} — {{ item.1.key }}"
      vars:
        _task:
          task:
            vms: "{{ item.1.value }}"
            group: "{{ item.1.key }}"
            cluster: "{{ item.0.0 }}"
        all_vms:
          clusterA:
            group1:
              - vm-01
              - vm-02
            group2:
              - vm-03
              - vm-04
          clusterB:
            group1:
              - vm-05
              - vm-06

    - debug:
        var: tasks

这会产生:

TASK [set_fact] ***************************************************************
ok: [localhost] => (item=clusterA — group1)
ok: [localhost] => (item=clusterA — group2)
ok: [localhost] => (item=clusterB — group1)

TASK [debug] ******************************************************************
ok: [localhost] => 
  tasks:
  - task:
      cluster: clusterA
      group: group1
      vms:
      - vm-01
      - vm-02
  - task:
      cluster: clusterA
      group: group2
      vms:
      - vm-03
      - vm-04
  - task:
      cluster: clusterB
      group: group1
      vms:
      - vm-05
      - vm-06

关于loops - 在 Ansible 中迭代嵌套字典,保留键名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72750712/

相关文章:

java - 使用带有 Java swing 组件的循环来摊销贷款。

ios - 我应该使用委托(delegate)在后台运行无限循环吗?

c++ - 在特定情况下无法向下渗透 MIN 二进制堆

amazon-web-services - 如何使用ansible将文件夹递归上传到aws s3

ansible - 我如何遍历字典列表及其内容列表

python - 在 Python 中创建随机字符串

c - 这个赋值是什么意思,p=q 其中 p 和 q 都是结构指针?

algorithm - 后缀树 VS 尝试 - 用简单的英语来说,有什么区别?

kubernetes - 如何在不使用引号的情况下使用 k8s Ansible 模块?

python - 计算 Pandas 地理密度的有效方法?