Updated April 4, 2023
Introduction to Ansible Handlers
Ansible provides feature named handlers, which is like a task but will only run when called by a notifier in another task. This feature is important because your requirements for running a task may depend on the state of a service, existence of a file or a follow up tasks when state changed. We can make use of variables in notify and handlers which makes it more flexible. Ansible Handlers are used extensively in production and live environments as you always depend on something else to decide whether a task should run or not.
What are Ansible Handlers?
Ansible handlers have same contents as a task can have.
But few points should be noted and remembered while using notify and handlers, otherwise you might not get desired results:
- Name of a handler should be unique and this is used for calling it by notifier.
- A handler is called at the end of playbook by default, so even if a handler is notified multiple times, the tasks under handler will only run once. Also, this is only when one of the calling tasks have state changed.
- If two handlers have the same name, only the one will run. Which is defined later in playbook.
- You can mention a variable in handler’s tasks section. But avoid using variables in name of a handler. As handler names are templated early on.
- We can use listen with mentioning topics when need to call multiple handlers by single notify.
- Handler’s name and listen topics live in global namespace.
- Handlers will always run in same order in which handlers are defined and they run only once if one of the calling tasks have state change. Handlers don’t run in the order of notify. Same case is with those handlers which used listen topic.
- If state of a task is not changed, then attached notify will not call handler.
A sample playbook format with notify and handler will look like below. Here we are running a task and by using notify in it we are calling handler.
notify: <Handler Name>
name: <Handler Name>
How Facts are done in Handlers?
- Ansible has remote nodes information gathered in the form of predefined variables which are known as facts.
- This information set is prepared in JSON format. When you are playing with real time data, this is useful to fetch these facts and use in playbooks as variables.
- This information can be hostname, IP address, mac address, installed OS related information, current status of machine etc.
- These facts can be useful while working with handlers.
- As we know that value of these variables differs from one remote host to another, so making decision to run task on basis of the fact of a remote node is useful.
- Also, we use facts to generate some other data and use this data to be used in handler.
Example of Ansible Handlers
Given below is the example mentioned:
Here we have an Ansible control server named ansible-controller and two remotes hosts named host- one and host-two. We will create playbooks and run ansible commands on ansible-controller node and manage the remote hosts.
In this example, we will install httpd package on remote nodes and when package is installed successfully, the state of handler will be changed. We have mentioned a notifier which will call the handler restart httpd service after seeing the state change of task.
The playbook will look like below:
hosts: all tasks:
name: Install httpd
yum: name=httpd state=installed notify:
name: Start HTTPD
service: name=httpd state=started
After running this playbook, we will get the output like below where you can see when httpd package was installed on remote nodes and state of task s changed, then notifier was called and handler tasks was run.
If we run the same playbook again, knowing that task’s state will not be changed as packages have been already installed. So, notifier will not be calling the handler this time.
We can use listen topic to call multiple handlers like below. Here, we are configuring web server on remote hosts. Playbook will be like below. Notifying the listener topic “web server configuration” we called two handlers.
hosts: all tasks:
name: Install httpd yum:
name: httpd state: installed
notify: "web server configuration"
name: start httpd service service:
listen: "web server configuration"
name: copy index.html from control server to remote nodes copy:
dest: /var/www/html/index.html listen: "web server configuration"
Here notified the listener topic “web server configuration” and thus called two handlers, one for starting httpd service and other for copying index.html from local to remote nodes.
Now we use ansible facts to decide whether to execute a task or not. Here we used ansible_hostname to check the hostname of remote server and based on that we installed web server package. For host-one we installed httpd and for host-two we installed nginx. We checked this by condition when.
hosts: all tasks:
name: This will run install httpd on host-one and nginx on host-two command: echo "Web Server Will Be Installed"
notify: "install web server"
name: install httpd yum:
when: ansible_hostname == "host-one" listen: "install web server"
name: install nginx yum:
name: nginx state: installed
when: ansible_hostname == "host-two" listen: "install web server"
In below output, you must note that httpd installation skipped on host-two and nginx installation skipped on host-one.
Ansible handler is an important feature and topic which an Ansible practitioner should learn and imbibe substantially. This makes the decision-making tasks easier. Using handlers with other ansible features like conditions, facts, roles etc. makes it more useful for production environment.
This is a guide to Ansible Handlers. Here we discuss the introduction, how facts are done in handlers and example of ansible handlers. You may also have a look at the following articles to learn more –