As rookie

ルーキーインフラエンジニアがインフラのこと以外も結構書いてしまうブログ

ansibleで多重ループ(6日坊主)

  • この記事はsolo_advent_calender 2016年12月6日のものです。

こんにちは ショート advent calender6日目です。

ansibleで多重ループについて書きます!

ansibleでのループの構文はwith_items を使います。それはご存知ですか?

# task
- name: install by yum
  yum: name={{ item }} 
  with_items:
    - vim
    - unzip

というふうにwith_itemsでリストを与えてその中身(item)でタスクを実行することができます。

この場合だとvimunzipyumでinstallするということですね。

また、あらかじめgroup_varsなどにリストを用意しておいて

# group_vars/all
yum_list:
  - vim
  - unzip
# task
- name: install by yum
  yum: name={{ item }} 
  with_items: "{{ yum_list }}"

というふうにすれば、上のものと同じことができます.

多重ループをするにはどうすれば良いでしょう?

どうやらloop-controlとういものがあるようです。 Loops — Ansible Documentation

通常with_itemsでリストから値を取り出したときリストの中身はitem という変数に格納されて扱われます。

ですがこのloop-controlというものを使うとitem の名前を変えることができるのです。

サンプルでは

- include: inner.yml
  with_items:
    - 1
    - 2
    - 3
  loop_control:
    loop_var: outer_item

# inner.yml
- debug: msg="outer item={{ outer_item }} inner item={{ item }}"
  with_items:
    - a
    - b
    - c

というふうになっています。inner.ymlをインクルードするのをwith_items でループさして、その中身はouter_item という変数に入るというtaskになっています。公式の説明では

2.0では、with_loopsとtask includesを使用することができます(ただし、プレイブックは含まれません)。 これにより、一連のタスクをワンショットでループする機能が追加されます。 不可能なデフォルトでは、各ループのループ変数項目が設定され、これらのネストループは「外側」ループのitemの値を上書きします。 2.1の時点で、loop_controlオプションを使用して、ループに使用する変数の名前を指定できます。(google翻訳のコピペ)

includeするのはtaskのincludeだけのようです。

  loop_control:
    loop_var: outer_item #outer_itemというループ用の変数を定義

で変数名を定義します。

上のyumの例でいくと(yumのときこんなことするはずないが)

# group_vars/all
yum_list:
  - vim
  - unzip
  - nginx
  - mysql

yum_state:
  - present
  - latest
# main.yml
- name: install by yum
  include: inner.yml
  with_items: "{{ yum_state }}"
  loop_control:
    loop_var: outer_item
# inner.yml
- name: install by yum
  yum: name={{ item }} state={{ outer_item }}
  with_items: "{{ yum_list }}"
  

stateがpresetとlatestで両方インストールするという わけのわからないtaskになってしまったが複数のループを使用するときはこういうふうな書き方になりそうです。

また

yum_list
  - statet: present
    package:
      - vim
      - unzip
  - statet: latest
    package:
      - vim
      - unzip

というvarsをつくったならwith_subelementsというloopを使えば子要素でloopできるそう。この記事は明日書く予定です