Help us understand the problem. What is going on with this article?

Ansible 変数の優先順位と書き方をまとめてみた

Ansibleは変数を色々な場所に書くことができるが、どんな書き方をすれば良いのかまとまった資料が僕の力では見つけられなかったので自分でまとめちゃえの会。

変数の優先順位についてはVariable precedence: Where should I put a variable?に記載されているので、これを上から実際に書いてみる。
一応オーバーライドされることの確認もしながらやります。

command line values (eg “-u user”)
role defaults
inventory file or script group vars
inventory group_vars/all
playbook group_vars/all
inventory group_vars/*
playbook group_vars/*
inventory file or script host vars
inventory host_vars/*
playbook host_vars/*
host facts / cached set_facts
play vars
play vars_prompt
play vars_files
role vars (defined in role/vars/main.yml)
block vars (only for tasks in block)
task vars (only for the task)
include_vars
set_facts / registered vars
role (and include_role) params
include params
extra vars (always win precedence)

はじめに

environment version
MacOS Mojave 10.14.6
Python 3.7.4
Ansible 2.8.3
  • Playbookはローカルに対して実行します
  • この記事で書いたコードは一応以下で公開しています
    https://github.com/answer-d/ansible_var_pecedence_test
  • 間違っているところや補足事項があったらコメント頂ければ幸いです

01. command line values (eg “-u user”)

playbook実行コマンドの引数に与える値であり、こっちで定義するものではないはず、割愛

(2019/08/19追記)
認識がちょっと間違っていたので訂正、説明だけでコードは書きません!(スマン)

playbookの実行時、例えば-u userというオプションを与えるとAnsible実行ユーザを変更できるが、そのユーザ名は内部的にはansible_userという変数に格納される
そのため、インベントリファイルで以下のように変数を定義することで、実行対象ホストごとにAnsible実行ユーザを変更することができたりする
(↑の話はWorking with Inventory - Hosts and non-standard portsにも書かれてます)

[targets]
localhost
other1.example.com ansible_user=answer_d
other2.example.com ansible_user=tekitou_user

この時、playbook実行時に指定している引数(-u userみたいなやつ)は実は一番弱くて、02. role defaultsに負けるんだよ!という話っぽい
※ 実際にdefaultsでansible_userをオーバーライドするケースは無いと思うけど、書いて実行してみたらそうなります

02. role defaults

ここからが本題

roles/*/defaults/main.ymlに記載される変数
01. command line valuesを除くと最も優先順位が低く、これ以降で実装する全ての変数定義でオーバーライドされる

ディレクトリ構成
.
├── inventory
├── roles
│   └── test_role
│       ├── defaults
│       │   └── main.yml
│       └── tasks
│           └── main.yml
└── site.yml
inventory
[local]
localhost
roles/test_role/defaults/main.yml
---
var_test02: "This is 'role defaults'"
roles/test_role/tasks/main.yml
---
- name: "test02 - role defaults"
  debug: var=var_test02
site.yml
---
- name: "test ansible var precedence"
  hosts: all
  roles:
    - test_role
Playbook実行
# ansible-playbook -i inventory site.yml

PLAY [test ansible var precedence] *********************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [localhost]

TASK [test_role : test02 - role defaults] **************************************************************************
ok: [localhost] => {
    "var_test02": "This is 'role defaults'"
}

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

03. inventory file or script group vars

inventoryファイルに書く変数のうち、グループに対して与えるやつのこと

inventory
[local]
localhost

# allは「全てのホスト」を意味するビルトインのグループ
[all:vars]
var_test03_1="This is 'inventory file or script group vars (all)'"
var_test03_2="This is 'inventory file or script group vars (all)'"

# 定義しているグループで指定、もちろんallより強くなる
[local:vars]
var_test03_2="This is 'inventory file or script group vars (local)'"
roles/test_role/defaults/main.yml
---
var_test02: "This is 'role defaults'"
var_test03_1: "This is 'role defaults'"
var_test03_2: "This is 'role defaults'"
roles/test_role/tasks/main.yml
---
- name: "test02 - role defaults"
  debug: var=var_test02

