Variables in playbooks
Sometimes, it is important to set and get variables in a playbook.
Very often, you'll need to automate multiple similar operations. In those cases, you'll want to create a single playbook that can be called with different variables to ensure code reusability.
Another case where variables are very important is when you have more than one data center, and some values will be data center-specific. A common example are the DNS servers. Let's analyze the following simple code that will introduce us to the Ansible way to set and get variables:
- hosts: all remote_user: vagrant tasks: - name: Set variable 'name' set_fact: name: Test machine - name: Print variable 'name' debug: msg: '{{ name }}'
Let's run it in the usual way:
$ ansible-playbook -i test01.fale.io, variables.yaml
You should see the following result:
PLAY [all] *********************************************************
TASK [Gathering Facts] *********************************************
ok: [test01.fale.io]
TASK [Set variable 'name'] *****************************************
ok: [test01.fale.io]
TASK [Print variable 'name'] ***************************************
ok: [test01.fale.io] => {
"msg": "Test machine"
}
PLAY RECAP *********************************************************
test01.fale.io : ok=3 changed=0 unreachable=0 failed=0
If we analyze the code we have just executed, it should be pretty clear what's going on. We set a variable (that in Ansible are called facts) and then we print it with the debug function.
Ansible allows you to set your variables in many different ways – that is, either by passing a variable file, declaring it in a playbook, passing it to the ansible-playbook command using -e / --extra-vars, or by declaring it in an inventory file (we will be discussing this in depth in the next chapter).
It's now time to start using some metadata that Ansible obtained during the setup phase. Let's start by looking at the data that is gathered by Ansible. To do this, we will execute the following code:
$ ansible all -i HOST, -m setup
In our specific case, this means executing the following code:
$ ansible all -i test01.fale.io, -m setup
We can obviously do the same with a playbook, but this way is faster. Also, for the setup case, you will only need to see the output during the development to be sure to use the right variable name for your goal.
The output will be something like this. Full code output is available on GitHub.
test01.fale.io | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.121.190"
],
"ansible_all_ipv6_addresses": [
"fe80::5054:ff:fe93:f113"
],
"ansible_apparmor": {
"status": "disabled"
},
"ansible_architecture": "x86_64",
"ansible_bios_date": "04/01/2014",
"ansible_bios_version": "?-20180531_142017-buildhw-08.phx2.fedoraproject.org-1.fc28",
...
As you can see from this huge list of options, you can gain a huge quantity of information, and you can use them as any other variable. Let's print the OS name and the version. To do so, we can create a new playbook called setup_variables.yaml, with the following content:
- hosts: all
remote_user: vagrant
tasks:
- name: Print OS and version
debug:
msg: '{{ ansible_distribution }} {{ ansible_distribution_version }}'
Run it with the following code:
$ ansible-playbook -i test01.fale.io, setup_variables.yaml
This will give us the following output:
PLAY [all] *********************************************************
TASK [Gathering Facts] *********************************************
ok: [test01.fale.io]
TASK [Print OS and version] ****************************************
ok: [test01.fale.io] => {
"msg": "CentOS 7.5.1804"
}
PLAY RECAP *********************************************************
test01.fale.io : ok=2 changed=0 unreachable=0 failed=0
As you can see, it printed the OS name and version as expected. In addition to the methods seen previously, it's also possible to pass a variable using a command-line argument. In fact, if we look in the Ansible help, we will notice the following:
Usage: ansible <host-pattern> [options]
Options:
-e EXTRA_VARS, --extra-vars=EXTRA_VARS
set additional variables as key=value or YAML/JSON, if
filename prepend with @
The same lines are present in the ansible-playbook command, as well. Let's make a small playbook called cli_variables.yaml, with the following content:
---
- hosts: all
remote_user: vagrant
tasks:
- name: Print variable 'name'
debug:
msg: '{{ name }}'
Execute it with the following:
$ ansible-playbook -i test01.fale.io, cli_variables.yaml -e 'name=test01'
We will receive the following:
[WARNING]: Found variable using reserved name: name
PLAY [all] *********************************************************
TASK [Gathering Facts] *********************************************
ok: [test01.fale.io]
TASK [Print variable 'name'] ***************************************
ok: [test01.fale.io] => {
"msg": "test01"
}
PLAY RECAP *********************************************************
test01.fale.io : ok=2 changed=0 unreachable=0 failed=0
If we forgot to add the additional parameter to specify the variable, we would have executed it as follows:
$ ansible-playbook -i test01.fale.io, cli_variables.yaml
We would have received the following output:
PLAY [all] *********************************************************
TASK [Gathering Facts] *********************************************
ok: [test01.fale.io]
TASK [Print variable 'name'] ***************************************
fatal: [test01.fale.io]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'name' is undefined\n\nThe error appears to have been in '/home/fale/Learning-Ansible-2.X-Third-Edition/Ch2/cli_variables.yaml': line 5, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n tasks:\n - name: Print variable 'name'\n ^ here\n"}
to retry, use: --limit @/home/fale/Learning-Ansible-2.X-Third-Edition/Ch2/cli_variables.retry
PLAY RECAP *********************************************************
test01.fale.io : ok=1 changed=0 unreachable=0 failed=1
Now that we have learned the basics of playbooks, let's create a web server from scratch using them. To do so, let's start from the beginning, creating an Ansible user and then moving forward from there.