
Ansibleのincludeとloop_varで複数のタスクを適切な変数名でループする
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
渡辺です。
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 }}"








