Answers: <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>
  
Answers: CC BY-SA 4.0
Answers: 2019-07-18T07:40:56.167Z
Answers: !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
Answers: maco1717
Answers: CC BY-SA 4.0
Answers: 2019-11-05T11:39:35.107Z
Answers: 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
Answers: maco1717
Answers: CC BY-SA 4.0
Answers: 2019-11-05T11:49:07.523Z
Answers: 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/).
Answers: Vladimir Botka
Answers: CC BY-SA 4.0
Answers: 2019-11-05T12:15:50.443Z
Answers: Thanks you very much!
Answers: maco1717
Answers: CC BY-SA 4.0
Answers: 2019-07-17T06:43:55.617Z
Answers: 2021-04-19T10:30:32.607Z
Answers: 2021-04-19T10:30:32.607Z
Answers: Vladimir Botka
Body: <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>
  
Comments: CC BY-SA 4.0
Comments: 2019-07-16T22:29:12.097Z
Comments: Thanks, I have not run this particular, but it was a generic version of mine, I missed that, thanks...
Comments: maco1717
Tags: <ansible><data>
Title: Traverse nested dictionary with keeping the keys in ansible
UserDisplayName: maco1717
ThreadText: # 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
  
  ```yaml
      - 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
  
  ```yaml
      "msg": "instance2 username1"
      "msg": "instance2 username2"
      "msg": "instance1 username1"
      "msg": "instance1 username2"
  
  ```
  
  Then we can create the structure
  
  ```yaml
      - set_fact:
          my_list: "{{ my_list|default([]) +
                       [ item.0.key, [ item.1 ]] }}"
        loop: "{{ nginx_users_selected|
                  dict2items|
                  subelements('value') }}"
      - debug:
          var: my_list
  
  ```
  
  give
  
  ```yaml
      "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!  
  
  ---
  
  