Ansible: 2つのリストの組み合わせを処理する
はじめに
Playbookを書いていると多次元のデータをループさせて処理させる場合がよくあります。
以下のようなデータ構造を考えてみます。
people: - taro - jiro - saburo sports: - soccer - baseball - bascketball
上記の2つのリストを使って、 <who> likes <sport>
のような文字列の組み合わせをそれぞれ出力したいとします。
多重ループ
loop
を利用して多重ループを構成する場合は内側のループを構成するタスクを別ファイルに分けて、外側のループから include_task
を使って呼び出します。
site_doubleloop.yml
--- - name: Process data with double loop hosts: localhost vars: people: - taro - jiro - saburo sports: - soccer - baseball - bascketball tasks: - name: Outer loop call inner loop include_tasks: "inner_loop.yml" loop: "{{ people }}" loop_control: loop_var: person
inner_loop.yml
--- - name: Output debug: msg: "{{ person }} likes {{ sport }}" loop: "{{ sports }}" loop_control: loop_var: sport
TASK [Output] ******************************************************* ok: [localhost] => (item=soccer) => { "msg": "taro likes soccer" } ok: [localhost] => (item=baseball) => { "msg": "taro likes baseball" } ok: [localhost] => (item=bascketball) => { "msg": "taro likes bascketball" } TASK [Output] ******************************************************* ok: [localhost] => (item=soccer) => { "msg": "jiro likes soccer" } ok: [localhost] => (item=baseball) => { "msg": "jiro likes baseball" } ok: [localhost] => (item=bascketball) => { "msg": "jiro likes bascketball" } TASK [Output] ******************************************************* ok: [localhost] => (item=soccer) => { "msg": "saburo likes soccer" } ok: [localhost] => (item=baseball) => { "msg": "saburo likes baseball" } ok: [localhost] => (item=bascketball) => { "msg": "saburo likes bascketball" }
filter を使ってデータを合成する
リストの直積を生成する product
フィルタを利用します。前の方法と違い、タスクファイルを分ける必要がないためロジックがシンプルになります。
site_singleloop_with_product_filter.yml
- name: Process 2 lists data with product filter hosts: localhost vars: people: - taro - jiro - saburo sports: - soccer - baseball - bascketball tasks: - name: Generate product of the lists ansible.builtin.set_fact: _pdct: "{{ people | product(sports) }}" - name: Output them ansible.builtin.debug: var: _pdct - name: Generate Strings with the product debug: msg: "{{ item[0] }} likes {{ item[1] }}" loop: "{{ _pdct }}"
PLAY [Process 2 lists data with product filter] ************************************************************************************************************************************************************************************************************ TASK [Gathering Facts] ************************************************************************************************************************************************************************************************************************************* ok: [localhost] TASK [Generate product of the lists] *********************************************************************************************************************************************************************************************************************** ok: [localhost] TASK [Output them] ***************************************************************************************************************************************************************************************************************************************** ok: [localhost] => { "_pdct": [ [ "taro", "soccer" ], [ "taro", "baseball" ], [ "taro", "bascketball" ], [ "jiro", "soccer" ], [ "jiro", "baseball" ], [ "jiro", "bascketball" ], [ "saburo", "soccer" ], [ "saburo", "baseball" ], [ "saburo", "bascketball" ] ] } TASK [Generate Strings with the product] ******************************************************************************************************************************************************************************************************************* ok: [localhost] => (item=['taro', 'soccer']) => { "msg": "taro likes soccer" } ok: [localhost] => (item=['taro', 'baseball']) => { "msg": "taro likes baseball" } ok: [localhost] => (item=['taro', 'bascketball']) => { "msg": "taro likes bascketball" } ok: [localhost] => (item=['jiro', 'soccer']) => { "msg": "jiro likes soccer" } ok: [localhost] => (item=['jiro', 'baseball']) => { "msg": "jiro likes baseball" } ok: [localhost] => (item=['jiro', 'bascketball']) => { "msg": "jiro likes bascketball" } ok: [localhost] => (item=['saburo', 'soccer']) => { "msg": "saburo likes soccer" } ok: [localhost] => (item=['saburo', 'baseball']) => { "msg": "saburo likes baseball" } ok: [localhost] => (item=['saburo', 'bascketball']) => { "msg": "saburo likes bascketball" } PLAY RECAP ************************************************************************************************************************************************************************************************************************************************* localhost : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# おわりに
2つのリストに対して要素の組み合わせを処理する方法をまとめました。