<p>Let's simplify the dictionary in the first task and loop the subelements in the second. The tasks below</p>
<pre class="lang-yaml prettyprint-override"><code>    - set_fact:
        nginx_users_selected: &quot;{{ nginx_users_selected|
                                  default({})|
                                  combine({item.key: item.value})
                                  }}&quot;
      loop: &quot;{{ nginx_users|
                dict2items|
                json_query('[*].{key: key, value: value.basic_auth}')
                }}&quot;
      when: item.value
    - debug:
        msg: &quot;{{ item.0.key }} {{ item.1 }}&quot;
      loop: &quot;{{ nginx_users_selected|
                dict2items|
                subelements('value')
                }}&quot;
</code></pre>
<p>give</p>
<pre class="lang-yaml prettyprint-override"><code>    &quot;msg&quot;: &quot;instance2 username1&quot;
    &quot;msg&quot;: &quot;instance2 username2&quot;
    &quot;msg&quot;: &quot;instance1 username1&quot;
    &quot;msg&quot;: &quot;instance1 username2&quot;
</code></pre>
<p>Then we can create the structure</p>
<pre class="lang-yaml prettyprint-override"><code>    - set_fact:
        my_list: &quot;{{ my_list|default([]) +
                     [ item.0.key, [ item.1 ]] }}&quot;
      loop: &quot;{{ nginx_users_selected|
                dict2items|
                subelements('value') }}&quot;
    - debug:
        var: my_list
</code></pre>
<p>give</p>
<pre class="lang-yaml prettyprint-override"><code>    &quot;my_list&quot;: [
        &quot;instance2&quot;, 
        [
            &quot;username1&quot;
        ], 
        &quot;instance2&quot;, 
        [
            &quot;username2&quot;
        ], 
        &quot;instance1&quot;, 
        [
            &quot;username1&quot;
        ], 
        &quot;instance1&quot;, 
        [
            &quot;username2&quot;
        ]
    ]
</code></pre>

