Idempotence and changed_when with Ansible execution modules
Most modules in Ansible is idempotent. Meaning you can apply it over and over again and get the same results. This concept is widely adopted for infrastructure automation across tools and services. It’s also quite practical to use the state change or no-op to make decisions further down the workflow. It could be a simple condition, if an object (file, directory, database entry - anything) doesn’t exist, create it before proceeding to the next step.
When using execution modules, such as raw, shell and command, it will always return changed: true if executed successfully. That might not be practical in the scenario where a tool always returns true regardless of outcome and you necessarily don’t want to simply treat errors (rc: 1) to track a state change.
Ansible task parameter changed_when
Any task in Ansible supports the changed_when condition to alter the changed outcome, not just execution modules. For example, interacting with a web service with the uri module could use the HTTP codes in combination with returned content signify a change. Complex idempotent playbooks could then be crafted to report an accurate number of changes instead of bucketing every “success” block as a state change when you have a mix of commands and API interactions.
Let’s assume the following playbook. We’ll use the ncmadm command from the HPE Nimble Storage Linux Toolkit to discover new LUNs. If the output contains “Login to the new devices:”, that means we have new LUNs on the host and we can proceed based on that assessment.
--- - hosts: prod tasks: - name: Discover new LUNs become: yes command: ncmadm -e {{ array_discovery_ip | quote }} register: ncmadm changed_when: ncmadm.stdout is search("Login to the new devices:") - name: Stuff to do with my new LUNs debug: msg: "We have new LUNs" when: ncmadm.changed
Ok, first run:
$ ansible-playbook -e array_discovery_ip=172.16.35.120 discover.yml PLAY [prod] *********************************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************ ok: [sjc-tme-vlnx000] TASK [Discover new LUNs] ********************************************************************************************************************** changed: [sjc-tme-vlnx000] TASK [Stuff to do with my new LUNs] *********************************************************************************************************** ok: [sjc-tme-vlnx000] => { "msg": "We have new LUNs" } PLAY RECAP ************************************************************************************************************************************ sjc-tme-vlnx000 : ok=3 changed=1 unreachable=0 failed=0
We can clearly see that we have new LUNs and acting on ncmadm.changed. We can also see in the recap that we made that one change.
Let’s run it again.
$ ansible-playbook -e array_discovery_ip=172.16.35.120 discover.yml PLAY [prod] *********************************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************ ok: [sjc-tme-vlnx000] TASK [Discover new LUNs] ********************************************************************************************************************** ok: [sjc-tme-vlnx000] TASK [Stuff to do with my new LUNs] *********************************************************************************************************** skipping: [sjc-tme-vlnx000] PLAY RECAP ************************************************************************************************************************************ sjc-tme-vlnx000 : ok=2 changed=0 unreachable=0 failed=0
Nope, nothing to see here.
Summary
Having idempotent playbooks is a cornerstone requirement to create safe playbooks for humans to run. Building safe systems to work in is a core DevOps principle. Ask yourself, would you run this playbook on a Friday afternoon? If the answer is no, get back to work!














