Home > Blockchain >  Check for objects in JSON other than the one mentioned in a condition
Check for objects in JSON other than the one mentioned in a condition

Time:06-30

I need to check if there are exit codes other than 0 in the JSON file below.

{
    "domains": {
        "app1": {
            "status": "Running"
        },
        "app2": {
            "status": "Terminated",
            "exit code": 2
        },
        "app3": {
            "status": "Running"
        },
        "app4": {
            "status": "Running"
        },
        "app5": {
            "status": "Terminated",
            "exit code": 0
        }
    }
}

Upon finding exit code other than 0, I want the Ansible task to fail. I tried the following code:

- name: Execute command to obtain json list.
  command: cat test.json
  register: result

- name: save the Json data to a Variable as a Fact
  set_fact:
     jsondata: "{{ result.stdout | from_json }}"

- name: Find string
  when: jsondata.stdout is search('Terminated')
  debug:
     msg: "{{ jsondata.stdout }}"
  failed_when: "{{ jsondata.stdout | jsonquery(domains.*[exit code] != 0) }}"

But, this does not seem to work.

CodePudding user response:

You do have multiple issues in your failing condition:

  1. when and its *_when derivates should never be templated — so you should get rid of the expressions delimiters {{ ... }}
  2. you are using a property stdout on your jsondata fact, that does not have one
  3. the filter name is json_query, not jsonquery
  4. you have to quote your JMESPath query passed to the filter: json_query('my_query_here_quoted')
  5. because you are doing a projection, using .*, you have to reset it in order to make a subsequent filter projection: domains.* | [?my_condition]
  6. because your array key contains a space you have to double quote it: [?"exit code"]
  7. because your condition is an integer you have to put it inside backticks. Also, your condition have to go inside the brackets, and start with a question mark: [?"exit code" == `0`]
  8. to get rid of the elements that do not have an exit code at all, a simpler solution would be to do a greater than: [?"exit code" > `0`]
  9. There is a fail task, it is maybe better suited in your case than a debug with a failed_when

With all this, you should end with the task:

- name: Fail when we have an abnormal exit status
  fail:
    msg: |-
      Some process have an abnormal exit:
      {{ _abnormal_exit }}  
  when: _abnormal_exit | length > 0
  vars:
    _abnormal_exit: >-
      {{
        jsondata | json_query('domains.* | [?"exit code" > `0`]')
      }}

Given the two tasks:

- name: Get content of test.json
  command: cat test.json
  register: result

- name: Fail when we have an abnormal exit status
  fail:
    msg: |-
      Some process have an abnormal exit:
      {{ _abnormal_exit }}  
  when: _abnormal_exit | length > 0
  vars:
    _abnormal_exit: >-
      {{
        result.stdout
        | from_json
        | json_query('domains.* | [?"exit code" > `0`]')
      }}

It would yield:

TASK [Get content of test.json] *****************************************
changed: [localhost]

TASK [Fail when we have an abnormal exit status] ************************
fatal: [localhost]: FAILED! => changed=false 
  msg: |-
    Some process have an abnormal exit:
    [{'status': 'Terminated', 'exit code': 2}]
  • Related