Ansible: Playbookの実行条件制御 `when` の使い方(2)
前回に引き続き、今回も Playbook でのタスク制御を行なう when
の使い方を勉強していきます。
題材は、引き続き本家のドキュメント。
Ansible Documentation > Playbooks > Conditionals
前回の記事はこちら。
https://blog.tacck.net/archives/101
Loops and Conditionals
ループと条件式、ということで、 when
で指定したものでループの制御を行なうところです。
tasks:
- command: echo {{ item }}
with_items: [ 0, 2, 4, 6, 8, 10 ]
when: item > 5
Ansible Playbook では、 with_items
を指定することで command
を繰り返し実行できますが、 when
の指定によって実行するものを調整することができるようです。 実際に実行した結果は、下記のように表示されます。
TASK [command] *****************************************************************
skipping: [server1] => (item=0)
skipping: [server1] => (item=2)
skipping: [server1] => (item=4)
changed: [server1] => (item=6)
changed: [server1] => (item=8)
changed: [server1] => (item=10)
5未満の数字は skipping
となり、タスク実行がスキップされていることがわかります。
次に、リストと辞書形式リストで繰り返しをするパターンの例が書かれています。 ドキュメントだけだとイマイチ掴めなかったので、実際にリストなどを定義した Playbook を書いて確かめてみました。
- hosts: all
vars:
mylist: [ 0, 2, 4, 6, 8, 10 ]
mydict:
a: 0
b: 2
c: 4
d: 6
e: 8
f: 10
tasks:
- command: echo {{ item }}
with_items: [ 0, 2, 4, 6, 8, 10 ]
when: item > 5
- command: echo {{ item }}
with_items: "{{ mylist | default([]) }}"
when: item > 5
- command: echo {{ item.key }}
with_dict: "{{ mydict | default({}) }}"
when: item.value > 5
こんな感じです。実行すると、下記のようになります。
TASK [command] *****************************************************************
skipping: [server1] => (item=0)
skipping: [server1] => (item=2)
skipping: [server1] => (item=4)
changed: [server1] => (item=6)
changed: [server1] => (item=8)
changed: [server1] => (item=10)
TASK [command] *****************************************************************
skipping: [server1] => (item=0)
skipping: [server1] => (item=2)
skipping: [server1] => (item=4)
changed: [server1] => (item=6)
changed: [server1] => (item=8)
changed: [server1] => (item=10)
TASK [command] *****************************************************************
skipping: [server1] => (item={'key': u'a', 'value': 0})
skipping: [server1] => (item={'key': u'c', 'value': 4})
skipping: [server1] => (item={'key': u'b', 'value': 2})
changed: [server1] => (item={'key': u'e', 'value': 8})
changed: [server1] => (item={'key': u'd', 'value': 6})
changed: [server1] => (item={'key': u'f', 'value': 10})
mylist
mydict
を実際に定義して動かしてみると、きちんと動きました。 また、 mylist
などの横にある default
ですが、これは Jinja2 の filter 機能で、 “変数が未定義の場合の初期値” として動作するようです。 つまり、 mylist
mydict
が未定義だった場合でも動作するような書き方、ということですね。
Loading in Custom Facts
ここはちょっと(私には)難しいところでした。 書いてある意味は、わかるのですが。。。
tasks:
- name: gather site specific fact data
action: site_facts
- command: /usr/bin/thingy
when: my_custom_fact_just_retrieved_from_the_remote_system == '1234'
説明としては、自作のモジュール site_facts
を実行し、その中で定義された facts
である my_custom_fact_just_retrieved_from_the_remote_system
を when
の条件に使えるよ ( Playbook 内の変数だけじゃないよ ) 、、、というものです。
自分で facts
を定義する話については Developing Modules を参照してね、、、とあるので、そのうちモジュール作成についても勉強したいと思います。
Applying ‘when’ to roles and includes
次は、 roles
や include
にも when
が使えるよ、というところです。 これも動きはわかりましたが、説明で一部わからないところが。。。
ドキュメントと順番を変えますが、先に roles
の例から。
- hosts: webservers
roles:
- { role: debian_stock_config, when: ansible_os_family == 'Debian' }
これはみた通り、 OSが Debian
系ならこのロールが実行される、、、となりそうです。
次は、 include
の例。
- include: tasks/sometasks.yml
when: "'reticulating splines' in output"
when
にある英文は、そのまま使えるものじゃありません。 文章的に「ここに色々と条件書けるよ」という風な意味合いですかね。。。
また、ここの説明に「条件はすべてのタスクに適用される」という風に書かれています。 つまり、 include
の条件に適合しなかったタスク(上記だと tasks/sometasks.yml
に記載されているタスクたち)は、すべて評価された上でスキップになる、、、という風な意味合いのようですね。 実際に動かして確認してみます。
試した Playbook は下記。
- hosts: all
vars:
item: 4
tasks:
- include: playbook_task.yml
when:
- item > 5
- item < 10
- hosts: all
vars:
item: 6
tasks:
- include: playbook_task.yml
when:
- item > 5
- item < 10
- debug:
msg: "Debug:1 {{ item }}"
- debug:
msg: "Debug:2 {{ item }}"
条件が成立する変数と成立しない変数を用意して、同じタスクを実行するような感じです。 これの実行結果がこちらになります。
PLAY [all] *********************************************************************
TASK [setup] *******************************************************************
ok: [server1]
TASK [debug] *******************************************************************
skipping: [server1]
TASK [debug] *******************************************************************
skipping: [server1]
PLAY [all] *********************************************************************
TASK [setup] *******************************************************************
ok: [server1]
TASK [debug] *******************************************************************
ok: [server1] => {
"msg": "Debug:1 6"
}
TASK [debug] *******************************************************************
ok: [server1] => {
"msg": "Debug:2 6"
}
前半に skipping
が二つ、後半に ok
が二つ、それぞれありますね。 つまり条件に当てはまらない場合でも、全てのタスクを一度読み込んでスキップ処理を行なう、、、ということですね。 説明に書かれてあったことを、きちんと確認できました。
また、ドキュメントには「group_by
モジュールを使うと、もっと良い感じにできるよ」と書かれているので、こちらも勉強必要ですね。
まとめ
今回は、 when
の使い方の中盤でした。 書かれていることはわかるけど、徐々に複雑なものを取り扱う感じになってきています。 関連して学ぶ必要のあるところも出てきて、まだまだ奥が深いこともわかってきました。
次回で、 when
の使い方を一通り完了したいと思います!