How to trigger handlers (notify) when using import_tasks?

Viewed 941

When using notify on a task using import_tasks the handlers are not fired. I'm wondering why. tags are working like expected.

How to trigger handlers on imported tasks?

Example:

playbook test.yml:

- hosts: all
  gather_facts: no

  handlers:
  - name: restart service
    debug: 
      msg: restart service

  tasks:
  - import_tasks: test_imports.yml
    notify: restart service
    tags: test

test_imports.yml

- name: test
  debug:
    msg: test
  changed_when: yes

- name: test2
  debug:
    msg: test2
  changed_when: yes

Expected:

> ansible-playbook -i localhost, test.yml

PLAY [all] *************************************************************************************************************

TASK [test] ************************************************************************************************************
changed: [localhost] => {
    "msg": "test"
}

TASK [test2] ***********************************************************************************************************
changed: [localhost] => {
    "msg": "test2"
}

RUNNING HANDLER [restart service] **************************************************************************************
ok: [localhost] => {
    "msg": "restart service"
}

...

Actual:

> ansible-playbook -i localhost, test.yml        

PLAY [all] *************************************************************************************************************

TASK [test] ************************************************************************************************************
changed: [localhost] => {
    "msg": "test"
}

TASK [test2] ***********************************************************************************************************
changed: [localhost] => {
    "msg": "test2"
}

...
1 Answers

This question has been partially answered in Ansible's bug tracker here:

import_tasks is processed at parse time and is effectively replaced by the tasks it imports. So when using import_tasks in handlers you would need to notify the task names within.

Source: mkrizek's comment: https://github.com/ansible/ansible/issues/59706#issuecomment-515879321


This has been also further explained here:

imports do not work like tasks, and they do not have an association between the import_tasks task and the tasks within the imported file really. import_tasks is a pre-processing trigger, that is handled during playbook parsing time. When the parser encounters it, the tasks within are retrieved, and inserted where the import_tasks task was located. There is a proposal to "taskify" includes at ansible/proposals#136 but I don't see that being implemented any time soon.

Source: sivel comment: https://github.com/ansible/ansible/issues/64935#issuecomment-573062042


And for the good part of it, it seems it has been recently fixed: https://github.com/ansible/ansible/pull/73572


But, for now, what would work would be:

- hosts: all
  gather_facts: no

  handlers:
  - name: restart service
    debug: 
      msg: restart service

  tasks:
  - import_tasks: test_imports.yml
    tags: test

And a test_imports.yml file like:

- name: test
  debug:
    msg: test
  changed_when: yes
  notify: restart service

- name: test2
  debug:
    msg: test2
  changed_when: yes
  notify: restart service

This all yields:

PLAY [all] *******************************************************************************************************

TASK [test] ******************************************************************************************************
changed: [localhost] => 
  msg: test

TASK [test2] *****************************************************************************************************
changed: [localhost] => 
  msg: test2

RUNNING HANDLER [restart service] ********************************************************************************
ok: [localhost] => 
  msg: restart service

PLAY RECAP *******************************************************************************************************
localhost                  : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Then if you want to import those tasks somewhere this handler is not defined you could use the environment variable ERROR_ON_MISSING_HANDLER that helps you transform the error thrown when there is a missing handler to a "simple" warning.

e.g.

$ ANSIBLE_ERROR_ON_MISSING_HANDLER=false ansible-playbook play.yml -i inventory.yml

PLAY [all] *******************************************************************************************************

TASK [test] ******************************************************************************************************
[WARNING]: The requested handler 'restart service' was not found in either the main handlers list nor in the
listening handlers list
changed: [localhost] => 
  msg: test

TASK [test2] *****************************************************************************************************
changed: [localhost] => 
  msg: test2

PLAY RECAP *******************************************************************************************************
localhost                  : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  
Related