• +43 660 1453541
  • contact@germaniumhq.com

Writing Repeatable (Idempotent) Plays in Ansible


Writing Repeatable (Idempotent) Plays in Ansible

At its core, Ansible is a declarative system. You describe the state in which you expect your parts of the system to be in, and Ansible, via its modules, tries to get the system there. That’s the reason why modules are idempotent. But how are we to approach simple shell executions?

If we have a shell (or command) execution, that’s always marking the step as changed, even if the step is not changing:

- name: Run a shell command
  shell: ls

One way is to mark the action that it doesn’t have any changes:

- name: Run a shell command
  shell: ls
  changed_when: false

But maybe this module actually has changes. For example running something like:

- name: Install nvm
  shell: wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash

This has changes. The problem with this step is that you need changes only if nvm is missing. If that’s the case, then simply leverage variable registration between the steps, and ignore errors if they happen. Using this simple pattern, allows keeping the Ansible play lean and mean:

- name: Check if nvm is installed
  shell: nvm --version
  register: nvm_version_cmd
  changed_when: false
  ignore_errors: true

- name: Install nvm
  shell: wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
  when: nvm_version_cmd is failed

Now nvm is only installed if it’s not already present. Otherwise no change is performed on the system.