ansibleはblock-whenの条件式をtask毎に評価をする。


ansibleではプログラミング言語のif文をwhenで表現します。

ansibleだと普通の条件式の挙動とは違い、ひとつづつのtaskで条件式を評価をする部分で理解が足りてなかったので、備忘録としてまとめます。

pythonで書いてみる

普通のプログラミング言語ではifの中で条件式に使用されている変数を変更しても途中でif文が終了する、ということはありません

number = 1
if number == 1:
    print('number is {}'.format(number))
    number = 10 #条件式が偽になるように変数を代入
    print('number is {}'.format(number)) #もう一度条件式は評価はされずに出力される

当たり前ですが number is 10も出力されます

output
number is 1
number is 10

ansbileで書いてみる

同じようなコードをansibleで書いてみます

ansible: 2.7.11


- hosts: localhost
  vars:
    NUMBER: 1
  tasks:
    - block:
        - name: debug when NUMBER is 1
          debug: var=NUMBER
        - set_fact:
            NUMBER: 10
        - name: debug when NUMBER is 10
          debug: var=NUMBER
      when: NUMBER == 1

TASK [debug when NUMBER is 10]の部分が skipping: [localhost] => {}になっていることが分かると思います。つまり各taskレベルでwhen の条件式の評価がされて、条件式で偽の判定がされています。

output
TASK [debug when NUMBER is 1] ************************************************************************************************************************************************************************************************
task path: /tmp/test.yml:6
ok: [localhost] => {
    "NUMBER": 1
}

TASK [set_fact] **************************************************************************************************************************************************************************************************************
task path: /tmp/test.yml:8
ok: [localhost] => {
    "ansible_facts": {
        "NUMBER": 10
    },
    "changed": false
}

TASK [debug when NUMBER is 10] ***********************************************************************************************************************************************************************************************
task path: /tmp/test.yml:10
skipping: [localhost] => {}
META: ran handlers
META: ran handlers

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

ansible自体はpythonで書かれていますがちょっとびっくりの仕様ですよね。

ansibleのコード思想が分かっていないので一概に悪いとは言えませんが普段の感覚でコードを書くと失敗する、というのは頭に入れておいた方が良さそうです。