wiwa1978
wiwa1978

Reputation: 2707

Ansible double loop using subelements

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

Answers (1)

Vladimir Botka
Vladimir Botka

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

Related Questions