Creating & Managing Ansible Variables

UNDERSTANDING THE SUBJECT MATTER

In our previous lesson, we learnt how to create a basic playbook, we also learnt the different indentation levels of plays and tasks in a playbook.

In this lesson, we will learn what variables are, how to add variables to a playbook, and how to reference variables outside of a playbook.

What Are Ansible Variables

Variables are like repositories that hold information and are used to store information that needs to be referenced.

Ansible variables can be declared in various ways, the most important thing is to know how to declare these variables cleverly so that the administration of the network environment can be easy and convenient.

Ansible variables can be defined inside of a playbook at a play level, however, in some cases, this makes the playbook long and difficult to read. The alternative to this is defining the variables outside of the playbook.

There are 22 different ways Ansible variables can be defined and they all have an order of precedence. Click here to see the order of precedence.

As we go on in this course, we will look at how to define variables in some of these 22 ways in the ACTION TIME section below, and we will always refer to the link above for better understanding.

How do you pass variables in Ansible?

A valid variable name constitutes letters, numbers, and the underscore punctuation only or a mixture of the three.

More so, variables can’t have any other punctuation apart from underscore and can’t also start with the underscore punctuation nor with a number.

A variable must start with a letter only and must include two curly brackets at the beginning and the end. More so, when a variable is a value to a key, in other words, when a key’s value begins with a variable, encapsulation is required.

An example of valid variables are shown below

{{ tekneed_variable }}
{{ tekneed_1 }}
{{ tekneed123 }}

An example of invalid variables are shown below

{{ 123tekneed }}
{{ 1_tekneed }}
{{ tek need }}
{{ tek.need }}
{{ tek-need }}

An example of valid variables that are values to keys, i.e, (key-value) pair are shown below

"{{ tekneed_variable }}"
"{{ tekneed_1 }}"
"{{ tekneed123 }}"

In the “ACTION TIME” section below, we will look at the different ways we can define and pass Ansible variables with examples.

ACTION TIME

Step By Step Guide Of How To Use Ansible Variables Example

In our previous lesson, we automated the installation of the httpd service by using an ansible playbook, however without variables. Let’s see how to use variables in the example below.

Example

In this example, as the user, lisa, we will automate the installation of the httpd service still, inclusive of some other packages such as firewalld and autofs but with variables this time around.

In my environment, the inventory file and the ansible configuration file can be seen below.

[lisa@drdev1 ~]$ cat inventory/static-ini-inventory
[group1]
hqdev1.tekneed.com
localhost
[lisa@drdev1 ~]$ cat .ansible.cfg
[defaults]
inventory=/home/lisa/inventory/static-ini-inventory
remote_user=root
ask_pass=false

[privilege_escalation]
become=true
become_user=root
become_method=sudo
beocme_ask_pass=false

Steps

1. create a playbook file

[lisa@drdev1 ~]$ vim my-third-playbook.yml

*add the first play (play name and hosts).

 1 ---
  2 - name: Packages Installation and deployment
  3   hosts: group1

*add the variable name and the variables. The variable name, in this case, is “packages” and the variables are httpd, firewalld and autofs.

  1 ---
  2 - name: Packages Installation and deployment
  3   hosts: group1
  4   vars:
  5     packages:
  6       - httpd
  7       - firewalld
  8       - auofs

note that this variable is being defined in the playbook at a play level, hence this variable will only work for this play, and in the order of variable precedence, referring to this link, this falls in number 12, which is “play vars”

*add the first task

 1 ---
  2 - name: Packages installation and deployment
  3   hosts: group1
  4   vars:
  5     packages:
  6       - httpd
  7       - firewalld
  8       - auofs
  9   tasks:
 10       - name: Install packages
 11         yum:
 12           name: "{{ packages }}"
 13           state: present

You can see that the name of the packages to be installed is referencing the variables using the variable name, packages.

At the end of creating the playbook, the playbook will be in the form below.

2. Do a playbook syntax check.

[lisa@drdev1 ~]$ ansible-playbook my-third-playbook.yml --syntax-check

playbook: my-third-playbook.yml

3. Do a dry run if you wish.

(This step is not necessary, it just further explains how dry run works just as I have explained in one of the previous chapters)

