How To Work With Ansible Variables And Facts?


Ansible is a widely−used open−source tool that helps in automating software provisioning, configuration management, and application deployment. One of its powerful features is the ability to use variables and facts, which can simplify your playbooks and tasks, and allow you to design more dynamic, flexible, and reusable automation scripts.

In this article, we'll dive into how to work with Ansible variables and facts, showcasing several examples and their corresponding output.

Understanding Ansible Variables

Variables in Ansible allow for the storage and manipulation of values, which can be utilized across multiple tasks or even different playbooks. Variables can be defined in various locations, and their scope is mainly determined by where they are defined.

Defining Variables

There are many ways to define variables in Ansible −

In a Playbook − Here's an example of how you can define a variable within a playbook −

---
- hosts: webservers
   vars:
      http_port: 80
      max_clients: 200
   tasks:
- name: Ensure Apache is at the latest version
   yum:
      name: httpd
      state: latest

In this playbook, the variables http_port and max_clients are defined and can be used in any tasks within this playbook.

In the Inventory File − Variables can also be defined in the inventory file −

[webservers]
server1 ansible_host=192.168.1.10 http_port=80 max_clients=200

In this inventory file, http_port and max_clients are defined for server1.

Using Variables

You can utilize these variables in tasks or templates by enclosing them in double curly braces. Here's an example −

---
- hosts: webservers
   vars:
      http_port: 80
      max_clients: 200
   tasks:
- name: Ensure Apache is configured with vars
   template:
      src: /etc/httpd/conf/httpd.conf.j2
      dest: /etc/httpd/conf/httpd.conf

In the template file, you would reference these variables like this −

Listen {{ http_port }}
MaxClients {{ max_clients }}

Understanding Ansible Facts

Ansible facts are pieces of information obtained from the target system, such as network interfaces, OS details, IP addresses, etc. These facts are stored in variables and can be used in playbooks.

Ansible uses a module called setup to gather facts. If you want to see what facts Ansible gathers about a system, run the following command −

ansible −m setup hostname

Replace hostname with the name or IP of the host you want to target. The output will be a JSON document that lists all the facts gathered for that host.

Here's an example of using facts in a task −

---
- hosts: webservers
  tasks:
  - name: Display OS family
    debug:
      msg: "The operating system family is {{ ansible_os_family }}"

In this example, ansible_os_family is a fact that gives the OS family of the target system.

Organizing Variables

As you scale your Ansible usage, you might find that you're dealing with a large number of variables. In such scenarios, it's advisable to manage your variables in dedicated files or even directories.

In separate Variables Files − You can define variables in separate files and then include those files in your playbooks like so:

---
- hosts: webservers
  vars_files:
    - vars/apache.yml
  tasks:
  - name: Ensure Apache is at the latest version
    yum:
      name: httpd
      state: latest

In vars/apache.yml, you might define the variables like this −

---
http_port: 80
max_clients: 200

In a Directory − For even better organization, especially for larger projects, you can store variables in a directory structure.

---
- hosts: webservers
  vars_files:
    - vars/apache.yml
    - vars/directory/extra_vars.yml
  tasks:
  - name: Ensure Apache is at the latest version
    yum:
      name: httpd
      state: latest

In vars/directory/extra_vars.yml, you might define additional variables.

Advanced Variable Usage: Facts Caching

One of the powerful features of Ansible is the ability to cache facts. This is especially useful when you're working with a large inventory or when you want to use gathered facts in multiple playbooks without re-gathering them every time.

To enable fact caching, you need to set the following parameters in your ansible.cfg file −

[defaults]
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts
fact_caching_timeout = 7200

With this configuration, Ansible will cache gathered facts in the /tmp/ansible_facts directory and will not re-gather them for 7200 seconds (2 hours).

This example demonstrates how to access cached facts −

---
- hosts: webservers
  tasks:
  - name: Display cached OS family
    debug:
      msg: "The cached operating system family is {{ ansible_os_family }}"

In this playbook, ansible_os_family will use the value from the cache if it's available and not older than 2 hours.

Variable Precedence

In Ansible, there are many ways to set variables, and it's crucial to understand the order in which they are evaluated. This order, known as variable precedence, allows you to control the final value of a variable.

Here's a simplified precedence order from lowest to highest −

  • Role defaults

  • Inventory file or script group vars

  • Inventory group_vars/all

  • Playbook group_vars/all

  • Inventory group_vars/*

  • Playbook group_vars/*

  • Inventory file or script host vars

  • Inventory host_vars/*

  • Playbook host_vars/*

  • Host facts / cached set_facts

  • 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)

  • Extra vars (always win precedence)

Variable Types

Apart from the standard variables, Ansible offers several special variable types that can be very helpful. These include −

List Variables − This type allows you to create a list (array) of values.

fruits:
  - Apple
  - Banana
  - Orange

Dictionary Variables − This type enables the storage of more complex data structures.

user:
  name: John Doe
  job: Developer

Boolean Variables − They are used for storing True/False values.

debug_mode: True

Accessing Complex Variables

For list and dictionary variables, you can access individual elements by their index or key. For example −

---
- hosts: localhost
  gather_facts: no
  vars:
    fruits:
      - Apple
      - Banana
      - Orange
    user:
      name: John Doe
      job: Developer
  tasks:
    - debug:
        msg: "The first fruit in the list is {{ fruits[0] }}"
    - debug:
        msg: "The user's job is {{ user['job'] }}"

The above playbook will output −

PLAY [localhost] 
***************************************************************

TASK [debug] 
*******************************************************************
ok: [localhost] => {
    "msg": "The first fruit in the list is Apple"
}

TASK [debug] 
*******************************************************************
ok: [localhost] => {
    "msg": "The user's job is Developer"
}

PLAY RECAP 
*********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Using Filters with Variables

Filters in Ansible can manipulate variables. They are used in conjunction with the | character. For instance, the 'default' filter can be used to assign a default value to a variable if it is not defined −

---
- hosts: localhost
  gather_facts: no
  vars:
    var1: "Hello"
  tasks:
    - debug:
        msg: "{{ var1 | default('Hi') }}"
    - debug:
        msg: "{{ var2 | default('Hi') }}"

The above playbook will output −

PLAY [localhost] 
***************************************************************

TASK [debug] 
*******************************************************************
ok: [localhost] => {
    "msg": "Hello"
}

TASK [debug] 
*******************************************************************
ok: [localhost] => {
    "msg": "Hi"
}

PLAY RECAP 
*********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

In the first debug task, var1 is defined, so the default filter does not change its value. In the second task, var2 is not defined, so the default filter assigns it the value 'Hi'.

Understanding how to leverage variables and facts in Ansible is the key to writing efficient, reusable automation scripts. Always keep learning and exploring these concepts to make the most out of Ansible.

Conclusion

Ansible variables and facts, when used properly, can greatly enhance your automation workflows by making your tasks more dynamic, reducing repetition, and allowing for more efficient resource utilization. From defining and using basic variables to employing advanced strategies like fact caching, there's a wide range of possibilities.

By understanding these concepts, you can write more flexible, efficient, and powerful Ansible playbooks. As always, make sure to consult the official Ansible documentation for the most accurate and up-to-date information.

Updated on: 17-Jul-2023

267 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements