I have this json block as an example:
"msg": {
"10.10.28.10": {
"core": 23,
"cpuCoreUsage": 0.0,
"cputhreshold": 80,
"status": "healthy",
"status_code": 0,
"status_reason": "Checks passed",
"timestamp": 1614281443,
"total": 0
},
"10.10.28.5": {
"core": 18,
"cpuCoreUsage": 2.0,
"cputhreshold": 80,
"status": "healthy",
"status_code": 0,
"status_reason": "Checks passed",
"timestamp": 1614281443,
"total": 0
},
"capacity": 1080
}
I'm trying to figure out how I can get this output with property name and status to look like something like this.
DESIRED OUTPUT:
IP: 10.10.28.5, status: healthy, status_code: 0
IP: 10.10.28.10, status: healthy, status_code: 0
I can print everything except the IP part with this:
- name: STATUS QUERY
debug:
msg: "code: {{ item }}"
loop: "{{ data.json | json_query(status_code_query) | list }}"
vars:
status_code_query: "*.{statuscode: status_code, status: status}"
I wouldn't use JMESPath for this, the reason is, although it is pretty good at querying JSON, it is not really good at displaying JSON keys.
The keys()
function is the closest you can find there, but it will yield you an array and since you cannot come back to a parent node you cannot do something like:
*.{IP: keys($)[0], statuscode: status_code, status: status}
Although this is a pretty frequently requested feature: https://github.com/jmespath/jmespath.js/issues/22
Now to solve your use case, you can use the keys()
function, but the one of Python.
You also have a issue in the fact that all your values of data.json
are not dictionaries: in "capacity": 1080
, the value is a simple int
.
You can go work around this odd data structure using a when
test and verify if you value is indeed a mapping
(or in other words a dictionary).
Given the playbook:
- hosts: all
gather_facts: yes
tasks:
- debug:
msg: >-
IP: {{ item }},
status: {{ data.json[item].status }},
status_code: {{ data.json[item].status_code }}
loop: "{{ data.json.keys() }}"
when: data.json[item] is mapping
vars:
data:
json:
10.10.28.10:
core: 23
cpuCoreUsage: 0
cputhreshold: 80
status: healthy
status_code: 0
status_reason: Checks passed
timestamp: 1614281443
total: 0
10.10.28.5:
core: 18
cpuCoreUsage: 2
cputhreshold: 80
status: healthy-
status_code: 0-
status_reason: Checks passed
timestamp: 1614281443
total: 0
capacity: 1080
This yields the recap:
PLAY [all] **********************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************
ok: [localhost]
TASK [debug] ********************************************************************************************************
ok: [localhost] => (item=10.10.28.10) => {
"msg": "IP: 10.10.28.10, status: healthy, status_code: 0"
}
ok: [localhost] => (item=10.10.28.5) => {
"msg": "IP: 10.10.28.5, status: healthy-, status_code: 0-"
}
skipping: [localhost] => (item=capacity)
PLAY RECAP **********************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
This said, it is also a perfect use case for the dict2items
filter:
- hosts: all
gather_facts: yes
tasks:
- debug:
msg: >-
IP: {{ item.key }},
status: {{ item.value.status }},
status_code: {{ item.value.status_code }}
loop: "{{ data.json | dict2items }}"
when: item.value is mapping
vars:
data:
json:
10.10.28.10:
core: 23
cpuCoreUsage: 0
cputhreshold: 80
status: healthy
status_code: 0
status_reason: Checks passed
timestamp: 1614281443
total: 0
10.10.28.5:
core: 18
cpuCoreUsage: 2
cputhreshold: 80
status: healthy-
status_code: 0-
status_reason: Checks passed
timestamp: 1614281443
total: 0
capacity: 1080
Would yield the same recap.