Including Handlers from Different File
The Handlers I Have Are Not Being Run by the Playbook or Tasks I Have the Following Directory Structur: - Playbook. Yml - - - Main. Yml - - -Main. Yml the...
The handlers I have are not being run by the playbook or tasks
I have the following directory structur:
<project>
- playbook.yml
- <roles>
-<handler>
- main.yml
-<meta>
-<tasks>
-main.yml
The problem is the handler is never called.
tasks/main.yml:
- name: run task1
command: run_task
notify: "test me now"
handler/main.yml:
- name: tested
register: val1
listen: "test me now"
The playbook just calls the task/main.yml and has host:all
Do I ned an include/import? I tried in playbook but it didn't help
3 Answers
The play below works as expected
- hosts: all
tasks:
- include_tasks: tasks/main.yml
- meta: flush_handlers
- debug:
var: val1.stdout
handlers:
- import_tasks: handlers/main.yml
- handlers must be imported to be present when a task notifies a handler
- tasks may be included, or imported
- flush_handlers is needed if you want to use the variable val1 in the playbook
A module is missing in handler/main.yml. This would cause:
ERROR! no action detected in task. This often indicates a misspelled module name, or incorrect module path.
Use some module in handler/main.yml. For example:
- name: tested
command: "echo 'running handler'"
register: val1
listen: "test me now"
Running such play gives
val1.stdout: running handler
Example of a complete playbook for testing
shell> cat playbook.yml
- hosts: localhost
tasks:
- include_tasks: tasks/main.yml
handlers:
- import_tasks: handlers/main.yml
shell> cat tasks/main.yml
- command: date
register: result
notify: test me now
shell> cat handlers/main.yml
- name: test me now
debug:
msg: "{{ result.stdout }} Running handler."
gives
shell> ansible-playbook playbook.yml
PLAY [localhost] *****************************************************************************
TASK [Gathering Facts] ***********************************************************************
ok: [localhost]
TASK [include_tasks] *************************************************************************
included: /export/scratch/tmp8/test-801/tasks/main.yml for localhost
TASK [command] *******************************************************************************
changed: [localhost]
RUNNING HANDLER [test me now] ****************************************************************
ok: [localhost] =>
msg: Mon 25 Apr 2022 04:59:02 PM CEST Running handler.
PLAY RECAP ***********************************************************************************
localhost: ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
You should have the structure described in thus the directory should be called handlers (and not handler)
Handlers folder with no imports ❌
The question of wether handlers in handlersfolder are loaded automatically. Like it's the case with roles.
Answer:
NO, they are not loaded automatically
- you have to import them
- If you do
- main.yml # playbook
- handlers
- simple.yml
- some.yml
And you don't import any handler. None will be loaded and available for notification.
✅ Importing handlers ✅
Must Read
The rules, behaviors and QA
import them in
handlers:of a playbookimport them with
import_tasks✅- Not
include_tasks❌ - Doc refs
import_tasks- run at parsing time statically
- Does resolve recursively all the tasks
- make a one list
- That list would be the list of handlers to add.
- It's not a handler itself.
- And it's name block, can't be referenced as a handler itself.
include_tasks- Is run at run time, dynamically
- The block is the handler himself.
- The tasks in the file will be loaded and executed dynamically once the handler (block) is notified and run.
- All of them at once.
- It's just bundling multiple tasks to run when the handler is notified. Instead of just a one module call.
- Not
What about
flushingthem ?- Not needed (at least in ansible
2.15.4Where i tested)- And the logic is
- handlers run when they are
flushed flush_handlersis automatically run once the tasks finish.- generally if some tasks fail. All handlers will not run with the default at end
flushing
- generally if some tasks fail. All handlers will not run with the default at end
flush_handlersgive us control to flush at the time that we want.- when a task call notify
- A handler is added to the list of handlers to flush. Or notified handlers.
- Flushing is running that list of handlers (the
notified handlerslist)
- handlers run when they are
- And the logic is
- Not needed (at least in ansible
More questions
Q: Can we import the file with a name and notify that name to run all handlers inside
- A:
No=> The import basically register the handler inside as if they were copied. (c++ and php, and confinclude)- So basically when you import any file, or if a file that you import does in it's turn import other files. =>
All will be resolved to a list of handlersand you can refer any of the final resolved handlers by there names.- There is no notion of grouping handlers under another. But only a one list of all resolved handlers.
- Assure you have unique names cross the files
- That behavior started in
v2.8 - Doc ref
Beginning in version 2.8, a task cannot notify import_tasks or a static include that is specified in handlers.
The goal of a static import is to act as a pre-processor, where the import is replaced by the tasks defined within the imported file. When using an import, a task can notify any of the named tasks within the imported file, but not the name of the import itself.
To achieve the results of notifying a single name but running multiple handlers, utilize include_tasks, or listen Handlers: running operations on change.
- So basically when you import any file, or if a file that you import does in it's turn import other files. =>
- A:
Q: What happens if two handlers in separate files have the same name ?
- A: The first handler in the first loaded file would take precedence (inverse of last take precedence)
- And clearly the best is to have unique names
- A: The first handler in the first loaded file would take precedence (inverse of last take precedence)
Q: Can we import roles within handlers ?
- A:
NOwe can't, it's a limitation of handlers- Doc Ref: Limitations
- A:
Q: Can we use
include_tasksfor handlers- A:
Depends- The way
include_tasks:works is that the name of the block, is a handler itself.- When you call that handler. You will execute all the tasks in
include_tasksfile - See next section, it does include doc ref too.
- When you call that handler. You will execute all the tasks in
- The way
- A: