Is there a way to map an array of objects in Ansible Playbook to a different array of objects? Let's say we have a source array being:
arr:
- value: a
- value: b
- value: c
And what we want is to get a different array based on objects in the first array, let's say:
arr2:
- const: 1
var: a
- const: 1
var: b
- const: 1
var: c
This would be doable by an element template of:
const: 1
var: {{ value }}
Is there a way to apply such a template to every element in an array? I haven't found an appropriate map
filter, as lookup('template', ...)
cannot be used inside map
.
Based on your answer (I must say it opened my eyes and I can't find words that tell the infinite gratitude I feel) I worked out what I think is a slightly more elegant solution.
I try to avoid the set_facts
module because the result will have a rather high precedence. I prefer to stick to role defaults and host and group inventory variables.
Also, I am more used to jinja2 templating than Ansible filters.
- 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"
And the very template.yaml.j2 file will contain the iteration:
{% for item in arr %}
- const: 1
var: {{ item.value }}
{% endfor %}
This opens the door for really crazy variable manipulation while keeping the playbook pretty simple.
Hope it helps somebody as much as it helped me!
As Konstantin Suvorov mentioned in the comment it can be done using recursive array building. This is how I did it:
#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 }}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With