AnsibleでJinja2を使って変数を上書きして二重ループをする

Ansibleで変数を上書きして二重ループをしてみたかったのでJinja2を使ってやってみました。

# 1. やりたこっと

pythonだとこんなイメージです。

```python:example.py
#!/usr/bin/env python3

if __name__ == "__main__":
    array = [{'name':'nanachi'}, {'name':'riko'}, {'name':'regu'}]
    key1 = [{'key': 'made in abyss'}, {'key': 'kawaii'}]

    for i in array:
        for j in key1:
            print("%s %s" % (i['name'], j['key']))
```

```shell-session
$ ./example.py
nanachi made in abyss
nanachi kawaii
riko made in abyss
riko kawaii
regu made in abyss
regu kawaii
```

# 2. Ansibleでやってみる

## 2-1. Playbook

ここでは、以下のPlaybookを書いてみました。

```yaml:example.yml
---
- name: Double loop test
  hosts: localhost
  gather_facts: no
  vars:
    array: [{'name':'nanachi'}, {'name':'riko'}, {'name':'regu'}]
    dict:
      key1:
        - key: made in abyss
        - key: kawaii
  tasks:
    - set_fact:
        v: >-
          {%- for i in array -%}
          {%-   set _ = i.update(dict) -%}
          {%- endfor -%}
          {{ array }}

    - debug:
        msg: "{{ item.0.name }} {{ item.1.key }}"
      with_subelements:
        - "{{ v }}"
        - key1
```

Playbookでは `array` と `dict` 変数を定義して使います。
二重ループの準備として `set_fact` で `array` の辞書を取り出して `dict` 辞書を追加しています。
[with_subelements](https://docs.ansible.com/ansible/latest/porting_guides/porting_guide_2.5.html?highlight=with_subelement#with-subelements) を使って `array` をループさせます。

## 2-2. with_subelementsについて

with_subelementsは以下のように指定して使います。

```yaml
with_subelements:
  - "{{ 外側ループ }}"
  - 内側ループ
```

`外側ループ` は `0` 、 `内側ループ` は `1` を指定して変数展開します。
今回作った `array` の中身は以下のようになっています。

```json
[
  {
    "name": "nanachi",
    "key1": [
      {
        "key": "made in abyss"
      },
      {
        "key": "kawaii"
      }
    ]
  },
  {
    "name": "riko",
    "key1": [
      {
        "key": "made in abyss"
      },
      {
        "key": "kawaii"
      }
    ]
  },
  {
    "name": "regu",
    "key1": [
      {
        "key": "made in abyss"
      },
      {
        "key": "kawaii"
      }
    ]
  }
]
```

`"{{ item.0.name }}"` は `name` キーの値が入ります。
`"{{ item.1.key }}"` は `key1` キーにある配列がループして `key` キーの値が入ります。
これを実行すると以下のようになります。

## 2-3. 実行

```shell-session
$ ansible-playbook example.yml
(snip)

PLAY [Double loop test] ***************************************************************************************************************************

TASK [set_fact] ***********************************************************************************************************************************
ok: [localhost]

TASK [debug] **************************************************************************************************************************************
ok: [localhost] => (item=None) => {
    "msg": "nanachi made in abyss"
}
ok: [localhost] => (item=None) => {
    "msg": "nanachi kawaii"
}
ok: [localhost] => (item=None) => {
    "msg": "riko made in abyss"
}
ok: [localhost] => (item=None) => {
    "msg": "riko kawaii"
}
ok: [localhost] => (item=None) => {
    "msg": "regu made in abyss"
}
ok: [localhost] => (item=None) => {
    "msg": "regu kawaii"
}

PLAY RECAP ****************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0
```

これでやりたいことができました :)