Ansible: Playbookの繰り返し制御の色々 (4)
今回もAnsible
のPlaybook
における繰り返し制御について、学んでいきます。
引き続き題材は本家のドキュメントから。
シリーズはこちら。
目次
Do-Until Loops
今回は、今までの繰り返しの指定 with_*
という書き方でない繰り返し方です。
プログラムを書いている人には、動作の原理はわかりやすいと思いますが、 Do-Unitl
の形式での繰り返しとなります。
つまり、今までは “繰り返しを続ける条件” を書いてきたのですが、これは “繰り返しを終了する条件” を書くイメージとなります。
ドキュメントのサンプルを見てみましょう。
- action: shell /usr/bin/foo register: result until: result.stdout.find("all systems go") != -1 retries: 5 delay: 10
ここでは、
shell /usr/bin/foo
を実行。- その結果を
result
という変数に格納。 result
の中の標準出力(stdout)の中に “all systems go” が含まれているか確認。- 3.の確認結果、含まれていればそこで終了。
- 3.の確認結果、含まれていなければ再び1.からリトライ。この時
delay
秒待つ。 - リトライは
retries
回失敗したらそこで終了。
という動きになります。
また、 retries
はデフォルトで “3”、 delay
はデフォルトで “5”、となるようです。
タスク全体としての結果は、最後の実行結果が反映されます。
つまり、上記手順の “4.” で終了すれば “ok” に、 “6.” で終了すると “failed” になります。
リトライが行なわれている場合の、個々の実行結果を確認したい場合には ansible-playbook
コマンドを -vv
オプション付きで実行すると良さそうです。
また、この until
を利用した場合、 変数 result
には attempts
というキーが追加され、ここにリトライ回数が保持されるようです。
Finding First Matched Files
次は with_first_found
です。
これは、ドキュメントにもありますが「滅多に使わないんじゃない?」というもので、少し変わった使い方になります。
正確にはループでは無いのですが、連続して処理をするものなので、似たようなものではあります。
これも、ドキュメントの例を見ながら動きを解説してみます。
- name: INTERFACES | Create Ansible header for /etc/network/interfaces template: src: "{{ item }}" dest: "/etc/foo.conf" with_first_found: - "{{ ansible_virtualization_type }}_foo.conf" - "default_foo.conf"
こちらの例ですと、 with_first_found
に書かれた順にファイルを探して、最初に見つかったものを template
モジュールに適用する、という動作になります。
そのため、リストの最後に "default_foo.conf"
のようにデフォルトで適用するファイルを記載しておくことで、確実にタスクの実行を行なうことができるようになります。
また、これは files
paths
と組み合わせて複雑な条件でも実行できるようです。
- name: some configuration template template: src: "{{ item }}" dest: "/etc/file.cfg" mode: 0444 owner: "root" group: "root" with_first_found: - files: - "{{ inventory_hostname }}/etc/file.cfg" paths: - ../../../templates.overwrites - ../../../templates - files: - etc/file.cfg paths: - templates
完全に初見殺しの書き方になっていますね。
files
と paths
の動作についてはAnsible: Playbookの実行条件制御 when
の使い方(3) Selecting Files And Templates Based On Variablesに解説していますので、ご確認ください。
Iterating Over The Results of a Program Execution
こちらも「滅多に使わないんじゃない?」という注意書きのあるものです。
ここでは、「プログラムの実行結果をリストとして扱ってタスクを繰り返し実行する」というやり方が書かれています。
- name: Example of looping over a command result shell: "/usr/bin/frobnicate {{ item }}" with_lines: - "/usr/bin/frobnications_per_host --param {{ inventory_hostname }}"
この例ですと、inventory_hostname
に応じて実際に実行するコマンドのオプションを複数生成して繰り返し実行したい、という時に使えることになります。
何言ってんだ、って感じですね。
ちなみに、 frobnications_per_host
コマンドは “ローカルマシン”、 frobnicate
コマンドは “リモートマシン”、で実行されます。
このように、 inventory
に応じて処理分けをしたいならDynamic Inventoryを使った方が良いよ、とドキュメントには書かれています。
また、同じようなことをすべて “リモートマシン”のコマンドで実現する場合には、下記のような書き方になるようです。
- name: Example of looping over a REMOTE command result shell: "/usr/bin/something" register: command_result - name: Do something with each result shell: "/usr/bin/something_else --param {{ item }}" with_items: - "{{ command_result.stdout_lines }}"
まとめ
今回取り扱ったものは、だいぶ複雑でイマイチイメージの掴みづらいところだったように思います。
動作を試すのも結構準備が必要そうなので、複雑な繰り返し条件が必要になったときに思い出せるように記録を残しておく、、、という感じになりそうです。
めげずに、残りの項目も翻訳していきたいと思います。