Home > Net >  Loop over multiple JSON arrays to filter the relevant JSON object based on a key value in Ansible
Loop over multiple JSON arrays to filter the relevant JSON object based on a key value in Ansible

Time:12-29

I am trying to loop over 2 different JSON array and filter only if the 2 key values are same.

I am comparing cidr from po-orig.json/po file and subnet from pocooling json. If the key values are same in both file, then print the pertaining details of pocooling json file as a list.

- name: Combine GP MGMT
      vars:
       pocidr: >-
         {{
          po 
          | json_query('ansible_facts.policyobject[].json[]')
         }}
       poname: >-
         {{
         pocidr
          | selectattr('cidr', '==', item.subnet)
          | map(attribute='name')
          | list
         }}
      set_fact:
       result: >-
         {{ 
            result | default([])
             
            [poname]
         }}
      with_items: "{{ pocooling }}"

Updated code

 - name: Compare the Current & Actual GP policy
      set_fact: 
           pocidr: "{{ po | json_query(\"ansible_facts.policyobject[].json[]\") }}"

    - name: Combine GP MGMT
      vars:
       poname: 
         "{{
         pocidr
          | selectattr('cidr', '==', item.subnet)
          | map(attribute='name')
          | first
         }}"
      set_fact:
       result: 
         "{{ 
            result | default([])
             
            [poname]
         }}"
      with_items: "{{ pocooling }}"

pocooling.json

[
    {
        "applianceIp": "10.10.10.10",
        "dhcpBootOptionsEnabled": false,
        "dhcpHandling": "Run a DHCP server",
        "dhcpLeaseTime": "1 day",
        "dhcpOptions": [],
        "dnsNameservers": "upstream_dns",
        "fixedIpAssignments": {},
        "id": 2222,
        "name": "Cooling",
        "networkId": "78984654989",
        "reservedIpRanges": [],
        "subnet": "10.10.10.0/28"
    },
    {
        "applianceIp": "10.10.10.10",
        "dhcpBootOptionsEnabled": false,
        "dhcpHandling": "Run a DHCP server",
        "dhcpLeaseTime": "1 day",
        "dhcpOptions": [],
        "dnsNameservers": "upstream_dns",
        "fixedIpAssignments": {},
        "id": 2222,
        "name": "Cooling",
        "networkId": "123456789",
        "reservedIpRanges": [],
        "subnet": "10.11.11.0/28"
    }
]

po-orig.json(po)

{
   "ansible_facts":{
      "policyobject":[
         {
            "invocation":{
               "module_args":{
                  "status_code":[
                     200,
                     201,
                     202
                  ],
                  "validate_certs":false
               }
            },
            "item":{
               "id":"123456",
               "name":"DC"
            },
            "json":[
               {
                  "category":"network",
                  "cidr":"10.1.1.1/28",
                  "createdAt":"2021-11-23T19:48:21Z",
                  "groupIds":[
                     
                  ],
                  "id":"545649843651365",
                  "name":"JM-Privat",
                  "networkIds":[
                     "545649843651365"
                  ],
                  "type":"cidr",
                  "updatedAt":"2021-11-23T19:48:21Z"
               },
               {
                  "category":"network",
                  "cidr":"10.10.10.0/28",
                  "createdAt":"2021-12-07T13:54:05Z",
                  "groupIds":[
                     "897987654689854"
                  ],
                  "id":"564678984565465",
                  "name":"PO-L-DE-MCC-COOLING_DMZ_LAB",
                  "networkIds":[
                     
                  ],
                  "type":"cidr",
                  "updatedAt":"2021-12-07T13:54:05Z"
               }
            ]
         }
      ]
   }
}

Error:

fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: {{ pocidr\n | selectattr('cidr', '==', item.subnet)\n | map(attribute='name')\n | list\n}}: 'dict object' has no attribute 'cidr

Expected result

[
    {
        "applianceIp": "10.10.10.10",
        "dhcpBootOptionsEnabled": false,
        "dhcpHandling": "Run a DHCP server",
        "dhcpLeaseTime": "1 day",
        "dhcpOptions": [],
        "dnsNameservers": "upstream_dns",
        "fixedIpAssignments": {},
        "id": 2222,
        "name": "Cooling",
        "networkId": "78984654989",
        "reservedIpRanges": [],
        "subnet": "10.10.10.0/28"
    }
]

CodePudding user response:

Given the list

  pocooling:
  - networkId: '78984654989'
    subnet: 10.10.10.0/28
  - networkId: '123456789'
    subnet: 10.11.11.0/28

Select list of cidr

  _cidr: "{{ ansible_facts.policyobject|json_query('[].json[].cidr') }}"

gives

  _cidr:
  - 10.1.1.1/28
  - 10.10.10.0/28

Then select the items that fit the condition

    - debug:
        msg: "{{ pocooling|selectattr('subnet', 'in' , _cidr) }}"
      vars:
        _cidr: "{{ ansible_facts.policyobject|json_query('[].json[].cidr') }}"

gives

  msg:
  - networkId: '78984654989'
    subnet: 10.10.10.0/28

Your code, fixed and simplified

    - include_vars:
        file: po-orig.json
        name: po
    - name: Combine GP MGMT
      vars:
        poname: "{{ po|json_query('ansible_facts.policyobject[].json[]')|
                    selectattr('cidr', '==', item.subnet)|
                    map(attribute='name')|
                    list }}"
      set_fact:
        result: "{{ result|default([])   [poname] }}"
      loop: "{{ pocooling }}"

gives

  result:
  - - PO-L-DE-MCC-COOLING_DMZ_LAB
  - []
  • Related