ansible json_query is omitting desired key/values - json

For example, I have the following structure that ansible is pulling via an API url:
"records": [
{
"data0": "string",
"data1": {
"internal0": "string",
"internal1": {
"subthing0": "string",
"subthing1": {
"otherstuff": {
"evenmore stuff": "string"
}
}
}
}
}
]
To filter the json and get the key/value I need I am using the following:
"{{ set_var.content | from_json | json_query('records[*].data1.internal1.subthing0') }}"
The debugger returns empty json, however if I use:
{{ set_var.content | from_json | json_query('records[*].data1.internal1') }}
I can see all of the key/values of subthing1 but subthing0 no longer shows up at all and the string of subthing0 is what is a needed variable to continue the next task. Why is subthing0 not returning at all unless I only query records?

Related

ansible dictionary key value pairs

I am new to Ansible/json and I am trying to parse the following json:
{
"resultCPU": {
"changed": false,
"msg": "All items completed",
"results": [
{
"ansible_facts": {
"CPU": "6",
"VM": "tigger"
},
{
"ansible_facts": {
"CPU": "4",
"VM": "pooh"
},
I need to set the value of the items in this json so that pooh=4 and tigger=6. I will need to refer to both these values later (advice on how to do that would help as well).
I have tried using cpuvm "{{ resultCPU.results |selectattr('VM') |map(attribute='CPU')|list }}" but it complains "'dict object' has no attribute VM".
What am I doing wrong?
Your selectattr ignored the ansible_facts between results: [] and the VM you tried to map. Thankfully, the attribute kwarg understands dot notation
- debug:
msg: >-
VMs are {{ resultCPU.results | map(attribute="ansible_facts.VM") | list }}
CPUs are {{ resultCPU.results | map(attribute="ansible_facts.CPU") | list }}
The together filter may interest you, too
and as for "I will need to refer to both these values later (advice on how to do that would help as well)." that is usually what set_fact: is used for, but without more specifics about what you have tried and what shape you are expecting, it's hard to give a more specific answer

Ansible fetching Stdout key value

I need some help regarding, how to fetch specific value using Ansible
My task:
- name: 'check Describe Information'
debug:
var: describeresult.stdout
I need IP address value from below stdout, what should I put in debug var to fetch IP address
TASK [check Describe Information] **********************************************
task path: /home/tom/Getipaddress.yml:28
ok: [127.0.0.1] => {
"describeresult.stdout": {
"failures": [],
"tasks": [
{
"attachments": [
{
"details": [
{
"name": "subnetId",
"value": "subnet-xxxxxxxxxxxxxx"
},
{
"name": "networkInterfaceId",
"value": "eni-xxxxxxxxxxxxxxxx"
},
{
"name": "macAddress",
"value": "xxxxxxxxxxxxxxxxxx"
},
{
"name": "privateIPv4Address",
"value": "xxxxxxxxxxxxxxxxxx"
}
Plus I am using AWS ECS command to generate the above output with --output as a JSON not sure how to use --query to filter or fetch above IP address only
Use json_query. For example
- set_fact:
my_privateIPv4Address: "{{ describeresult.stdout.tasks|
json_query(query) }}"
vars:
query: "[].attachments[].details[?name=='privateIPv4Address'].value"
json_query returns by default a list.
You can use something like this for getting private IP address only
"{{describeresult.stdout['tasks'][0]['attachments'][0]['details'][3]['value']}}"
The above might have slight syntax issues but should work.
I have done something like this earlier for ec2_group_info module in ansible
You can start off by generating output in pieces describeresult.stdout['tasks'] should return JSON for the task attribute.
[0] indicates the first element when there is a box bracket for a JSON implying more than one element/list.
Let me know how it goes.

Parsing json using Ansible

I have a json as below :
"instances": {
"biometricsManagerInstance": {
"appId": "biometrics-manager",
"spawnType": "uniqueSiteWide"
},
"videoSensorInstance": {
"appId": "video-sensor",
"spawnType": "reuse"
},
"faceDetectionInstance":{
"appId": "face-detection",
"spawnType": "reuse"
},
"faceMatchingInstance":{
"appId": "face-matching",
"spawnType": "new"
},
"faceAnnotatorInstance":{
"appId": "face-annotator",
"spawnType": "new"
}
}
I have a variable where the json is stored. Lets say : my_json_contents
I want to create a dictionary from this data which has values like :
{"biometrics-manager":"biometricsManagerInstance","video-sensor":"videoSensorInstance","face-detection":"faceDetectionInstance",..}
I want to achieve it using ansible. Help is appreciated.TIA.
Here you are:
- set_fact:
instances_modified: "{{ instances_modified | default({}) | combine({item.1.appId: item.0}) }}"
loop: "{{ instances | dictsort }}"

How to sort with JMESPath in ansible playbook?

I have an array returned by curl from consul during playing ansible playbook:
[
{
"Node": {
"Node": "test-eu-west-2-staging-0"
},
"Node": {
"Node": "test-nyc1-staging-0"
},
"Node": {
"Node": "test-sfo1-staging-0"
}
}
]
I want to have it sorted by "Node": {"Node" : "hostname"} in ansible playbook
- name: Set TEST vars, servers info and number
set_fact:
TEST_SERVERS="{{ test.json | json_query('SOME SORTING QUERY') }}"
TEST_SRV_NUM="{{ test.json | length }}"
I have read JMESPath and ansible docs for whole day but still don't know how to implement it (btw it is easy in jq sort_by(.Node.Node) but this trick is not applicable to ansible)
As #techraf noted, your sample JSON is malformed. I can make a guess that you have a list of objects with Node.Node inside, in this case you can use sort Jinja2 filter:
---
- hosts: localhost
gather_facts: no
vars:
myvar: [
{ "Node": { "Node": "test-c" } },
{ "Node": { "Node": "test-b" } },
{ "Node": { "Node": "test-a" } }
]
tasks:
- debug:
msg: "{{ myvar | sort(attribute='Node.Node') }}"

Ansible 2.0 parsing Json and store in another variable

My Task is
- name: task name
shell: some command --format json
register: result
The output will be in below json format
[
{
"mac_address": "x.x.x.x.x.x",
"fixed_ips": "{\"subnet_id\": \"s-s-s-s\",\"ip_address\": \"172.*.*.*\"}",
"id": "1",
"name": ""
},
{
"mac_address": "x.x.x.x",
"fixed_ips": "{\"subnet_id\": \"s-s-s-s\", \"ip_address\": \"192.*.*.*\"}",
"id": "2",
"name": ""
}
]
What i want to do is,get only the ip address that starts with 192 and store it into a variable so that i can use it in another task.
If it is a list of dicts, use selectattr:
"{{ (result.stdout | from_json | selectattr('ip_address','match','^192') | list | fist).ip_address }}"
I assume that you need only one element, so I use first to get single element from the list.
Updated expression due to modifications of input data:
- set_fact:
ip_address: "{{ ( result.stdout |
from_json |
map(attribute='fixed_ips') |
map('from_json') |
selectattr('ip_address','match','^192') |
list |
first
).ip_address }}"
fixed_ips is a string, so you need to apply from_json with map to convert every item to be able to apply selectattr filter.