[lisa@drdev1 ~]$ ansible-playbook my-third-playbook.yml -C

PLAY [Packages installation and deployment] *********************************************
.........

4. run the playbook.

[lisa@drdev1 ~]$ ansible-playbook my-third-playbook.yml

PLAY [Packages installation and deployment] *********************************************
.........

Like I said above, variables can be declared in many ways. Keep this on your right palm

Moving this exercise forward, let’s update the playbook to start and enable httpd, firewalld and autofs packages.

Steps

1. In the variable section, add the variable names which in this case are httpd_service, firewall_services, and autofs_services, and the variable values.

......
  9     httpd_service: httpd
 10     firewall_services: firewalld
 11     autofs_services: autofs

2. In the task section, add the tasks referencing the variables.

.............. 
18      - name: start and enable httpd service
 19       service:
 20          name: "{{ httpd_service }}"
 21          enabled: true
 22          state: started
 23
 24      - name: start and enable firewall services
 25        service:
 26          name: "{{ firewall_services }}"
 27          enabled: true
 28          state: started
 29
 30      - name: start and enable autofs
 31        service:
 32          name: "{{ autofs_services }}"
 33          enabled: true
 34          state: started
ansible variables

3. Do a playbook syntax check

[lisa@drdev1 ~]$ ansible-playbook my-third-playbook.yml --syntax-check

playbook: my-third-playbook.yml

4. Run the playbook

[lisa@drdev1 ~]$ ansible-playbook my-third-playbook.yml

PLAY [Packages installation and deployment] ***********************************************************************************
.....
ok: [localhost]
......

Moving this example forward, let’s add the https service to the firewall rule and add a test web server content to test if httpd has been well configured

Steps

1. In the variable section, add the variable name, which is firewall_rule, and the variable, which is https.

  .......
  9     httpd_service: httpd
 10     firewall_services: firewalld
 11     autofs_services: autofs
 12     firewall_rule: https

2. Using the copy module, add a web server content in the task section for testing

 ..............
 44      - name: copy a basic website content to test
 45        copy:
 46          content: "Hello World"
 47          dest: /var/www/html/index.html

3. Do a playbook syntax check

[lisa@drdev1 ~]$ ansible-playbook my-third-playbook.yml --syntax-check

playbook: my-third-playbook.yml

4. Run the playbook.

[lisa@drdev1 ~]$ ansible-playbook my-third-playbook.yml

PLAY [Packages installation and deployment] ************************************************************
.......

Moving this example forward, let’s make sure the packages are updated to the latest

Steps

1. In the task section, add the task to make sure the three packages installed have the latest update.

.........
 49      - name: update packages variable to the latest
 50        yum:
 51          name: "{{ packages }}"
 52          state: latest

2. Do a playbook syntax check

[lisa@drdev1 ~]$ ansible-playbook my-third-playbook.yml --syntax-check

playbook: my-third-playbook.yml

3. Run the playbook

[lisa@drdev1 ~]$ ansible-playbook my-third-playbook.yml

PLAY [Packages installation and deployment] 
.......

Moving this example forward, do a test from the local server using the uri module to see if the httpd package was successfully deployed on hqdev1.tekneed.com

Steps

1. Add a new play since we are going to be testing from the local server and also add the task to verify that the web content is accessible

 55 - name: Test if httpd was successfully deployed
 56   hosts: localhost
 57   tasks:
 58      - name: verify if the web content is accessible
 59        uri:
 60          url: htpp://hqdev1.tekneed.com
 61          return_content: yes
 62          status_code: 200

2. do a syntax check

[lisa@drdev1 ~]$ ansible-playbook my-third-playbook.yml --syntax-check

playbook: my-third-playbook.yml

3. Run the playbook

[lisa@drdev1 ~]$ ansible-playbook my-third-playbook.yml

PLAY [Packages installation and deployment] 
.......
TASK [verify if the web content is accessible] *************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "content": "", "elapsed": 0, "msg": "Status code was -1 and not [200]: Request failed: <urlopen error unknown url type: htpp>", "redirected": false, "status": -1, "url": "htpp://hqdev1.tekneed.com"}

You can see that we have hit a road block. If you look at the error, it points to the last task. It showed

