how to get json_query display property name in ansible playbook

Viewed 582

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}"
1 Answers

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.

Related