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
.