52

I am having a hard time understanding the logic of ansible with_subelements syntax, what exactly does with_subelements do? i took a look at ansible documentation on with_subelements here https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#with-subelements and was not very helpful. I also saw a playbook with with_subelements example on a blog

---
- hosts: cent
  vars:
    users:
     - name: jagadish
       comments:
         - 'Jagadish is Good'

     - name: srini
       comments:
         - 'Srini is Bad' 

  tasks:
   - name: User Creation
     shell: useradd -c "{{ item.1 }}" "{{ item.0.name }}"
     with_subelements:
         - users
         - comments

what do item.1 and item.0 refer to?

Eduardo Santana
  • 5,780
  • 3
  • 19
  • 21
ahmedjaad
  • 683
  • 1
  • 8
  • 14
  • 1
    Hello, If you find some documentation not as useful as it should be, don't hesitate to open an issue with the information you're expected to find. Developers can have difficulties to impersonate their users when writing the doc. – Baptiste Mille-Mathias Sep 07 '18 at 18:50
  • I wont, though this particular case I wouldn't consider this as an issue, it's more like a how to question – ahmedjaad Sep 08 '18 at 08:42

1 Answers1

93

This is really bad example of how subelements lookup works. (And has old, unsupported, syntax as well).

Look at this one:

---
- hosts: localhost
  gather_facts: no
  vars:
    families:
      - surname: Smith
        children:
          - name: Mike
            age: 4
          - name: Kate
            age: 7
      - surname: Sanders
        children:
          - name: Pete
            age: 12
          - name: Sara
            age: 17

  tasks:
    - name: List children
      debug:
        msg: "Family={{ item.0.surname }} Child={{ item.1.name }} Age={{ item.1.age }}"
      with_subelements:
        - "{{ families }}"
        - children

Task List children is like a nested loop over families list (outer loop) and over children subelement in each family (inner loop).
So you should provide a list of dicts as first argument to subelements and name of subelement you want to iterate inside each outer item.

This way item.0 (family in my example) is an outer item and item.1 (child in my example) is an inner item.

In Ansible docs example subelements is used to loop over users (outer) and add several public keys (inner).

Konstantin Suvorov
  • 65,183
  • 9
  • 162
  • 193
  • 5
    this is a million time better explanation than the one from Ansible docs,now a follow up question, what if i want to have another inner loop say grandchildren, how would subelements work on such a scenario? – ahmedjaad Jan 28 '17 at 12:07
  • 1
    No way for third nested loop, afaik. Depending on your task `map` or `json_query` may be useful. – Konstantin Suvorov Jan 28 '17 at 13:09
  • 5
    The ansible subelements docs example has been removed between 2.4 [1] and 2.7 [2]. The new way to do it is with `loop: "{{ families|subelements('children') }}"` [2]. A second thanks for this example. [1] https://docs.ansible.com/ansible/2.4/playbooks_loops.html#looping-over-subelements [2] https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#with-subelements – Wes Turner Mar 20 '19 at 01:54
  • 1
    @ahmedjaad as I understood `subelements` works only 2 levels deep. I could still place the children and grandchildren processing into a role, so I could iterate through the families with that role being called for each one. – Gergely Máté Oct 28 '21 at 22:53