- name: "test03 - inventory file or script group vars"
  debug: var=var_test03_{{ item }}
  with_items: [1, 2]

var_test03_1にはdefaultsがオーバーライドされて「inventory file or script group vars (all)」が
var_test03_2には↑がさらにオーバーライドされて「inventory file or script group vars (local)」が入るはず

Playbook実行
# ansible-playbook -i inventory site.yml

PLAY [test ansible var precedence] *********************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [localhost]

TASK [test_role : test02 - role defaults] **************************************************************************
ok: [localhost] => {
    "var_test02": "This is 'role defaults'"
}

TASK [test_role : test03 - inventory file or script group vars] ****************************************************
ok: [localhost] => (item=1) => {
    "ansible_loop_var": "item",
    "item": 1,
    "var_test03_1": "This is 'inventory file or script group vars (all)'"
}
ok: [localhost] => (item=2) => {
    "ansible_loop_var": "item",
    "item": 2,
    "var_test03_2": "This is 'inventory file or script group vars (local)'"
}

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

ちょっと待った

ここでファイル構造の都合が悪いことがわかったのでちょっと構成を変更
inventoryフォルダを作って、その中にインベントリファイルを置く、ついでに名前をhostsに
ファイルの内容は今までのinventoryと一緒

ディレクトリ構成
.
├── inventory
│   └── hosts
├── roles
│   └── test_role
│       ├── defaults
│       │   └── main.yml
│       └── tasks
│           └── main.yml
└── site.yml

一応動作確認(Playbook実行コマンドは変わる)

Playbook実行
# ansible-playbook -i inventory/hosts site.yml

PLAY [test ansible var precedence] *********************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [localhost]

TASK [test_role : test02 - role defaults] **************************************************************************
ok: [localhost] => {
    "var_test02": "This is 'role defaults'"
}

TASK [test_role : test03 - inventory file or script group vars] ****************************************************
ok: [localhost] => (item=1) => {
    "ansible_loop_var": "item",
    "item": 1,
    "var_test03_1": "This is 'inventory file or script group vars (all)'"
}
ok: [localhost] => (item=2) => {
    "ansible_loop_var": "item",
    "item": 2,
    "var_test03_2": "This is 'inventory file or script group vars (local)'"
}

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

04. inventory group_vars/all

<インベントリファイルが置いてあるパス>/group_vars/all.ymlに書いてあるやつ(もしくはallフォルダの中の任意のyamlファイルでも良いっぽい)

ディレクトリ構成
.
├── inventory
│   ├── group_vars
│   │   └── all.yml
│   └── hosts
├── roles
│   └── test_role
│       ├── defaults
│       │   └── main.yml
│       └── tasks
│           └── main.yml
└── site.yml
inventory/hosts
[local]
localhost

# allは「全てのホスト」を意味するビルトインのグループ
[all:vars]
var_test03_1="This is 'inventory file or script group vars (all)'"
var_test03_2="This is 'inventory file or script group vars (all)'"
var_test04_1="This is 'inventory file or script group vars (all)'"

# 定義しているグループで指定、もちろんallより強くなる
[local:vars]
var_test03_2="This is 'inventory file or script group vars (local)'"
var_test04_2="This is 'inventory file or script group vars (all)'"
inventory/group_vars/all.yml
---
var_test04_1: "This is 'inventory group_vars/all'"
var_test04_2: "This is 'inventory group_vars/all'"
roles/test_role/tasks/main.yml(長くなってしまうので差分のみ)
- name: "test04 - inventory group_vars/all"
  debug: var=var_test04_{{ item }}
  with_items: [1, 2]

公式ドキュメントの順位によれば、var_test04_1var_test04_2はともに、inventory/group_vars/all.ymlに書いてある値になるはず

Playbook実行(長くなってしまうので一部のみ)
TASK [test_role : test04 - inventory group_vars/all] ***************************************************************
ok: [localhost] => (item=1) => {
    "ansible_loop_var": "item",
    "item": 1,
    "var_test04_1": "This is 'inventory group_vars/all'"
}
ok: [localhost] => (item=2) => {
    "ansible_loop_var": "item",
    "item": 2,
    "var_test04_2": "This is 'inventory group_vars/all'"
}

