shellモジュールを使うときは必ず
-
check_mode: noをつける
システムに変更を伴わないコマンドの場合は
-
changed_when: noをつける -
failed_whenは実行するコマンドによって適切に設定する
システムに変更を伴うコマンドの場合は
- 実行したいコマンドの前に
test {{ansible_check_mode}} = False &&をつける -
register: resultをつけてfailed_when: ansible_check_mode==False and result.rc!=0とする
サンプル
以下は/tmp/tmpディレクトリがなかったら作成するというplaybookをshellモジュールだけで記述した例
- hosts: all
become: yes
tasks:
- name: check directory
shell: test -d /tmp/tmp
register: directory_exist
check_mode: no
failed_when: no
changed_when: no
- name: create directory
shell: "test {{ansible_check_mode}} = False && mkdir /tmp/tmp"
check_mode: no
register: result
failed_when: ansible_check_mode==False and result.rc!=0
when: directory_exist.rc == 1
解説
ansibleのshellモジュールは--checkをつけてdry runを実行するとskippedになってしまい、そのタスクが実行されるかどうかが判定できない。このshellモジュールで--checkだからskippedはwhenの条件より前に判定されるためwhenの条件が満たされているのかどうかも分からない。
このshellモジュールで--checkだからskippedという事象を回避するにはcheck_mode:noをつけるしかない。なのでまずcheck_mode:noは必須。
そしてshellモジュールでchech_mode:noの時の結果だが、これは必ずchengedになる。cheangedになってほしいのはシステムに変更が伴うコマンドを実行するときなので、システムに変更が伴わないコマンドの場合はchanged_when: noをつけて結果をokにする。
しかし、check_mode:noにしてしまうと--checkの場合でもコマンドが実行されてしまいシステムに変更が加えらる可能性がある。これではdry runにならない。なのでシステムに変更を伴うコマンドを実行したい場合はコマンドを実行するかどうかをshellモジュールのコマンドの中で判定する。それがtest {{ansible_check_mode}} = False &&をコマンドの最初につけることだ。check_mode:noとしても--checkで実行した場合はansible_check_modeはTrueになるのでdry runの時は以降のコマンドは実行されない。
ただし、このままだと--checkの時はコマンド結果が必ず失敗になるのでfiled_whenで--checkの時は失敗判定しないようにする。