Ansibleで、通常実行でもCheck modeでもきちんとエラーを吐かずに動くようにするためには、エラーハンドリングが必須になる。
#ignore_errors
ignore_errosをyesにすると、そのタスクでエラーが発生しても無視して次のタスクに進むことができる。
コマンドの実行結果を確認したい時などに使える。
- name: 必ず失敗するタスク
command: /bin/false
ignore_errors: yes
- debug:
msg: '手前のタスクが失敗しても、無視して次に進む'
RECAPではignoredにカウントされ、okにはならない。
PLAY RECAP *************************************************************************************************************
192.168.1.2 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=1
#changed_when
これを使うと、モジュール本来のchangedステータスを上書きすることができる。
- name: 必ず失敗するタスク
command: /bin/false
changed_when: no
これの実行結果は常にok
だ。
#failed_when
これもchanged_whenに似ていて、モジュール本来のfailedステータスを上書きすることができる。
- name: 必ず失敗するタスク
command: /bin/false
failed_when: no
上のコードはignore_errorsと似ているように思えるが、ignore_errorsがRECAPでignoredにカウントされるのに対し、上記の場合はokとカウントされる。
PLAY RECAP *************************************************************************************************************
192.168.1.2 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
#check_mode
バージョン2.2からdeprecatedになったalways_run
に代わって推奨されているオプション。
これは少しややこしいが、以下のような動作になる。
check_mode: yes
の場合、--checkオプションがつけられていない場合でも常にdry runになる。
check_mode: no
の場合、--checkオプションがつけらている場合でも常に通常実行になる。
noにする時は、事故が起きないように気を付けよう。
#block~rescue
これはプログラミング言語でいうtry~catchに近い。
エラーが発生しても全体を強制終了させることなく継続させることができる。
tasks:
- name: Handle the error
block:
- debug:
msg: 'ここは実行されます'
- name: 必ず失敗するタスク
command: /bin/false
- debug:
msg: '手前のタスクがfailになるので、このタスクまでは到達しません'
rescue:
- debug:
msg: 'タスクが失敗した場合、ここが実行されます'
#check modeにおけるshell/commandの挙動について
check modeで実行した場合、commandモジュールやshellモジュールは無条件でskippedのステータスになる仕様のようだ。
これはchanged_whenなどで上書きすることはできない。
このことはAnsibleの公式ドキュメントにも以下のように書かれている。
冪等性を担保したい時はCreate/Removeオプションを使えとのこと。
Check mode is supported when passing creates or removes. If running in check mode and either of these are specified, the module will check for the existence of the file and report the correct changed status. If these are not supplied, the task will be skipped.
例で示すと、以下のようなPlaybookをcheck modeで実行した時、2番目のタスクはwhenの内容に関わらず常にskippedになってしまう。
これだと、2番目のタスクが実際に実行されるかを事前に確認することができない。(Playbookを目で追えば分かるが)
tasks:
- name: 何かコマンドを実行
shell: /bin/some/command/a
register: result
check_mode: no
- name: 前のコマンドが失敗した時だけ実行するコマンド
shell: /bin/some/command/b
when: not result.rc == 0
shellやcommandは通常実行した時は常にchangedになるのだから、check modeにおいても常にchangedになるべきでは?と思うのだが、何か意図があるのだろうか。
同じことを疑問に思っている人はこことか、ここで見つけたが、どちらも結局解決はしていないようだ。
うまいやり方を知っている人は教えてください。
###参考URL
https://docs.ansible.com/ansible/latest/user_guide/playbooks_error_handling.html
https://docs.ansible.com/ansible/latest/user_guide/playbooks_checkmode.html