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

今回もAnsiblePlaybookにおける繰り返し制御について、学んでいきます。

引き続き題材は本家のドキュメントから。

シリーズはこちら。

Ansible: Loops

Looping over Subelements

今回は with_subelements からです。
これは、かなり複雑な使い方ですね。

「繰り返しのアイテム内にある連想配列として参照可能なリストを指定して、繰り返し実行ができる。」という動き方になります。

例を見てみましょう。
ドキュメント通りだと複雑な感じなので、少しシンプルな形の例にしたいと思います。

- hosts: 127.0.0.1
  connection: local
  vars:
    users:
    - name: alice
      authorized:
      - /tmp/alice/onekey.pub
      - /tmp/alice/twokey.pub
    - name: bob
      authorized:
      - /tmp/bob/id_rsa.pub
  tasks:
  - name: debug
    debug:
      msg: "{{ item.0.name }},{{ item.1 }}"
    with_subelements:
    - "{{ users }}"
    - authorized

この場合 {{ users }} でアイテムを一つ取り出し、そのアイテム内に定義されている authorized の配列をさらに繰り返し使う、というイメージになりそうです。

では、実際に実行してみましょう。

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

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

TASK [debug] *******************************************************************
ok: [localhost] => (item=({u'name': u'alice'}, u'/tmp/alice/onekey.pub')) => {
    "item": [
        {
            "name": "alice"
        }, 
        "/tmp/alice/onekey.pub"
    ], 
    "msg": "alice,/tmp/alice/onekey.pub"
}
ok: [localhost] => (item=({u'name': u'alice'}, u'/tmp/alice/twokey.pub')) => {
    "item": [
        {
            "name": "alice"
        }, 
        "/tmp/alice/twokey.pub"
    ], 
    "msg": "alice,/tmp/alice/twokey.pub"
}
ok: [localhost] => (item=({u'name': u'bob'}, u'/tmp/bob/id_rsa.pub')) => {
    "item": [
        {
            "name": "bob"
        }, 
        "/tmp/bob/id_rsa.pub"
    ], 
    "msg": "bob,/tmp/bob/id_rsa.pub"
}

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

結果、想定通りの動きになりましたね。

Looping over Integer Sequences

次は with_sequence です。
これは、順番に数字を生成して繰り返しを行なうものになります。

ここで気をつけなければいけないのは、「パラメータは key=value のスタイルで書いてね!」とドキュメントにはあるのですが、例の方では key: value のスタイルになっていて、このままコピペしてしまうとうまく動作しません(でした)。

ということで、うまくいく形で記載した例を書いてみます。

- hosts: 127.0.0.1
  connection: local
  tasks:
  - name: start and end
    debug:
      msg: "{{ item }}"
    with_sequence: start=0 end=2

  - name: stride
    debug:
      msg: "{{ item }}"
    with_sequence: start=10 end=14 stride=2

  - name: format
    debug:
      msg: "{{ item }}"
    with_sequence: start=9 end=11 format=item%02d

  - name: count
    debug:
      msg: "{{ item }}"
    with_sequence: count=3

実行結果は、下記となります。

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

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

TASK [start and end] ***********************************************************
ok: [localhost] => (item=0) => {
    "item": "0", 
    "msg": "0"
}
ok: [localhost] => (item=1) => {
    "item": "1", 
    "msg": "1"
}
ok: [localhost] => (item=2) => {
    "item": "2", 
    "msg": "2"
}

TASK [stride] ******************************************************************
ok: [localhost] => (item=10) => {
    "item": "10", 
    "msg": "10"
}
ok: [localhost] => (item=12) => {
    "item": "12", 
    "msg": "12"
}
ok: [localhost] => (item=14) => {
    "item": "14", 
    "msg": "14"
}

TASK [format] ******************************************************************
ok: [localhost] => (item=item09) => {
    "item": "item09", 
    "msg": "item09"
}
ok: [localhost] => (item=item10) => {
    "item": "item10", 
    "msg": "item10"
}
ok: [localhost] => (item=item11) => {
    "item": "item11", 
    "msg": "item11"
}

TASK [count] *******************************************************************
ok: [localhost] => (item=1) => {
    "item": "1", 
    "msg": "1"
}
ok: [localhost] => (item=2) => {
    "item": "2", 
    "msg": "2"
}
ok: [localhost] => (item=3) => {
    "item": "3", 
    "msg": "3"
}

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

ということで、 key=value で記載すればうまくいきました。
連続したユーザー作成や、数字を使ったデータ格納などの定型処理で活用できそうですね。

Random Choices

今回の最後は with_random_choice です。
名前の通り、指定したアイテムの中からランダムでアイテムを取り出せるものです。

- hosts: 127.0.0.1
  connection: local
  tasks:
  - name: random
    debug:
      msg: "{{ item }}"
    with_random_choice:
    - "go through the door"
    - "drink from the goblet"
    - "press the red button"
    - "do nothing"

結果は下記のようになりました。

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

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

TASK [random] ******************************************************************
ok: [localhost] => (item=press the red button) => {
    "item": "press the red button", 
    "msg": "press the red button"
}

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

これの使い所ですが、、、あまり明確な用途が浮かばないですね。
ドキュメントの中には、「簡単なロードバランサー的な使い方ができるんじゃない?」という風に書かれていました。。。

まとめ

今回は、 with_subelementswith_sequencewith_random_choice の内容を学びました。

今回は、特殊な使い方が多く、実際に触ってみないとイメージの付きにくいものでした。
やはり、手を動かしてみるのは大切ですね。

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

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

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

コメントする

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

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