Idempotence in Ansible

Question : Restarting HTTPD Service is not idempotent in nature and also consumes more resources suggest a way to rectify this challenge in Ansible playbook.

Devashish Kumar Pan
3 min readMar 21, 2021

What is Idempotence?

An idempotent operation is one that can be applied multiple times without changing the result beyond the initial application, such as multiplication by zero. Ansible modules are idempotent.

This means that if an operation is run by ansible playbook 100 times it will affect the remote system or run on the remote system only once.

But there are instances where the ansible modules are not idempotent by default like when we restart a service. When restarting a service, it will run every time whether re-starting is needed or not.

To change that and to make restarting a service Idempotent we first need to known the reason for restarting a service. It is mostly due to some changes done within the configuration file.

So, to make restarting Idempotent we need to add a condition to the task which configures the service which tell it to run a handlers which contain the task of restarting the service.

If no changes are made to the configuration file then the task of configuration will not be executed and thus restarting handler will not run.

Below is the example of http server set-up ansible playbook with a handler handling the restarting task.

Ansible Playbook:

---
- name: Configuring HTTPD web server
hosts: all
vars_files:
- webserver_var.yml
tasks:
- name: Installing httpd
package:
name: "httpd"
state: present
- name: Creating web server root directory and creating a web page
file:
path: "{{doc_root}}"
state: directory
mode: '0755'
- copy:
dest: "{{doc_root}}/web.html"
content: "This is my web page."
- name: Configuring httpd
template:
dest: "/etc/httpd/conf.d/{{mywebsite}}.conf"
src: "website_template.conf.j2"
notify: "Restarting Httpd"

- name: Starting httpd service
service:
name: httpd
state: started

- firewalld:
port: "{{port_}}/tcp"
state: enabled
permanent: yes
immediate: yes

handlers:
- name: Restarting Httpd
service:
name: httpd
state: restarted

webserver_var.yml :

doc_root: "/var/www/myweb2"
port_: "443"
mywebsite: "myweb2"

website_template.conf.j2 :

Listen {{port_}}<virtualhost {{ansible_facts["default_ipv4"]["address"]}}:{{port_}}>documentroot {{doc_root}}</virtualhost>

Now the first time we run the playbook, the tasks run as they are and then if we run the playbook again we see that no changes take place:

First Run
First Configuration
Second run with same configuration

Now we change the configuration :

Second Configuration

Then we run the playbook again, we see that changes take place.

Third Run

This means this playbook only makes changes to remote system if there is any change in either the originally running service or the configuration of the service is what we want to update.

THANKS FOR READING!!!

--

--