Ansible Playbookで利用できる、マジック変数たち。
公式docに一覧がなかったので、一覧にしてみた。
マジック変数とは
Ansible Playbookには gather_facts:False
でも使える変数がある。
「定義済み変数」であり、マジック変数 と呼ばれる。
主に、インベントリに関する情報が得られる。
マジック変数の一覧
値は、Playbookを実行しているターゲットマシン毎にセットされる。
変数名 | 内容 |
---|---|
group_names |
このターゲットマシンが属する全グループの一覧 |
groups |
グループ-to-ホストのマッピング |
inventory_hostname |
インベントリに書かれたホスト名 |
inventory_hostname_short |
inventory_hostname の最初の "." まで |
play_hosts |
Playbookが適用されるホスト一覧 |
inventory_dir |
インベントリファイルのあるディレクトリパス |
inventory_file |
インベントリファイルのベース名 |
groups
は、グループ階層(グループのグループ)を平たく展開し
グループX:[ ホスト1, ホスト2, ... ]
グループY:[ ホスト1, ホスト2, ホスト3, ... ]
といった形式で、値を保持している。
inventory_hostname_short
は、inventory_hostname
をFQDNと見なしてドメイン部分を除いたホスト名。ただ、IPv4 アドレス xx.yy.zz.ww では "xx" となってしまう。思いもよらないバグとならないよう、使わない方がよいかもしれない。
inventory_{dir,file}
は、{{ inventory_dir ~ "/" ~ inventory_file }}
とすることで、フルパスを構成できる。
Factsのためのマジック変数
重要なマジック変数。
変数名 | 内容 |
---|---|
hostvars |
Playbookを適用する全マシンの facts の集合 |
gather_facts:True
の場合、hostvars
には、Playbook を実行する全マシンの facts が含まれる。
gather_facts:False
だと、値は空になる(未定義ではない)。
★ hostvarsを{{ hostvars["host名"] }}
で参照すると、参照時点で以下のメンバが追加される模様。
追加されるメンバ | 内容 |
---|---|
ansible_connection | sshやlocalなどコネクションタイプ |
group_name | 前述のマジック変数 |
inventory_hostname | 前述のマジック変数 |
inventory_hostname_short | 前述のマジック変数 |
ただ、ドキュメントに記述を見つけられなかった。
公式仕様なのか、たまたまなのか、利用するなら念のため本家に質問したほうがよいかもしれない。
予約済みマジック変数
値は入っていない。ユーザが使ってはいけない変数らしい。
変数名 | 内容 |
---|---|
environment |
予約済み変数 |
実際に取得できた値
小さな Playbook を書いて、マジック変数の値を調べてみた。
groups
の動きを見るため、インベントリに定義したグループは、無理やり階層化している。こんな感じ。
test-servers
+---- test-servers1
| +---- localhost1
|
+---- test-servers2
+---- localhost2
実行結果
まず、取得できた値から示す。
gather_facts:False
で実行している。
[ansibleman@ponet ~]$ ansible-playbook -i hosts magic_vars.yml
PLAY [test-servers] ***********************************************************
TASK: [Facts | ansible_hostname] **********************************************
ok: [localhost1] => {
"ansible_hostname": "{{ ansible_hostname }}"
}
ok: [localhost2] => {
"ansible_hostname": "{{ ansible_hostname }}"
}
TASK: [Facts | ansible_default_ipv4] ******************************************
ok: [localhost1] => {
"ansible_default_ipv4": "{{ ansible_default_ipv4 }}"
}
ok: [localhost2] => {
"ansible_default_ipv4": "{{ ansible_default_ipv4 }}"
}
TASK: [Facts | ansible_env] ***************************************************
ok: [localhost1] => {
"ansible_env": "{{ ansible_env }}"
}
ok: [localhost2] => {
"ansible_env": "{{ ansible_env }}"
}
TASK: [Magic | group_names] ***************************************************
ok: [localhost1] => {
"group_names": [
"test-servers",
"test-servers1"
]
}
ok: [localhost2] => {
"group_names": [
"test-servers",
"test-servers2"
]
}
TASK: [Magic | groups] ********************************************************
ok: [localhost1] => {
"groups": {
"all": [
"localhost1",
"localhost2"
],
"test-servers": [
"localhost1",
"localhost2"
],
"test-servers1": [
"localhost1"
],
"test-servers2": [
"localhost2"
],
"ungrouped": []
}
}
ok: [localhost2] => {
"groups": {
"all": [
"localhost1",
"localhost2"
],
"test-servers": [
"localhost1",
"localhost2"
],
"test-servers1": [
"localhost1"
],
"test-servers2": [
"localhost2"
],
"ungrouped": []
}
}
TASK: [Magic | inventory_hostname] ********************************************
ok: [localhost1] => {
"inventory_hostname": "localhost1"
}
ok: [localhost2] => {
"inventory_hostname": "localhost2"
}
TASK: [Magic | inventory_hostname_short] **************************************
ok: [localhost1] => {
"inventory_hostname_short": "localhost1"
}
ok: [localhost2] => {
"inventory_hostname_short": "localhost2"
}
TASK: [Magic | play_hosts] ****************************************************
ok: [localhost1] => {
"play_hosts": [
"localhost1",
"localhost2"
]
}
ok: [localhost2] => {
"play_hosts": [
"localhost1",
"localhost2"
]
}
TASK: [Magic | inventory_dir] *************************************************
ok: [localhost1] => {
"inventory_dir": "/home/ansibleman"
}
ok: [localhost2] => {
"inventory_dir": "/home/ansibleman"
}
TASK: [Magic | inventory_file] ************************************************
ok: [localhost1] => {
"inventory_file": "hosts"
}
ok: [localhost2] => {
"inventory_file": "hosts"
}
TASK: [Magic for Facts | hostvars] ********************************************
ok: [localhost1] => {
"hostvars": {
"localhost1": {},
"localhost2": {}
}
}
ok: [localhost2] => {
"hostvars": {
"localhost1": {},
"localhost2": {}
}
}
TASK: [Reserved | environment] ************************************************
ok: [localhost1] => {
"environment": {}
}
ok: [localhost2] => {
"environment": {}
}
PLAY RECAP ********************************************************************
localhost1 : ok=12 changed=0 unreachable=0 failed=0
localhost2 : ok=12 changed=0 unreachable=0 failed=0
若干の説明
Factsは、
gather_facts:False
にしたので、未定義変数の状態。debugモジュールでは、未定義変数は文字列として処理される。group_name
では、localhost1 と localhost2 で、ちゃんと別々のグループ一覧を取得できている。play_hosts
では、Playbookを実行する全ターゲットマシン名を取得できている。
少し脇道にそれるが、ansible_hostname
は、ターゲットマシンの本当のホスト名になる。Factsの一つなので、gather_facts:True
にすると、ちゃんとターゲットマシン上で取得して、正しい値が入る。
Playbook
上記の結果を得るために書いた Playbook は、こちら。
--- # file: magic_vars.yml
- hosts: test-servers
gather_facts: "{{ check_env | default(False) }}"
tasks:
# Facts
- name: Facts | ansible_hostname
debug: var=ansible_hostname
- name: Facts | ansible_default_ipv4
debug: var=ansible_default_ipv4
- name: Facts | ansible_env
debug: var=ansible_env
# Magic variables
- name: Magic | group_names
debug: var=group_names
- name: Magic | groups
debug: var=groups
- name: Magic | inventory_hostname
debug: var=inventory_hostname
- name: Magic | inventory_hostname_short
debug: var=inventory_hostname_short
- name: Magic | play_hosts
debug: var=play_hosts
- name: Magic | inventory_dir
debug: var=inventory_dir
- name: Magic | inventory_file
debug: var=inventory_file
# Magic variable for Facts
- name: Magic for Facts | hostvars
debug: var=hostvars
# Reserved magic variable
- name: Reserved | environment
debug: var=environment
check_env
変数をコマンドラインの -e
オプションから与えると、Playbookを書き換えなくても、gather_facts:
を制御できるようにしている。
以下のように実行する。
ansible-playbook -i hosts magic_vars.yml
Factsを収集したいときには、こう。
ansible-playbook -i hosts magic_vars.yml -e "check_env=True"
インベントリと /etc/hosts
利用したインベントリファイルはこちら。
[test-servers1]
localhost1 ansible_connection=local
[test-servers2]
localhost2 ansible_connection=local
[test-servers:children]
test-servers1
test-servers2
/etc/hosts で、インベントリ上のホスト名とIPアドレスを対応付け。
127.0.0.1 localhost localhost.localdomain
127.0.0.1 localhost1
127.0.0.1 localhost2
活用例|ホスト名の一括設定
インベントリに書かれたホスト名を使って、全ターゲットマシンにホスト名を一括設定してみる。
--- # file: set_hostname.yml
- hosts: test-servers
gather_facts: False
tasks:
- name: Set the hostname using the inventory
hostname: name={{ inventory_hostname }}
sudo: yes
インベントリに書いてあるホスト名は、/etc/hostsなどに登録し、IPアドレスと対応させておく。
こんな感じで実行。
$ ansible-playbook -i hosts set_hostname.yml
沢山の仮想マシンを新規に立ち上げ、初期セットアップするときに便利かもしれない。gather_facts:False
なので、動作も軽快。