How to make a non-idempotent task an idempotent task in ansible

Anand D S
2 min readMar 21, 2021

What is Idempotent in Ansible?

The principle that enables Ansible to be declarative and yet reliable is idempotence, a concept borrowed from mathematics. 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. For example, if one of the tasks is to create a directory on the server, then the directory will be created if and only if it does not already exist. This sounds pretty simple to implement in the case of filesystem operations, but it’s not as trivial when considering more complex modules. Nonetheless, Ansible guarantees idempotence in all of its core modules.

But there are still some modules where the tasks are non-idempotent, taking an example of “service” module of ansible used to controls services on remote hosts, in this module we have a state called restarted which is non-idempotent this task always run when a play book is executed.

When we use this module for HTTPD services to restart the HTTPD service after updating our HTTPD .conf file it always restart the service even if there is no update in the .conf file this consume more RAM and CPU, to make our tasks more optimize we can use handlers here.

What is ansible handlers?

Handlers are similar to tasks used to run operations on change, these are the tasks that only run when it is notified by any other task when they are in changed state. Each handler should have a globally unique name.

Ansible playbook example using handlers for restarting HTTPD service

---
- name: Verify apache installation
hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: Ensure apache is at the latest version
yum:
name: httpd
state: latest

- name: Write the apache config file
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
notify:
- Restart apache

- name: Ensure apache is running
service:
name: httpd
state: started

handlers:
- name: Restart apache
service:
name: httpd
state: restarted

--

--