Search code examples
ansiblejinja2

How to get value from nested array?


I've below JSON structure, and I'd like to get the interface name if type is "DHCP".

{
    "host": [
        {
            "interfaces": [
                {
                    "bootproto": "none", 
                    "name": "ens5f0", 
                    "nets": [
                        {
                            "ipaddr": "10.1.1.10", 
                            "type": "DHCP", 
                        },
                        {
                            "ipaddr": "10.1.1.10", 
                            "type": "STATIC", 
                        }
                    ]
                }, 
                {
                    "bootproto": "none", 
                    "name": "ens5f1", 
                    "nets": [
                        {
                            "ipaddr": "10.1.1.11", 
                            "type": "STATIC", 
                        }
                    ]
                }, 
                {
                    "bootproto": "none", 
                    "name": "ensf2", 
                    "nets": [
                        {
                            "ipaddr": "192.168.1.1", 
                            "type": "DHCP", 
                        }
                    ]
                }
            ]
        }
    ]
}

Here the expected output is

['ens5f0', 'ens5f2']

I tried below Ansible play to get the install name.

- name: Get DHCP interface name
  set_fact:
    dhcp_interfaces: "{{ main_host_network_interfaces[0].interfaces | map(attribute='nets') | flatten | selectattr('type', 'match', 'DHCP') | list }}"

but it returns the

{
    "ipaddr": "10.1.1.10", 
    "type": "DHCP", 
}

Solution

  • Use the filter json_query

      dhcp_interfaces: "{{ host|json_query(_query) }}"
      _query: '[].interfaces[?nets[?type == `DHCP`]].name|[]'
    

    gives what you want

      dhcp_interfaces:
        - ens5f0
        - ensf2
    

    Example of a complete playbook for testing

    - hosts: all
    
      vars:
    
        host:
          - interfaces:
            - bootproto: none
              name: ens5f0
              nets:
              - {ipaddr: 10.1.1.10, type: DHCP}
              - {ipaddr: 10.1.1.10, type: STATIC}
            - bootproto: none
              name: ens5f1
              nets:
              - {ipaddr: 10.1.1.11, type: STATIC}
            - bootproto: none
              name: ensf2
              nets:
              - {ipaddr: 192.168.1.1, type: DHCP}
    
        dhcp_interfaces: "{{ host|json_query(_query) }}"
        _query: '[].interfaces[?nets[?type == `DHCP`]].name|[]'
    
      tasks:
    
        - debug:
            var: dhcp_interfaces