Avoiding Missed Handlers with Ansible
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|