Write an idempotent Ansible playbook

short · 35 min · Objective 4.1

Task

Write a playbook that configures a service, and prove the property that distinguishes configuration management from a script: running it twice changes nothing the second time. Then break idempotence deliberately with the command module and see the difference.

Steps

  1. Write an inventory with one host (localhost is fine) grouped as web.
  2. Write a playbook that installs a web server, deploys a config from a template, and enables and starts the service -- using the package, template and service modules, each declaring desired STATE.
  3. Run it and read the PLAY RECAP: note changed= on the first run.
  4. Run it again unchanged and confirm the recap shows changed=0. This is idempotence, and it is what lets the playbook be re-run safely at any time.
  5. Break it: replace the service task with a command: systemctl restart task. Run twice and observe it reports changed every time, because a bare command cannot know whether it changed anything.
  6. Restore the module version. Use --check --diff to preview what a run WOULD change without changing it, and confirm the preview is accurate.
  7. Use a when: condition on a gathered fact so one task runs only on the right OS family, and confirm it skips elsewhere.

Verify

ansible-playbook -i inventory site.yml | tee run1.txt
ansible-playbook -i inventory site.yml | tee run2.txt
grep -q 'changed=0' run2.txt && echo "idempotent: second run changed nothing"
ansible-playbook -i inventory site.yml --check --diff | grep -qi 'changed\|ok' && echo "check mode works"

changed=0 on the second run is the whole point. A playbook that reports changes every time it runs -- as the command version does -- has lost the property that makes --check meaningful and makes it safe to run from automation.

Notes

Prefer a module to command or shell for exactly this reason: a module declares state and reports truthfully whether it changed anything, while a bare command runs every time and always claims to have changed something. The --check preview is only trustworthy because the modules are honest about change.