在Ansible中创建自定义字典列表可以通过以下方式实现:

huangapple go评论93阅读模式
英文:

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 

huangapple
  • 本文由 发表于 2023年8月8日 22:19:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76860457.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定