備忘
課題: Ansibleにおいて、独立した複数要素を変化させるループをどうするか。
例えばxを[x0, x1]、yを[y0,y1], zを[z0,z1]の範囲で変化させるloopを考える。
素直な実装としては、x,y,zで3重loopで対応する方法が考えられる。
しかしAnsibleではblockに対するloopができない為、include_tasksにloopを適用することで多重ループに対応する必要がある。つまりtasksファイルを3つに分割しなければならず、可読性、メンテナンス性などに影響が生じる。
ソリューション: productフィルターにより1重ループにならす
productフィルターを用いて1重ループにならす事で対応できるケースがあると思われる。
task例
- debug:
var: item
loop: "{{ x|product(y,z) }}"
vars:
x: [x0, x1]
y: [y0, y1]
z: [z0, z1]
- 2次元ならばx|product(y)で良い
- 次元を増やすにはproductフィルターに与えるlistを増やす
実行ログ例
TASK [debug] ********************************************************************************************************
ok: [localhost] => (item=['x0', 'y0', 'z0']) => {
"ansible_loop_var": "item",
"item": [
"x0",
"y0",
"z0"
]
}
ok: [localhost] => (item=['x0', 'y0', 'z1']) => {
"ansible_loop_var": "item",
"item": [
"x0",
"y0",
"z1"
]
}
ok: [localhost] => (item=['x0', 'y1', 'z0']) => {
"ansible_loop_var": "item",
"item": [
"x0",
"y1",
"z0"
]
}
ok: [localhost] => (item=['x0', 'y1', 'z1']) => {
"ansible_loop_var": "item",
"item": [
"x0",
"y1",
"z1"
]
}
ok: [localhost] => (item=['x1', 'y0', 'z0']) => {
"ansible_loop_var": "item",
"item": [
"x1",
"y0",
"z0"
]
}
ok: [localhost] => (item=['x1', 'y0', 'z1']) => {
"ansible_loop_var": "item",
"item": [
"x1",
"y0",
"z1"
]
}
ok: [localhost] => (item=['x1', 'y1', 'z0']) => {
"ansible_loop_var": "item",
"item": [
"x1",
"y1",
"z0"
]
}
ok: [localhost] => (item=['x1', 'y1', 'z1']) => {
"ansible_loop_var": "item",
"item": [
"x1",
"y1",
"z1"
]
}
- 各要素はitem[0], item[1], item[2]などとして参照可能
注意/制約
- 要素が独立していないケースでは使用できない
- blockに対する操作では無いので、複数タスクに対して行うには、以下の様な対応が必要
- それぞれのtaskでloopを行う
- include_tasksに対するloopとする
- この場合、1回のファイル分離が必要。(なお、多重ループによる実装では、ループ毎にファイル分離が必要なので、それよりは少なくて済む)