restansibleconditional-statementsjinja2nested-lists

Ansible: save item from nested list based on match from a separate list


I'm new to ansible so i'll try to explain this as best as I can...

I have two lists created from separate json_query results. One of them contains nested lists with two related items each (vm and cluster). The other is just a list of vm's that needs to be compared against. If the vm's match, I need to use the related cluster name in an API call.

Here are sample lists:

      [
            [
                "vm3",
                "cluster1"
            ],
            [
                "vm5",
                "cluster2"
            ],
            [
                "vm9",
                "cluster3"
            ]
        ],
        [
            [
                "vm5"
            ],
            [
                "vm1"
            ],
            [
                "vm3"
            ]
        ]

From the above example, vm5 and vm3 are matches so I would save cluster1 and cluster2 in a list to be used in an API call using a loop. Also, we have many clusters with varying numbers of vm's on each, so actual lists can (and will) vary widely.

I have tried using ansible.builtin.set_fact with a loop but the variable only stores the last iteration. It seems that jinja2 templates might work with nested loops, but I don't know how to store the variable for future use in later API calls.


Solution

  • Given the data

    data:
      - - [vm3, cluster1]
        - [vm5, cluster2]
        - [vm9, cluster3]
      - - [vm5]
        - [vm1]
        - [vm3]
    

    Create the dictionary

    vc: "{{ dict(data.0) }}"
    

    gives

    vc:
      vm3: cluster1
      vm5: cluster2
      vm9: cluster3
    

    and the list of vm(s) in the dictionary

    vm: "{{ data.1 | flatten | select('in', vc) }}"
    

    gives

    vm: [vm5, vm3]
    

    Extract the result

    result: "{{ vm | map('extract', vc) }}"
    

    gives

    result: [cluster2, cluster1]
    

    Example of a complete playbook for testing

    - hosts: localhost
    
      vars:
    
        data:
          - - [vm3, cluster1]
            - [vm5, cluster2]
            - [vm9, cluster3]
          - - [vm5]
            - [vm1]
            - [vm3]
        vc: "{{ dict(data.0) }}"
        vm: "{{ data.1 | flatten | select('in', vc) }}"
        result: "{{ vm | map('extract', vc) }}"
    
      tasks:
    
        - debug:
            var: vc | to_nice_yaml
        - debug:
            var: vm | to_yaml
        - debug:
            var: result | to_yaml