Ansible notify handlers in another role
AnsibleAnsible PlaybookAnsible Problem Overview
Can I notify the handler in another role? What should I do to make ansible find it?
The use case is, e.g. I want to configure some service and then restart it if changed. Different OS have probably different files to edit and even the file format can be different. So I would like to put them into different roles (because the file format can be different, it can't be done by setting group_vars). But the way to restart the service is the same, using service
module; so I'd like to put the handler to common
role.
Is anyway to achieve this? Thanks.
Ansible Solutions
Solution 1 - Ansible
You can also call handlers of a dependency role. May be cleaner than including files or explicitly listing roles in a playbook just for the purpose of role to role relationship. E.g.:
-
roles/my-handlers/handlers/main.yml
--- - name: nginx restart service: > name=nginx state=restarted
-
roles/my-other/meta/main.yml
--- dependencies: - role: my-handlers
-
roles/my-other/tasks/main.yml
--- - copy: > src=nginx.conf dest=/etc/nginx/ notify: nginx restart
Solution 2 - Ansible
You should be able to do that if you include the handler file.
Example:
handlers:
- include: someOtherRole/handlers/main.yml
But I don't think its elegant.
A more elegant way is to have a play that manages both roles, something like this:
- hosts: all
roles:
- role1
- role2
This will make both roles able to call other handlers.
But again I would suggest to make it all in one role and separate files and use a conditional include http://docs.ansible.com/playbooks_conditionals.html#conditional-imports
Hope that helps
Solution 3 - Ansible
You may import additional handlers from YourRole/handlers/main.yml
file by using import_tasks
.
So, if MyRole
needs to call handlers in some OtherRole
, roles/MyRole/handlers/main.yml
will look like this:
- import_tasks: roles/OtherRole/handlers/main.yml
Of course roles/MyRole/handlers/main.yml
may include additional handlers as well.
This way if I want to run MyRole
without running tasks from the OtherRole
, ansible will be able to correctly import and run handlers from the OtherRole
Solution 4 - Ansible
I had a similar issue, but needed to take many actions in the other dependent roles.
So rather than invoking the handeler - we set a fact like so:
- name: install mylib to virtualenv
pip: requirements=/opt/mylib/requirements.txt virtualenv={{ mylib_virtualenv_path }}
sudo_user: mylib
register: mylib_wheel_upgraded
- name: set variable if source code was upgraded
set_fact:
mylib_source_upgraded: true
when: mylib_wheel_upgraded.changed
Then elsewhere in another role:
- name: restart services if source code was upgraded
command: /bin/true
notify: restart mylib server
when: mylib_source_upgraded
Solution 5 - Ansible
Currently I'm using ansible v2.10.3 and it supports to call handlers
on different roles. This was because the handlers
are visible on the play-level, as per Ansible Docs says. You can see the docs mentioned that in the bottom-most point.
> handlers are play scoped and as such can be used outside of the role they are defined in.
FYI, I tested the solution i.e. calling other role's handlers
and it works! No need to import or else, just make sure that the roles are in the same playbook execution.
To illustrate:
-
roles/vm/handlers/main.yaml
--- - name: rebootvm ansible.builtin.reboot: reboot_timeout: 600 test_command: whoami
-
roles/config-files/tasks/main.yaml
--- - name: Copy files from local to remote ansible.builtin.copy: dest: /home/ubuntu/config.conf src: config.conf backup: yes force: yes notify: - rebootvm
So when the config file (i.e. config.conf
) changed, Ansible will send it to the remote location and it will notify the handler rebootvm
, then the VM is rebooted.
P.S. I don't know what version exactly Ansible support this.
Edit: code indentation fix