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"
]
}
]
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']