Ansible:- Variable format, Precedence, jinja2 and various method to define the variables in playbook

Ansible:- Variable format, Precedence, jinja2 and various method to define the variables in playbook

While automation exists to make it easier to make things repeatable, it also require to develop the reusable code by defining the variables.

All systems are not exactly alike; some may require configuration that is slightly different from others.

Example: Assume that you have a playbook which will install oracle binary and configure Oracle on prod and non-prod environment. While configuration of Oracle need to define an unique oracle home specific to environment(prod, uat and dev -: it may be same or unique for your environment).

Now this can be achieved in two ways.

  1. Create multiple environment specific playbook to install and configure oracle in respective environment(Here you will define oracle home for each environment) — But this is not the right way to use Ansible.

Example:

2. Create a single playbook by defining the variable inside the playbook, that make you to create a reusable playbook for any environment.

Now, you can see the variable importance when you define the variable key and value in the playbook as mentioned below.

Define oracle_environment variable in ansible playbook : /u01/product/19.0.0/{{ oracle_environment }}/dbhome” where can be oracle_environment variable value is — test/dev/uat/prod.

oracle_environment → variable key

test/dev/uat/prod → variable value

Where to define variable, in my case I am defining the oracle home variable in vars->main.yml

Execute the oracle playbook by changing the “oracle_environment” that will set oracle home for dev environment as mentioned below.

Now, i want to execute the same playbook for prod then replace the variable value from dev to prod for prod environment as mentioned below.

create an oracle home path to configure oracle home by adding {{ oracle_environment }} variable value in path.

Part-1

Ansible variables format:

Before you start variables, it’s impotent to know what are the valid variable names.

Note: Variables should always start with a letter. Variables names should be letters, numbers and underscores.

oracle_listener_port is a great variable. servername01 is fine too.

oracle_listener_port, oracle listener port, oracle.listener.port and 01 are not valid variable names.

Part-2

Ansible variables Precedence: where should I put variables to consume in playbook?

If multiple variables of the same name are defined in different places, they get overwritten in a certain order.

Here is the order of precedence from least to greatest (the last listed variables winning prioritization):

https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable

command line values (eg “-u user”)

role defaults [1]

inventory file or script group vars [2]

inventory group_vars/all [3]

playbook group_vars/all [3]

inventory group_vars/* [3]

playbook group_vars/* [3]

inventory file or script host vars [2]

inventory host_vars/* [3]

playbook host_vars/* [3]

host facts / cached set_facts [4]

play vars

play vars_prompt

play vars_files

role vars (defined in role/vars/main.yml)

block vars (only for tasks in block)

task vars (only for the task)

include_vars

set_facts / registered vars

role (and include_role) params

include params

extra vars (always win precedence)

Basically, anything that goes into “role defaults” (the defaults folder inside the role) is the most malleable and easily overridden. Anything in the vars directory of the role overrides previous versions of that variable in namespace. The idea here to follow is that the more explicit you get in scope, the more precedence it takes with command line -e extra vars always winning. Host and/or inventory variables can win over role defaults, but not explicit includes like the vars directory or an include_vars task.

So far i have explained correct why variable is impotent in playbook, variables format and variable precedence.

Now, I will explain multiple way to consume the variables in Ansible Playbook.

1) Defining variables in a playbook:-

You can define variables directly in a playbook:

2) Defining variables in included files and roles:-

As described variable above by creating oracle roles,

Include_vars can be used in a playbook or roles to call a variables from file.

stuff.yaml file is located in same directory

Playbook output

3) Using variables with Jinja2:-

Once you’ve defined variables, you can use them in your playbooks using the Jinja2 templating system. Here’s a simple Jinja2 template:

here “number_of_huge_pages” variable value need to replace with 256

here “number_of_huge_pages” variable value will be assigned to vm.nr_hugepages in sysctl.conf file

When template will copy from src to dest then jinja2 templating will replace the variable to variable value

4) Variables discovered from systems:- Facts

To use facts you need to enable gather fact in the playbook by add a parameter called “gather_facts: yes” (more details you can get from given link)

Now, print OS distribution of server by using facts {{ ansible_distribution }}

5) Registering variables:-

Another major use of variables is running a command and registering the result of that command as a variable. When you execute a task and save the return value in a variable for use in later tasks, you create a registered variable.

For example:

6) Accessing complex variable data:-

We already described facts a little higher up in the documentation.

Some provided facts, like networking information, are made available as nested data structures. Here’s how we get an IP address:

OR alternatively:

7) Accessing information about other hosts with magic variables:-

Magic variable names are reserved — do not set variables with these names. The variable environment is also reserved.

The most commonly used magic variables are hostvars, groups, group_names, and inventory_hostname.

hostvars lets you access variables for another host, including facts that have been gathered about that host. You can access host variables at any point in a playbook. Even if you haven’t connected to that host yet in any play in the playbook or set of playbooks, you can still get the variables, but you will not be able to see the facts.

If your database server wants to use the value of a ‘fact’ from another node, or an inventory variable assigned to another node, it’s easy to do so within a template or even an action line:

groups is a list of all the groups (and hosts) in the inventory. This can be used to enumerate all hosts within a group. For example:

If a server needs to use the value of a “fact” from another node, it’s easy to do so within a template templates/hosts.j2

The playbook:

inventory_hostname is the name of the hostname as configured in Ansible’s inventory host file. This can be useful when you’ve disabled fact-gathering, or you don’t want to rely on the discovered hostname ansible_hostname. If you have a long FQDN, you can use inventory_hostname_short, which contains the part up to the first period, without the rest of the domain.

8. Defining variables in files

You can do this by using an external variables file, or files, just like this:

This removes the risk of sharing sensitive data with others when sharing your playbook source with them.

The contents of each variables file is a simple YAML dictionary, like this:

9. Passing variables on the command line

In addition to vars_prompt and vars_files, it is possible to set variables at the command line using the --extra-vars (or -e) argument. Variables can be defined using a single quoted string (containing one or more variables) using one of the formats below

key=value format:

If this post was helpful, please click the clap 👏 button below a few times to show your support for the author! ⬇

Reference: