はじめに
Ansible には、値が期待したした条件を満たすかどうかをチェック assert
モジュールがあります(標準モジュール)。
基本的には、assert 結果が fail だとその時点で Playbook の処理が中止されます。
一方で、1つ fail しただけで止めるのではなく、いくつかの assert を一通り実行しそれらの結果がすべて success なら success としたい場合もあるのではないでしょうか。
ignore_errors
を併用すると実現できます。 この記事では簡単なサンプルでご紹介します。
(もっといい方法があるかも知れません)
- 動作確認環境
- ansible-base 2.10.1
サンプル Playbook
2つの 個別の assert があります。fail しても中止しないように、ignore_errors: true
を指定します。(タスクごとに指定するのが面倒の場合は block で囲って指定)
また、あとで、assert 結果を参照できるように、個別の assert には register
で結果を受け取るようにします。
ここでは 1つめの assert が fail するようにしています。
--- - hosts: all gather_facts: false tasks: - name: assert 1 # 個別 assert assert: that: 1 == 0 # fail する ignore_errors: true register: res_assert1 - name: assert 2 # 個別 assert assert: that: 2 == 2 ignore_errors: true register: res_assert2 - name: all assert assert: that: # 複数指定で and 条件 - not res_assert1.failed # fail - not res_assert2.failed # success - name: Finished debug: msg: Finished!
実行1(failパターン)
まずは、1つめの assert が fail するパターンです。
実行
$ ansible-playbook -i localhost, assert.yml PLAY [all] ********************************************************************************************************** TASK [assert 1] ***************************************************************************************************** fatal: [localhost]: FAILED! => { "assertion": "1 == 0", "changed": false, "evaluated_to": false, "msg": "Assertion failed" } ...ignoring TASK [assert 2] ***************************************************************************************************** ok: [localhost] => { "changed": false, "msg": "All assertions passed" } TASK [all assert] *************************************************************************************************** fatal: [localhost]: FAILED! => { "assertion": "not res_assert1.failed", "changed": false, "evaluated_to": false, "msg": "Assertion failed" } PLAY RECAP ********************************************************************************************************** localhost : ok=2 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=1
中断せずに 2つめに assert しているのが分かります。また、2つの結果をまとめて assert するタスク「all assert」では fail していることが分かります。
実行2 (successパターン)
1つめの assert の条件を以下のようにして、success になるようにして再実行します。
- name: assert 1 # 個別 assert assert: that: 1 == 1 # ★修正 ignore_errors: true register: res_assert1
実行
$ ansible-playbook -i localhost, assert.yml PLAY [all] ********************************************************************************************************** TASK [assert 1] ***************************************************************************************************** ok: [localhost] => { "changed": false, "msg": "All assertions passed" } TASK [assert 2] ***************************************************************************************************** ok: [localhost] => { "changed": false, "msg": "All assertions passed" } TASK [all assert] *************************************************************************************************** ok: [localhost] => { "changed": false, "msg": "All assertions passed" } TASK [Finished] ***************************************************************************************************** ok: [localhost] => { "msg": "Finished!" } PLAY RECAP ********************************************************************************************************** localhost : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
個別の assert もまとめの assert も success となり、最後の debug タスクも実行されました。
応用
再 assert ではなく、結果を一覧で 表示する場合は、タスク all assert
の代わりに以下のようにします。
- name: assert results debug: msg: - "{{ res_assert1 }}" - "{{ res_assert2 }}"
実行結果(抜粋)
TASK [assert results] *************************************************************************************************** ok: [localhost] => { "msg": [ { "assertion": "1 == 0", "changed": false, "evaluated_to": false, "failed": true, "msg": "Assertion failed" }, { "changed": false, "failed": false, "msg": "All assertions passed" } ] }
別解(loop
の活用)
今回のように、比較する値が予めすべて取り揃っている状態から assert する場合は、loop で回すという方法もあります。 loop で assert すると、一通り assert しつつも、1つでも fail になるとそのタスクが fail となります。
--- - hosts: all gather_facts: false tasks: - name: assert assert: that: "{{ item }}" loop: - 1 == 0 # fail - 2 == 2 # success - name: Finished debug: msg: Finished!
実行
$ ansible-playbook -i localhost, assert_loop.yml PLAY [all] ********************************************************************************************************** TASK [assert] ******************************************************************************************************* failed: [localhost] (item=1 == 0) => { "ansible_loop_var": "item", "assertion": "1 == 0", "changed": false, "evaluated_to": false, "item": "1 == 0", "msg": "Assertion failed" } ok: [localhost] => (item=2 == 2) => { "ansible_loop_var": "item", "changed": false, "item": "2 == 2", "msg": "All assertions passed" } PLAY RECAP ********************************************************************************************************** localhost : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0