【Ansible Tower/AWX】ループ処理の記述方法③


この記事はプロモーションを含みます。

Ansible

ホーム > Ansible Tower・AWX リファレンス

Ansibleも他言語と同様にループ処理を実装することが可能です。ここでは、実例を交えながらループ処理の記述方法を解説したいと思います。

Ansibleでのループ処理は、他言語でよく見かける For~文ではなく、「with_~」ディレクティブを使用します。
前回に引き続き、今回は以下のディレクティブを解説します。

この記事で解説するループ処理

with_subelements:配列のサブ要素を元にループ

with_subelements は、配列のサブ要素を元にしてループを行います。
他のループより少し分かりにくいループ処理ですが、意外に使用頻度は高いです。

書式

with_subelements の書式です。

with_subelements:
  - 配列
  - 配列のサブ要素

「配列のサブ要素」を指定する際に1つ気を付けることがあります。
それは、配列のサブ要素を指定する際は「要素名」で指定する必要があります。
なので、サンプルのように「module」と記述する必要があります。
「”{{ module }}”」と記述するとエラーになってしまいます。

プレイブック

サンプルのプレイブックです。

---
- hosts: all
  gather_facts: False
  tasks:

  - name: 配列の作成
    set_fact:
      deploy_info:
        - process: tomcat001
          module:
            - foo.war
            - bar.war
        - process: tomcat002
          module:
            - tomcat.war
            - root.war

  - name: ループ処理【with_subelements】
    debug:
      msg: "{{ item.0.process }}/{{ item.1 }}"
    with_subelements:
      - "{{ deploy_info }}"
      - module

まず、配列を作成していますが、これは「with_subelements」で使用するテスト用の配列を作成しています。

タスク「ループ処理」では、with_subelementsのインプットとなる配列[deploy_info]の要素と、そのサブ要素[module]でループが行われます。
これだけではイメージが難しいと思うので、ここからさらに砕いて解説していきます。

今回実行したプレイブックで表示している情報は「msg: “{{ item.0.process }}/{{ item.1 }}”」となっています。
この「item.0.process」と「item.1」は、下記のように配列と紐づいています。

item.0.process

まず、[item.0]に分割して確認します。
これは、with_subelements のインプットとしている配列で、サンプルでは「”{{ deploy_info }}”」となっている箇所になります。

そして、[item.0.process]ですが、
[item.0]が「”{{ deploy_info }}”」なので、言い換えると「”{{ deploy_info.*.process }}”」となります。

赤字の[*]ですが、[deploy_info]は配列につき、添え字が必要なので、[*]としました。
添え字も含めて表示した場合、下記のようになります。

1周目のループ:deploy_info.0.process = tomcat001
2周目のループ:deploy_info.1.process = tomcat002

item.1

with_subelements のインプットとしている配列のサブ要素で、サンプルでは「module」となっている箇所になります。

下記が実行結果の一部です。
with_subelements の配列「deploy_info」の要素が2つ、そのサブ要素の「module」の要素が2つなので、2×2で4回ループされています。

TASK [ループ処理【with_subelements】] *************************************************
ok: [192.168.56.105] => (item=[{'process': 'tomcat001'}, 'foo.war']) => {
    "msg": "tomcat001/foo.war"
}
ok: [192.168.56.105] => (item=[{'process': 'tomcat001'}, 'bar.war']) => {
    "msg": "tomcat001/bar.war"
}
ok: [192.168.56.105] => (item=[{'process': 'tomcat002'}, 'tomcat.war']) => {
    "msg": "tomcat002/tomcat.war"
}
ok: [192.168.56.105] => (item=[{'process': 'tomcat002'}, 'root.war']) => {
    "msg": "tomcat002/root.war"
}

ループ回数と配列を表にすると下記のようになります。

ループ回数item.0.processitem.1
1周目tomcat001foo.war
2周目tomcat001bar.war
3周目tomcat002tomcat.war
4周目tomcat002root.war

実行結果

サンプルのプレイブックを実行した結果になります。

SSH password: 
BECOME password[defaults to SSH password]: 

PLAY [all] *********************************************************************

TASK [配列の作成] *******************************************************************
ok: [192.168.56.105]

TASK [ループ処理【with_subelements】] *************************************************
ok: [192.168.56.105] => (item=[{'process': 'tomcat001'}, 'foo.war']) => {
    "msg": "tomcat001/foo.war"
}
ok: [192.168.56.105] => (item=[{'process': 'tomcat001'}, 'bar.war']) => {
    "msg": "tomcat001/bar.war"
}
ok: [192.168.56.105] => (item=[{'process': 'tomcat002'}, 'tomcat.war']) => {
    "msg": "tomcat002/tomcat.war"
}
ok: [192.168.56.105] => (item=[{'process': 'tomcat002'}, 'root.war']) => {
    "msg": "tomcat002/root.war"
}

PLAY RECAP *********************************************************************
192.168.56.105             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

with_nested:複数のリストを総当たりするようにループ

with_nested は、複数のリストの要素を総当たりのように組み合わせてループを行います。

書式

with_nested の書式です。
リストの数は3つ以上でも可能ですが、あまり多くするとログ出力が大量になります。

with_nested:
  - リスト1
  - リスト2

プレイブック

