2

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}"
β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83

1 Answers1

1

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.

β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83
  • Thank you for your help! I get this error: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'int object' has no attribute 'status_code' I use this instead of your vars: - name: GET HEALTH CHECK uri: url: http://{{ ansible_fqdn }}:8888/healthcheck method: GET return_content: yes status_code: 200 body_format: json validate_certs: no register: data - debug: msg: >- IP: {{ item }}, status_code: {{ data.json[item].status_code }} loop: "{{ data.json.keys() }}" ''' – confusedjoe Feb 25 '21 at 21:11
  • Means `data.json[item]` is not a dictionary like your provided it in your question. Debug it to see what it give and edit it in your question: `-debug: var=data.json` – β.εηοιτ.βε Feb 25 '21 at 21:14
  • I added my debug output as an answer. – confusedjoe Feb 25 '21 at 21:38
  • You should have [edited](https://stackoverflow.com/posts/66375540/edit) your question rather – β.εηοιτ.βε Feb 25 '21 at 21:40
  • This said, I edited the answer to cover your issue. – β.εηοιτ.βε Feb 25 '21 at 21:48
  • thanks works like a charm! You're a life saver! – confusedjoe Feb 25 '21 at 21:51
  • @confusedjoe I also have a less cumbersome idea included now, if you're ever interested. – β.εηοιτ.βε Feb 25 '21 at 21:57
  • yes I'm interested, can you please share your idea? – confusedjoe Feb 25 '21 at 22:47