CC BY-SA 4.0
2019-07-18T07:40:56.167Z
!Thanks! that worked beautifully, It required me installing "jmespath" but don't care about that. I found another solution using include_tasks and outer and inner loop. this is way better. I still need to understand it tho. So loads reading to do. I would have never found this out. Thanks
maco1717
CC BY-SA 4.0
2019-11-05T11:39:35.107Z
I was wondering is you could recommend any reading material for this, I have had some time not to racap this and looking into this I really really can't head my head around it xD - I have a new requirement similar to this, but I dont know how to use your example as a starting point
maco1717
CC BY-SA 4.0
2019-11-05T11:49:07.523Z
FWIW. Moving forward I kept examples in [GitHub](https://github.com/vbotka/ansible-examples). Start with [example 2](https://github.com/vbotka/ansible-examples/blob/master/examples/example-002/json_query.yml) then see files  in [example 20](https://github.com/vbotka/ansible-examples/blob/master/examples/example-020). There is a tutorial and some examples at [jmespath.org](http://jmespath.org/).
Vladimir Botka
CC BY-SA 4.0
2019-11-05T12:15:50.443Z
Thanks you very much!
maco1717
CC BY-SA 4.0
2019-07-17T06:43:55.617Z
2021-04-19T10:30:32.607Z
2021-04-19T10:30:32.607Z
Vladimir Botka
<p>I'm not able to loop a list in a dict and keep the key of the original dict.</p>

<p>Bellow an example of my data</p>

<pre><code>vars:
 nginx_users:
    'instance1':
       roles:
          - product
          - nginx_instance
       cert_source: internal-ca
       URL: page-nginx.domain.internal
       port: 8090
       downtime: true
       basic_auth:
          - username1
          - username2
       ip_restriction:
          - '0.0.0.0/0'
    'instance2':
       roles:
          - product
          - nginx_instance
       cert_source: internal-ca
       URL: page2-nginx.domain.internal
       port: 8091
       downtime: true
       basic_auth:
          - username1
          - username2
       ip_restriction:
          - '0.0.0.0/0'
    'instance3':
       roles:
          - product
          - nginx_instance
</code></pre>

<p>I need to loop it in a manner that It iterates like this</p>

<pre><code>"msg": [
        "instance1",
        [
            "username1"
        ],
        "instance1",
        [
            "username2"
        ],
       "instance2",
        [
            "username1"
        ],
        "instance2",
        [
            "username2"
        ]
...
    ]
</code></pre>

<p>I am using</p>

<blockquote>
  <p>when: item.value.basic_auth is defined</p>
</blockquote>

<p>In a loop which will filter out the items without the desired <strong>value/item</strong> and return only the "items" that I need to parse, like.</p>

<pre><code>...
loop: "{{ nginx_users | dict2items }}"
when: item.value.basic_auth is defined
...
</code></pre>

<p>However from there I don't know how to loop those "items" to get the list of users on a way that it returns the single user per iteration and preserve the key.</p>

<p>I know a work around would be to have use another variable instead of the key so I could just select it. but that wouldn't work for me in this escenario.</p>

<p>I have tried using subelements and lookup but I don't seem to be able narrow down the exact combination also thought about using product too and try and traverse the data. But I wasn't able to use that either.</p>

<p>After reading this:</p>

<p><a href="https://github.com/ansible/ansible/pull/6370" rel="nofollow noreferrer">https://github.com/ansible/ansible/pull/6370</a></p>

<p><a href="https://github.com/ansible/ansible/pull/4982" rel="nofollow noreferrer">https://github.com/ansible/ansible/pull/4982</a></p>

<p>I'm starting to think I will have to use Jinja to be able to do this.</p>

<p>This is as close as I have been able to get to what I'm trying to achieve</p>

<pre><code>- name: loop
  debug:
    msg:
    - "{{ item.key }}"
    - "{{ item.value.basic_auth }}"
  loop: "{{ nginx_users | dict2items }}"
  when: item.value.basic_auth is defined

- name: loop
  debug:
    msg:
    - "{{ item.1 }}"
  loop: "{{ lookup('subelements', nginx_users, 'basic_auth', {'skip_missing': True}) }}"
</code></pre>

<p>which results on this:</p>

<pre><code> TASK [loop]
 ************************************************************************ skipping: [nginx-test-01.domain.internal] =&gt; (item={'key':
 u'instance1', 'value': {u'roles': [u'product', u'nginx_instance']}})
 ok: [nginx-test-01.domain.internal] =&gt; (item={'key': u'username2',
 'value': {u'roles': [u'product', u'nginx_instance'], u'URL':
 u'page-nginx.symplectic.internal', u'ip_restriction': [u'0.0.0.0/0'],
 u'basic_auth': [u'username1', u'username2'], u'port': 8090,
 u'zerodowntime': True, u'cert_source': u'internal-ca'}}) =&gt; {
     "msg": [
         "instance1",
         [
             "username1",
             "username2"
         ]
     ]}

 TASK [loop]
 ************************************************************************ ok: [nginx-test-01.domain.internal] =&gt; (item=[{u'roles':
 [u'product', u'nginx_instance'], u'URL':
 u'page-nginx.domain.internal', u'ip_restriction': [u'0.0.0.0/0'],
 u'port': 8090, u'downtime': True, u'cert_source':
 u'internal-ca'}, u'username1']) =&gt; {
     "msg": [
         "username1"
     ] } ok: [nginx-test-01.domain.internal] =&gt; (item=[{u'roles': [u'product', u'nginx_instance'], u'URL':
 u'page-nginx.symplectic.internal', u'ip_restriction': [u'0.0.0.0/0'],
 u'port': 8091, u'downtime': True, u'cert_source':
 u'internal-ca'}, u'username2']) =&gt; {
     "msg": [
         "username2"
     ] }
</code></pre>

<p>Any thought/suggestions would be appreciated.</p>

<p>UPDATE: I have learned that using <strong>loop control inner with and outer variable</strong> I can achieve this. But this requires me to use a separated .yml Is there any way to do this on the same .yml file?</p>

CC BY-SA 4.0
2019-07-16T22:29:12.097Z
Thanks, I have not run this particular, but it was a generic version of mine, I missed that, thanks...
maco1717
<ansible><data>
Traverse nested dictionary with keeping the keys in ansible
maco1717
# Traverse nested dictionary with keeping the keys in ansible

(Asked by: username_0 on 2019-07-13)

I'm not able to loop a list in a dict and keep the key of the original dict.
Bellow an example of my data
vars:
 nginx_users:
    'instance1':
       roles:
          - product
          - nginx_instance
       cert_source: internal-ca
       URL: page-nginx.domain.internal
       port: 8090
       downtime: true
       basic_auth:
          - username1
          - username2
       ip_restriction:
          - '0.0.0.0/0'
    'instance2':
       roles:
          - product
          - nginx_instance
       cert_source: internal-ca
       URL: page2-nginx.domain.internal
       port: 8091
       downtime: true
       basic_auth:
          - username1
          - username2
       ip_restriction:
          - '0.0.0.0/0'
    'instance3':
       roles:
          - product
          - nginx_instance

I need to loop it in a manner that It iterates like this
"msg": [
        "instance1",
        [
            "username1"
        ],
        "instance1",
        [
            "username2"
        ],
       "instance2",
        [
            "username1"
        ],
        "instance2",
        [
            "username2"
        ]
...
    ]

I am using

when: item.value.basic_auth is defined

In a loop which will filter out the items without the desired value/item and return only the "items" that I need to parse, like.
...
loop: "{{ nginx_users | dict2items }}"
when: item.value.basic_auth is defined
...

However from there I don't know how to loop those "items" to get the list of users on a way that it returns the single user per iteration and preserve the key.
I know a work around would be to have use another variable instead of the key so I could just select it. but that wouldn't work for me in this escenario.
I have tried using subelements and lookup but I don't seem to be able narrow down the exact combination also thought about using product too and try and traverse the data. But I wasn't able to use that either.
After reading this:
https://github.com/ansible/ansible/pull/6370
https://github.com/ansible/ansible/pull/4982
I'm starting to think I will have to use Jinja to be able to do this.
This is as close as I have been able to get to what I'm trying to achieve
- name: loop
  debug:
    msg:
    - "{{ item.key }}"
    - "{{ item.value.basic_auth }}"
  loop: "{{ nginx_users | dict2items }}"
  when: item.value.basic_auth is defined

- name: loop
  debug:
    msg:
    - "{{ item.1 }}"
  loop: "{{ lookup('subelements', nginx_users, 'basic_auth', {'skip_missing': True}) }}"

which results on this:
 TASK [loop]
 ************************************************************************ skipping: [nginx-test-01.domain.internal] => (item={'key':
 u'instance1', 'value': {u'roles': [u'product', u'nginx_instance']}})
 ok: [nginx-test-01.domain.internal] => (item={'key': u'username2',
 'value': {u'roles': [u'product', u'nginx_instance'], u'URL':
 u'page-nginx.symplectic.internal', u'ip_restriction': [u'0.0.0.0/0'],
 u'basic_auth': [u'username1', u'username2'], u'port': 8090,
 u'zerodowntime': True, u'cert_source': u'internal-ca'}}) => {
     "msg": [
         "instance1",
         [
             "username1",
             "username2"
         ]
     ]}

 TASK [loop]
 ************************************************************************ ok: [nginx-test-01.domain.internal] => (item=[{u'roles':
 [u'product', u'nginx_instance'], u'URL':
 u'page-nginx.domain.internal', u'ip_restriction': [u'0.0.0.0/0'],
 u'port': 8090, u'downtime': True, u'cert_source':
 u'internal-ca'}, u'username1']) => {
     "msg": [
         "username1"
     ] } ok: [nginx-test-01.domain.internal] => (item=[{u'roles': [u'product', u'nginx_instance'], u'URL':
 u'page-nginx.symplectic.internal', u'ip_restriction': [u'0.0.0.0/0'],
 u'port': 8091, u'downtime': True, u'cert_source':
 u'internal-ca'}, u'username2']) => {
     "msg": [
         "username2"
     ] }

Any thought/suggestions would be appreciated.
UPDATE: I have learned that using loop control inner with and outer variable I can achieve this. But this requires me to use a separated .yml Is there any way to do this on the same .yml file?

**Tags:** ansible, data

> **Comments:**
> **username_0**: Thanks, I have not run this particular, but it was a generic version of mine, I missed that, thanks...  

---

## 1 answers

### Answer by username_1 on 2019-07-17. Score: 3 | Accepted answer

Let's simplify the dictionary in the first task and loop the subelements in the second. The tasks below
    - set_fact:
        nginx_users_selected: "{{ nginx_users_selected|
                                  default({})|
                                  combine({item.key: item.value})
                                  }}"
      loop: "{{ nginx_users|
                dict2items|
                json_query('[*].{key: key, value: value.basic_auth}')
                }}"
      when: item.value
    - debug:
        msg: "{{ item.0.key }} {{ item.1 }}"
      loop: "{{ nginx_users_selected|
                dict2items|
                subelements('value')
                }}"

