Block Handlers in Ansible (Why they don't work and what you can do instead)
Block handlers are as it turns out not a thing, lets go through what a block handler is, why they as of writing do not work:
Say you have a block of code you would like to run as a handler in roles/config/handlers/main.yml
1
2
3
4
5
6
7
8
9
10
11
12
# This example does NOT work
- name: Restart service
block:
- name: Stop Service
ansible.builtin.service:
name: my-service
state: stopped
- name: Start Service
ansible.builtin.service:
name: my-service
state: started
Intuitively you would think that adding notify: Restart Service to the task you want to run the handler with would work but this is not the case due to how Ansible works with Blocks.
“Block names are for documentation only, they do not apply to the contained tasks”
As such there are two choices you can follow, and I think the one you choose is mostly based on whereabouts the handler code in use is stored
Listen attribute
Use of the listen attribute allows setting what should respond to a notify:
1
2
3
4
5
6
7
8
9
10
11
# This handler 'name' is now just for documentation.
# The 'listen' topic is what matters.
- name: Restart service
block:
- name: Stop Service
<...>
listen: Restart Service Handler
- name: Start Service
<...>
listen: Restart Service Handler
Things marked listener will be respond when notified e.g. any tasks with notify: Restart service handler will call the above tasks
1
2
3
- name: Task which needs a restart after
<...>
notify: Restart Service Handler
Include_tasks
If you have an Restart Service tasks.yml file then you can do the following:
roles/tasks/restart_service.yml
1
2
3
4
5
- name: Stop Service
<...>
- name: Start Service
<...>
Then in your handlers file you can have roles/config/handlers/main.yml
1
2
- name: Restart Service
include_tasks: roles/tasks/restart_service.yml
And then be able to use in your code and plays
1
2
3
- name: Task which needs a restart after
<...>
notify: Restart Service
Conclusions
Both these both seem quite convoluted so there is a lot of interest in updating Ansible to allow calls to a block as a handler (see discussion on Stack Overflow and GitHub ) but in the meantime they are both standard patterns for grouping multiple tasks into a singular handler action.