Search code examples
ansible

Ansible create dict and double loop a list which has a list


I have this variable

result:
    results:
    - ansible_loop_var: item
      item: /bigdata/gidn/data/input/datalake/test_workspace_3
      stdout: |2-
 
        snapshot_input
      stdout_lines:
      - ''
      - snapshot_input
    - ansible_loop_var: item
      item: /bigdata/gidn/data/output/datalake/test_workspace_3
      stdout: |2-
 
        snapshot_output
      stdout_lines:
      - ''
      - snapshot_output
    - ansible_loop_var: item
      item: /bigdata/gidn/projets/datalake/test_workspace_3
      stdout: |2-
 
        snapshot_projet_1
        snapshot_projet_2
      stdout_lines:
      - ''
      - snapshot_projet_1
      - snapshot_projet_2

I wanted to loop over result.results and of each item, I loop again over stdout_lines and create a dict like this :

{'path': /bigdata/gidn/data/input/datalake/test_workspace_3, 'id':snapshot_input},{'path': /bigdata/gidn/data/output/datalake/test_workspace_3, 'id':snapshot_output},{'path': /bigdata/gidn/projets/datalake/test_workspace_3, 'id':snapshot_projet_1},{'path': /bigdata/gidn/projets/datalake/test_workspace_3, 'id':snapshot_projet_2}

Solution

  • Ansible doesn't support nested loops directly, but we can fake it using things like the subelements filter, like this:

    - hosts: localhost
      gather_facts: false
      vars:
        result:
            results:
            - ansible_loop_var: item
              item: /bigdata/gidn/data/input/datalake/test_workspace_3
              stdout: |2-
        
                snapshot_input
              stdout_lines:
              - ''
              - snapshot_input
            - ansible_loop_var: item
              item: /bigdata/gidn/data/output/datalake/test_workspace_3
              stdout: |2-
        
                snapshot_output
              stdout_lines:
              - ''
              - snapshot_output
            - ansible_loop_var: item
              item: /bigdata/gidn/projects/datalake/test_workspace_3
              stdout: |2-
        
                snapshot_project_1
                snapshot_project_2
              stdout_lines:
              - ''
              - snapshot_project_1
              - snapshot_project_2
    
      tasks:
        - loop: "{{ result.results|subelements('stdout_lines')}}"
          when: item.1
          vars:
            myvar: []
          set_fact:
            myvar: "{{ myvar + [{'path': item.0.item, 'id': item.1}]}}"
    
        - debug:
            msg: "{{ myvar }}"
    

    This will produce the following output:

    TASK [debug] *******************************************************************
    ok: [localhost] => {
        "msg": [
            {
                "id": "snapshot_input",
                "path": "/bigdata/gidn/data/input/datalake/test_workspace_3"
            },
            {
                "id": "snapshot_output",
                "path": "/bigdata/gidn/data/output/datalake/test_workspace_3"
            },
            {
                "id": "snapshot_project_1",
                "path": "/bigdata/gidn/projects/datalake/test_workspace_3"
            },
            {
                "id": "snapshot_project_2",
                "path": "/bigdata/gidn/projects/datalake/test_workspace_3"
            }
        ]
    }
    

    (NB: In your question you say, "I want to create a dict like this...", but the example you show is a list of dictionaries, which is what I have produced here.)