Idempotent shell command in Ansible
Ever wanted to make your command
or shell
call in Ansible playbook idempotent and avoid those nasty yellow changed
lines in run logs? Wait no more! Here's bash
trick for you:
- name: Put docker package on hold
shell: >
apt-mark showholds | grep -q docker-ce
&& echo -n HOLDED
|| apt-mark hold docker-ce
register: docker_hold
changed_when: docker_hold.stdout != 'HOLDED'
What do we do here?
-
We execute "check" command
apt-mark showholds | grep -q docker-ce
.
Because of quietgrep
, this command does not print anything, but exits with zero-code ifdocker-ce
is already on hold or with non-zero-code ifdocker-ce
is not found in the list of frozen packages. -
Next we use shell control operator
&&
– this ensures thatecho -n HOLDED
is executed if and only if previous command has zero exit code (package is already on hold). -
Next we use shell control operator
||
– this ensures thatapt-mark hold docker-ce
is executed if and only if previous command has non-zero exit code (package not found in a list of frozen packaged).
So it's a kind of if (test) then (skip) else (do things)
statement.
This will prevent unnecessary command execution if test passes, and also signals to Ansible that nothing changed.