# Please help me understand nested loops

**URL:** <https://forum.ansible.com/t/please-help-me-understand-nested-loops/38231>\
**Category:** Ansible Project\
**Created:** [July 16, 2023, 7:30am UTC](https://forum.ansible.com/t/please-help-me-understand-nested-loops/38231 "2023-07-16T07:30:42Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Werner\_van\_der\_Merwe](https://avatars.discourse-cdn.com/v4/letter/w/5e9695/32.png) [@Werner\_van\_der\_Merwe](https://forum.ansible.com/u/Werner_van_der_Merwe)\
**Post date:** [July 16, 2023, 7:30am UTC](https://forum.ansible.com/t/please-help-me-understand-nested-loops/38231/1 "2023-07-16T07:30:42Z")

</div>

Hi,

This code works, I just don’t understand the indexing and loop behaviour. Hoping someone can help me understand the indexing, and why the variables are equal to the values.

Here the code:

```auto
engineers:
- username: user1
state: present
keys:
- ssh-rsa AAAAB3Nza....
- ssh-rsa AAAAB3Nza....
- username: user2
state: present
keys:
- ssh-rsa AAAAB3NzaC....
- username: user3
state: present
keys:
- ssh-rsa AAAAB3NzaC1....

```

and I have a working code snippet:

```auto
- name: Manage authorized keys
authorized_key:
user: "{{ item.0.username }}"
state: present
key: "{{ item.1 }}"
with_subelements:
- "{{ engineers }}"
- keys
loop_control:
loop_var: item

```

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/ansible/original/1X/1882d9a01da5d8996a862359b0913cc568a39b84.svg) [@system](https://forum.ansible.com/u/system)\
**Post date:** [July 17, 2023, 1:49pm UTC](https://forum.ansible.com/t/please-help-me-understand-nested-loops/38231/2 "2023-07-17T13:49:37Z")

</div>

This is really not a 'nested' loop, you are using the 'subelements'  
lookup to change the data provided to a single loop.

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [July 18, 2023, 1:58am UTC](https://forum.ansible.com/t/please-help-me-understand-nested-loops/38231/3 "2023-07-18T01:58:36Z")

</div>

Is it loop behaviour in general that’s confusing, or the effect of **with\_subelements**? Remember that the **with\_\*** construct is implemented as a **lookup**. Once you understand what the **subelements**  **lookup** does, then this specific loop should make more sense.

Here’s a playbook and its output log, using a your data with some modifications to make it easier to see what’s going on. I’ve added a ‘ **user4** ’ with no ‘ **keys** ’ to show how to handle that case, too.

The first **debug** task loops they same way your playbook loops, using **with\_subelements**.

The second **debug** task doesn’t loop, but invokes the **subelements**  **lookup** directly, with parameters identical to those passed to the prior task’s **with\_subelements**. The **subelements**  **lookup** produces a list which, not surprisingly, matches what the prior task looped over.

```auto
[utoddl@tango ansible]$ **cat test-subelements2.yml** 
---
- name: Demonstrate subelements
  hosts: localhost
  gather_facts: false
  vars:
    engineers:
      - username: user1
        state: present
        keys:
          - user1keyA
          - user1KeyB
      - username: user2
        state: present
        keys:
          - user2keyA
      - username: user3
        state: present
        keys:
          - user3keyA
      - username: user4
        state: present
        note: Look! No 'keys'!
  tasks:
    - name: **Show subelements one per loop**
      ansible.builtin.debug:
        msg: "{{ item }}"
      with_subelements:
        - "{{ engineers }}"
        - keys
        - {'skip_missing': true}

    - name: **Show the same subelements all in one go**
      ansible.builtin.debug:
        msg: "{{ **lookup('subelements', engineers, 'keys', {'skip_missing': true})** }}"
[utoddl@tango ansible]$ **ansible-playbook test-subelements2.yml** 

PLAY [Demonstrate subelements] *********************************************************

TASK [**Show subelements one per loop**] ***************************************************
ok: [localhost] => (item=[{'username': 'user1', 'state': 'present'}, 'user1keyA']) => {
    "msg": [
        {
            "state": "present",
            "username": "user1"
        },
        "user1keyA"
    ]
}
ok: [localhost] => (item=[{'username': 'user1', 'state': 'present'}, 'user1KeyB']) => {
    "msg": [
        {
            "state": "present",
            "username": "user1"
        },
        "user1KeyB"
    ]
}
ok: [localhost] => (item=[{'username': 'user2', 'state': 'present'}, 'user2keyA']) => {
    "msg": [
        {
            "state": "present",
            "username": "user2"
        },
        "user2keyA"
    ]
}
ok: [localhost] => (item=[{'username': 'user3', 'state': 'present'}, 'user3keyA']) => {
    "msg": [
        {
            "state": "present",
            "username": "user3"
        },
        "user3keyA"
    ]
}

TASK [**Show the same subelements all in one go**] *****************************************
ok: [localhost] => {
    "msg": [
        [
            {
                "state": "present",
                "username": "user1"
            },
            "user1keyA"
        ],
        [
            {
                "state": "present",
                "username": "user1"
            },
            "user1KeyB"
        ],
        [
            {
                "state": "present",
                "username": "user2"
            },
            "user2keyA"
        ],
        [
            {
                "state": "present",
                "username": "user3"
            },
            "user3keyA"
        ]
    ]
}

PLAY RECAP ************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 

```

Do let us know if something is still unclear.

---

<div class="post-metadata">

**Author:** ![Endure\_Kona](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/endure_kona/32/391_2.png) [@Endure\_Kona](https://forum.ansible.com/u/Endure_Kona)\
**Post date:** [July 18, 2023, 2:25am UTC](https://forum.ansible.com/t/please-help-me-understand-nested-loops/38231/4 "2023-07-18T02:25:17Z")

</div>

I don’t know what with\_subelements: is but here is what I know of with\_nested that works for me - this is creating a Oracle databse server…with the database name…which some of these files from db\_create\_files\_1 needs the ora\_sid to replace it inside the files, that is all mapped out with the when if the inventory\_host name equals the host in the var then use that ora\_sid. If this helps

:

- name: Create scripts for database configuration files on the target without ORA\_SID placing in the root of DBcreate  
ansible.builtin.template:  
src: “{{ Oracle\_Template\_Dir }}/create/{{ item.0.file\_name }}”  
dest: “{{ DB\_Create\_Dir }}/{{ item.0.file\_name | replace(‘.j2’, ‘’) }}.{{ item.0.ext }}”  
mode: ‘a+x’  
with\_nested:
- “{{ db\_create\_files\_1 }}” # ← for the vars with item.0.x pulling from this entry in the variable file
- “{{ specific\_hosts\_conf }}” # ← for the vars with item.1.x pulling from this entry in the variable file  
when: (item.1.ora\_sid|upper not in Database\_Name.stdout) and (inventory\_hostname == item.1.host)

Defined in the variable…

specific\_hosts\_conf:

- {host: ‘[servername.domain.com](http://servername.domain.com)’, specific\_ip: ‘192.168.1.46’, specific\_host: ‘[servername.domain.com](http://servername.domain.com)’, ora\_sid: ‘DogsDB’, RCATHOST\_IP: ‘192.168.1.49’, db\_domain: ‘[domain.com](http://domain.com)’}

db\_create\_files\_1: #ora\_stage/DBcreate/

- {file\_name: ‘profile19c\_new.j2’, ext: ‘’}
- {file\_name: ‘cr\_temp\_profile.j2’, ext: ‘sql’}
- {file\_name: ‘cron.j2’, ext: ‘header’}
- {file\_name: ‘tnsnames.j2’, ext: ‘ora’}
- {file\_name: ‘sqlnet.ora.j2’, ext: ‘default’}
- {file\_name: ‘init.j2’, ext: ‘new’}
- {file\_name: ‘listener.j2’, ext: ‘ora’}

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/ansible/original/1X/1882d9a01da5d8996a862359b0913cc568a39b84.svg) [@system](https://forum.ansible.com/u/system)\
**Post date:** [July 18, 2023, 2:03pm UTC](https://forum.ansible.com/t/please-help-me-understand-nested-loops/38231/5 "2023-07-18T14:03:40Z")

</div>

The way 'with\_' works is more or less the same a a loop with a lookup  
in it's item list

with\_nested ... == loop: '{{ lookup("nested", ... )}}'

Most find the `loop` syntax a bit clearer, it is less 'magical', but  
the with\_ syntax is more convenient.
