Ansible: Playbookの繰り返し制御の色々 (1)

以前のシリーズで、 when を中心とした実行時の条件制御について見てきました。
今回からは、 Loops のドキュメントを参考に、繰り返し制御について学んでいきたいと思います。

こちらも、題材は本家のドキュメント。

シリーズはこちら。

Ansible: Loops

Standard Loops

まずは、標準的なループの指定です。
ここでは、 with_items の使い方を見ていきます。

サンプルでは、「単純な指定」、「変数の配列による指定」「ハッシュ形式の配列による指定」とあるので、それらを確認できる Playbook を準備します。

- hosts: 127.0.0.1
  connection: local
  vars:
    somelist:
    - var_item1
    - var_item2

  tasks:
  - name: debug with "with_items"
    debug:
      msg: "{{ item }}"
    with_items:
    - item1
    - item2

  - name: debug with "vars"
    debug:
      msg: "{{ item }}"
    with_items: "{{ somelist }}"

  - name: debug with hash items
    debug:
      msg: "{{ item.name }}, {{ item.value }}"
    with_items:
    - { name: "item1", value: "foo" }
    - { name: "item2", value: "bar" }

こちらを実行すると、下記のようにそれぞれきちんと動いていることが確認できます。

PLAY [127.0.0.1] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [debug with "with_items"] *************************************************
ok: [localhost] => (item=item1) => {
    "item": "item1", 
    "msg": "item1"
}
ok: [localhost] => (item=item2) => {
    "item": "item2", 
    "msg": "item2"
}

TASK [debug with "vars"] *******************************************************
ok: [localhost] => (item=var_item1) => {
    "item": "var_item1", 
    "msg": "var_item1"
}
ok: [localhost] => (item=var_item2) => {
    "item": "var_item2", 
    "msg": "var_item2"
}

TASK [debug with hash items] ***************************************************
ok: [localhost] => (item={u'name': u'item1', u'value': u'foo'}) => {
    "item": {
        "name": "item1", 
        "value": "foo"
    }, 
    "msg": "item1, foo"
}
ok: [localhost] => (item={u'name': u'item2', u'value': u'bar'}) => {
    "item": {
        "name": "item2", 
        "value": "bar"
    }, 
    "msg": "item2, bar"
}

PLAY RECAP *********************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=0

ここでサラッと書かれているのですが、 with_ + lookup() という形式で上記のようなループ処理を行なうことができます。
つまり、 <a rel="nofollow" href="http://docs.ansible.com/ansible/playbooks_lookups.html" target="_blank">Lookupプラグイン</a> をそのまま使える、ということのようです。
こちらの詳細は、別の機会に調べたいと思います。

Nested Loops

Loopの条件をネスト(入れ子)にできるようです。
つまり、複数の配列に対して全組み合わせの繰り返しができる、という感じですね。
こちらは with_nested を利用します。

本文の例を基に、実際に Playbook を作成して動作を確認してみましょう。

- hosts: 127.0.0.1
  connection: local
  vars:
    users:
    - user_a
    - user_b

  tasks:
  - name: show users and commands
    debug:
      msg: "{{ item[0] }}, {{ item[1] }}"
    with_nested:
    - [ "user_1", "user_2" ]
    - [ "command_a", "command_b", "command_c" ]

  - name: show users and commands with vars
    debug:
      msg: "{{ item[0] }}, {{ item[1] }}"
    with_nested:
    - "{{ users }}"
    - [ "command_a", "command_b", "command_c" ]

実行すると、下記のようになります。