"url": "htpp://hqdev1.tekneed.com"}

This is because there was a typo. It should be http and not htpp, hence, we need to correct this in the playbook to fix this error. Though the typo was corrected in step 1 screenshot.

4. Rerun the playbook

[lisa@drdev1 ~]$ ansible-playbook my-third-playbook.yml

PLAY [Packages installation and deployment] 
.......

Now, you can see that the playbook ran successfully.

5. verify.

[lisa@drdev1 ~]$ curl http://hqdev1.tekneed.com
Hello World[lisa@drdev1 ~]$

So far so good, the playbook data for this example is as below

---
- name: Packages installation and deployment
  hosts: group1
  vars:
    packages:
      - httpd
      - firewalld
      - autofs
    httpd_service: httpd
    firewall_services: firewalld
    autofs_services: autofs
    firewall_rule: http
  tasks:
     - name: Install packages
       yum:
         name: "{{ packages }}"
         state: present

     - name: start and enable httpd service
       service:
         name: "{{ httpd_service }}"
         enabled: true
         state: started

     - name: start and enable firewall services
       service:
         name: "{{ firewall_services }}"
         enabled: true
         state: started

     - name: start and enable autofs
       service:
         name: "{{ autofs_services }}"
         enabled: true
         state: started

     - name: allow apache in firewall
       firewalld:
         service: "{{ firewall_rule }}"
         state: enabled
         permanent: true
         immediate: true

     - name: copy a basic website content to test
       copy:
         content: "Hello World"
         dest: /var/www/html/index.html

     - name: update packages variable to the latest
       yum:
         name: "{{ packages }}"
         state: latest


- name: Test if httpd was successfully deployed
  hosts: localhost
  tasks:
     - name: verify if the web content is accessible
       uri:
         url: http://hqdev1.tekneed.com
         return_content: yes
         status_code: 200

Defining Ansible Variables Outside Of Ansible Playbook

Variables can be defined outside of a playbook file.

Just as I mentioned in this and the previous lesson, one should always endeavor to create a playbook that is easy to understand and troubleshoot, and putting variables in a playbook can make the playbook long, especially when one will have to define so many variables in the playbook.

Apart from defining variables in a playbook, variables can also be defined in an inventory, in an external file, and a command line using Ansible ad hoc

Using the example above, we are going to define the variables we defined in the playbook outside of the playbook in an external file.

Variables can be defined in 22 different ways and these ways take order of precedence, hence, you need to be mindful of how you define variables. You can click here to see the order of precedence.

To define the variables we defined in our last example in a file, follow the steps below:

1. Edit the playbook and change the hosts value in the first play to “all”. Also, delete all the variables in the playbook.

NOTE: changing the hosts value to all means that the tasks in the play will execute on all managed hosts in the inventory file.

[lisa@drdev1 ~]$ vim  my-third-playbook.yml
  1 ---
  2 - name: Packages installation and deployment
  3   hosts: all
  4   tasks:
  5      - name: Install packages
  6        yum:
  7          name: "{{ packages }}"
  8          state: present
.............

The playbook after editing will be as below.

2. create the variable file and define the variables in the file.

*create the variable file for all the inventory group variables. (inventory group_vars/all).

In the order of variable precedence, this falls in number 4.

[lisa@drdev1 ~]$ mkdir group_vars
[lisa@drdev1 ~]$ vim group_vars/all
packages:
  - httpd
  - firewalld
  - autofs
httpd_service: httpd
firewall_services: firewalld
autofs_services: autofs
firewall_rule: http

3. Run the playbook

[lisa@drdev1 ~]$ ansible-playbook my-third-playbook.yml

PLAY [Packages installation and deployment] *******************************************************

Moving this example forward, let’s create a variable for individual groups (inventory group_vars/*), in this case, group1 only.

In the order of precedence, this falls in number 6.

Steps

1. create the variable file and define the variables in the file.

This time around, let’s add one more package called kmod-kvdo to the packages variable.

[lisa@drdev1 ~]$ vim group_vars/group1
packages:
  - httpd
  - firewalld
  - autofs
  - kmod-kvdo
httpd_service: httpd
firewall_services: firewalld
autofs_services: autofs
firewall_rule: http

This means that the variables will be executed only on group1 managed hosts in the inventory file.

2. Run the playbook.

[lisa@drdev1 ~]$ ansible-playbook my-third-playbook.yml

PLAY [Packages installation and deployment] *******************************************************

Moving this example forward, let’s create a variable for individual hosts (inventory host_vars/* ), in this case, hqdev1.tekneed.com only

In the order of precedence, this falls in number 9.

Steps

1. create the variable file and define the variables in the file.

[lisa@drdev1 ~]$ mkdir host_vars
[lisa@drdev1 ~]$ vim host_vars/hqdev1.tekneed.com

Let’s also add one more package, gdisk to the packages variable.

packages:
  - httpd
  - firewalld
  - autofs
  - kmod-kvdo
  - gdisk
httpd_service: httpd
firewall_services: firewalld
autofs_services: autofs
firewall_rule: http

2. Run the playbook

[lisa@drdev1 ~]$ ansible-playbook my-third-playbook.yml

PLAY [Packages installation and deployment] *******************************************************

This means the variables will be executed on hqdev1.tekneed.com only.

In the examples we have done so far, we have been able to declare variables in four different ways which are play vars (12), inventory group_vars/all (4), inventory group_vars/* (6), and inventory host_vars/* (9).

Looking at the order of precedence, play var, which is number 12 takes higher precedence than all of them, followed by number 9, then number 6, and number 4.

Other Methods of Defining Variables In Ansible

Having defined variables in the previous example in four different ways, let’s again define a variable using number 14 (play vars_file) in the order of precedence using the example below.

EXAMPLE I

Steps

1. create a playbook that defines the variables inside of the playbook with the syntax, vars_file, and pair, which is classified.yml

---
- name: create users
  hosts: hqdev1.tekneed.com
  vars_files:
  - classified.yml
  tasks:
    - name: create users and password
      user:
        name: "{{ username }}"
        password: "{{ password }}"
        state: present

2. create the variable file

[lisa@drdev1 ~]$ vim classified.yml
username: tayo
password: toyota

3. Do a syntax check on the playbook

[lisa@drdev1 ~]$ ansible-playbook play3.yml --syntax-check

playbook: play3.yml
[lisa@drdev1 ~]$

4. Run the playbook.

[lisa@drdev1 ~]$ ansible-playbook play3.yml

PLAY [create users] ************************************************************
ERROR! Attempting to decrypt but no vault secrets found
[lisa@drdev1 ~]$

NB: Don’t worry about the error, we will look at how to fix such errors as we go on in this course

EXAMPLE II

Let’s create another playbook and define its variable outside of the playbook.

Steps

1. create a playbook

[lisa@drdev1 ~]$ vim play4.yml
---
- name: create users
  hosts: hqdev1.tekneed.com
  tasks:
    - name: create users and password
      user:
        name: "{{ username }}"
        password: "{{ password }}"
        state: present

2. create the variable file

[lisa@drdev1 ~]$ mkdir -p host_vars/hqdev1.tekneed.com/
[lisa@drdev1 ~]$ vim host_vars/hqdev1.tekneed.com/classified.yml
username: tayo
password: toyota

3. Do a syntax check on the playbook

[lisa@drdev1 ~]$ ansible-playbook play4.yml --syntax-check

playbook: play4.yml

4. Run the playbook

[lisa@drdev1 ~]$ ansible-playbook play4.yml

PLAY [create users] ************************************************************
ERROR! Attempting to decrypt but no vault secrets found

Ignore the error for now, we will treat how to fix it in the next lesson.

As we go on in this course, we will look at the other ways variables can be declared with other examples.

You can also click on this link to see more ways ansible variables can be defined.

Class Activity

Create a playbook with variables that must install, start and enable the autofs service

If you like this article, you can support us by

1. sharing this article.

2. Buying the article writer a coffee (click here to buy a coffee)

3. Donating to move our project to the next level. (click here to donate)

If you need personal training, send an email to info@tekneed.com

Click Here To Watch Video On Creating and Managing Ansible Variables In Linux

RHCE EX294 Exam Practice Question On Creating & Managing Ansible Variables

Your feedback is welcomed. If you love others, you will share with others

Be the first to comment

Leave a Reply

Your email address will not be published.


*