プログラミングだとreturn
やexit(0)
などで、以降の処理が不要な場合に、その時点で処理を終了させることができる。
Ansibleのplaybookでも似たようなことができ、metaモジュールを使用し、任意のタイミングで処理を終了させるタスクを作成できる。
このモジュールはパラメタに指定するワードによっていろいろな動作を指せることができ、本エントリではend_play
とend_host
について説明する。
以下、ansible-core 2.12.2
で確認。
end_play
Playの実行をその時点で終了する。
--- - hosts: localhost gather_facts: false tasks: - name: task1 debug: msg: task1 - name: task2 debug: msg: task2 - name: end play ansible.builtin.meta: end_play - name: task3 debug: msg: task3
このplaybookの内容でAnsibleを実行すると、end play
タスクで処理が終了し、task3
は実行されない。
PLAY [localhost] **************************************************************** TASK [task1] ******************************************************************** ok: [localhost] => msg: task1 TASK [task2] ******************************************************************** ok: [localhost] => msg: task2 TASK [end play] ***************************************************************** PLAY RECAP ********************************************************************** localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
条件によって以降の全ての処理を丸ごとスキップしたい場合に使える。
end_host
end_play
が全処理を終了するのに対し、end_host
は指定ホストを対象とした処理のみその時点で終了する。
たとえば処理対象ホストにRHELホストとDebianホストがあり、Debianの場合は後続の処理が何もないので処理終了させて、RHELは続きの処理を行う、みたいなことができる。
--- - hosts: all gather_facts: true gather_subset: - min tasks: - name: task1 debug: msg: task1 - name: end host ansible.builtin.meta: end_host when: ansible_os_family == 'Debian' - name: task2 debug: msg: task2 - name: task3 debug: msg: task3
このplaybookの内容でAnsibleを実行すると、facts変数のansible_os_family
の値がDebian
のホストはend host
タスク以降の処理が行われず、それ以外のホストはtask2
・task3
と処理が継続する。
実行例の処理対象ホストは以下の通り。
host | distro |
---|---|
cheddar | Debian |
cloud-dev | CentOS |
これでansible-playbook
を実行すると以下の通り。
PLAY [all] ********************************************************************** TASK [Gathering Facts] ********************************************************** ok: [cheddar] ok: [cloud-dev] TASK [task1] ******************************************************************** ok: [cloud-dev] => msg: task1 ok: [cheddar] => msg: task1 TASK [end host] ***************************************************************** skipping: [cloud-dev] TASK [end host] ***************************************************************** TASK [task2] ******************************************************************** ok: [cloud-dev] => msg: task2 TASK [task3] ******************************************************************** ok: [cloud-dev] => msg: task3 PLAY RECAP ********************************************************************** cheddar : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 cloud-dev : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
(追記) 複数のPlayの場合
end_play
やend_host
でPlayが終了しても、後続のPlayがある場合は、そこからは処理が始まる。
--- - name: play1 hosts: localhost gather_facts: false tasks: - name: task1 debug: msg: task1 - name: task2 debug: msg: task2 - name: end play ansible.builtin.meta: end_play - name: task3 debug: msg: task3 - name: play2 hosts: localhost gather_facts: false tasks: - name: task1 debug: msg: task1
このようにplay1
のPlayがend_play
で終了した場合、task3
は処理されないがplay2
は処理が始まる。
実行結果は以下。
PLAY [play1] ******************************************************************** TASK [task1] ******************************************************************** ok: [localhost] => msg: task1 TASK [task2] ******************************************************************** ok: [localhost] => msg: task2 TASK [end play] ***************************************************************** PLAY [play2] ******************************************************************** TASK [task1] ******************************************************************** ok: [localhost] => msg: task1 PLAY RECAP ********************************************************************** localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
end_host
も同様。
--- - name: play1 hosts: all gather_facts: true gather_subset: - min tasks: - name: task1 debug: msg: task1 - name: end host ansible.builtin.meta: end_host when: ansible_os_family == 'Debian' - name: task2 debug: msg: task2 - name: task3 debug: msg: task3 - name: play2 hosts: all gather_facts: false tasks: - name: task1 debug: msg: task1
この内容のPlaybookで実行すると、play2
は全ホストで処理が開始する。
PLAY [play1] ******************************************************************** TASK [Gathering Facts] ********************************************************** ok: [cheddar] ok: [cloud-dev] TASK [task1] ******************************************************************** ok: [cloud-dev] => msg: task1 ok: [cheddar] => msg: task1 TASK [end host] ***************************************************************** skipping: [cloud-dev] TASK [end host] ***************************************************************** TASK [task2] ******************************************************************** ok: [cloud-dev] => msg: task2 TASK [task3] ******************************************************************** ok: [cloud-dev] => msg: task3 PLAY [play2] ******************************************************************** TASK [task1] ******************************************************************** ok: [cloud-dev] => msg: task1 ok: [cheddar] => msg: task1 PLAY RECAP ********************************************************************** cheddar : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 cloud-dev : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
後続のPlayは実行されるので、イメージとしてはexit()
ではなくreturn
だね。
when
を使ってスキップしてももちろん良いが、実行しない後続のタスク定義数が多い場合はend_hsot
でスパッと抜けるという実装もできる。
え、MISRA-C準拠で実装してる?playbookを?まさかそんな。。