Getting Started With Ansible - Part Ten (Handlers)

This is in continuation to the articles of the series “Learning Ansible”.In this article we will be learning handlers.

This is in continuation to the articles of the series “Learning Ansible”. In the previous article Getting started with Ansible – Part 9 we have seen how we can set up the local NTP configuration file and how we can deploy it to the servers to get the benefit of setting up the configuration at one place and not doing this again and again in case we have 100s of servers.
 
But If we look closely at the playbook that we wrote we can see that if we again run the same playbook then the NTP service will again get restarted, and this should not happen as we have already deployed the NTP config file and if we have not done any change in that config then the NTP service should not get restarted.
 
So, we should devise a way such that NTP service will only get restarted if we have made some change in NTP configuration files. To resolve this, we can make use of handlers in Ansible. Thus, in this article we will be covering Handlers in Ansible.
 

Handlers in Ansible

 
Handlers are just like regular tasks in an Ansible playbook (see Tasks) but are only run if the Task contains a “notify” directive and also indicates that it changed something. For example, if a config file is changed then the task referencing the config file templating operation may notify a service restart handler.
 
Handlers are the same as tasks, but they get executed only when they are notified but tasks get executed every time we run the playbook. Handlers should be in the same line as that of tasks inside the playbook.
 
So below is the updated version of the playbook that we wrote in the previous article Getting started with Ansible – Part 9.
  1. ---                                                                                                                                                                                                                   
  2.                                                                                                                                                                                                                       
  3. - name: Deploying NTP Service                                                                                                                                                                                         
  4.   hosts: all                                                                                                                                                                                                          
  5.   become: yes                                                                                                                                                                                                         
  6.   tasks:                                                                                                                                                                                                              
  7.           - name: Install packages on RedHat OS                                                                                                                                                                       
  8.             yum:                                                                                                                                                                                                      
  9.               name: "{{item}}"                                                                                                                                                                                        
  10.               state: present                                                                                                                                                                                          
  11.             loop:                                                                                                                                                                                                     
  12.               - ntp                                                                                                                                                                                                   
  13.               - unzip                                                                                                                                                                                                 
  14.               - git                                                                                                                                                                                                   
  15.               - wget                                                                                                                                                                                                  
  16.               - zip                                                                                                                                                                                                   
  17.             when: ansible_os_family == "RedHat"                                                                                                                                                                       
  18.                                                                                                                                                                                                                       
  19.           - name: Install packages on Debian OS                                                                                                                                                                       
  20.             apt:                                                                                                                                                                                                      
  21.               name: "{{item}}"                                                                                                                                                                                        
  22.               state: present                                                                                                                                                                                          
  23.             loop:                                                                                                                                                                                                     
  24.               - ntp                                                                                                                                                                                                   
  25.               - unzip                                                                                                                                                                                                 
  26.               - git                                                                                                                                                                                                   
  27.               - wget                                                                                                                                                                                                  
  28.               - zip                                                                                                                                                                                                   
  29.             when: ansible_os_family == "Debian"                                                                                                                                                                       
  30.                                                                                                                                                                                                                       
  31.           - name: Start and Enable NTP service in RedHat OS                                                                                                                                                           
  32.             service:                                                                                                                                                                                                  
  33.               name: ntpd                                                                                                                                                                                              
  34.               state: started                                                                                                                                                                                          
  35.               enabled: yes                                                                                                                                                                                            
  36.             when: ansible_os_family == "RedHat"                                                                                                                                                                       
  37.                                                                                                                                                                                                                       
  38.           - name: Start and Enable NTP service in Debian OS                                                                                                                                                           
  39.             service:                                                                                                                                                                                                  
  40.               name: ntp                                                                                                                                                                                               
  41.               state: started                                                                                                                                                                                          
  42.               enabled: yes                                                                                                                                                                                            
  43.             when: ansible_os_family == "Debian"                                                                                                                                                                       
  44.                                                                                                                                                                                                                       
  45.           - name: Deploy the NTP configuration file for Debian OS                                                                                                                                                     
  46.             copy:                                                                                                                                                                                                     
  47.               src: files/ntp_debian.conf                                                                                                                                                                              
  48.               dest: /etc/ntp.conf                                                                                                                                                                                     
  49.               backup: yes                                                                                                                                                                                             
  50.             when: ansible_os_family == "Debian"                                                                                                                                                                       
  51.             notify:                                                                                                                                                                                                   
  52.                 - Restart NTP service in Debian OS                                                                                                                                                                    
  53.                                                                                                                                                                                                                       
  54.           - name: Deploy the NTP configuration file for RedHat OS                                                                                                                                                     
  55.             copy:                                                                                                                                                                                                     
  56.               src: files/ntp_redhat.conf                                                                                                                                                                              
  57.               dest: /etc/ntp.conf                                                                                                                                                                                     
  58.               backup: yes                                                                                                                                                                                             
  59.             when: ansible_os_family == "RedHat"                                                                                                                                                                       
  60.             notify:                                                                                                                                                                                                   
  61.                 - Restart NTP service in RedHat OS                                                                                                                                                                    
  62.                                                                                                                                                                                                                       
  63.   handlers:                                                                                                                                                                                                           
  64.           - name: Restart NTP service in RedHat OS                                                                                                                                                                    
  65.             service:                                                                                                                                                                                                  
  66.               name: ntpd                                                                                                                                                                                              
  67.               state: restarted                                                                                                                                                                                        
  68.             when: ansible_os_family == "RedHat"                                                                                                                                                                       
  69.                                                                                                                                                                                                                       
  70.           - name: Restart NTP service in Debian OS                                                                                                                                                                    
  71.             service:                                                                                                                                                                                                  
  72.               name: ntp                                                                                                                                                                                               
  73.               state: restarted                                                                                                                                                                                        
  74.             when: ansible_os_family == "Debian"  
 
