In this lab we will continue our journey with Ansible by learning about variables, facts, and includes.
There are multiple ways that variables can be utilized in Ansible to store values that can be reused to simplify the creation and maintenance of a project while reducing errors.
Using variables provide a convenient way to manage dynamic values for a given environment in your Ansible project. Some examples of values that variables might contain include:
-
credentials (user and passwords)
-
file names
-
file paths
-
urls
Variables should have names which consist of a string that must start with a letter and can only contain letters, numbers, and underscores. Here is a list of variables named using the correct terminology:
-
user_name
-
file_1
-
file_2
-
openstack_api_url
You could define variables in multiple ways for the execution, and there are three scope levels where a variable could be defined:
-
Global scope: Global scope variables are set from the command line or in the Ansible configuration file
-
Play scope: Play scope variables are set in the play and related structures
-
Host scope: Host scope variables are set on host groups and individual hosts by the inventory, fact gathering, or registered tasks
There is something fundamental to know when defining variables: if the same variable name is set at more than one level, the higher wins. Here is an example: if the variable openstack_api_url is defined by the inventory, could be overridden if the same variable is defined at the playbook, and that could be overridden if defined on the command line.
You could define variables in Playbooks, for example, a variable glance_image_name can be defined with a value of CirrOS.img. This could be defined in multiple ways, as exemplified below:
-
In vars block at the beginning of Playbook:
- hosts: localhost
vars:
glance_image_name: CirrOS.img
openstack_api_url: https://api.magicasaservice.com:8773
-
In an external variable file:
- hosts: localhost
vars_files:
- vars/os_vars.yml
Inside the variable file, variables are defined in YAML format:
glance_image_name: CirrOS.img
openstack_api_url: https://api.magicasaservice.com
Now, to use the variable, you need to reference it inside double curly braces {{ }}. Ansible will substitute the variable with its value when the task is executed:
- hosts: localhost
vars:
glance_image_name: CirrOS.img
openstack_api_url: https://api.magicasaservice.com:8773
tasks:
- name: Upload Glance Image
os_image:
auth: "{{ openstack_api_url }}"
username: admin
password: ansible
project_name: admin
name: CirrOS
container_format: bare
disk_format: qcow2
state: present
filename: "{{ glance_image_name }}"
kernel: cirros-vmlinuz
ramdisk: cirros-initrd
properties:
cpu_arch: x86_64
ditro: ubuntu
In the previous example, we are using the variables declared for the openstack_api_url and glance_image_name. Also, notice the quotes, we are using them because we are declaring variables as the first element starting the value.
There is another type of variable in Ansible that is applied at the inventory level. They can be host variables, that apply to specific hosts and group variables, that use all hosts under a group.
-
Here is an example for a host variable:
[servers]
ansible1.magicasaservice.com ansible_user=ansible_i2
-
Here is an example for a group variable:
[servers]
ansible1.magicasaservice.com
ansible2.magicasaservice.com
[servers:vars]
ansible_user=ansible_i2
For more detail on host and group variables, please visit: here .
Facts in Ansible are variables that are automatically discovered. Facts contain host-specific information that can be used just like regular variables.
Some of the facts gathered for a managed host might include:
-
Host name
-
Kernel version
-
IP addresses
-
OS version
-
and more…
Every play runs the setup module automatically before the first task to gather facts from the managed node. You don’t need to have a task to run setup in your play; it is automatically run for you by Ansible.
Here is an example playbook that shows the running kernel and hostname of a system:
---
- hosts: all
tasks:
- name: Prints various Ansible facts
debug:
msg: >
The running Kernel of {{ ansible_hostname }}
is {{ ansible_kernel }}
In order to see how the Setup module works, please check: http://docs.ansible.com/ansible/latest/modules/setup_module.html
For more details about facts: http://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#information-discovered-from-systems-facts
A best practice when writing complex or lengthy playbooks is to use separate files to divide tasks and lists of variables for more natural management. There are multiple ways to include task files and variables in a playbook.
-
Tasks can be included in a playbook from an external file:
tasks:
- name: Include tasks to manage Images on OpenStack
include: tasks/os_image.yml
also, you could use the include_vars as previously show to include variables from JSON or YAML files:
- hosts: localhost
vars_files:
- vars/os_vars.yml
Using multiple, external files for tasks and variables is a convenient way to build the main playbook in a modular way. You could use the include directive to have a task file inserted at a particular point in a playbook.