■ はじめに
ループするためにリストの変数を渡すときに、以下の2パターンを特に区別なく使ってしまうことがあります(私が)。
- pattern1
- name: pattern1 debug: msg: "{{ item }}" with_items: "{{ test_list }}" # ここにリストの変数を渡す
- pattern2
- name: pattern2 debug: msg: "{{ item }}" with_items: - "{{ test_list }}" # ここにリストの変数を渡す
どちらも結果は同じなのですが、内部の挙動が異なります。
この記事では、簡単な例で違いを説明します。
■ 動作確認
Playbook
以下のパターンのタスクを準備します。
| pattern | 説明 |
|---|---|
| pattern1 | with_items に直接リストを指定 |
| pattern2 | with_items の最初の要素にリストを指定 |
| pattern3 | loop に直接リストを指定 |
| pattern4 | loop の最初の要素にリストを指定 |
この中で一つだけ結果が異なるパターンがあります。
- hosts: localhost gather_facts: no vars: test_list: # ループに使うリストの変数 - a - b - c tasks: - name: pattern1 debug: msg: "{{ item }}" with_items: "{{ test_list }}" - name: pattern2 debug: msg: "{{ item }}" with_items: - "{{ test_list }}" - name: pattern3 debug: msg: "{{ item }}" loop: "{{ test_list }}" - name: pattern4 debug: msg: "{{ item }}" loop: - "{{ test_list }}"
実行結果
実行して確認します。
$ ansible-playbook -i localhost, looplist.yml
PLAY [localhost] ************************************************************
TASK [pattern1] ************************************************************
ok: [localhost] => (item=a) => {
"msg": "a"
}
ok: [localhost] => (item=b) => {
"msg": "b"
}
ok: [localhost] => (item=c) => {
"msg": "c"
}
TASK [pattern2] ************************************************************
ok: [localhost] => (item=a) => {
"msg": "a"
}
ok: [localhost] => (item=b) => {
"msg": "b"
}
ok: [localhost] => (item=c) => {
"msg": "c"
}
TASK [pattern3] ************************************************************
ok: [localhost] => (item=a) => {
"msg": "a"
}
ok: [localhost] => (item=b) => {
"msg": "b"
}
ok: [localhost] => (item=c) => {
"msg": "c"
}
TASK [pattern4] ************************************************************
ok: [localhost] => (item=[u'a', u'b', u'c']) => {
"msg": [
"a",
"b",
"c"
]
}
PLAY RECAP ******************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0
解説
pattern1 -3 が一次元のリストとしてループしたのに対して、pattern4 だけ二次元のリストとしてループしました。
pattern4 では、リスト0番目の要素に ["a", "b", "c"] というリストが入っている状態です。
patterm 2 も構造上は二次元のリストですが、with_times がループ時に事前に、一次元のリストに flatten します。その結果、pattern1 や 3 と同じ結果になります。
with_itemsとloopの違いについての参考
■ まとめ
with_items を利用したループにおいて、同じ結果でも内部の挙動が異なる点をご紹介しました。
loop との違いや、リストが意図した通りに処理されているかは意識したほうが良いと思いました。