Reputation: 182
I have a task to extract the ID value of VM's through the uri module, using Ansible 2.9 .
I save the result into a variable called uri_comp
The structure of the output of uri_comp
that i need to extract a value from is as such:
I had to manually recreate this, so indentation might not be 100% correct.
"results": [
{
"json": {
"computers": [
{
"ID": 1167,
"agentFingerPrint": "editedvalue",
"agentGUID": "editedvalue",
"agentVersion": "editedvalue",
"biosUUID": "editedvalue",
"description": "",
"displayName": "",
"groupID": 0,
"hostGUID": "editedvalue",
"hostName": "editedvalue",
"lastAgentCommunication": editedvalue,
"lastIPUsed": "editedvalue",
"platform": "",
"policyID": editedvalue,
"relayListID": 0
}
]
},
"computers": [
{
"ID": 27,
"agentFingerPrint": "editedvalue",
"agentGUID": "editedvalue",
"agentVersion": "editedvalue",
"biosUUID": "editedvalue",
"description": "",
"displayName": "",
"groupID": 0,
"hostGUID": "editedvalue",
"hostName": "editedvalue",
"lastAgentCommunication": editedvalue,
"lastIPUsed": "editedvalue",
"platform": "",
"policyID": editedvalue,
"relayListID": 0
}
]
},
I need a variable set as a set fact which contains as in underneath output just the comp_id number. So in this case:
comp_id:
- 17
- 1167
I extract the computers ID value with a lot of extra looping clutter, in this way.
- name: "Print ID of computers"
debug:
msg: "{{ item|json_query('json.computers')|map(attribute='ID') }}"
loop: "{{ uri_comp|json_query('results') }}"
output:
TASK [Print ID of computers] **********************************************************************************************************
ok: [localhost] => (item={'content': '{"computers":[{CLUTTER}) => { CLUTTER CLUTTER CLUTTERCLUTTERCLUTTERCLUTTERCLUTTERCLUTTERCLUTTERCLUTTERCLUTTERCLUTTERCLUTTERCLUTTER
"msg": [
17
]
}
ok: [localhost] => (item={'content': '{"computers":[{CLUTTER}) => { CLUTTER CLUTTER CLUTTERCLUTTERCLUTTERCLUTTERCLUTTERCLUTTERCLUTTERCLUTTERCLUTTERCLUTTERCLUTTERCLUTTER
"msg": [
1167
]
}
I manage to extract the values with the debug but once i try and save this into a variable with set_fact, it gets overwritten by the loop and i loose the first ID value.
- set_fact:
comp_ID: "{{ item|map(attribute='ID') }}"
loop: "{{ uri_comp|json_query('results[*].json.computers') }}"
Type of data for computers
is a list. Which i checked with type_debug. If i'm not wrong i believe that inside the list there's a dictionary. Probably that's where my issue is.
When googling " how to extract a value from a list of dictionary" i find interesting things but nothing leading towards a solution.
So i've been told to do this without a loop which does not work, i manage to map the attribute until computers
but then whatever i tried does not work.
- set_fact:
comp_ID: "{{ uri_comp.results|map(attribute='json')|map(attribute='computers')}}"
output:
ok: [localhost] => {
"msg": [
[
{
"ID": 17,
"agentFingerPrint": "0editedvalue",
"agentGUID": "editedvalue",
"agentVersion": "editedvalue",
"biosUUID": "editedvalue",
"description": "",
"displayName": "",
"groupID": 0,
"hostGUID": "editedvalue",
"hostName": "editedvalue",
"lastAgentCommunication": editedvalue,
"lastIPUsed": "editedvalue",
"platform": "",
"policyID": 10,
"relayListID": 0
}
],
[
{
"ID": 1167,
"agentFingerPrint": "editedvalue",
"agentGUID": "editedvalue",
"agentVersion": "editedvalue",
"biosUUID": "editedvalue",
"description": "",
"displayName": "",
"groupID": 0,
"hostGUID": "editedvalue",
"hostName": "editedvalue",
"lastAgentCommunication": editedvalue,
"lastIPUsed": "editedvalue",
"platform": "",
"policyID": 10,
"relayListID": 0
}
]
]
}
I tried:
- set_fact:
comp_ID: "{{ uri_comp.results|map(attribute='json')|map(attribute='computers')|map(attribute='ID') }}"
output:
TASK [debug set_fact] *****************************************************************************************************************
ok: [localhost] => {
"msg": "[AnsibleUndefined, AnsibleUndefined]"
}
I tried:
- set_fact:
comp_ID: "{{ uri_comp.results|map(attribute='json')|map(attribute='computers')|json_query('ID')}}"
output:
ok: [localhost] => {
"msg": ""
}
I tried dot notation,
- set_fact:
comp_ID: "{{ uri_comp.results.json.computers }}"
I tried also to use items2dict filter wihtout any success. I also tried dict2items as in this post Extract values from a list of dictionaries in Ansible I tried selectattr('ID', defined) I've seen lots of similar questions on this site and on google, though none seemed to fit my issue. https://sleeplessbeastie.eu/2022/09/26/how-to-lookup-specific-element-in-ansible-dictionary-or-list-of-these/ Which leads me to think that i have something fundamentally wrong here. Is this really possible without a loop? I would be most grateful to read which tool i should use or which data structure this is or any leads really.
Upvotes: 0
Views: 2057
Reputation: 44799
I had to manually recreate this, so indentation might not be 100% correct.
It is your responsibility to create a correct minimal reproducible example. In this case not only the indentation (crucial for yaml but not so important for pure json) but the entire structure is wrong. I guessed the below structure in my example from your code samples and current results but I cannot guaranty it sticks exactly to yours.
Please systematically check, lint and fix your data examples and make sure they are correct.
The following playbook
---
- hosts: localhost
gather_facts: false
vars:
uri_comp: {
"results": [
{
"json": {
"computers": [
{
"ID": 1167,
"agentFingerPrint": "editedvalue",
"agentGUID": "editedvalue",
"agentVersion": "editedvalue",
"biosUUID": "editedvalue",
"description": "",
"displayName": "",
"groupID": 0,
"hostGUID": "editedvalue",
"hostName": "editedvalue",
"lastAgentCommunication": editedvalue,
"lastIPUsed": "editedvalue",
"platform": "",
"policyID": editedvalue,
"relayListID": 0
}
]
}
},
{
"json": {
"computers": [
{
"ID": 27,
"agentFingerPrint": "editedvalue",
"agentGUID": "editedvalue",
"agentVersion": "editedvalue",
"biosUUID": "editedvalue",
"description": "",
"displayName": "",
"groupID": 0,
"hostGUID": "editedvalue",
"hostName": "editedvalue",
"lastAgentCommunication": editedvalue,
"lastIPUsed": "editedvalue",
"platform": "",
"policyID": editedvalue,
"relayListID": 0
}
]
}
}
]
}
comp_ID: "{{ uri_comp.results | map(attribute='json.computers') | flatten | map(attribute='ID') }}"
tasks:
- debug:
var: comp_ID
gives:
PLAY [localhost] **************************************************************************************************************************************************************************************************
TASK [debug] ******************************************************************************************************************************************************************************************************
ok: [localhost] => {
"comp_ID": [
1167,
27
]
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Upvotes: 3