ansibleでの実行結果のsuccess/failedとignore_errors/failed_whenがよくわからなかったので調べてみた

More than 3 years have passed since last update.


知りたいこと


  • 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されています。つまりresultfailedだったってことですね。

ということは、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とはいえない)けど、resultfailedなのでdebugは実行される

...あれ、頭がこんがらがってきた。