1

I am trying to replace the key values in a dict inside a list(here only for the values inside Objectids) with the matching values from another list. Somehow i am only able to replace the 1st value but not iterating the whole list. Here the same key in the input.json will have multiple matching values from the finallist.json and all those values needs to be matched and added to the get the final expected output.

Input.json

[
    {
        "name": "DNS_One",
        "objectIds": [
            "DNS_One",
            "DNS_One-HO",
            "NTP"
        ]
    },
    {
        "name": "DNS_Two",
        "objectIds": [
            "NTP"
        ]
    }
]

finallist.json

[
    {
        "id": "123456",
        "net_name": "DNS_One"
    },
    {
        "id": "789101112",
        "net_name": "DNS_One"
    },
    {
        "id": "131415161718",
        "net_name": "DNS_One-HO"
    },
    {
        "id": "23897845",
        "net_name": "NTP"
    },
    {
        "id": "9879879546",
        "net_name": "NTP"
    }
]

Playbook

- name: Id mapping
      vars: 
       objectid: >-
        {{ 
          finallist
          | selectattr('net_name', 'in', item.1)
          | map(attribute = 'id')
          | first
          | default([])
          }}
      set_fact:
        obj: >-
         {{
            obj | default([]) + 
            [item.0 | combine({'objectIds': [objectid]})]
         }}
      with_subelements:
           - "{{ input }}"
           - objectIds
      ignore_errors: yes

Expected Output

[
    {
        "name": "DNS_One",
        "objectIds": [
            "123456","789101112"
            "131415161718",
            "23897845","9879879546"
        ]
    },
    {
        "name": "DNS_Two",
        "objectIds": [
            "23897845","9879879546"
        ]
    }
]
Vinny
  • 302
  • 2
  • 11
  • There is a missing comma in the lists of the expected result. It's not clear what format of the lists you want. The answer gives you both nested and flatted lists. – Vladimir Botka Mar 08 '22 at 08:07
  • @Vladimir Botka, Sorry, thats my bad. Expected is with a comma. – Vinny Mar 08 '22 at 09:48

1 Answers1

1

Read the data and create the variables finallist and input

    - set_fact:
        finallist: "{{ lookup('file', 'finallist.json')|from_yaml }}"
    - set_fact:
        input: "{{ lookup('file', 'input.json')|from_yaml }}"

gives

finallist:
  - id: '123456'
    net_name: DNS_One
  - id: '789101112'
    net_name: DNS_One
  - id: '131415161718'
    net_name: DNS_One-HO
  - id: '23897845'
    net_name: NTP
  - id: '9879879546'
    net_name: NTP
input:
  - name: DNS_One
    objectIds:
    - DNS_One
    - DNS_One-HO
    - NTP
  - name: DNS_Two
    objectIds:
    - NTP

In finallist, group the items by net_name and convert the list to a dictionary

    - set_fact:
        finaldict: "{{ finaldict|d({})|
                       combine({item.0: item.1|map(attribute='id')}) }}"
      loop: "{{ finallist|groupby('net_name') }}"

gives

  finaldict:
    DNS_One:
    - '123456'
    - '789101112'
    DNS_One-HO:
    - '131415161718'
    NTP:
    - '23897845'
    - '9879879546'

Iterate input and substitute the IDs

    - set_fact:
        new: "{{ new|d([]) + [item|combine({'objectIds': _ids})] }}"
      loop: "{{ input }}"
      vars:
        _ids: "{{ item.objectIds|map('extract', finaldict)|list }}"

gives the expected result

  new:
    - name: DNS_One
      objectIds:
      - ['123456', '789101112']
      - ['131415161718']
      - ['23897845', '9879879546']
    - name: DNS_Two
      objectIds:
      - ['23897845', '9879879546']

You can flatten the lists if you want to

       _ids: "{{ item.objectIds|map('extract', finaldict)|flatten }}"

gives

  new:
    - name: DNS_One
      objectIds: ['123456', '789101112', '131415161718', '23897845', '9879879546']
    - name: DNS_Two
      objectIds: ['23897845', '9879879546']
Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63