PLAY [127.0.0.1] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [show users and commands] *************************************************
ok: [localhost] => (item=[u'user_1', u'command_a']) => {
    "item": [
        "user_1", 
        "command_a"
    ], 
    "msg": "user_1, command_a"
}
ok: [localhost] => (item=[u'user_1', u'command_b']) => {
    "item": [
        "user_1", 
        "command_b"
    ], 
    "msg": "user_1, command_b"
}
ok: [localhost] => (item=[u'user_1', u'command_c']) => {
    "item": [
        "user_1", 
        "command_c"
    ], 
    "msg": "user_1, command_c"
}
ok: [localhost] => (item=[u'user_2', u'command_a']) => {
    "item": [
        "user_2", 
        "command_a"
    ], 
    "msg": "user_2, command_a"
}
ok: [localhost] => (item=[u'user_2', u'command_b']) => {
    "item": [
        "user_2", 
        "command_b"
    ], 
    "msg": "user_2, command_b"
}
ok: [localhost] => (item=[u'user_2', u'command_c']) => {
    "item": [
        "user_2", 
        "command_c"
    ], 
    "msg": "user_2, command_c"
}

TASK [show users and commands with vars] ***************************************
ok: [localhost] => (item=[u'user_a', u'command_a']) => {
    "item": [
        "user_a", 
        "command_a"
    ], 
    "msg": "user_a, command_a"
}
ok: [localhost] => (item=[u'user_a', u'command_b']) => {
    "item": [
        "user_a", 
        "command_b"
    ], 
    "msg": "user_a, command_b"
}
ok: [localhost] => (item=[u'user_a', u'command_c']) => {
    "item": [
        "user_a", 
        "command_c"
    ], 
    "msg": "user_a, command_c"
}
ok: [localhost] => (item=[u'user_b', u'command_a']) => {
    "item": [
        "user_b", 
        "command_a"
    ], 
    "msg": "user_b, command_a"
}
ok: [localhost] => (item=[u'user_b', u'command_b']) => {
    "item": [
        "user_b", 
        "command_b"
    ], 
    "msg": "user_b, command_b"
}
ok: [localhost] => (item=[u'user_b', u'command_c']) => {
    "item": [
        "user_b", 
        "command_c"
    ], 
    "msg": "user_b, command_c"
}

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0   

上記のように、それぞれ6通りずつ実行されました。

Looping over Hashes

ここでは、ハッシュ形式を使ったループの例となっています。
最初に「ハッシュ形式の配列による指定」がありましたが、全体がハッシュ形式となった変数での例です。
利用するのは with_dict となります。

- hosts: 127.0.0.1
  connection: local
  vars:
    users:
      alice:
        name: Alice Appleworth
        telephone: 123-456-7890
      bob:
        name: Bob Bananarama
        telephone: 987-654-3210

  tasks:
  - name: Print phone records
    debug: msg="User {{ item.key }} is {{ item.value.name }} ({{ item.value.telephone }})"
    with_dict: "{{ users }}"

実行してみると、下記のようになります。

PLAY [127.0.0.1] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [Print phone records] *****************************************************
ok: [localhost] => (item={'key': u'bob', 'value': {u'name': u'Bob Bananarama', u'telephone': u'987-654-3210'}}) => {
    "item": {
        "key": "bob", 
        "value": {
            "name": "Bob Bananarama", 
            "telephone": "987-654-3210"
        }
    }, 
    "msg": "User bob is Bob Bananarama (987-654-3210)"
}
ok: [localhost] => (item={'key': u'alice', 'value': {u'name': u'Alice Appleworth', u'telephone': u'123-456-7890'}}) => {
    "item": {
        "key": "alice", 
        "value": {
            "name": "Alice Appleworth", 
            "telephone": "123-456-7890"
        }
    }, 
    "msg": "User alice is Alice Appleworth (123-456-7890)"
}

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

このように、ハッシュ形式のデータを直接利用することができました。

まとめ

今回はループを行なうものとして、 with_itemswith_nestedwith_dict の例を見てきました。
今回の範囲は比較的シンプルで、プログラミング経験があればかなり直感的に理解できるところだと思います。

原文のこの章はまだまだ先が長いので、じっくりと確認しながら学んで行きたいと思います。

tacck
  • tacck
  • 北の大地の普通のソフトウェアエンジニア。
    インフラ・バックエンド・フロントエンドと、色々やります。

    初心者・若手向けのメンターも希望あればお受けします。

    勉強会運営中
    * ゆるWeb勉強会@札幌
    * スマートスピーカーで遊ぼう会@札幌

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください