Ansibleのincludeとloop_varで複数のタスクを適切な変数名でループする
渡辺です。
Ansibleのwit_items
のループは単一タスクしか繰り返すことができません。
今日は、複数のタスクをループさせる場合に役立つinclude
とloop_var
を紹介します。
with_itemsは単一タスクしかループできない
例えば、複数のシステムユーザを作成する時、ユーザ毎にタスクを作成したならば、ユーザ数のタスクが必要です。 可読性が悪いだけでなく、コピペの弊害は修正作業に大きな影響を与えます。
- debug: msg: "user=user1" - debug: msg: "user=user2"
このような場合、Ansibleでは with_items
を使うことでタスクを複数回実行できます。
- debug: msg: "user={{ item.name }}" with_items: - user1 - user2
ところが、with_items
は単一タスクをループするため、複数のタスク、例えばユーザ作成とグループ作成をループさせることはできません。
このため、ループをタスクの数だけ行うことになります。
- name: user debug: msg: "user={{ item.name }}" with_items: - name: user1 group: A - name: user2 group: B - name: groups debug: msg: "group={{ item.group }}" with_items: - name: user1 group: A - name: user2 group: B
変数はvars
などに追い出せますが、いけてません。
次のようなイメージで定義できると幸せになれます。
# ここから - name: user debug: msg: "user={{ item.name }}" - name: groups debug: msg: "group={{ item.group }}" # ここまでをループさせたい with_items: - name: user1 group: A - name: user2 group: B
複数のタスクをループさせたい場合includeを利用する
include
は外部ファイルに定義されたタスクを取り込む機能です。
Playbookが肥大化してきた時にファイルを分割するために利用したり、検証環境と本番環境で異なるタスクを実行させた場合に利用することができます。
- include: inner-tasks.yml
include
するファイルにはタスクを定義します。
# inner-tasks.yml - debug: msg: "Hello" - debug: msg: "World"
include
もまたwith_items
でループ可能です。
したがって、次のように記述すればinner-tasks.yml
が2回実行されます。
- include: inner-tasks.yml with_items: - hoge - huga
ループ変数はitem
で参照できます。
次のように書き換えれば、ループ変数を利用できるでしょう。
# inner-tasks.yml - debug: msg: "Hello" - debug: msg: "{{ item }}"
しかし、include
されるファイルでitem
は変数名としていけてません。
ループ時の変数を定義するloop_var
loop_control
のloop_var
を利用すると、ループ時の変数を制御可能です。
- include: inner-tasks.yml with_items: - hoge - huga loop_control: loop_var: user
これでitem
ではなくuser
を変数名として利用可能です。
# inner-tasks.yml - debug: msg: "Hello" - debug: msg: "{{ user }}"
まとめ
include
とloop_var
を利用することで、複数のタスクを適切な変数名でループさせることができます。
PlaybookやRoleの可読性向上には必須テクニックなので必ず覚えておきましょう。
最後にサンプルコードです。
--- # loop_control.yml.yml - hosts: localhost connection: local gather_facts: False tasks: - include: inner.yml with_items: - name: user1 group: A - name: user2 group: B loop_control: loop_var: user
--- # inner.yml - name: user debug: msg: "user={{ user.name }}" - name: group debug: msg: "group={{ user.group }}"