Extra variables
You may have seen in our template example in the previous chapter that we used a
variable called group_names . This is one of the magic variables that are provided by
Ansible itself. At the time of writing there are seven such variables, described in the
following sections.
hostvars allows you to retrieve variables about all the hosts that the current play
has dealt with. If the setup module hasn't yet been run on that host in the current
play, only its variables will be available. You can access it like you would access
other complex variables, such as ${hostvars.hostname.fact} , so to get the Linux
distribution running on a server named ns1 , it would be ${hostvars.ns1.ansible_
distribution} . The following example sets a variable called zone master to the
server named ns1 . It then calls the template module, which would use this to set the
masters for each zone.
---
#1
- name: Setup DNS Servers
#2
hosts: allnameservers
#3
tasks:
#4
- name: Install BIND
#5
yum: name=named state=installed
#6
- name: Setup Slaves
#7
hosts: slavenamesservers
#8
tasks:
#9
- name: Get the masters IP
#10
set_fact: dns_master="{{
hostvars.ns1.ansible_default_ipv4.address }}"
- name: Configure BIND
#12
template: dest=/etc/named.conf
src/templates/named.conf.j2
#11
#13
Using hostvars, you can further abstract templates from your
environment. If you nest your variable calls, then instead of placing an
IP address in the variable section of the play, you can add the hostname.
To find the address of a machine named in the variable the_machine
you would use, {{ hostvars.[the_machine].default_ipv4.
address }}.
The groups variable
The groups variable contains a list of all hosts in the inventory grouped by the
inventory group. This lets you get access to all the hosts that you have configured.
This is potentially a very powerful tool. It allows you to iterate across a whole group
and for every host apply an action to the current machine.
---
- name: Configure the database
hosts: dbservers
user: root
tasks:
- name: Install mysql
yum: name={{ item }} state=installed
with_items:
- mysql-server
- MySQL-python
- name: Start mysql
service: name=mysqld state=started enabled=true
- name: Create a user for all app servers
with_items: groups.appservers
mysql_user: name=kate password=test host={{
hostvars.[item].ansible_eth0.ipv4.address }}
state=present
You can even use this variable to create known_hosts files for all of your machines
containing the host keys of all the other machines. This would allow you to then SSH
from one machine to another without confirming the identity of the remote host. It
would also handle removing machines when they leave service or updating them when
they are replaced. The following is a template for a known_hosts file that does this:
{% for host in groups['all'] %}
{{ hostvars[host]['ansible_hostname'] }}
{{
hostvars[host]['ansible_ssh_host_key_rsa_public'] }}
{% endfor %}
The playbook that uses this template would look like this:
---
hosts: all
tasks:
- name: Setup known hosts
hosts: all
tasks:
- name: Create known_hosts
template: src=templates/known_hosts.j2
dest=/etc/ssh/ssh_known_hosts owner=root group=root
mode=0644
state=present
你甚至可以使用这个变量,创建一个known_hosts文件,包含所有这台主机已知的其他主机,然后应用给你的所有主机。这样当你使用ssh从一台机器登陆到另外一台的时候就不需要身份验证了。它也可以处理在服务断开或则因更新时被替换时,用来移除主机。下面是known_hosts文件模板的代码:
{% for host in groups['all'] %}
The group_names variable
The group_names variable contains a list of strings with the names of all the
groups the current host is in. This is not only useful for debugging, but also for
conditionals detecting group membership. This was used in the last chapter to
set up a nameserver.
This variable is mostly useful for skipping a task or in a template as a condition. For
instance, if you had two configurations for the SSH daemon, one secure and one less
secure, but you only wanted the secure configuration on the machines in the secure
group, you would do it like this:
- name: Setup SSH
hosts: sshservers
tasks:
- name: For secure machines
set_fact: sshconfig=files/ssh/sshd_config_secure
when: "'secure' in group_names"
- name: For non-secure machines
set_fact: sshconfig=files/ssh/sshd_config_default
when: "'secure' not in group_names"
- name: Copy over the config
copy: src={{ sshconfig }} dest=/tmp/sshd_config
In the previous example, we used the set_fact module to set the fact
for each case, and then used the copy module. We could have used
the copy module in place of the set_facts modules and used one
fewer task. The reason this was done is that the set_fact module
runs locally and the copy module runs remotely. When you use the
set_facts module first and only call the copy module once, the copies
are made on all the machines in parallel. If you used two copy modules
with conditions, then each would execute on the relevant machines
separately. Since copy is the longer task of the two, it benefits the most
from running in parallel.
The inventory_hostname variable
The inventory_hostname variable stores the hostname of the server as recorded in
the inventory. You should use this if you have chosen not to run the setup module
on the current host, or if for various reasons the value detected by the setup module
is not correct. This is useful when you are doing the initial setup of the machine and
changing the hostname.
The inventory_hostname_short variable
The inventory_hostname_short variable is the same as the previous variable;
however, it only includes the characters up to the first dot. So for host.example.
com , it would return host .
The inventory_dir variable
The inventory_dir variable is the path name of the directory containing the
inventory file.
The inventory_file variable
The inventory_file variable is the same as the previous one, except it also includes
the filename.