Skip to content

Checking a RESTful health endpoint#

Problem#

How do we check if the RESTful application is healthy after modification?

Solution#

If an application provides an HTTP endpoint to return the state of the application, we can also reuse this in Ansible. In our first example, the service returns the HTTP status code 200 if successful.

- name: Flush handlers
  ansible.builtin.meta: flush_handlers

- name: Check health endpoint
  ansible.builtin.uri:
    url: "http://{{ ansible_default_ipv4.address }}:8080/health"
  retries: 12
  delay: 5
  headers:
    Host: myapp.example.com
  until: healthcheck.status == 200
  register: healthcheck
  check_mode: true
  tags: always

If the service offers further information via JSON in the event of an error, we can use and display it:

- name: Flush handlers
  ansible.builtin.meta: flushhandlers

- name: Check health endpoint
  ansible.builtin.uri:
    url: "http://{{ ansible_default_ipv4.address }}:8080/health"
    returncontent: true
  retries: 12
  delay: 5
  headers:
    Host: myapp.example.com
  until: healthcheck.status == 200
  register: healthcheck
  check_mode: true
  ignore_errors: true
  tags: always

- name: Fail with custom message
  fail:
    msg: >
        "Fail if healthcheck is not ok, "
        "reason: {{ healthcheck.content.error_msg | default('unknown') }}"
  when: healthcheck is failed
  tags: always

Explanation#

Firstly, we execute any notified handlers that might restart or reload the service.

In our first example, the service returns the HTTP status code 200 if successful. We execute the health endpoint on the host and check with its IP, but include the host header of the service. This can be important if vhosts are used.

As we want to give the healthcheck some time and fault tolerance, we use a loop with 12 attempts and a delay of 5 seconds per run.

With check_mode: true we also check when --check is given. We also want the check to be carried out when a tag is used; we achieve this with tags: always.

See also#