[Ansible]変数の優先とスコープのメモ

# 概要
- Ansibleの変数の扱いを確認
- 変数を、定義した場所による優先順位とスコープを動作確認
- 優先順位が決まっているが、参照時はスコープ範囲をも意識した上で、優先順位の把握が必要になる
- versionは2.9で確認

# 変数の規定
## [変数の優先順位](https://docs.ansible.com/ansible/2.9/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable)

> 1 command line values (eg “-u user”)
> 2 role defaults
> 3 inventory file or script group vars
> 4 inventory group_vars/all
> 5 playbook group_vars/all
> 6 inventory group_vars/*
> 7 playbook group_vars/*
> 8 inventory file or script host vars
> 9 inventory host_vars/*
> 10 playbook host_vars/*
> 11 host facts / cached set_facts
> 12 play vars
> 13 play vars_prompt
> 14 play vars_files
> 15 role vars (defined in role/vars/main.yml)
> 16 block vars (only for tasks in block)
> 17 task vars (only for the task)
> 18 include_vars
> 19 set_facts / registered vars
> 20 role (and include_role) params
> 21 include params
> 22 extra vars (always win precedence)

## [変数のスコープ](https://docs.ansible.com/ansible/2.9/user_guide/playbooks_variables.html#scoping-variables)
> Global: this is set by config, environment variables and the command line
> グローバル: これは、設定、環境変数、およびコマンドラインで設定されます。

> Play: each play and contained structures, vars entries (vars; vars_files; vars_prompt), role defaults and vars.
> プレイ: 各プレイおよび含まれる構造、変数エントリー (vars、vars_files、vars_prompt)、ロールのデフォルト、および変数

> Host: variables directly associated to a host, like inventory, include_vars, facts or registered task outputs
> ホスト: インベントリー、include_vars、ファクト、または登録されたタスク出力などのホストに直接関連付けられる変数

# 動作確認
- 変数の定義場所として下記に同一名の変数名**（tmp_var）**を定義  
※ inventoryには上記変数未定義
    - gourp_vars/all.yml
    - host_vars/*
    - playbook
        - play vars
        - task vars

- 上記で定義した規定での優先順位
17 task vars(only for the task) > 12 play vars > 9 inventory host_vars/* > 4 inventory group_vars/all

## 設定ファイル
- グループ変数ファイル

```group_vars/all.yml 
---
tmp_var: group_varsファイルに記載のグループ変数
```


- ホスト変数ファイル

```host_vars/node-1.yml
--- #未定義
```

```host_vars/node-3.yml 
---
tmp_var: node-3のhost_varsファイル記載
```

- playbook

```~/working/vars_play_playbook.yml
---
- hosts: node-1
  gather_facts: no
  vars:
    tmp_var: play vars  # プレイ変数
  tasks:
    - name: "[play1]プレイ変数の参照(ホスト変数未定義)"
      debug:
        var: tmp_var

- hosts: node-1
  gather_facts: no
  tasks:
    - name: "[play2]一つ前のプレイのプレイ変数は参照できるか？"
      debug:
        var: tmp_var


- hosts: node-3
  gather_facts: no
  tasks:
    - name: "[play3]playbook内では未定義,group_varとhost_varsには定義ありの参照"
      debug:
        var: tmp_var


- hosts: node-3
  gather_facts: no
  vars:
    tmp_var: node-3のplay変数
  tasks:
    - name: "[play4]play変数とtask変数,group_var,host_varsに定義ありの参照"
      vars: # タスク変数
        tmp_var: node-3のtask変数 
      debug:
        var: tmp_var
    - name: "[play4-2]1つ前でtask変数を指定しているが、別のタスクでの参照"
      debug:
        var: tmp_var

- hosts: node-3
  gather_facts: no
  tasks:
    - name: "[play5]前でplay変数とtask変数定義,group_var,host_varsに定義あるけど、playを跨ぐと"
      debug:
        var: tmp_var
```


## playbook実行

```

[root@4918c1b5d6a7 working]# ansible-playbook vars_play_playbook.yml

PLAY [node-1] ***********************************************************************************

TASK [[play1]プレイ変数の参照(ホスト変数未定義)] *********************************************************
ok: [node-1] => {
    "tmp_var": "play vars"
}

```
ここはplay varsの確認。
~~17 task vars(only for the task) >~~ 12 play vars > ~~9 inventory host_vars/* >~~ 4 inventory group_vars/all
によりplay varsが参照できている。


```
PLAY [node-1] ***********************************************************************************

TASK [[play2]一つ前のプレイのプレイ変数は参照できるか？] *************************************************************
ok: [node-1] => {
    "tmp_var": "group_varsファイルに記載のグループ変数"
}
```
一つ前のplayで定義したplay変数があるが、**play varsは別のplayを跨げない**ため、
4 inventory group_vars/allの変数を参照している
~~17 task vars(only for the task) >~~12 play vars > ~~9 inventory host_vars/* >~~ 4 inventory group_vars/all



```
PLAY [node-3] ***********************************************************************************

TASK [[play3]playbook内では未定義,group_varとhost_varsには定義ありの参照] ***************************************
ok: [node-3] => {
    "tmp_var": "node-3のhost_varsファイル記載"
}
```
別のnode-3でplaybook内での変数未定義のパターンなので、**inventory host_vars/node-3**からの参照となっている
~~17 task vars(only for the task) > 12 play vars >~~ 9 inventory host_vars/* > 4 inventory group_vars/all



```
PLAY [node-3] ***********************************************************************************

TASK [[play4]play変数とtask変数,group_var,host_varsに定義ありの参照] *****************************************
ok: [node-3] => {
    "tmp_var": "node-3のtask変数"
}
```

task varsを定義しているため、最優先のtask varsを参照している
7 task vars(only for the task) > 12 play vars > 9 inventory host_vars/* > 4 inventory group_vars/all


```
TASK [[play4-2]1つ前でtask変数を指定しているが、別のタスクでの参照] ****************************************************
ok: [node-3] => {
    "tmp_var": "node-3のplay変数"
}

PLAY [node-3] ***********************************************************************************
```
説明では"7 task vars(only for the task)"と1タスク内でのスコープと読み取れるので、
同一play内の2つ目のタスクとして変数参照
同一のtasks内であればtask varsが参照できる事を確認


```
TASK [[play5]前でplay変数とtask変数定義,group_var,host_varsに定義あるけど、playを跨ぐと] *********************************
ok: [node-3] => {
    "tmp_var": "node-3のhost_varsファイル記載"
}

PLAY RECAP **************************************************************************************
node-1                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
node-3                     : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@4918c1b5d6a7 working]# 
```
**前playで定義したtask vars/play varsがあるが、どちらもはplayを跨げないため**、
9 inventory host_vars/*が参照されている
~~7 task vars(only for the task) > 12 play vars >~~ 9 inventory host_vars/* > 4 inventory group_vars/all

# まとめ
- 決められた変数の優先順位はあるが、参照時のスコープにも配慮する必要がある
- より範囲の狭い場所で定義したものが高優先になるイメージ
- 上記で試してはいないが、ホストごとに変数を持つため、
　特定のホストで変数を定義していない場合は、未定義でエラーとなる