We can syntax check our playbook with the below command.
 
ansible-playbook ntp_playbook.yml --syntax-check
 
and then can run the playbook with the below command.
 
ansible-playbook ntp_playbook.yml
 
OUTPUT
 
Ansible
 
Here we can see that as we have not changed anything inside the RedHat and Debian NTP configuration files, our handlers didn’t execute.
 
Now let’s try to add some dummy values inside the RedHat and Debian NTP configuration files and see if our handlers get executed or not.
 
Ansible
 
Now ansible knows that the source NTP configuration files and the destination NTP configuration files are different so will execute the tasks and will notify the handlers.
 
I am using the debug module to print the output for one of the tasks that deploy NTP configuration files for suppose RedHat OS based servers.
 
I have registered redhat_deployment_output variables that will store the JSON output of our task “Deploy the NTP configuration file for RedHat OS” and will get it printed using the debug module.
 
Below is the updated playbook.
  1. ---                                                                                                                                                                                                                   
  2.                                                                                                                                                                                                                       
  3. - name: Deploying NTP Service                                                                                                                                                                                         
  4.   hosts: all                                                                                                                                                                                                          
  5.   become: yes                                                                                                                                                                                                         
  6.   tasks:                                                                                                                                                                                                              
  7.           - name: Install packages on RedHat OS                                                                                                                                                                       
  8.             yum:                                                                                                                                                                                                      
  9.               name: "{{item}}"                                                                                                                                                                                        
  10.               state: present                                                                                                                                                                                          
  11.             loop:                                                                                                                                                                                                     
  12.               - ntp                                                                                                                                                                                                   
  13.               - unzip                                                                                                                                                                                                 
  14.               - git                                                                                                                                                                                                   
  15.               - wget                                                                                                                                                                                                  
  16.               - zip                                                                                                                                                                                                   
  17.             when: ansible_os_family == "RedHat"                                                                                                                                                                       
  18.                                                                                                                                                                                                                       
  19.           - name: Install packages on Debian OS                                                                                                                                                                       
  20.             apt:                                                                                                                                                                                                      
  21.               name: "{{item}}"                                                                                                                                                                                        
  22.               state: present                                                                                                                                                                                          
  23.             loop:                                                                                                                                                                                                     
  24.               - ntp                                                                                                                                                                                                   
  25.               - unzip                                                                                                                                                                                                 
  26.               - git                                                                                                                                                                                                   
  27.               - wget                                                                                                                                                                                                  
  28.               - zip                                                                                                                                                                                                   
  29.             when: ansible_os_family == "Debian"                                                                                                                                                                       
  30.                                                                                                                                                                                                                       
  31.           - name: Start and Enable NTP service in RedHat OS                                                                                                                                                           
  32.             service:                                                                                                                                                                                                  
  33.               name: ntpd                                                                                                                                                                                              
  34.               state: started                                                                                                                                                                                          
  35.               enabled: yes                                                                                                                                                                                            
  36.             when: ansible_os_family == "RedHat"                                                                                                                                                                       
  37.                                                                                                                                                                                                                       
  38.           - name: Start and Enable NTP service in Debian OS                                                                                                                                                           
  39.             service:                                                                                                                                                                                                  
  40.               name: ntp                                                                                                                                                                                               
  41.               state: started                                                                                                                                                                                          
  42.               enabled: yes                                                                                                                                                                                            
  43.             when: ansible_os_family == "Debian"                                                                                                                                                                       
  44.                                                                                                                                                                                                                       
  45.           - name: Deploy the NTP configuration file for Debian OS                                                                                                                                                     
  46.             copy:                                                                                                                                                                                                     
  47.               src: files/ntp_debian.conf                                                                                                                                                                              
  48.               dest: /etc/ntp.conf                                                                                                                                                                                     
  49.               backup: yes                                                                                                                                                                                             
  50.             when: ansible_os_family == "Debian"                                                                                                                                                                       
  51.             notify:                                                                                                                                                                                                   
  52.                 - Restart NTP service in Debian OS                                                                                                                                                                    
  53.                                                                                                                                                                                                                       
  54.                                                                                                                                                                                                                       
  55.           - name: Deploy the NTP configuration file for RedHat OS                                                                                                                                                     
  56.             copy:                                                                                                                                                                                                     
  57.               src: files/ntp_redhat.conf                                                                                                                                                                              
  58.               dest: /etc/ntp.conf                                                                                                                                                                                     
  59.               backup: yes                                                                                                                                                                                             
  60.             when: ansible_os_family == "RedHat"                                                                                                                                                                       
  61.             notify:                                                                                                                                                                                                   
  62.                 - Restart NTP service in RedHat OS                                                                                                                                                                    
  63.             register:                                                                                                                                                                                                 
  64.                     redhat_deployment_output                                                                                                                                                                          
  65.           - debug:                                                                                                                                                                                                    
  66.               var: redhat_deployment_output                                                                                                                                                                           
  67.                                                                                                                                                                                                                       
  68.   handlers:                                                                                                                                                                                                           
  69.           - name: Restart NTP service in RedHat OS                                                                                                                                                                    
  70.             service:                                                                                                                                                                                                  
  71.               name: ntpd                                                                                                                                                                                              
  72.               state: restarted                                                                                                                                                                                        
  73.             when: ansible_os_family == "RedHat"                                                                                                                                                                       
  74.                                                                                                                                                                                                                       
  75.           - name: Restart NTP service in Debian OS                                                                                                                                                                    
  76.             service:                                                                                                                                                                                                  
  77.               name: ntp                                                                                                                                                                                               
  78.               state: restarted                                                                                                                                                                                        
  79.             when: ansible_os_family == "Debian"  
 
OUTPUT
 
Ansible
 
We can see that the changed value is true for dbsrv01, similarly it is true for webserver 01 and 02 except web server 03 as web server 03 is a Debian based server.
 
We can also see from the output that our handlers also got triggered and executed successfully.
 
Handlers are lists of tasks, not really any different from regular tasks, that are referenced by a globally unique name, and are notified by notifiers. If nothing notifies a handler, it will not run. Regardless of how many tasks notify a handler, it will run only once, after all of the tasks complete in a particular play.
 
IMPORTANT NOTE
 
Handlers gets executed in the end of the playbook, so if you want to execute some task immediately as soon as the configuration gets changes then handlers won’t help and that can be handled via Conditions.
 

Summary

 
In this article we have learned about handlers and their use case and how they can be implemented in a real-life project scenario.
 
I hope you find this article helpful. Stay tuned for more … Cheers!!
 
You can also check out some of my previous articles of the series “Learning Ansible” here,