What is Idempotency?
Idempotence is a term given to certain operations in mathematics and computer science whereby:
an action which, when performed multiple times, has no further effect on its subject after the first time it is performed.
In mathematics, idempotency can be seen when we multiply x by 1. It doesn’t matter how many times we perform this operation the result (x) is the same.
Lets now look at idempotent actions in the world of computing…
Python
If we first look at Python. We can see an example below of an idempotent method - discard
. The discard
method removes an element from a set
. But the result/behaviour is the same if we run the operation again.
>>> vlans = {100, 200, 300}
>>>
>>> vlans.discard(100)
>>> vlans
{200, 300}
>>>
>>> vlans.discard(100)
>>> vlans
{200, 300}
REST API’s
Certain methods of REST-based APIs can also be considered idempotent. For example:
Method | Idempotent | Details |
---|---|---|
GET | YES | The `GET` method never changes the resource state. Therefore only resource data is returned and no change is made to the server. |
PUT | YES | The `PUT` method updates the resource state. If you invoke the same `PUT` request N times, the first request will update the resource then the additional requests will overwrite the same resource. |
POST | NO | The `POST` method creates a new resource on the server. Therefore when you invoke the same `POST` request N times, you will have N new resources on the server. |
DELETE | YES | The `DELETE` method deletes the resource on the first request. Further requests will return `404 (Not Found)` to the client. Therefore no further changes are performed on the server. |
Ansible
One key benefit that Ansible provides is that it (i.e its modules) are idempotent*.
Below provides an example around using the nxos_static_route
module. We first run the playbook against a single host. As a result we can see that the host was changed
. However, on rerunning the playbook we can see that no change is reported, due to the route already being present. Therefore the operation can be termed as idempotent.
(venv) rick@N-20HJPF0UTUW6:~/ansible/ansible$ ansible-playbook -i inventory/hosts --limit core1-nxos1 playbooks/cisco-nxos-configure-static-route.yml
PLAY [Configure Static Route] *****************************************************************************************************************************************
TASK [Configure Route] ************************************************************************************************************************************************
changed: [core1-nxos1]
PLAY RECAP ************************************************************************************************************************************************************
core1-nxos1 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
(venv) rick@N-20HJPF0UTUW6:~/ansible/ansible$ ansible-playbook -i inventory/hosts --limit core1-nxos1 playbooks/cisco-nxos-configure-static-route.yml
PLAY [Configure Static Route] *****************************************************************************************************************************************
TASK [Configure Route] ************************************************************************************************************************************************
ok: [core1-nxos1]
PLAY RECAP ************************************************************************************************************************************************************
core1-nxos1 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
- Please note. There are caveats within the various modules around idempotence. Such as shorthand syntax in the
*_config modules
or privacy/password strings in thenxos_snmp_user
module. Though, I'm sure there are other caveats across the other modules, but the key point here is to always check and review the module documentation before implementing.
References
"Idempotent REST APIs – REST API Tutorial - RESTful API." https://restfulapi.net/idempotent-rest-apis/. Accessed 13 Feb. 2020.