listdictionaryansiblejson-query

Ansible - parse a list of nested dictionaries to create a new list


I have the following list of dictionaries

"tor_vlan_list": [
    {
        "switch_01": {
            "Vlan1": {
                "id": "1",
                "ip": "unassigned",
                "ok": "NO",
                "protocol": "down",
                "status": "up"
            },
            "Vlan10": {
                "id": "10",
                "ip": "10.10.10.2/24",
                "ok": "YES",
                "protocol": "up",
                "status": "up"
            },
            "Vlan20": {
                "id": "20",
                "ip": "10.10.20.2/24",
                "ok": "YES",
                "protocol": "up",
                "status": "up"
            },
            "Vlan30": {
                "id": "30",
                "ip": "10.10.30.2/24",
                "ok": "YES",
                "protocol": "up",
                "status": "up"
            }
        }
    },
    {
        "switch_02": {
            "Vlan1": {
                "id": "1",
                "ip": "unassigned",
                "ok": "NO",
                "protocol": "down",
                "status": "up"
            },
            "Vlan10": {
                "id": "10",
                "ip": "10.10.10.3/24",
                "ok": "YES",
                "protocol": "up",
                "status": "up"
            },
            "Vlan20": {
                "id": "20",
                "ip": "10.10.20.3/24",
                "ok": "YES",
                "protocol": "up",
                "status": "up"
            },
            "Vlan30": {
                "id": "30",
                "ip": "10.10.30.3/24",
                "ok": "YES",
                "protocol": "up",
                "status": "up"
            }
        }
    }
]

from this, i need to extract the list of vlan IDs for each switch and store these as follows

"new_list": [
    { 
     "switch_01": [1,10,20,30]
    },
    {
     "switch_02": [1,10,20,30]
    }
]

I would like to pass the list values as a var in the command *show vlan {{item}}"

I've tried getting the needed detail using combinations of selectattr, map, combine, json_query, etc to set a new ansible fact but, all have eluded me.


Solution

  • The below expressions

      new_list_keys: "{{ tor_vlan_list|json_query('[].keys(@)') }}"
      new_list_vals: "{{ tor_vlan_list|json_query('[].*.*.id') }}"
      new_list: |
        [{% for i in new_list_keys|zip(new_list_vals) %}
        {{ dict(i.0|zip(i.1|map('map', 'int'))) }},
        {% endfor %}]
    

    give what you want

      new_list:
        - switch_01: [1, 10, 20, 30]
        - switch_02: [1, 10, 20, 30]
    
      new_list_keys:
        - [switch_01]
        - [switch_02]
    
      new_list_vals:
        - - ['1', '10', '20', '30']
        - - ['1', '10', '20', '30']
    

    Example of a complete playbook for testing

    - hosts: localhost
    
      vars:
    
        tor_vlan_list:
        - switch_01:
            Vlan1: {id: '1', ip: unassigned, ok: 'NO', protocol: down, status: up}
            Vlan10: {id: '10', ip: 10.10.10.2/24, ok: 'YES', protocol: up, status: up}
            Vlan20: {id: '20', ip: 10.10.20.2/24, ok: 'YES', protocol: up, status: up}
            Vlan30: {id: '30', ip: 10.10.30.2/24, ok: 'YES', protocol: up, status: up}
        - switch_02:
            Vlan1: {id: '1', ip: unassigned, ok: 'NO', protocol: down, status: up}
            Vlan10: {id: '10', ip: 10.10.10.3/24, ok: 'YES', protocol: up, status: up}
            Vlan20: {id: '20', ip: 10.10.20.3/24, ok: 'YES', protocol: up, status: up}
            Vlan30: {id: '30', ip: 10.10.30.3/24, ok: 'YES', protocol: up, status: up}
    
        new_list_keys: "{{ tor_vlan_list|json_query('[].keys(@)') }}"
        new_list_vals: "{{ tor_vlan_list|json_query('[].*.*.id') }}"
        new_list: |
          [{% for i in new_list_keys|zip(new_list_vals) %}
          {{ dict(i.0|zip(i.1|map('map', 'int'))) }},
          {% endfor %}]
    
      tasks:
    
        - debug:
            var: new_list_keys|to_yaml
        - debug:
            var: new_list_vals|to_yaml
        - debug:
            var: new_list|type_debug
        - debug:
            var: new_list|to_yaml