Ansible variable types

Razi Chennouf
4 min readMar 26, 2023

--

Hello this is my first writeup about Ansible automation tool. I’m already working on my RHCE EX294 exam, and don’t worry its not going to be the last one … Have fun reading.

Static variables : are variables that are defined in your playbook or inventory and have a fixed value that does not change during the course of the playbook execution. For example, a static variable might be a username or password that is used to authenticate to a remote system.

Dynamic variables : are variables whose value is determined at runtime— extra-vars” and may change during the course of the playbook execution. Dynamic variables can be further categorized into two types: eager variables and lazy variables.

Eager variables : are variables whose values are determined immediately when the variable is defined. These variables are evaluated and their values are determined before the playbook execution begins. For example, a variable that retrieves the current date and time would be an eager variable.

Lazy variables : are variables whose values are not evaluated until they are actually used in the playbook. vars_files directive with with_first_found. They are useful in situations where you need to perform a task that takes a long time to complete or when you need to retrieve a value that is not available until later in the playbook.

Example Of playbook with dynamic variables :

Let’s suppose we have a web application that runs on multiple environments, such as development, testing, and production. Each environment has a different configuration, such as the database URL, API key, and logging level. You want to manage these configurations using Ansible and keep them in separate files for each environment. To achieve this, you can use dynamic variables in Ansible to load the configuration files for each environment based on the environment name or hostname.

- name: Configure web app
hosts: all
vars:
# Define default configuration values
default_config:
db_url: "localhost"
api_key: "api-key"
log_level: "info"
tasks:
- name: Load environment-specific configuration
include_vars: "env/{{ ansible_env }}.yml"
ignore_errors: yes

- name: Load host-specific configuration
include_vars: "host_vars/{{ ansible_host }}.yml"
ignore_errors: yes

- name: Merge configuration variables
set_fact:
config: "{{ default_config|combine(env_config|default({}), host_config|default({})) }}"

- name: Install web application
# Install web application using the merged configuration variables
# 1- Use the db_url and api_key values from the merged config
# 2- Set the log level to debug instead of the default info level
# 3- Pass any other required configuration options to the installation command

command: /path/to/installation_script --db-url="{{ config.db_url }}" --api-key="{{ config.api_key }}" --log-level="{{ config.log_level }}" --other-options="{{ config.other_options }}"

Examples Of playbook with dynamic variables :

let’s suppose you have a playbook that generates a report on the disk usage of multiple managed hosts. The playbook uses multiple loops and filters to retrieve and aggregate the disk usage data, which can be time-consuming and resource-intensive for large-scale deployments.

To optimize the performance of the playbook, you can use eager variables in Ansible to precompute and cache the results of the loops and filters. This allows you to avoid repeating the same calculations and reduce the number of API requests to the remote hosts

- name: generate disk usage report
hosts: all
gather_facts: no
tasks:
- name: retrieve disk usage data
shell: "df -h"
register: disk_usage_raw
changed_when: false

- name: extract disk usage values
set_fact:
disk_usage_values: "{{ disk_usage_raw.stdout_lines[1:] }}"

- name: calculate total disk usage
set_fact:
total_disk_usage: "{{ disk_usage_values|map(attribute='split')|map('last')|map('int')|sum }}"

- name: calculate host-specific disk usage
set_fact:
host_disk_usage: "{{ disk_usage_values|map(attribute='split')|map('last')|map('int')|list }}"

- name: calculate top 10 disk usage hosts
set_fact:
top_10_hosts: "{{ host_disk_usage|sort(reverse=true)|limit(10)|map('string')|list }}"
# Use eager variable to precompute the list of top 10 hosts
# This avoids recalculating the list for every iteration of the loop

- name: generate report for each host
vars:
# Use eager variable to cache the list of top 10 hosts
# This avoids repeating the calculation for each host
top_10_hosts_cache: "{{ top_10_hosts }}"
debug:
msg: "report for {{ item }}: {{ host_disk_usage[hostnames.index(item)] }}, top 10 hosts: {{ top_10_hosts_cache }}"
loop: "{{ hostnames }}"
vars:
hostnames: "{{ host_disk_usage|map('string')|list }}"

This is a simple example 2

- name: example of eager variable
hosts: localhost
vars:
current_time: "{{ ansible_date_time.date }} {{ ansible_date_time.time }}"
tasks:
- name: print current time
debug:
var: current_time

Example Of playbook with Lazy variables :

Let’s suppose we have a playbook that deploys a web application on multiple managed servers. The playbook uses multiple variables and filters to configure the application and its environment, which can be complex and time-consuming to compute for large-scale deployments.

To optimize the performance of the playbook, you can use lazy variables in Ansible to delay the evaluation of expressions until they are needed. This allows you to avoid computing unnecessary values and reduce the memory usage of the playbook:

- name: deploy web application
hosts: webservers
vars:
app_name: myapp
app_env: production
app_version: latest
app_config:
server:
hostname: "{{ ansible_hostname }}"
port: 80
database:
host: db.example.com
port: 5432
username: "{{ app_name }}_user"
password: "{{ app_name }}_pass"
tasks:
- name: install dependencies
apt:
name: "{{ ['python3', 'nginx']|join(' ') }}"
state: present

- name: configure web application
template:
src: "{{ app_name }}-{{ app_env }}.conf.j2"
dest: "/etc/nginx/sites-available/{{ app_name }}.conf"
notify: reload nginx

- name: deploy web application
git:
repo: "{{ app_name }}"
version: "{{ app_version }}"
dest: "/var/www/{{ app_name }}"
register: deploy_output

- name: configure database
template:
src: "{{ app_name }}-{{ app_env }}.yml.j2"
dest: "/etc/{{ app_name }}/{{ app_env }}.yml"
when: app_config.database is defined

- name: start web application
systemd:
name: "{{ app_name }}"
state: started
when: deploy_output.changed

handlers:
- name: reload nginx
systemd:
name: nginx
state: restarted

--

--