なりました

05. playbook group_vars/all

inventory group_vars/allと似たような感じで、<Playbookが置いてあるパス>/group_vars/all.ymlに書くってことかな?

ディレクトリ構成
.
├── group_vars
│   └── all.yml
├── inventory
│   ├── group_vars
│   │   └── all.yml
│   └── hosts
├── roles
│   └── test_role
│       ├── defaults
│       │   └── main.yml
│       └── tasks
│           └── main.yml
└── site.yml
inventory/group_vars/all.yml
---
var_test04_1: "This is 'inventory group_vars/all'"
var_test04_2: "This is 'inventory group_vars/all'"
var_test05: "This is 'inventory group_vars/all'"
group_vars/all.yml
---
var_test05: "This is 'playbook group_vars/all'"
roles/test_role/tasks/main.yml(差分のみ)
- name: "test05 - playbook group_vars/all"
  debug: var=var_test05
Playbook実行(一部のみ)
TASK [test_role : test05 - playbook group_vars/all] ****************************************************************
ok: [localhost] => {
    "var_test05": "This is 'playbook group_vars/all'"
}

へぇーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー(初めて知ったマン)

06. inventory group_vars/*

07. playbook group_vars/*

group_varsをall.ymlじゃなくてlocal.ymlに書くだけ、似てるので2つまとめてやる

ディレクトリ構成
.
├── group_vars
│   ├── all.yml
│   └── local.yml
├── inventory
│   ├── group_vars
│   │   ├── all.yml
│   │   └── local.yml
│   └── hosts
├── roles
│   └── test_role
│       ├── defaults
│       │   └── main.yml
│       └── tasks
│           └── main.yml
└── site.yml
group_vars/all.yml
---
var_test05: "This is 'playbook group_vars/all'"
var_test06: "This is 'playbook group_vars/all'"
inventory/group_vars/local.yml
---
var_test06: "This is 'inventory group_vars/*'"
var_test07: "This is 'inventory group_vars/*'"
group_vars/local.yml
---
var_test07: "This is 'playbook group_vars/*'"
roles/test_role/tasks/main.yml(差分のみ)
- name: "test06 - inventory group_vars/*"
  debug: var=var_test06

- name: "test07 - playbook group_vars/*"
  debug: var=var_test07
Playbook実行(一部のみ)
TASK [test_role : test06 - inventory group_vars/*] *****************************************************************
ok: [localhost] => {
    "var_test06": "This is 'inventory group_vars/*'"
}

TASK [test_role : test07 - playbook group_vars/*] ******************************************************************
ok: [localhost] => {
    "var_test07": "This is 'playbook group_vars/*'"
}

この辺知らないでinventory group_varsもplaybook group_varsも使ってるとハマりそうだなーとか思ったりした

まとめ:group_varsの優先順位
inventory group_vars/all
    < playbook group_vars/all
        < inventory group_vars/*
            < playbook group_vars/*

08. inventory file or script host vars

03. inventory file or script group varsのホストver
iniファイル形式の場合host_varsはホスト名の後ろに書くみたい。インベントリファイルもyamlの方が書きやすそうだ

inventory/hosts
[local]
localhost var_test08="This is 'inventory file or script host vars'"

# allは「全てのホスト」を意味するビルトインのグループ
[all:vars]
var_test03_1="This is 'inventory file or script group vars (all)'"
var_test03_2="This is 'inventory file or script group vars (all)'"
var_test04_1="This is 'inventory file or script group vars (all)'"

# 定義しているグループで指定、もちろんallより強くなる
[local:vars]
var_test03_2="This is 'inventory file or script group vars (local)'"
var_test04_2="This is 'inventory file or script group vars (all)'"
inventory/group_vars/local.yml
---
var_test06: "This is 'inventory group_vars/*'"
var_test07: "This is 'inventory group_vars/*'"
var_test08: "This is 'inventory group_vars/*'"
roles/test_role/tasks/main.yml(差分のみ)
- name: "test08 - inventory file or script host vars"
  debug: var=var_test08
Playbook実行(一部のみ)
TASK [test_role : test08 - inventory file or script host vars] *****************************************************
ok: [localhost] => {
    "var_test08": "This is 'inventory file or script host vars'"
}

09. inventory host_vars/*

10. playbook host_vars/*

06. inventory group_vars/*07. playbook group_vars/*のホストver
host_varsに「all」はないようである

ディレクトリ構成
.
├── group_vars
│   ├── all.yml
│   └── local.yml
├── host_vars
│   └── localhost.yml
├── inventory
│   ├── group_vars
│   │   ├── all.yml
│   │   └── local.yml
│   ├── host_vars
│   │   └── localhost.yml
│   └── hosts
├── roles
│   └── test_role
│       ├── defaults
│       │   └── main.yml
│       └── tasks
│           └── main.yml
└── site.yml

にわかに「これがAnsibleディレクトリ構成のベストプラクティスだよワッショイショイ!!」みたいなドキュメントで見る形になってきた

inventory/hosts
[local]
localhost var_test08="This is 'inventory file or script host vars'" var_test09="This is 'inventory host_vars/*'"

# allは「全てのホスト」を意味するビルトインのグループ
[all:vars]
var_test03_1="This is 'inventory file or script group vars (all)'"
var_test03_2="This is 'inventory file or script group vars (all)'"
var_test04_1="This is 'inventory file or script group vars (all)'"

# 定義しているグループで指定、もちろんallより強くなる
[local:vars]
var_test03_2="This is 'inventory file or script group vars (local)'"
var_test04_2="This is 'inventory file or script group vars (all)'"
inventory/host_vars/localhost.yml
---
var_test09: "This is 'inventory host_vars/*'"
var_test10: "This is 'inventory host_vars/*'"
host_vars/localhost.yml
---
var_test10: "This is 'playbook host_vars/*''"
roles/test_role/tasks/main.yml(差分のみ)
- name: "test09 - inventory host_vars/*"
  debug: var=var_test09

- name: "test10 - inventory host_vars/*"
  debug: var=var_test10
Playbook実行(一部のみ)
TASK [test_role : test09 - inventory host_vars/*] ******************************************************************
ok: [localhost] => {
    "var_test09": "This is 'inventory host_vars/*'"
}

TASK [test_role : test10 - inventory host_vars/*] ******************************************************************
ok: [localhost] => {
    "var_test10": "This is 'playbook host_vars/*''"
}

11. host facts / cached set_facts

host factsはLocal facts (facts.d)のことかな?
/etc/ansible/facts.d/*.factなファイルを参照して設定されるfactのことで、こんな感じのところに読み込まれる

{{ ansible_local['preferences']['general']['asdf'] }}

また、cached set_factsについてはCaching Factsに書かれている
「とってきたfactはオプションをオンにしておくとキャッシュすることができて、それをPlaybook実行時に使えるから強い」みたいなことが書いてある(適当)

With a very large infrastructure with thousands of hosts, fact caching could be configured to run nightly. Configuration of a small set of servers could run ad-hoc or periodically throughout the day. With fact caching enabled, it would not be necessary to “hit” all servers to reference variables and information about them.

With fact caching enabled, it is possible for machine in one group to reference variables about machines in the other group, despite the fact that they have not been communicated with in the current execution of /usr/bin/ansible-playbook.

こんな感じのところに読み込まれる

{{ hostvars['asdf.example.com']['ansible_facts']['os_family'] }}

格納される場所を見る感じ、これらは他の変数定義で上書きするようなモノではなさそうである、割愛

12. play vars

PLAYに対して指定するvars

host_vars/localhost.yml
---
var_test10: "This is 'playbook host_vars/*''"
var_test12: "This is 'playbook host_vars/*''"
site.yml
---
- name: "test ansible var precedence"
  hosts: all
  vars:
    - var_test12: "This is 'play vars'"
  roles:
    - test_role
roles/test_role/tasks/main.yml(差分のみ)
- name: "test12 - play vars"
  debug: var=var_test12
Playbook実行(一部のみ)
TASK [test_role : test12 - play vars] ******************************************************************************
ok: [localhost] => {
    "var_test12": "This is 'play vars'"
}

13. play vars_prompt

vars_promptはPlaybook実行時に変数の入力をさせる機能、詳細はPrompts参照

site.yml
---
- name: "test ansible var precedence"
  hosts: all
  vars:
    - var_test12: "This is 'play vars'"
    - var_test13: "This is 'play vars'"
  vars_prompt:
    - name: var_test13
      prompt: "input var_test13"
      private: no
  roles:
    - test_role
roles/test_role/tasks/main.yml(差分のみ)
- name: "test13 - play vars_prompt"
  debug: var=var_test13
Playbook実行(一部のみ)
# ansible-playbook -i inventory/hosts site.yml
input var_test13: This is 'play vars_prompt'

Playbook実行時にプロンプトが出てきて変数に格納される

TASK [test_role : test13 - play vars_prompt] ***********************************************************************
ok: [localhost] => {
    "var_test13": "This is 'play vars_prompt'"
}

これよりも強い変数があるってことは、上書きされる可能性があるということか…入力させといて上書きされたら結構ショックかもしれないな(´・ω・`)

14. play vars_files

vars_filesディレクティブで明示的にインポートする変数。vars_promptより強いのは意識しておかないとハマるかも?

ディレクトリ構成
.
├── group_vars
│   ├── all.yml
│   └── local.yml
├── host_vars
│   └── localhost.yml
├── inventory
│   ├── group_vars
│   │   ├── all.yml
│   │   └── local.yml
│   ├── host_vars
│   │   └── localhost.yml
│   └── hosts
├── roles
│   └── test_role
│       ├── defaults
│       │   └── main.yml
│       └── tasks
│           └── main.yml
├── site.yml
└── vars_files_test.yml
vars_files_test.yml
---
var_test14: "This is 'play vars_files'"
site.yml
---
- name: "test ansible var precedence"
  hosts: all
  vars:
    - var_test12: "This is 'play vars'"
    - var_test13: "This is 'play vars'"
  vars_prompt:
    - name: var_test13
      prompt: "input var_test13"
      private: no
    - name: var_test14
      prompt: "input var_test14"
      private: no
  vars_files:
    - vars_files_test.yml
  roles:
    - test_role
roles/test_role/tasks/main.yml(差分のみ)
- name: "test14 - play vars_files"
  debug: var=var_test14
Playbook実行(一部のみ)
# ansible-playbook -i inventory/hosts site.yml
input var_test13: This is 'play vars_prompt'
input var_test14: This is 'play vars_prompt'
TASK [test_role : test14 - play vars_files] ************************************************************************
ok: [localhost] => {
    "var_test14": "This is 'play vars_files'"
}

15. role vars (defined in role/vars/main.yml)

もはや説明不要な変数記載場所、キミ実は結構強めの位置なんだね!

ディレクトリ構成
.
├── group_vars
│   ├── all.yml
│   └── local.yml
├── host_vars
│   └── localhost.yml
├── inventory
│   ├── group_vars
│   │   ├── all.yml
│   │   └── local.yml
│   ├── host_vars
│   │   └── localhost.yml
│   └── hosts
├── roles
│   └── test_role
│       ├── defaults
│       │   └── main.yml
│       ├── tasks
│       │   └── main.yml
│       └── vars
│           └── main.yml
├── site.yml
└── vars_files_test.yml
roles/test_role/vars/main.yml
---
var_test15: "This is 'role vars'"
vars_files_test.yml
---
var_test14: "This is 'play vars_files'"
var_test15: "This is 'play vars_files'"
roles/test_role/tasks/main.yml(差分のみ)
- name: "test15 - role vars"
  debug: var=var_test15
Playbook実行(一部のみ)
TASK [test_role : test15 - role vars] ******************************************************************************
ok: [localhost] => {
    "var_test15": "This is 'role vars'"
}

16. block vars (only for tasks in block)

17. task vars (only for the task)

BLOCK < TASKの順に強くなる、まぁそりゃそうだよね

roles/test_role/vars/main.yml
---
var_test15: "This is 'role vars'"
var_test16: "This is 'role vars'"
roles/test_role/tasks/main.yml(差分のみ)
- block:
  - name: "test16 - block vars"
    debug: var=var_test16
  - name: "test17 - task vars"
    debug: var=var_test17
    vars:
      - var_test17: "This is 'task vars'"
  vars:
    - var_test16: "This is 'block vars'"
    - var_test17: "This is 'block vars'"
Playbook実行(一部のみ)
TASK [test_role : test16 - block vars] *****************************************************************************
ok: [localhost] => {
    "var_test16": "This is 'block vars'"
}

TASK [test_role : test17 - task vars] ******************************************************************************
ok: [localhost] => {
    "var_test17": "This is 'task vars'"
}

単純にPLAY < BLOCK < TASKじゃなくてPLAY < role vars < BLOCK < TASKなのはちょっと違和感あるかもな?

18. include_vars

include_vars – Load variables from files, dynamically within a taskで読み込む変数
↑見るとわかるけど、読み込みの仕方が実は色々あるみたい、知らなかった!
今回は一番シンプルなやつで

ディレクトリ構成
.
├── group_vars
│   ├── all.yml
│   └── local.yml
├── host_vars
│   └── localhost.yml
├── include_vars_test.yml
├── inventory
│   ├── group_vars
│   │   ├── all.yml
│   │   └── local.yml
│   ├── host_vars
│   │   └── localhost.yml
│   └── hosts
├── roles
│   └── test_role
│       ├── defaults
│       │   └── main.yml
│       ├── tasks
│       │   └── main.yml
│       └── vars
│           └── main.yml
├── site.yml
└── vars_files_test.yml
include_vars_test.yml
---
var_test18: "This is 'include_vars'"
roles/test_role/tasks/main.yml(差分のみ)
- name: "include_vars"
  include_vars: include_vars_test.yml

- name: "test18 - include_vars"
  debug: var=var_test18
  vars:
    - var_test18: "This is 'task vars'"
Playbook実行(一部のみ)
TASK [test_role : include_vars] ************************************************************************************
ok: [localhost]

TASK [test_role : test18 - include_vars] ***************************************************************************
ok: [localhost] => {
    "var_test18": "This is 'include_vars'"
}

19. set_facts / registered vars

前者はset_fact – Set host facts from a taskで設定する変数
factなのでfact_cacheが効いたり、グローバル変数っぽい感じになったりする

後者はRegister Variables参照
これで他変数を上書きするケースってあんまり無いような気がする

ということでset_factだけやるます

include_vars_test.yml
---
var_test18: "This is 'include_vars'"
var_test19: "This is 'include_vars'"
roles/test_role/tasks/main.yml(差分のみ)
- name: "set_facts"
  set_fact:
    var_test19: "This is 'set_facts'"

- name: "test19 - set_facts"
  debug: var=var_test19
Playbook実行(一部のみ)
TASK [test_role : set_facts] ***************************************************************************************
ok: [localhost]

TASK [test_role : test19 - set_facts] ******************************************************************************
ok: [localhost] => {
    "var_test19": "This is 'set_facts'"
}

20. role (and include_role) params

role実行時にパラメータ渡しができるらしい → Role Duplication and Execution

site.yml
---
- name: "test ansible var precedence"
  hosts: all
  vars:
    - var_test12: "This is 'play vars'"
    - var_test13: "This is 'play vars'"
  vars_prompt:
    - name: var_test13
      prompt: "input var_test13"
      private: no
    - name: var_test14
      prompt: "input var_test14"
      private: no
  vars_files:
    - vars_files_test.yml
  roles:
    - role: test_role
      var_test20: "This is 'role (and include_role) params'"
roles/test_role/tasks/main.yml(差分のみ)
- name: "set_facts"
  set_fact:
    var_test19: "This is 'set_facts'"
    var_test20: "This is 'set_facts'"

- name: "test19 - set_facts"
  debug: var=var_test19

- name: "test20 - role (and include_role) params"
  debug: var=var_test20

Playbook実行(一部のみ)
TASK [test_role : test20 - role (and include_role) params] *********************************************************
ok: [localhost] => {
    "var_test20": "This is 'role (and include_role) params'"
}

21. include params

情報がなかなか見つけられなくて苦労した…
include – Include a play or task listと同時に変数指定するパターンのことだと思う

ディレクトリ構成
.
├── group_vars
│   ├── all.yml
│   └── local.yml
├── host_vars
│   └── localhost.yml
├── include_vars_test.yml
├── inventory
│   ├── group_vars
│   │   ├── all.yml
│   │   └── local.yml
│   ├── host_vars
│   │   └── localhost.yml
│   └── hosts
├── roles
│   └── test_role
│       ├── defaults
│       │   └── main.yml
│       ├── tasks
│       │   ├── main.yml
│       │   └── test21.yml
│       └── vars
│           └── main.yml
├── site.yml
└── vars_files_test.yml
site.yml
---
- name: "test ansible var precedence"
  hosts: all
  vars:
    - var_test12: "This is 'play vars'"
    - var_test13: "This is 'play vars'"
  vars_prompt:
    - name: var_test13
      prompt: "input var_test13"
      private: no
    - name: var_test14
      prompt: "input var_test14"
      private: no
  vars_files:
    - vars_files_test.yml
  roles:
    - role: test_role
      var_test20: "This is 'role (and include_role) params'"
      var_test21: "This is 'role (and include_role) params'"
roles/test_role/tasks/test21.yml
---
- name: "test21 - include params"
  debug: var=var_test21
roles/test_role/tasks/main.yml(差分のみ)
- name: "include test21"
  include: test21.yml
  var_test21: "This is 'include params'"
Playbook実行(一部のみ)
TASK [test_role : test21 - include params] *************************************************************************
ok: [localhost] => {
    "var_test21": "This is 'include params'"
}

なお、このPlaybookの実行時は以下のWARNINGが出たので、この方式で変数を書くのはやめておいた方が良さそう

[DEPRECATION WARNING]: Specifying include variables at the top-level of the task is deprecated. Please see:
https://docs.ansible.com/ansible/playbooks_roles.html#task-include-files-and-encouraging-reuse   for currently
supported syntax regarding included files and variables. This feature will be removed in version 2.12. Deprecation
warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.

ちなみに、include_tasksで以下のように書いてもsyntax errorになるので注意

- name: "include test21"
  include_tasks: test21.yml
  var_test21: "This is 'include_tasks params'"
ERROR! 'var_test21' is not a valid attribute for a TaskInclude

The error appears to be in '/Users/answer_d/work/ansible_var_pecedence_test/roles/test_role/tasks/main.yml': line 78, column 3, but may
be elsewhere in the file depending on the exact syntax problem.

(2019/08/23追記)
これならinclude_tasksでもいけました

- name: "include test21"
  include_tasks: test21.yml
  vars:
    var_test21: "This is 'include params'"
TASK [test_role : test21 - include params] ******************************************************************************
ok: [localhost] => {
    "var_test21": "This is 'include params'"
}

書き方はtask varsと一緒っぽいけど、role (and include_role) paramsをしっかり上書きしているので優先度が違っているのがわかる
こっちだとDEPRECATION WARNINGは出ないので今後使うならこれ

22. extra vars (always win precedence)

Playbook実行時に-eをつけて変数を書くやり方、こいつが最強

roles/test_role/tasks/test21.yml
---
- name: "test21 - include params"
  debug: var=var_test21

- name: "test22 - extra vars"
  debug: var=var_test22
roles/test_role/tasks/main.yml(差分のみ)
- name: "include test21"
  include: test21.yml
  var_test21: "This is 'include params'"
  var_test22: "This is 'include params'"
Playbook実行(一部のみ)
# ansible-playbook -i inventory/hosts site.yml -e '{"var_test22":"This is \'extra vars\'"}'
TASK [test_role : test22 - extra vars] *****************************************************************************
ok: [localhost] => {
    "var_test22": "This is 'extra vars'"
}
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away