The goal is to iterate over a list which contains another list. If the nested list is empty I want to use the values of the parent instead. Sadly I can't find a possible solution.
List to iterate:
users:
- name: Mario
username: admin_mario
state: present
role: admin
ssh: []
- name: luigi
username: just_luigi
state: present
role: qa
ssh:
- username: qa_luigi
role: qa
state: present
- username: admin_luigi
role: admin
state: present
So I would like to iterate over this list if ssh is empty use username, state and role as defaults.
- name: test
include_tasks: "mytasks.yml"
loop: "{{ users|subelements(ssh) }}"
loop_control:
loop_var: user
when: users is defined
- name: test
include_tasks: "mytasks.yml"
loop: "{{ users|default({'ssh': [{'username': user.username}]})|subelements('ssh') }}"
loop_control:
loop_var: user
Sadly I couldn't figure out a solution with the Dokumentation e.g. with_items, loop control, subelements nothing seems to work as expected.
Create defaults
defaults: "{{ users|json_query('[].{username: username,
state: state,
role: role}') }}"
gives
defaults:
- role: admin
state: present
username: admin_mario
- role: qa
state: present
username: just_luigi
Create list of ssh
ssh_str: |
{% for i,j in users|zip(defaults) %}
{% if i.ssh|length == 0 %}
- ssh: [{{ j }}]
{% else %}
- {}
{% endif %}
{% endfor %}
ssh: "{{ ssh_str|from_yaml }}"
ssh_str: |
{% for i,j in users|zip(defaults) %}
- {{ i.ssh|ternary({}, {'ssh': [j]}) }}
{% endfor %}
gives
ssh:
- ssh:
- role: admin
state: present
username: admin_mario
- {}
Combine the items of the lists
- debug:
msg: "{{ item.0.name }} {{ item.1.username }} {{ item.1.role }} {{ item.1.state }}"
with_subelements:
- "{{ users|zip(ssh)|map('combine') }}"
- ssh
gives (abridged)
msg: Mario admin_mario admin present
msg: luigi qa_luigi qa present
msg: luigi admin_luigi admin present
Example of a complete playbook for testing
- hosts: localhost
vars:
users:
- name: Mario
username: admin_mario
state: present
role: admin
ssh: []
- name: luigi
username: just_luigi
state: present
role: qa
ssh:
- username: qa_luigi
role: qa
state: present
- username: admin_luigi
role: admin
state: present
defaults: "{{ users|json_query('[].{username: username,
state: state,
role: role}') }}"
ssh_str: |
{% for i,j in users|zip(defaults) %}
{% if i.ssh|length == 0 %}
- ssh: [{{ j }}]
{% else %}
- {}
{% endif %}
{% endfor %}
ssh: "{{ ssh_str|from_yaml }}"
tasks:
- debug:
var: defaults
- debug:
var: ssh
- debug:
msg: "{{ item.0.name }} {{ item.1.username }} {{ item.1.role }} {{ item.1.state }}"
with_subelements:
- "{{ users|zip(ssh)|map('combine') }}"
- ssh