I have an ansible playbook that calls a role, containing many tasks and handlers. the handlers will be triggered if my desired configuration of service is changed.
What I am looking for is a way to trigger multiple handlers on the hosts sequently. for example, if I have to targets target1
and target2
and I have also two handlers handler1
and handler2
, What I want in execution of handlers on targets would be something like below:
RUNNING HANDLER [myrole : handler 1] ********************************************
changed: [target1]
RUNNING HANDLER [myrole : handler2] *************************************************
changed: [target1]
RUNNING HANDLER [myrole : handler 1] ********************************************
changed: [target2]
RUNNING HANDLER [myrole : handler2] *************************************************
changed: [target2]
But as is known, the normal execution of handlers on targets are as below:
RUNNING HANDLER [myrole : handler 1] ********************************************
changed: [target1]
changed: [target2]
RUNNING HANDLER [myrole : handler 2] ********************************************
changed: [target1]
changed: [target2]
That it is not what I want.
I know that with using of serial
option in playbook level we can restrict parallelism, but this option will bring the cost of huge time consuming because all of my tasks would be executed in serial as well.
The ways I have tried was using both of throttle
option and block
directive on handlers but it wasn't usefull.
flush_handlers on each host separately. Dynamically create and include the file. For example, the playbook
shell> cat pb.yml
- hosts: target1,target2
tasks:
- debug:
msg: Notify handler1
changed_when: true
notify: handler1
- debug:
msg: Notify handler2
changed_when: true
notify: handler2
- block:
- copy:
dest: "{{ playbook_dir }}/flush_handlers_serial.yml"
content: |
{% for host in ansible_play_hosts_all %}
- meta: flush_handlers
when: inventory_hostname == '{{ host }}'
{% endfor %}
delegate_to: localhost
- include_tasks: flush_handlers_serial.yml
run_once: true
when: flush_handlers_serial|d(false)|bool
handlers:
- name: handler1
debug:
msg: Run handler1
- name: handler2
debug:
msg: Run handler2
by default runs the handlers in parallel (see linear strategy)
shell> ansible-playbook pb.yml
PLAY [target1,target2] ***************************************************************************************
TASK [debug] *************************************************************************************************
changed: [target1] =>
msg: Notify handler1
changed: [target2] =>
msg: Notify handler1
TASK [debug] *************************************************************************************************
changed: [target2] =>
msg: Notify handler2
changed: [target1] =>
msg: Notify handler2
TASK [copy] **************************************************************************************************
skipping: [target1]
TASK [include_tasks] *****************************************************************************************
skipping: [target1]
RUNNING HANDLER [handler1] ***********************************************************************************
ok: [target1] =>
msg: Run handler1
ok: [target2] =>
msg: Run handler1
RUNNING HANDLER [handler2] ***********************************************************************************
ok: [target1] =>
msg: Run handler2
ok: [target2] =>
msg: Run handler2
PLAY RECAP ***************************************************************************************************
target1: ok=4 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
target2: ok=4 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
When you enable flush_handlers_serial=true
the file below will be created and included
shell> cat flush_handlers_serial.yml
- meta: flush_handlers
when: inventory_hostname == 'target1'
- meta: flush_handlers
when: inventory_hostname == 'target2'
This will run the handlers serially, similarly to the strategy host_pinned
shell> ansible-playbook pb.yml -e flush_handlers_serial=true
PLAY [target1,target2] ***************************************************************************************
TASK [debug] *************************************************************************************************
changed: [target1] =>
msg: Notify handler1
changed: [target2] =>
msg: Notify handler1
TASK [debug] *************************************************************************************************
changed: [target1] =>
msg: Notify handler2
changed: [target2] =>
msg: Notify handler2
TASK [copy] **************************************************************************************************
changed: [target1 -> localhost]
TASK [include_tasks] *****************************************************************************************
included: /export/scratch/tmp7/test-172/flush_handlers_serial.yml for target1
TASK [meta] **************************************************************************************************
RUNNING HANDLER [handler1] ***********************************************************************************
ok: [target1] =>
msg: Run handler1
RUNNING HANDLER [handler2] ***********************************************************************************
ok: [target1] =>
msg: Run handler2
RUNNING HANDLER [handler1] ***********************************************************************************
ok: [target2] =>
msg: Run handler1
TASK [meta] **************************************************************************************************
skipping: [target1]
RUNNING HANDLER [handler2] ***********************************************************************************
ok: [target2] =>
msg: Run handler2
PLAY RECAP ***************************************************************************************************
target1: ok=6 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
target2: ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0