Reputation: 2942
According to docs "Handlers always run in the order they are defined". When running a role multiple times with the same handler name, Ansible overwrites the first ones and uses only the last handler. This way the handler has less priority than defined in the handlers file.
Is there a way to run a handler at first when triggered multiple times via a loop?
Example
Playbook "test.yml"
- hosts: localhost
gather_facts: no
become: yes
become_method: sudo
vars:
services:
- service_name: abc
- service_name: xyz
tasks:
- include_role:
name: install-service
vars:
service_name: "{{ item.service_name }}"
loop: "{{ services }}"
Role "install-service" tasks
- name: Installing service {{ service_name }}
command: echo hello {{ service_name }}
notify:
- reload systemd
- restart service {{ service_name }}
Role "install-service" handlers
- name: reload systemd
debug:
msg: Reloading systemd
- name: restart service {{ service_name }}
debug:
msg: Restarting {{ service_name }}
Run
> ansible-playbook test.yml
PLAY [localhost] *******************************************************************************************************
TASK [include_role : install-service] **********************************************************************************
TASK [install-service : Installing service abc] ************************************************************************
changed: [localhost]
TASK [install-service : Installing service xyz] ************************************************************************
changed: [localhost]
RUNNING HANDLER [install-service : restart service abc] ****************************************************************
ok: [localhost] =>
msg: Restarting abc
RUNNING HANDLER [install-service : reload systemd] *********************************************************************
ok: [localhost] =>
msg: Reloading systemd
RUNNING HANDLER [install-service : restart service xyz] ****************************************************************
ok: [localhost] =>
msg: Restarting xyz
PLAY RECAP *************************************************************************************************************
localhost : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
In this example the role "install-service" is called multiple times for all "services". And at the end, Ansible should reload systemd and then restart all services.
But actually Ansible will Restart all services but the last, then it will reload systemd and then the last service is restarted.
This makes sence as the role gets included multiple times and the handlers with the same name overwriting themself. Only the last one is kept. And the last "reload systemd" handler is defined before the last "restart service ...".
So how can I run the handler "reload systemd" before all the services?
Upvotes: 0
Views: 874
Reputation: 17017
the only way i see to resolv your problem is to notify the restart from handlers:
handlers:
- name: reload systemd
debug:
msg: Reloading systemd
changed_when: true
notify:
- restart service
- name: restart service
debug:
msg: Restarting {{ service_name }}
vars:
service_name: "{{ item.service_name }}"
loop: "{{ services }}"
role:
- name: Installing service {{ service_name }}
command: echo hello {{ service_name }}
notify:
- reload systemd
result:
PLAY [localhost]
TASK [include_role : install-service]
TASK [install-service : Installing service abc]
changed: [localhost]
TASK [install-service : Installing service xyz]
changed: [localhost]
RUNNING HANDLER [install-service : reload systemd]
changed: [localhost] => {
"msg": "Reloading systemd"
}
RUNNING HANDLER [install-service : restart service]
ok: [localhost] => (item={'service_name': 'abc'}) => {
"msg": "Restarting abc"
}
ok: [localhost] => (item={'service_name': 'xyz'}) => {
"msg": "Restarting xyz"
}
Upvotes: 0