What does idempotent mean in Ansible, and how do check mode and diff help on network devices?
Show the answer
Say this first
Idempotent means running the playbook again changes nothing if the device is already right: the first
run reports changed, the second reports ok with changed=0. Modules get there by reading the current
state, comparing it with the desired state and sending only the difference. --check runs without
changing anything and reports what would change; --diff shows the before and after. Together they are
my dry run before every change.
Go deeper
How you see it
$ ansible-playbook ntp.yml
TASK [Set NTP server] **********************************************************
changed: [SW1]
PLAY RECAP *********************************************************************
SW1 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$ ansible-playbook ntp.yml
TASK [Set NTP server] **********************************************************
ok: [SW1]
PLAY RECAP *********************************************************************
SW1 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0How modules achieve it
ios_configreads the running config and compares yourlines(under theirparents) with it. It sends only lines that are missing.- Resource modules (
ios_vlans,ios_interfaces) gather the current state as structured data and compute the commands needed. ios_commandruns commands. It is for reading, not for managing config.
What breaks idempotency with ios_config
- Lines the device never shows:
no shutdownis the default and does not appear in the running config, so it is "missing" on every run. - Abbreviations:
int gi1/0/1ordescnever match the full words in the running config. - Lines the device rewrites: secrets are stored hashed, so the plain text never matches.
Check mode and diff
ansible-playbook vlans.yml --check --diff --limit SW1Run it in the change ticket and in CI. A playbook that shows changed in check mode on an unchanged
device has an idempotency bug.
They will ask next
Can every module run in check mode?
Only modules that declare check mode support. Others are skipped in check mode, and the documentation says which. Network config modules and resource modules generally support it.
How do you save the config only when something changed?
ios_confighassave_when: modified, which writes memory only if the running config differs from startup. You can also notify a handler from changed tasks and save once at the end.
Traps
- Writing
no shutdownwithios_configand wondering why every run reports changed. - Treating
changed=0as proof of correct config. It only shows Ansible saw no difference in the lines it manages.