知りたいこと
- ansibleでのsuccessとfailedの判定
- それをハンドリングするための ignore_errors と failed_when の使い方
事前実験
存在しないコマンドを実行してみる
ansibleでの接続先(リモートサーバー。CentOS6)で `sakaimo --version' コマンドしてみる。ちなみに現時点のsakaimoのversionは39.7くらいのはず。
# sakaimo --version
-bash: sakaimo: command not found
CentOSさんにはこんなコマンドは存在しないのでnot foundになります。
ansibleでやってみる
playbook
- shell: sakaimo --version
- debug: msg="debug"
実行結果
PLAY [app] ********************************************************************
TASK: [sakaimo| shell sakaimo --version] *************************************
failed: [qa-lecture01] => {"changed": true, "cmd": "sakaimo --version", "delta": "0:00:00.146319", "end": "2015-05-12 10:52:53.548610", "rc": 127, "start": "2015-05-12 10:52:53.402291", "warnings": []}
stderr: /bin/sh: sakaimo: command not found
FATAL: all hosts have already failed -- aborting
PLAY RECAP ********************************************************************
to retry, use: --limit @/root/qa-lecture-playbook.retry
qa-lecture01 : ok=0 changed=0 unreachable=0 failed=1
一つ目でエラーが出た場合に- debug: msg="debug"
は実行されていないことがわかります。しれっと「エラーが出た場合」と言っていますが、何がansibleで「エラー」と判定されるのかどうかを知りたくて調べてるんですけどねw
ignore_errors
ignore_errors
を付けてみる。
playbook
- shell: sakaimo --version
ignore_errors: True #←ここ
- debug: msg="debug"
出力結果
PLAY [app] ********************************************************************
TASK: [sakaimo | shell sakaimo --version] *************************************
failed: [qa-lecture01] => {"changed": true, "cmd": "sakaimo --version", "delta": "0:00:00.143888", "end": "2015-05-12 10:53:30.886426", "rc": 127, "start": "2015-05-12 10:53:30.742538", "warnings": []}
stderr: /bin/sh: sakaimo: command not found
...ignoring
TASK: [sakaimo | debug msg="debug"] ****************************************
ok: [qa-lecture01] => {
"msg": "debug"
}
PLAY RECAP ********************************************************************
qa-lecture01 : ok=2 changed=1 unreachable=0 failed=0
ignore_errors: True
では文字通りエラーがあっても無視して先にすすんでくれるようです。(debugが出力されているから) つまりcommand not found
はエラーとして認識されるみたいね。
実行結果によって分岐させてみる
when: result|failed
を付けてみた。
playbook
- shell: sakaimo --version
register: result
ignore_errors: True
- debug: msg="debug"
when: result|failed #←ここ
実行結果
PLAY [app] ********************************************************************
TASK: [sakaimo | shell sakaimo --version] *************************************
failed: [qa-lecture01] => {"changed": true, "cmd": "sakaimo --version", "delta": "0:00:00.142611", "end": "2015-05-12 11:00:33.019179", "rc": 127, "start": "2015-05-12 11:00:32.876568", "warnings": []}
stderr: /bin/sh: sakaimo: command not found
...ignoring
TASK: [sakaimo | debug msg="debug"] ****************************************
ok: [qa-lecture01] => {
"msg": "debug"
}
PLAY RECAP ********************************************************************
qa-lecture01 : ok=2 changed=1 unreachable=0 failed=0
failedをsuccessにしてみたplaybook
- shell: sakaimo --version
register: result
ignore_errors: True
- debug: msg="debug"
when: result|success #←ここ
実行結果
PLAY [app] ********************************************************************
TASK: [sakaimo | shell sakaimo --version] *************************************
failed: [qa-lecture01] => {"changed": true, "cmd": "sakaimo --version", "delta": "0:00:00.144219", "end": "2015-05-12 11:01:29.798585", "rc": 127, "start": "2015-05-12 11:01:29.654366", "warnings": []}
stderr: /bin/sh: sakaimo: command not found
...ignoring
TASK: [sakaimo | debug msg="debug"] ****************************************
skipping: [qa-lecture01]
PLAY RECAP ********************************************************************
qa-lecture01 : ok=1 changed=1 unreachable=0 failed=0
resultがfailedなので、debugがskipされています。ということはcommand not found
は'failed'と判定されるということね。
TASK: [sakaimo | debug msg="debug"] ****************************************
skipping: [qa-lecture01]
では成功するコマンドだったらどうなるのか。uname
コマンドで実験。
リモートサーバーでの実行結果は
# uname
Linux
になってます。
playbook
- shell: uname
register: result
ignore_errors: True
- debug: msg="debug"
when: result|success
実行結果
PLAY [app] ********************************************************************
TASK: [sakaimo | shell uname] *************************************************
changed: [qa-lecture01]
TASK: [sakaimo | debug msg="debug"] *******************************************
ok: [qa-lecture01] => {
"msg": "debug"
}
PLAY RECAP ********************************************************************
qa-lecture01 : ok=2 changed=1 unreachable=0 failed=0
successをfailedにしてみる
playbook
- shell: uname
register: result
ignore_errors: True
- debug: msg="debug"
when: result|failed #←ここ
実行結果
PLAY [app] ********************************************************************
TASK: [sakaimo | shell uname] *************************************************
changed: [qa-lecture01]
TASK: [sakaimo | debug msg="debug"] *******************************************
skipping: [qa-lecture01]
PLAY RECAP ********************************************************************
qa-lecture01 : ok=1 changed=1 unreachable=0 failed=0
これにより、unameでLinuxって返ってきてることはsuccessと判断されているってことね。
failed_when
どうやらfailed_when
は「こういう時はfailedにしてね」って感じのコマンドのようです。
ansible公式サイトより
例としてこんなんが載ってるので、
- name: this command prints FAILED when it fails
command: /usr/bin/example-command -x -y -z
register: command_result
failed_when: "'FAILED' in command_result.stderr"
私の例で言うと
- shell: sakaimo --version
register: result
failed_when: "'command not found' in result.stderr"
- debug: msg="debug"
標準エラー(stderr)に「command not found」っていう文字列が含まれていたらfailedとして判定してね、って指定しました。
実行結果
PLAY [app] ********************************************************************
TASK: [sakaimo | shell sakaimo --version] *************************************
failed: [qa-lecture01] => {"changed": true, "cmd": "sakaimo --version", "delta": "0:00:00.139589", "end": "2015-05-12 12:07:03.049756", "failed": true, "failed_when_result": true, "rc": 127, "start": "2015-05-12 12:07:02.910167", "stdout_lines": [], "warnings": []}
stderr: /bin/sh: sakaimo : command not found
FATAL: all hosts have already failed -- aborting
PLAY RECAP ********************************************************************
to retry, use: --limit @/root/qa-lecture-playbook.retry
qa-lecture01 : ok=0 changed=0 unreachable=0 failed=1
うん、想定通りエラーになりました。そしてエラーになって処理が止まっているので、debugは出力されていません。
では今度は実行結果にerrorrrrr
っていう文字列があったらfailedにするようにしてみます。
- shell: sakaimo --version
register: result
failed_when: "'errorrrrr'in result.stderr"
- debug: msg="debug"
にした場合、
PLAY [app] ********************************************************************
TASK: [sakaimo | shell sakaimo --version] *************************************
changed: [qa-lecture01]
TASK: [sakaimo | debug msg="debug"] *******************************************
ok: [qa-lecture01] => {
"msg": "debug"
}
PLAY RECAP ********************************************************************
qa-lecture01 : ok=2 changed=1 unreachable=0 failed=0
となりました。errorrrrr
は(リモートサーバーから)出力されていないので success
とみなされfailed
ではないとみなされ、次の処理に進んでdebugも表示されています。
ではwhen: result|success
を追加したらどうでしょうか。
- shell: sakaimo --version
register: result
failed_when: "'errorrrrr'in result.stderr"
- debug: msg="debug"
when: result|success #←ここ
PLAY [app] ********************************************************************
TASK: [sakaimo | shell sakaimo --version] *************************************
changed: [qa-lecture01]
TASK: [sakaimo | debug msg="debug"] *******************************************
skipping: [qa-lecture01]
PLAY RECAP ********************************************************************
qa-lecture01 : ok=1 changed=1 unreachable=0 failed=0
debug
がskipされています。つまりresult
はfailed
だったってことですね。
ということは、failed_when
を使って「こういう時はfailedにしてね」という指定はできるけれども、これは「それ以外のときはsuccsess
だよ」という指定ではないってことですよねあたりまえかw
ためしに
- shell: sakaimo --version
register: result
failed_when: "'errorrrrr'in result.stderr"
- debug: msg="debug"
when: result|failed #←ここを変えた
にして実行したら
PLAY [app] ********************************************************************
TASK: [sakaimo | shell sakaimo --version] *************************************
changed: [qa-lecture01]
TASK: [sakaimo | debug msg="debug"] *******************************************
ok: [qa-lecture01] => {
"msg": "debug"
}
PLAY RECAP ********************************************************************
qa-lecture01 : ok=2 changed=1 unreachable=0 failed=0
になりました。
ということは
- shell: sakaimo --version
register: result
failed_when: "'errorrrrr'in result.stderr"
- debug: msg="debug"
when: result|failed #←ここを変えた
において、
-
sakaimo --version
のリモートサーバーでの実行結果は-bash: sakaimo: command not found
- だから
result
にはfailed
が入る (when: result|failed
がtrue判定されてdebugが出力されているから) - なんだけど
failed_when: "'errorrrrr'in result.stderr"
でfailedの条件を指定してしまっている - だからこの3行全体での処理結果としては「failedじゃない」(successとはいえない)けど、
result
はfailed
なのでdebugは実行される
...あれ、頭がこんがらがってきた。