So after reading Ansible docs, I found out that Handlers
are only fired when tasks report changes, so for example:
some tasks ...
notify: nginx_restart
# our handler
- name: nginx_restart
vs
some tasks ...
register: nginx_restart
# do this after nginx_restart changes
when: nginx_restart|changed
Is there any difference between these 2 methods? When should I use each of them?
For me, register
seems to have more functionality here, unless I am missing something...
In Ansible, a handler refers to a particular task that executes when triggered by the notify module. Handlers perform an action defined in the task when a change occurs in the remote host. Handlers are helpful when you need to perform a task that relies on a specific task's success or failure.
Notifying handlersNotifying the same handler multiple times will result in executing the handler only once regardless of how many tasks notify it. For example, if multiple tasks update a configuration file and notify a handler to restart Apache, Ansible only bounces Apache once to avoid unnecessary restarts.
In Ansible, handlers are typically used to start, reload, restart, and stop services. If your playbook involves changing configuration files, there is a high chance that you'll need to restart a service so that the changes take effect.
Ansible register is a way to capture the output from task execution and store it in a variable. This is an important feature, as this output is different for each remote host, and the basis on that we can use conditions loops to do some other tasks. Also, each register value is valid throughout the playbook execution.
There are some differences and which is better depends on the situation.
Handlers will only be visible in the output if they have actually been executed. Not notified, there will be no skipped tasks in Ansibles output. Tasks always have output no matter if skipped, executed with change or without. (except they are excluded via tags/skip-tags)
Handlers can be called from any role. This gets handy if you have more complex roles which depend on each other. Let's say you have a role to manage iptables but which rules you define is actually depending on other roles (e.g. database role, redis role etc...) Each role can add their rules to a config file and at the end you notify the iptables role to reload iptables if changed.
Handlers by default get executed at the end of the playbook. Tasks will get executed immediately where they are defined. This way you could configure all your applications and at the end the service restart for all changed apps will be triggered per handler. This can be dangerous though. In case your playbook fails after a handler has been notified, the handler will actually not be called. If you run the playbook again, the triggering task may not have a changed state any longer, therefore not notifying the handler. This results in Ansible actually not being idempotent. Since Ansible 1.9.1 you can call Ansible with the --force-handler
option or define force_handlers = True
in your ansible.cfg
to even fire all notified handlers after the playbook failed. (See docs)
If you need your handlers to be fired at a specific point (for example you configured your system to use an internal DNS and now want to resolve a host through this DNS) you can flush all handlers by defining a task like:
- meta: flush_handlers
A handler would be called only once no matter how many times it was notified. Imagine you have a service that depends on multiple config files (for example bind/named: rev, zone, root.db, rndc.key, named.conf) and you want to restart named if any of these files changed. With handlers you simply would notify from every single task that managed those files. Otherwise you need to register 5 useless vars, and then check them all in your restart task.
Personally I prefer handlers. It appears much cleaner than dealing with register
. Tasks triggered per register was safer before Ansible 1.9.1.
On the Ansible Variables page, you can see how register
works.
Another major use of variables is running a command and using the result of that command to save the result into a variable.
Registered variables are just like facts:
Effectively registered variables are just like facts.
This is very different from notify
, which triggers handlers. It does not save or store variables or facts.
with ignore_errors: True
you can avoid the failed handler from stopping other handlers defined after it continue to run
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With