サンプルのプレイブックです。

---
- hosts: all
  gather_facts: False
  tasks:

  - name: ループ処理【with_nested】
    debug:
      msg: "{{ item }}"
    with_nested:
      - ["one", "two"]
      - ["要素1", "要素2", "要素3"]

このプレイブックでは、下記の2つのリストでループしています。
・リスト1(要素2つ):[“one”, “two”]
・リスト2(要素3つ):[“要素1”, “要素2”, “要素3”]

上記を組み合わせて実行されるループは以下のようになります。

ループ回数組み合わせ
1周目one, 要素1
2周目one, 要素2
3周目one, 要素3
4周目two, 要素1
5周目two, 要素2
6周目two, 要素3

下記は実行結果の一部で、先程の組み合わせのように実行されていることが分かります。

TASK [ループ処理【with_nested】] ******************************************************
ok: [192.168.56.105] => (item=['one', '要素1']) => {
    "msg": [
        "one",
        "要素1"
    ]
}
ok: [192.168.56.105] => (item=['one', '要素2']) => {
    "msg": [
        "one",
        "要素2"
    ]
}
ok: [192.168.56.105] => (item=['one', '要素3']) => {
    "msg": [
        "one",
        "要素3"
    ]
}
ok: [192.168.56.105] => (item=['two', '要素1']) => {
    "msg": [
        "two",
        "要素1"
    ]
}
ok: [192.168.56.105] => (item=['two', '要素2']) => {
    "msg": [
        "two",
        "要素2"
    ]
}
ok: [192.168.56.105] => (item=['two', '要素3']) => {
    "msg": [
        "two",
        "要素3"
    ]
}

実行結果

サンプルのプレイブックを実行した結果になります。

SSH password: 
BECOME password[defaults to SSH password]: 

PLAY [all] *********************************************************************

TASK [ループ処理【with_nested】] ******************************************************
ok: [192.168.56.105] => (item=['one', '要素1']) => {
    "msg": [
        "one",
        "要素1"
    ]
}
ok: [192.168.56.105] => (item=['one', '要素2']) => {
    "msg": [
        "one",
        "要素2"
    ]
}
ok: [192.168.56.105] => (item=['one', '要素3']) => {
    "msg": [
        "one",
        "要素3"
    ]
}
ok: [192.168.56.105] => (item=['two', '要素1']) => {
    "msg": [
        "two",
        "要素1"
    ]
}
ok: [192.168.56.105] => (item=['two', '要素2']) => {
    "msg": [
        "two",
        "要素2"
    ]
}
ok: [192.168.56.105] => (item=['two', '要素3']) => {
    "msg": [
        "two",
        "要素3"
    ]
}

PLAY RECAP *********************************************************************
192.168.56.105             : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

with_cartesian:複数のリストを総当たりするようにループ

with_nested と同じ処理なので、with_nested をご覧ください。

with_random_choice:リストの要素から1つを選択してループ

with_random_choice は、指定したリストから、要素を1つランダムに選択し、それを元にしてループを行います。

書式

with_random_choice の書式です。

with_random_choice: リスト

プレイブック

サンプルのプレイブックです。

---
- hosts: all
  gather_facts: False
  tasks:

  - name: リストの作成
    set_fact:
      list:
        - "要素0"
        - "要素1"
        - "要素2"

  - name: ループ処理【with_random_choice】
    debug:
      msg: "{{ item }}"
    with_random_choice: "{{ list }}"

このプレイブックでは、まずループに使用するリストを作成しています。
[list]という名前のリストを作成し、要素は[要素0, 要素1, 要素2]の3つを設定しました。

ループ処理では、「with_random_choice: “{{ list }}”」と記述しています。
これは、前のタスクで作成したリスト[list]を元にしてループを行っています。
with_random_choice では、リストからランダムに要素の1つを選択してループするので、リスト[list]に含まれる要素のどれか1つが使用されてループが行われます。

下記のように記述することも可能です。

with_random_choice: [“要素0”, “要素1”, “要素2”]

このプレイブックを2度実行して、実行結果を見てみます。

1回目は、「要素2」が選択されました。

1回目
TASK [ループ処理【with_random_choice】] ***********************************************
ok: [192.168.56.105] => (item=要素2) => {
    "msg": "要素2"
}

2回目は、「要素1」が選択されました。

2回目
TASK [ループ処理【with_random_choice】] ***********************************************
ok: [192.168.56.105] => (item=要素1) => {
    "msg": "要素1"
}

1回目の実行と2回目の実行で、使用される要素が変わることが確認出来ました。

要素はランダムで選択されるので、同じ要素が連続で使用される場合もあります。

実行結果

サンプルのプレイブックを実行した結果になります。

SSH password: 
BECOME password[defaults to SSH password]: 

PLAY [all] *********************************************************************

TASK [リストの作成] ******************************************************************
ok: [192.168.56.105]

TASK [ループ処理【with_random_choice】] ***********************************************
ok: [192.168.56.105] => (item=要素1) => {
    "msg": "要素1"
}

PLAY RECAP *********************************************************************
192.168.56.105             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

「ループ処理の記述方法③」は以上になります。
他のループ処理については、以下の記事をご覧ください。

コメント

タイトルとURLをコピーしました