英文:
Create custom list of dicts in Ansible
问题
我需要在Ansible中使用set_fact
创建一个变量,它是一个字典列表。
具体来说,我有一个名为previous.results
的变量,内容如下:
{
path: /aaa
files: [f1.txt, f2.txt]
[其他字典内容]
},
{
path: /bbb
files: [f3.txt]
[其他字典内容]
}
我希望得到的结果是:
[{path: /aaa, files:[f1.txt, f2.txt]}, {path: /bbb, files: [f3.txt]}]
我尝试了以下代码:
- name: init
ansible.builtin.set_fact:
files: "{{ files|default([]) + [ { path: item['path'], files: item.keys() } ] }}"
with_items: "{{ previous.results }}"
但是我得到了以下错误:
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'path' is undefined. 'path' is undefined\n\nThe error appears to be in 'test-playbook.yaml': line 47, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: init\n ^ here\n"}
我的目标是在本地创建这些文件,然后按照这个stackoverflow的解决方案,添加内容(item.values()
)。我将files
变量视为链接中解决方案中的objs
。
英文:
I need to create in Ansible a variable with set_fact
as a list of dictionaries.
In particular I have previous.results
as:
{
path: /aaa
files: [f1.txt, f2.txt]
[other dict content]
},
{
path: /bbb
files: [f3.txt]
[other dict content]
}
and I want to have:
[{path: /aaa, files:[f1.txt, f2.txt]}, {path: /bbb, files: [f3.txt]}]
I tried with the following code:
- name: init
ansible.builtin.set_fact:
files: "{{ files|default([]) + [ { path: item['path'], files: item.keys() } ] }}"
with_items: "{{ previous.results }}"
But I get:
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'path' is undefined. 'path' is undefined\n\nThe error appears to be in 'test-playbook.yaml': line 47, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: init\n ^ here\n"}
My objective is to create these files locally and then add content (item.values()
) following this stackoverflow solution. I'm treating files
var as objs
in the solution I linked.
答案1
得分: 1
你不需要对初始的字典列表进行任何转换步骤,可以直接使用它:
---
- hosts: localhost
gather_facts: false
vars:
previous:
results:
- path: /aaa
files: [f1.txt, f2.txt]
toto: 1
pipo: 2
- path: /bbb
files: [f3.txt]
toto: 3
pipo: 4
tasks:
- name: Show the result in a debug task
ansible.builtin.debug:
msg: "I would create {{ item.0.path }}/{{ item.1 }}"
# 注意下面的行与以下行是严格等价的:
# with_subelements:
# - "{{ previous.results }}"
# - files
loop: "{{ previous.results | subelements('files') }}"
# 添加控制以限制循环输出的数据量
loop_control:
label: "{{ item.0.path }}, {{ item.1 }}"
上述的playbook输出结果为:
PLAY [localhost] **************************************************************************************************************************************************************************************************
TASK [Show the result in a debug task] ****************************************************************************************************************************************************************************
ok: [localhost] => (item=/aaa, f1.txt) => {
"msg": "I would create /aaa/f1.txt"
}
ok: [localhost] => (item=/aaa, f2.txt) => {
"msg": "I would create /aaa/f2.txt"
}
ok: [localhost] => (item=/bbb, f3.txt) => {
"msg": "I would create /bbb/f3.txt"
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
英文:
You don't need any step to transform your initial list of dicts, you can use it as it is:
---
- hosts: localhost
gather_facts: false
vars:
previous:
results:
- path: /aaa
files: [f1.txt, f2.txt]
toto: 1
pipo: 2
- path: /bbb
files: [f3.txt]
toto: 3
pipo: 4
tasks:
- name: Show the result in a debug task
ansible.builtin.debug:
msg: "I would create {{ item.0.path }}/{{ item.1 }}"
# Note the below line is strictly equivalent to:
# with_subelements:
# - "{{ previous.results }}"
# - files
loop: "{{ previous.results | subelements('files') }}"
# Adding control to limit loop output to only a few data
loop_control:
label: "{{ item.0.path }}, {{ item.1 }}"
The above playbook gives:
PLAY [localhost] **************************************************************************************************************************************************************************************************
TASK [Show the result in a debug task] ****************************************************************************************************************************************************************************
ok: [localhost] => (item=/aaa, f1.txt) => {
"msg": "I would create /aaa/f1.txt"
}
ok: [localhost] => (item=/aaa, f2.txt) => {
"msg": "I would create /aaa/f2.txt"
}
ok: [localhost] => (item=/bbb, f3.txt) => {
"msg": "I would create /bbb/f3.txt"
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论