Listen feature for handlers in Ansible
There is one important improvement which appeared in Ansible 2.2: handlers now can listen
for notifications send for other handlers.
Pain to solve
I’ll describe my local problem I solved with listen
feature, as it looks like most vivid example of configuration which couldn't be solved in other way.
I have application which listen on specific interface, which is different from normal interfaces. I have a role to configure that interface, it done some crazy things with rule-based routing, alternative routing tables, etc. It all done through Debian ‘interface.d’ configuration style. After interface.d/ethNAME
has been changed, it’s reloaded by ‘restart ethNAME’ hander. Right after that interface has been restarted application should be restarted too, even it does not receive any changes in its configuration file.
Role to configure interface is used on few hosts, each has had own application. All of them should be restarted.
In pre-2.2 times I done this with a rather nasty trick: I added ‘same name’ handler (I called it ‘restart app’) in each role for each application, and I called it from network configuration role. It’s a pain, it’s a mess. You can’t have two applications on the same playbook to provide handle, you need to provide fake handle if you have no application on some host with network configuration.
Cure for pain
It all have been changed after listen
appears. Now I just use notify restart ethNAME
command in network-configure role. And any application could have own handler which reacts on that notification, as well, as to ‘own’ notifications related changes in tasks inside own role.
No more clutches and ugly code.
Code examples
Let’s say we have role with name role1
and role with name role2
. Role1 have hander to do own things:
role1/handlers/main.yaml
---
- name: Restart foobar
service: name=foobar state=restarted
It’s triggered by notify
statement somewhere inside role1/tasks/main.yaml:
---
- name: Doing something
command: some_command
notify: Restart foobar- name: Doing another thing
command: another_command
notify: Restart foobar
We want in role2 reacts if foobar is restarted. We’ll listen for notifications in role2/handlers/main.yaml:
---
- name: Doing own business
listen: Restart foobar
command: restarting
Great news that if we have more than one role (let’s says role3
), it can listen on this notification too:
(role3/handlers/main.yaml)
---
- name: Some other handler
listen: Restart foobar
command: other_important_handler
By combining those roles in a single playbook we can dynamically change who will reacts to ‘Restart foobar’:
---
- hosts:
- host1
- host2
roles:
- role1
- role2
- role3