Ansible notify handlers in another role

AnsibleAnsible Playbook

Ansible 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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKan LiView Question on Stackoverflow
Solution 1 - AnsiblefamousgarkinView Answer on Stackoverflow
Solution 2 - AnsibleDomaNitroView Answer on Stackoverflow
Solution 3 - AnsibleDima L.View Answer on Stackoverflow
Solution 4 - AnsiblestackdumpView Answer on Stackoverflow
Solution 5 - AnsiblekxuView Answer on Stackoverflow