Ansible - 将对象数组映射到不同的对象数组

Bar*_*zak 6 yaml templating jinja2 ansible

有没有办法将 Ansible Playbook 中的对象数组映射到不同的对象数组?假设我们有一个源数组:

arr:
  - value: a
  - value: b
  - value: c
Run Code Online (Sandbox Code Playgroud)

我们想要的是根据第一个数组中的对象获得一个不同的数组,让我们说:

arr2:
  - const: 1
    var: a
  - const: 1
    var: b
  - const: 1
    var: c
Run Code Online (Sandbox Code Playgroud)

这可以通过以下元素模板来实现:

const: 1
var: {{ value }}
Run Code Online (Sandbox Code Playgroud)

有没有办法将这样的模板应用于数组中的每个元素?我还没有找到合适的map过滤器,因为lookup('template', ...)不能在map.

N1n*_*ngu 5

根据您的回答(我必须说它让我大开眼界,我无法用言语表达我所感受到的无限感激)我想出了一个我认为稍微优雅的解决方案。

我尽量避免使用该set_facts模块,因为结果将具有相当高的优先级。我更喜欢使用角色默认值以及主机和组库存变量。

此外,与 Ansible 过滤器相比,我更习惯于 jinja2 模板。

- hosts: localhost
  gather_facts: no
  vars:
    arr:
      - value: a
      - value: b
      - value: c
    arr2: "{{ lookup('template', 'template.yaml.j2') | from_yaml }}"

  tasks:
    - debug:
        var: "arr2"
Run Code Online (Sandbox Code Playgroud)

非常 template.yaml.j2 文件将包含迭代:

{% for item in arr %}
- const: 1
  var: {{ item.value }}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

这为真正疯狂的变量操作打开了大门,同时保持剧本非常简单。

希望它对某人的帮助和对我的帮助一样多!


Bar*_*zak 2

正如 Konstantin Suvorov 在评论中提到的,可以使用递归数组构建来完成。我就是这样做的:

#role test
---
- hosts: localhost
  gather_facts: no
  vars:
    arr:
      - value: a
      - value: b
      - value: c

  tasks:
    - set_fact:
        arr2: "{{ (arr2 | default([])) + [ lookup('template', 'template.yaml.j2') | from_yaml ] }}"
      with_items: "{{ arr }}"
    - debug:
        msg: "{{ arr2 }}"


#template.yaml.j2
const: 1
var: {{ item.value }}
Run Code Online (Sandbox Code Playgroud)