Ansible Handlers

handle-with-care-md

Ansible handlers are defined in a handlers section or file and are called at the end of each play1)block of ansible configuration that is mapped to a specific group of hosts if they have been triggered. This is useful as it means you can have multiple tasks trigger another action, but ensure that the triggered action only runs once.

A potential problem

If a task notifies a handler, then a subsequent task in the same play fails, then the whole playbook run will terminate and the handler will not be called. Thats fair enough – its expected behaviour for ansible to stop running tasks on a node once its had a failure. The problem is that the condition that notified the handler may not be true on a re-run, in which case the handler will never be run.

An example (this is just a task list, not a complete play)

- name: drop file 
  copy:
    src: afile
    dest: /tmp/afile
  notify: restart athing

- name: Fail
  shell: false

In this example a file is dropped, then a handler is notified to restart something, then the next task fails so the run ends and the handler is not called. If we re-run a playbook containing these tasks, the restart notify will not be fired on the second run as /tmp/afile already exists.

One workaround is to flush handlers immediately after notifying:

- name: drop file 
  copy:
    src: afile
    dest: /tmp/afile
  notify: restart athing

- meta: flush_handlers

- name: Fail
  shell: false

Another option is to run ansible-playbook with the –force-handlers option when you are retrying a failed run. This may have interesting side effects though if your handlers are only designed to be run under very specific circumstances.

So handlers are useful but be aware of potentially missing them on retry.

Notes   [ + ]

1. block of ansible configuration that is mapped to a specific group of hosts