さまざまな事情があって、Ansibleでシェルスクリプトを1つのtaskとして実行したくなったり、コマンドのreturn codeに応じて処理を分岐したりしたくなると思います。
itamaeなら execute
や not_if
で実現できるのですが、同じことをAnsibleでやろうとして手間がかかったので記録しておきます。
シェルスクリプトを実行する
shell
リソースでコマンドを実行することができます。
さらに、YAMLでは複数行の文字列を書くことができるので、次のように書くことができます。
- shell: VAR=`command_expand` command1; command2; command3
注意点としては、複数行のコマンドを入力しても一度に実行されるので、シェルスクリプトと異なりコマンド区切りの ;
が必要です。
あまり検証していませんが、POSIXに準拠しているシェルスクリプトなら対応しているのではないでしょうか。
コマンドのreturn codeを取得する
shell
リソースでコマンドを実行することができるので、その結果を変数に格納すればreturn codeが取れそうだなということをすぐに思いつくと思います。
たとえば次のように書けそうです。
- shell: which hoge register: check_result
しかしこれだけでは、 which hoge
のreturn codeが0でない場合にfailになります。
この場合ではfailになりうることは分かっていて、我々はreturn codeを使って分岐したいのです。
ここではfailを無視するために ignore_errors: yes
を追加します。
- shell: which hoge register: check_result ignore_errors: yes
これでめでたく which hoge
のreturn codeを check_result.rc
で取得できるようになりました、といきたいところですが、まだあります。
このtaskは、check modeのときは実行されません。
したがって check_result
という変数が定義されないので、これ以降のtaskで check_result
を参照するとエラーで落ちます(!)。
check_mode: no
を追加してやればcheck modeでも実行が強制されるので、 check_result
を参照できるようになります。
- shell: which hoge register: check_result ignore_errors: yes check_mode: no
組み合わせる
- shell: which hoge register: check_result ignore_errors: yes - shell: VAR=`command_expand` command1; command2; command3 when: check_result.rc != 0
これで execute
と not_if
のようなことができるようになりました。よかったですね。もうちょっと楽に書けないものか。
参考
- itamaeのwiki
- Ansibleのドキュメント
- https://docs.ansible.com/Ansible/latest/modules/shell_module.html
- https://docs.ansible.com/Ansible/latest/user_guide/playbooks_variables.html
- https://docs.ansible.com/Ansible/latest/user_guide/playbooks_conditionals.html
- https://docs.ansible.com/Ansible/latest/user_guide/playbooks_error_handling.html
- https://docs.ansible.com/Ansible/latest/user_guide/playbooks_checkmode.html