22

I have a service call that returns system status in json format. I want to use the ansible URI module to make the call and then inspect the response to decide whether the system is up or down

{"id":"20161024140306","version":"5.6.1","status":"UP"}

This would be the json that is returned

This is the ansible task that makes a call:

 - name: check sonar web is up
   uri:
    url: http://sonarhost:9000/sonar/api/system/status
    method: GET
    return_content: yes
    status_code: 200
    body_format: json
    register: data

Question is how can I access data and inspect it as per ansible documentation this is how we store results of a call. I am not sure of the final step which is to check the status.

Hafiz
  • 4,921
  • 3
  • 19
  • 28
  • 4
    You can start with simple `debug: var=data` as next task to see what's inside the registered variable. This will help you to move on. – Konstantin Suvorov Oct 25 '16 at 08:59
  • Thanks that helped break down the issue for me. :) – Hafiz Oct 25 '16 at 09:48
  • 1
    Notice how `register` is indented this resulted in `data is undefined` error to fix this you would need to unindent to same spacing as `uri` – Hafiz Oct 25 '16 at 10:02

3 Answers3

47

This works for me.

- name: check sonar web is up
uri:
  url: http://sonarhost:9000/sonar/api/system/status
  method: GET
  return_content: yes
  status_code: 200
  body_format: json
register: result
until: result.json.status == "UP"
retries: 10
delay: 30

Notice that result is a ansible dictionary and when you set return_content=yes the response is added to this dictionary and is accessible using json key

Also ensure you have indented the task properly as shown above.

Hafiz
  • 4,921
  • 3
  • 19
  • 28
  • This is nice, the fact that result comes in as an Ansible dictionary and there's a Jinja2 JSON parser already there to extract info from it. – ocean Oct 25 '16 at 10:15
  • 1
    @Halfiz Thank you, thank you, thank you. My until: condition was not working and it was the indentation that was biting me. – TJA Sep 16 '19 at 00:08
  • Is it somehow possible using content? For some reason content does not work (probably because of some escaping issues). Could you check that if you have time? – Mohammed Noureldin May 17 '23 at 20:15
6

You've made the right first step by saving the output into a variable.

The next step is to use either when: or failed_when: statement in your next task, which will then switch based on the contents of the variable. There are a whole powerful set of statements for use in these, the Jinja2 builtin filters, but they are not really linked well into the Ansible documentation, or summarised nicely.

I use super explicitly named output variables, so they make sense to me later in the playbook :) I would probably write yours something like:

- name: check sonar web is up
  uri:
    url: http://sonarhost:9000/sonar/api/system/status
    method: GET
    return_content: yes
    status_code: 200
    body_format: json
  register: sonar_web_api_status_output

- name: do this thing if it is NOT up
  shell: echo "OMG it's not working!"
  when: sonar_web_api_status_output.stdout.find('UP') == -1

That is, the text "UP" is not found in the variable's stdout.

Other Jinja2 builtin filters I've used are:

  • changed_when: "'<some text>' not in your_variable_name.stderr"
  • when: some_number_of_files_changed.stdout|int > 0

The Ansible "Conditionals" docs page has some of this info. This blog post was also very informative.

ocean
  • 1,335
  • 15
  • 26
4

As per documentation at https://docs.ansible.com/ansible/latest/modules/uri_module.html

Whether or not to return the body of the response as a "content" key in the dictionary result. Independently of this option, if the reported Content-type is "application/json", then the JSON is always loaded into a key called json in the dictionary results.

---
- name: Example of JSON body parsing with uri module
  connection: local
  gather_facts: true
  hosts: localhost
  tasks:

    - name: Example of JSON body parsing with uri module
      uri: 
        url: https://jsonplaceholder.typicode.com/users
        method: GET
        return_content: yes
        status_code: 200
        body_format: json
      register: data
      # failed_when: <optional condition based on JSON returned content>

    - name: Print returned json dictionary
      debug:
        var: data.json

    - name: Print certain element
      debug:
        var: data.json[0].address.city
Boeboe
  • 2,070
  • 1
  • 17
  • 21