give
    "msg": "instance2 username1"
    "msg": "instance2 username2"
    "msg": "instance1 username1"
    "msg": "instance1 username2"

Then we can create the structure
    - set_fact:
        my_list: "{{ my_list|default([]) +
                     [ item.0.key, [ item.1 ]] }}"
      loop: "{{ nginx_users_selected|
                dict2items|
                subelements('value') }}"
    - debug:
        var: my_list

give
    "my_list": [
        "instance2", 
        [
            "username1"
        ], 
        "instance2", 
        [
            "username2"
        ], 
        "instance1", 
        [
            "username1"
        ], 
        "instance1", 
        [
            "username2"
        ]
    ]

> **Comments:**
> **username_0**: !Thanks! that worked beautifully, It required me installing "jmespath" but don't care about that. I found another solution using include_tasks and outer and inner loop. this is way better. I still need to understand it tho. So loads reading to do. I would have never found this out. Thanks  
> **username_0**: I was wondering is you could recommend any reading material for this, I have had some time not to racap this and looking into this I really really can't head my head around it xD - I have a new requirement similar to this, but I dont know how to use your example as a starting point  
> **username_1**: FWIW. Moving forward I kept examples in [GitHub](https://github.com/vbotka/ansible-examples). Start with [example 2](https://github.com/vbotka/ansible-examples/blob/master/examples/example-002/json_query.yml) then see files  in [example 20](https://github.com/vbotka/ansible-examples/blob/master/examples/example-020). There is a tutorial and some examples at [jmespath.org](http://jmespath.org/).  
> **username_0**: Thanks you very much!  

---

