Ansible: Playbookの繰り返し制御の色々 (5)
今回もAnsible
のPlaybook
における繰り返し制御について、学んでいきます。
引き続き題材は本家のドキュメントから。
Ansible Documentation > Playbooks > Loops
シリーズはこちら。
https://blog.tacck.net/ansible-documents-translate/ansible-loops
Looping Over A List With An Index
こちらも「滅多に使わないんじゃない?」という注意書きのあるものです。 ループを利用する際に、配列の数値の添え字を取り出せるよ、ということだそうです。
実際に見てみましょう。
- hosts: 127.0.0.1
connection: local
vars:
some_list: [ 'item1', 'item2' ]
tasks:
- name: indexed loop demo
debug:
msg: "at array position {{ item.0 }} there is a value {{ item.1 }}"
with_indexed_items:
- "{{ some_list }}"
with_indexed_items
を使って書くと、 item.0
で添え字を取り出せます。
PLAY [127.0.0.1] ***************************************************************
TASK [setup] *******************************************************************
ok: [localhost]
TASK [indexed loop demo] *******************************************************
ok: [localhost] => (item=(0, u'item1')) => {
"item": [
0,
"item1"
],
"msg": "at array position 0 there is a value item1"
}
ok: [localhost] => (item=(1, u'item2')) => {
"item": [
1,
"item2"
],
"msg": "at array position 1 there is a value item2"
}
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0
Using ini file with a loop
続いては、 ini
形式のファイルをループとして使う方法です。 ini
内のキーを正規表現で取り出して使えるようです。
こちらは、具体的なところが本家のドキュメントに記載されています。
まずは、iniファイル。
[section1]
value1=section1/value1
value2=section1/value2
[section2]
value1=section2/value1
value2=section2/value2
そして、Ansible Playbook。
- debug:
msg: "{{ item }}"
with_ini:
- value[1-2]
- section: section1
- file: "lookup.ini"
- re: true
これらを揃えて、実行した結果が下記となるようです。
{
"changed": false,
"msg": "All items completed",
"results": [
{
"invocation": {
"module_args": "msg=\"section1/value1\"",
"module_name": "debug"
},
"item": "section1/value1",
"msg": "section1/value1",
"verbose_always": true
},
{
"invocation": {
"module_args": "msg=\"section1/value2\"",
"module_name": "debug"
},
"item": "section1/value2",
"msg": "section1/value2",
"verbose_always": true
}
]
}
iniファイル内の section1
の中の、さらにキー名を value[1-2]
という正規表現で取り出していますね。
Flattening A List
タイトルを訳すと「リストの平坦化」といった意味になります。 あまり伝わってこないので、実際に確かめてみます。
ドキュメント内にある例を、実際にAnsible Playbookにしてみます。
- hosts: 127.0.0.1
connection: local
vars:
packages_base:
- [ 'foo-package', 'bar-package' ]
packages_apps:
- [ ['one-package', 'two-package' ]]
- [ ['red-package'], ['blue-package']]
tasks:
- name: indexed loop demo
debug:
msg: "{{ item }}"
with_flattened:
- "{{ packages_base }}"
- "{{ packages_apps }}"
これを実行すると、下記となります。
PLAY [127.0.0.1] ***************************************************************
TASK [setup] *******************************************************************
ok: [localhost]
TASK [indexed loop demo] *******************************************************
ok: [localhost] => (item=foo-package) => {
"item": "foo-package",
"msg": "foo-package"
}
ok: [localhost] => (item=bar-package) => {
"item": "bar-package",
"msg": "bar-package"
}
ok: [localhost] => (item=one-package) => {
"item": "one-package",
"msg": "one-package"
}
ok: [localhost] => (item=two-package) => {
"item": "two-package",
"msg": "two-package"
}
ok: [localhost] => (item=red-package) => {
"item": "red-package",
"msg": "red-package"
}
ok: [localhost] => (item=blue-package) => {
"item": "blue-package",
"msg": "blue-package"
}
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0
このように、配列の構造に関わらずすべてを単純な一次元の配列として扱うようになります。 色々と集めた処理結果の配列を、構造を気にせずに一気に処理したい、、というような使い方だと使えるかも、、、といったところでしょうか。
Using register with a loop
次は、 register
を使って、ループの実行結果を変数内に results
属性として保存できるよ、というところです。
というわけで、ドキュメント内の例をベースに動きを確かめます。
- hosts: 127.0.0.1
connection: local
tasks:
- name: indexed loop demo
shell: "echo {{ item }}"
with_items:
- "one"
- "two"
register: echo
- name: result
debug:
msg: "{{ echo }}"
with_items
の直後に register
を記載しています。これで echo
という変数の中に結果が格納され、次の debug
で中身を確認できます。
動作結果も見てみましょう。
PLAY [127.0.0.1] **************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************
ok: [localhost]
TASK [indexed loop demo] ******************************************************************************************
changed: [localhost] => (item=one)
changed: [localhost] => (item=two)
TASK [result] *****************************************************************************************************
ok: [localhost] => {
"msg": {
"changed": true,
"msg": "All items completed",
"results": [
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": true,
"cmd": "echo one",
"delta": "0:00:00.005954",
"end": "2017-06-26 23:03:36.802751",
"invocation": {
"module_args": {
"_raw_params": "echo one",
"_uses_shell": true,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"warn": true
}
},
"item": "one",
"rc": 0,
"start": "2017-06-26 23:03:36.796797",
"stderr": "",
"stderr_lines": [],
"stdout": "one",
"stdout_lines": [
"one"
]
},
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": true,
"cmd": "echo two",
"delta": "0:00:00.006686",
"end": "2017-06-26 23:03:37.089991",
"invocation": {
"module_args": {
"_raw_params": "echo two",
"_uses_shell": true,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"warn": true
}
},
"item": "two",
"rc": 0,
"start": "2017-06-26 23:03:37.083305",
"stderr": "",
"stderr_lines": [],
"stdout": "two",
"stdout_lines": [
"two"
]
}
]
}
}
PLAY RECAP ********************************************************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0
with_items
で与えた二つの要素の実行結果が、配列で results
の中に格納されていますね。
また、 results
の結果も配列なので、その後にループの要素として利用できます。 ドキュメント内の例ですと、実行結果が失敗の場合の処理を判定するものになっています。
- name: Fail if return code is not 0
fail:
msg: "The command ({{ item.cmd }}) did not have a 0 return code"
when: item.rc != 0
with_items: "{{ echo.results }}"
また、最初の例ではループが全て終わってから結果を取り出していましたが、各要素ごとの結果を利用する例も記載されています。
- shell: echo "{{ item }}"
with_items:
- one
- two
register: echo
changed_when: echo.stdout != "one"
つまり、 changed_when
の呼ばれるタイミングでは、 変数 echo
の属性 stdout
には、要素一つずつの実行結果が格納されている、ということになりますね。
まとめ
今回も、複雑な動きや独特な取り扱いのものが多かったと思います。 こういうものでも、自分で動かしながら確かめることで、意味を理解しやすくなるのでは無いでしょうか。
次回が、繰り返し制御の最終回になるはずです!