Listen feature for handlers in Ansible

George Shuklin
2 min readApr 10, 2017

--

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 notifystatement 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

--

--

George Shuklin

I work at Servers.com, most of my stories are about Ansible, Ceph, Python, Openstack and Linux. My hobby is Rust.