Reputation: 2707
I'm writing an Ansible playbook and I have the following variable:
contracts:
- name: 'https'
subjects:
- name: 'permit'
filters:
- filter: tcp_443
A contract has multiple subjects and a subject can have multiple filters. The playbook needs to loop over this variable.
I'm currently doing the following:
- name: Task - Contract Subjects Have Filters
contract_subject_to_filter:
state: "present"
tenant: "{{ tenant }}"
contract: "{{ item..0.name }}"
subject: "{{ item.1.name }}"
filter: "{{ item.2.filter }}"
loop: "{{ contracts | subelements('subjects') | subelements('filters') }}"
tags: contract
{"msg": "Unexpected templating type error occurred on ({{ contracts | subelements('subjects') | subelements('filters') }}): the key filters should point to a dictionary, got '({'name': 'https', 'subjects': [{'name': 'permit', 'filters': [{'filter': 'tcp_443'}]}]}, {'name': 'permit', 'filters': [{'filter': 'tcp_443'}]})'"}
How can I do a double loop (contracts has subjects and subjects have filters) in an Ansible playbook? I cannot change the variable structure or use a different Ansible module.
Upvotes: 1
Views: 1071
Reputation: 68179
Flatten the list, e.g.
- set_fact:
my_list: "{{ _my_list|from_yaml }}"
vars:
_my_list: |-
{% for i in contracts %}
{% for j in i.subjects %}
{% for k in j.filters %}
- {name: {{ i.name }}, subject: {{ j.name }}, filter: {{ k.filter }}}
{% endfor %}
{% endfor %}
{% endfor %}
gives
my_list:
- filter: tcp_443
name: https
subject: permit
Then, the iteration is trivial
- name: Task - Contract Subjects Have Filters
debug:
msg: |-
state: "present"
tenant: "tenant"
contract: "{{ item.name }}"
subject: "{{ item.subject }}"
filter: "{{ item.filter }}"
loop: "{{ my_list }}"
gives
msg: |-
state: "present"
tenant: "tenant"
contract: "https"
subject: "permit"
filter: "tcp_443"
Upvotes: 4