Ansible 迭代字典的字典
Ansible iterate on dict of dict
我如何使用 Ansible 迭代包含另一个字典的字典?
mydict
可以包含 X“foo”并且 fooX(如 foo1)可以包含(至少)一个或多个参数“bar”。
我真的无法更改 vars 类型,目前是:
mydict: 字典
mydict.foo1: 字典
mydict.foo1.params: 字典
Ansible 剧本:localvars.yml
---
- hosts: localhost
connection: local
gather_facts: false
vars:
mydict:
foo1:
dest: /tmp/foo1.txt
content: "foo1"
params:
bar1:
alias: foo1foo
bar2:
alias: foo1foo
foo2:
dest: /tmp/foo2.txt
content: "foo2"
params:
bar1:
alias: foo1foo
tasks:
- name: Print records
debug:
msg: |-
Item {{ item.key }} dest {{ item.value.dest }} content {{ item.value.content }} params {{ item.value.params }}"
loop: "{{ mydict | dict2items }}"
Ansible 命令:ansible-playbook -vv -i localhost, localvars.yml
预期结果:
为“fooX”中的每个“barX”参数动态获取 mydict.fooX.params.barX.alias
为每个“fooX”动态获取 mydict.fooX.dest
感谢您的帮助
我试过了:
- name: Using dict2items
ansible.builtin.debug:
msg: |-
"item.key = {{ item.key }}
item.value = {{ item.value }}"
loop: "{{ mydict | dict2items }}"
像 mydict.foo1.dest 一样可以很好地获取 mydict
中的所有值,但我很难获取所有参数值
感谢您的帮助
这有点难看,但我相信它符合您的要求:
- name: Print records
vars:
_records_to_items: "{{ mydict | dict2items }}"
_params_to_items: "{{ _records_to_items | map(attribute='value.params') | map('dict2items') }}"
_consolidate: "{{ _records_to_items | zip(_params_to_items) }}"
my_msg: |-
Item: {{ item.0.0.key }}
dest: {{ item.0.0.value.dest }}
content {{ item.0.0.value.content }}
curent param
name: {{ item.1.key }}
value: {{ item.1.value }}
debug:
msg: "{{ my_msg | split('\n') }}"
loop: "{{ _consolidate | subelements([1]) }}"
loop_control:
label: "Processing params for {{ item.0.0.key }}"
这给出了(运行 根据您的上述数据):
PLAY [localhost] **************************************************************************************************************************************************************************************************
TASK [Print records] **********************************************************************************************************************************************************************************************
ok: [localhost] => (item=Processing params for foo1) => {
"msg": [
"Item: foo1",
"dest: /tmp/foo1.txt",
"content foo1",
"curent param",
" name: bar1",
" value: {'alias': 'foo1foo'}"
]
}
ok: [localhost] => (item=Processing params for foo1) => {
"msg": [
"Item: foo1",
"dest: /tmp/foo1.txt",
"content foo1",
"curent param",
" name: bar2",
" value: {'alias': 'foo1foo'}"
]
}
ok: [localhost] => (item=Processing params for foo2) => {
"msg": [
"Item: foo2",
"dest: /tmp/foo2.txt",
"content foo2",
"curent param",
" name: bar1",
" value: {'alias': 'foo1foo'}"
]
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
最简单的选项是包含文件中属性 params 的迭代,例如创建一个文件
shell> cat iterate-params.yml
- debug:
msg: |-
item: {{ outer_item.key }}
dest: {{ outer_item.value.dest }}
content: {{ outer_item.value.content }}
param: {{ item }}
loop: "{{ outer_item.value.params|dict2items }}"
loop_control:
label: "{{ outer_item.key }}: {{ item.key }}"
并将其包含在循环中
- include_tasks: iterate-params.yml
loop: "{{ mydict|dict2items }}"
loop_control:
loop_var: outer_item
label: "{{ outer_item.key }}"
给予
TASK [debug] *******************************************************
included: /export/scratch/tmp8/iterate-params.yml for localhost => (item=foo1)
included: /export/scratch/tmp8/iterate-params.yml for localhost => (item=foo2)
TASK [debug] *******************************************************
ok: [localhost] => (item=foo1: bar1) =>
msg: |-
item: foo1
dest: /tmp/foo1.txt
content: foo1
param: {'key': 'bar1', 'value': {'alias': 'foo1foo'}}
ok: [localhost] => (item=foo1: bar2) =>
msg: |-
item: foo1
dest: /tmp/foo1.txt
content: foo1
param: {'key': 'bar2', 'value': {'alias': 'foo1foo'}}
TASK [debug] *******************************************************
ok: [localhost] => (item=foo2: bar1) =>
msg: |-
item: foo2
dest: /tmp/foo2.txt
content: foo2
param: {'key': 'bar1', 'value': {'alias': 'foo1foo'}}
如果可以使用最新的过滤器 community.general.dict_kv,下一个选项是将属性 params 转换为列表和迭代 with_subelements
- debug:
msg: |-
dest: {{ item.0.dest }}
content: {{ item.0.content }}
param: {{ item.1 }}
with_subelements:
- "{{ _values|zip(_params)|map('combine') }}"
- params
loop_control:
label: "{{ item.0.dest }}"
vars:
_list: "{{ mydict|dict2items }}"
_values: "{{ _list|map(attribute='value') }}"
_params: "{{ _list|map(attribute='value.params')|
map('dict2items')|
map('community.general.dict_kv', 'params') }}"
给予
TASK [debug] ***********************************************************
ok: [localhost] => (item=/tmp/foo1.txt) =>
msg: |-
dest: /tmp/foo1.txt
content: foo1
param: {'key': 'bar1', 'value': {'alias': 'foo1foo'}}
ok: [localhost] => (item=/tmp/foo1.txt) =>
msg: |-
dest: /tmp/foo1.txt
content: foo1
param: {'key': 'bar2', 'value': {'alias': 'foo1foo'}}
ok: [localhost] => (item=/tmp/foo2.txt) =>
msg: |-
dest: /tmp/foo2.txt
content: foo2
param: {'key': 'bar1', 'value': {'alias': 'foo1foo'}}
我如何使用 Ansible 迭代包含另一个字典的字典?
mydict
可以包含 X“foo”并且 fooX(如 foo1)可以包含(至少)一个或多个参数“bar”。
我真的无法更改 vars 类型,目前是:
mydict: 字典
mydict.foo1: 字典
mydict.foo1.params: 字典
Ansible 剧本:localvars.yml
---
- hosts: localhost
connection: local
gather_facts: false
vars:
mydict:
foo1:
dest: /tmp/foo1.txt
content: "foo1"
params:
bar1:
alias: foo1foo
bar2:
alias: foo1foo
foo2:
dest: /tmp/foo2.txt
content: "foo2"
params:
bar1:
alias: foo1foo
tasks:
- name: Print records
debug:
msg: |-
Item {{ item.key }} dest {{ item.value.dest }} content {{ item.value.content }} params {{ item.value.params }}"
loop: "{{ mydict | dict2items }}"
Ansible 命令:ansible-playbook -vv -i localhost, localvars.yml
预期结果:
为“fooX”中的每个“barX”参数动态获取 mydict.fooX.params.barX.alias
为每个“fooX”动态获取 mydict.fooX.dest
感谢您的帮助
我试过了:
- name: Using dict2items
ansible.builtin.debug:
msg: |-
"item.key = {{ item.key }}
item.value = {{ item.value }}"
loop: "{{ mydict | dict2items }}"
像 mydict.foo1.dest 一样可以很好地获取 mydict
中的所有值,但我很难获取所有参数值
感谢您的帮助
这有点难看,但我相信它符合您的要求:
- name: Print records
vars:
_records_to_items: "{{ mydict | dict2items }}"
_params_to_items: "{{ _records_to_items | map(attribute='value.params') | map('dict2items') }}"
_consolidate: "{{ _records_to_items | zip(_params_to_items) }}"
my_msg: |-
Item: {{ item.0.0.key }}
dest: {{ item.0.0.value.dest }}
content {{ item.0.0.value.content }}
curent param
name: {{ item.1.key }}
value: {{ item.1.value }}
debug:
msg: "{{ my_msg | split('\n') }}"
loop: "{{ _consolidate | subelements([1]) }}"
loop_control:
label: "Processing params for {{ item.0.0.key }}"
这给出了(运行 根据您的上述数据):
PLAY [localhost] **************************************************************************************************************************************************************************************************
TASK [Print records] **********************************************************************************************************************************************************************************************
ok: [localhost] => (item=Processing params for foo1) => {
"msg": [
"Item: foo1",
"dest: /tmp/foo1.txt",
"content foo1",
"curent param",
" name: bar1",
" value: {'alias': 'foo1foo'}"
]
}
ok: [localhost] => (item=Processing params for foo1) => {
"msg": [
"Item: foo1",
"dest: /tmp/foo1.txt",
"content foo1",
"curent param",
" name: bar2",
" value: {'alias': 'foo1foo'}"
]
}
ok: [localhost] => (item=Processing params for foo2) => {
"msg": [
"Item: foo2",
"dest: /tmp/foo2.txt",
"content foo2",
"curent param",
" name: bar1",
" value: {'alias': 'foo1foo'}"
]
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
最简单的选项是包含文件中属性 params 的迭代,例如创建一个文件
shell> cat iterate-params.yml
- debug:
msg: |-
item: {{ outer_item.key }}
dest: {{ outer_item.value.dest }}
content: {{ outer_item.value.content }}
param: {{ item }}
loop: "{{ outer_item.value.params|dict2items }}"
loop_control:
label: "{{ outer_item.key }}: {{ item.key }}"
并将其包含在循环中
- include_tasks: iterate-params.yml
loop: "{{ mydict|dict2items }}"
loop_control:
loop_var: outer_item
label: "{{ outer_item.key }}"
给予
TASK [debug] *******************************************************
included: /export/scratch/tmp8/iterate-params.yml for localhost => (item=foo1)
included: /export/scratch/tmp8/iterate-params.yml for localhost => (item=foo2)
TASK [debug] *******************************************************
ok: [localhost] => (item=foo1: bar1) =>
msg: |-
item: foo1
dest: /tmp/foo1.txt
content: foo1
param: {'key': 'bar1', 'value': {'alias': 'foo1foo'}}
ok: [localhost] => (item=foo1: bar2) =>
msg: |-
item: foo1
dest: /tmp/foo1.txt
content: foo1
param: {'key': 'bar2', 'value': {'alias': 'foo1foo'}}
TASK [debug] *******************************************************
ok: [localhost] => (item=foo2: bar1) =>
msg: |-
item: foo2
dest: /tmp/foo2.txt
content: foo2
param: {'key': 'bar1', 'value': {'alias': 'foo1foo'}}
如果可以使用最新的过滤器 community.general.dict_kv,下一个选项是将属性 params 转换为列表和迭代 with_subelements
- debug:
msg: |-
dest: {{ item.0.dest }}
content: {{ item.0.content }}
param: {{ item.1 }}
with_subelements:
- "{{ _values|zip(_params)|map('combine') }}"
- params
loop_control:
label: "{{ item.0.dest }}"
vars:
_list: "{{ mydict|dict2items }}"
_values: "{{ _list|map(attribute='value') }}"
_params: "{{ _list|map(attribute='value.params')|
map('dict2items')|
map('community.general.dict_kv', 'params') }}"
给予
TASK [debug] ***********************************************************
ok: [localhost] => (item=/tmp/foo1.txt) =>
msg: |-
dest: /tmp/foo1.txt
content: foo1
param: {'key': 'bar1', 'value': {'alias': 'foo1foo'}}
ok: [localhost] => (item=/tmp/foo1.txt) =>
msg: |-
dest: /tmp/foo1.txt
content: foo1
param: {'key': 'bar2', 'value': {'alias': 'foo1foo'}}
ok: [localhost] => (item=/tmp/foo2.txt) =>
msg: |-
dest: /tmp/foo2.txt
content: foo2
param: {'key': 'bar1', 'value': {'alias': 'foo1foo'}}