Octet

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

Output
$ 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=0

How modules achieve it

  • ios_config reads the running config and compares your lines (under their parents) 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_command runs commands. It is for reading, not for managing config.

What breaks idempotency with ios_config

  • Lines the device never shows: no shutdown is the default and does not appear in the running config, so it is "missing" on every run.
  • Abbreviations: int gi1/0/1 or desc never 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

Shell
ansible-playbook vlans.yml --check --diff --limit SW1

Run it in the change ticket and in CI. A playbook that shows changed in check mode on an unchanged device has an idempotency bug.

Traps

  • Writing no shutdown with ios_config and wondering why every run reports changed.
  • Treating changed=0 as proof of correct config. It only shows Ansible saw no difference in the lines it manages.
How did you do?