てくなべ (tekunabe)

ansible / network automation / 学習メモ

[Ansible] インベントリ変数、set_fact、include_vars などで定義した変数の評価タイミング

この記事は、Ansible Advent Calendar 2022 (Adventar 版) の 18日目の記事です。

はじめに

あらためて考えると「あれ、どうだっけ?」となることの一つに、変数の評価タイミングがあります。

インベントリ変数や、Play変数、vars_filesset_factinclude_vars で定義した変数をそれぞれ2回参照したときの比較結果を、ど忘れしたときのために記しておきます。

  • 環境
    • ansible-core 2.14.1

ファイル構成

.
├── eval_vars.yml        # Playbook
├── host_vars
│   └── localhost.yml    # インベントリ変数
└── vars
    ├── files.yml        # vars_files で指定する対象
    └── included.yml     # include_vars で指定する対象

変数ファイルの中身はそれぞれ以下のとおりです。すべて中身は "{{ now }}" で、変数名だけ定義した場所が区別できるように変えています。

host_vars/localhost.yml

---
now_host_vars: "{{ now() }}"

vars/files.yml (vars_files で指定する対象)

---
now_vars_files: "{{ now() }}"

vars/included.yml (include_vars で指定する対象)

---
now_include_vars: "{{ now() }}"

Playbook

Playbook は以下のとおりです。先程定義した変数ファイルたちをいろいろな方法で読み込みつつ、Play 変数 now_play_varsset_fact で定義する変数 now_set_fact は、Playbook 内で定義します。2回変数を debug で表示しますが、間に 1秒 pause をかけます。これにより、 "{{ now }}" が変わったり変わらなかったりするところ比較するのが目的です。

---
- name: Test evaluating vars
  hosts: localhost
  gather_facts: false
  connection: local

  vars:
    now_play_vars: "{{ now() }}"

  vars_files:
    - files.yml

  tasks:
    - name: set_fact
      ansible.builtin.set_fact:
        now_set_fact: "{{ now() }}"

    - name: include_vars
      ansible.builtin.include_vars:
        file: included.yml

    - name: debug vars 1
      ansible.builtin.debug:
        msg:
          - "{{ now_host_vars }} now_host_vars"
          - "{{ now_play_vars }} now_play_vars"
          - "{{ now_vars_files }} now_vars_files"
          - "{{ now_set_fact }} now_set_fact"
          - "{{ now_include_vars }} now_include_vars"
          
    - name: pause
      ansible.builtin.pause:
        seconds: 1

    - name: debug vars 2
      ansible.builtin.debug:
        msg:
          - "{{ now_host_vars }} now_host_vars"
          - "{{ now_play_vars }} now_play_vars"
          - "{{ now_vars_files }} now_vars_files"
          - "{{ now_set_fact }} now_set_fact"
          - "{{ now_include_vars }} now_include_vars"

実行結果

Playbook の実行結果です。

% ansible-playbook -i localhost, eval_vars.yml

PLAY [Test evaluating vars] *************************************************************************************

TASK [set_fact] *************************************************************************************************
ok: [localhost]

TASK [include_vars] *********************************************************************************************
ok: [localhost]

TASK [debug vars 1] *********************************************************************************************
ok: [localhost] => {
    "msg": [
        "2022-12-18 11:40:59.351505 now_host_vars",
        "2022-12-18 11:40:59.353803 now_play_vars",
        "2022-12-18 11:40:59.355511 now_vars_files",
        "2022-12-18 11:40:59.228503 now_set_fact",
        "2022-12-18 11:40:59.358674 now_include_vars"
    ]
}

TASK [pause] ****************************************************************************************************
Pausing for 1 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
ok: [localhost]

TASK [debug vars 2] *********************************************************************************************
ok: [localhost] => {
    "msg": [
        "2022-12-18 11:41:00.455484 now_host_vars",
        "2022-12-18 11:41:00.458050 now_play_vars",
        "2022-12-18 11:41:00.460399 now_vars_files",
        "2022-12-18 11:40:59.228503 now_set_fact",
        "2022-12-18 11:41:00.462725 now_include_vars"
    ]
}

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

set_fact で取得した now() だけが変化しなかったことが分かります。