Understanding Ansible variables

Most of the examples we have looked at so far have been static in nature. This is fine for the simplest playbook examples, but in many cases, it is desirable to be able to either store values or define them easily in a central place, rather than having to go hunting through a playbook (and tree of roles) for a specific hardcoded value. As in other languages, it is also desirable to capture values somehow, for reuse later.

There are many different types of variables in Ansible, and it is important to know that they have a strict order of precedence. Although we won't encounter this much in this book, it is important to be aware of this, as you might otherwise receive unexpected results from your variables.

In short, variables can be defined in a number of locations, and the right location for a given scenario will be driven by the objective of the playbook. For example, if a variable is common to an entire group of servers, it would be logical to define it in the inventory as a group variable. If it applies to every host a specific playbook runs against regardless, then you would almost certainly define it in the playbook. Let's take a quick look at this by modifying our simple.yml playbook from earlier in this chapter, this time, defining a play variable called message for our debug statement to display when the playbook is run, as follows:

---
- name: Simple playbook
hosts: localhost
become: false

vars:
message: "Life is beautiful!"

tasks:
- name: Show a message
debug:
msg: "{{ message }}"
- name: Touch a file
file:
path: /tmp/foo
state: touch

Note that we have now defined a vars section before the tasks one and that the variable is accessed by placing it in pairs of curly braces. Running this playbook yields the following results:

If you refer to the variable precedence order list, you will note that variables passed to the ansible-playbook binary on the command line are top of the list, and override all other variables. Thus, if we want to override the contents of our message variable without editing the playbook, we can do so as follows:

$ ansible-playbook simple.yml -e "message="Hello from the CLI""

Note the special quoting and escaping required to handle the spaces in the variable content, and the effects of this on the operation of the playbook:

Variables can also be passed to roles, and are a simple yet powerful way of creating generic roles that can be used in a multitude of scenarios, without using identical configuration data. For example, in the previous section, we explored installing a MariaDB server. While this is a good candidate for a role, you certainly don't want the same root database password to be configured on every server. It thus makes sense to define a variable for the password, and pass this to the role from the calling playbook (or another appropriate source, such as a host or group variable).

As well as user-defined variables, Ansible also has a number of built-in variables, referred to as special variables. These can be accessed from anywhere in the playbook, and are useful for obtaining certain details pertaining to the state of the play.

For example, if you needed to know the hostname currently being acted upon for a specific task, this is available through the inventory_hostname variable. A full list of these variables is available at https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html

Many readers will, by now, have noticed that the output from all our example playbooks contains a line that says Gathering Facts. Although this can be turned off, it is, in fact, incredibly useful, and populates a wide array of variables with useful key system data. To get an idea of the kind of data gathered during this phase, run the following code from the command line:

$ ansible -m setup localhost

This command, rather than running a playbook, instructs Ansible to run the setup module directly on the localhostthe setup module is the one that is run behind the scenes, during the Gathering Facts stage. The output will look something like this, and goes on for pages—this is just the first few lines:

We can immediately see there is some really useful information there, such as the IP addresses of the host, the root volume, and so on. Remember our discussion about commonality in Chapter 1, Building a Standard Operating Environment on Linux, and the difficulty in detecting the operating system you are running against? Well, Ansible makes this easy, as that data is all readily available in the gathered facts. We can modify our debug statement to display the Linux distribution we are running against, simply by specifying the appropriate fact, accessible from the output from the last command, as follows:

    - name: Show a message
debug:
msg: "{{ ansible_distribution }}"

Now, when we run the playbook, we can easily tell we are running on Ubuntu, as can be seen in the following screenshot:

Ansible enables you to conditionally run individual tasks, roles, or even entire blocks of tasks, and hence having access to facts makes it straightforward to write robust playbooks that can be run against multiple platforms and perform the correct actions on each platform. 

It is also worth noting that variables do not need to be stored in unencrypted text. Occasionally, it might be necessary to store a password in a variable (as discussed earlier—perhaps the root password for our MariaDB server install). Storing those details in plain text format presents a big security risk, but fortunately, Ansible includes a technology called Vault, which is capable of storing variable data encrypted using AES256. These encrypted vaults can be referenced by any playbook, provided the vault password is passed to the playbook when it is run. Vaults are beyond the scope of this chapter, but if you would like to read more about them, please see https://docs.ansible.com/ansible/latest/user_guide/playbooks_vault.html. In this book, we will not use them extensively, simply to keep the example code concise. However, it is strongly recommended that in a production environment, you use vaults wherever sensitive data for a playbook needs to be stored.

Now that we have introduced the concept of variables in Ansible, and the various types available, let's take a look at an important means for managing configuration files in Ansible—the use of templates.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset