我有一个如下所示的数据结构:
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/