How to Create and Use Custom Fact Variables in Ansible

How to Create and Use Custom Fact Variables in Ansible

In Ansible, fact variables are dynamically gathered data about the managed hosts. Ansible collects these variables, known as "facts," by using its setup module, which gathers details like OS type, network settings, hardware details, and more. You can also create custom fact variables to store specific information or perform calculations to use in your playbooks, enhancing automation flexibility.

In this guide, I’ll walk you through understanding fact variables and creating custom facts in Ansible.

?

Lab Setup

To demonstrate the usage of Ansible’s built-in fact variables and the creation of custom fact variables, I’ve set up a lab environment using Ubuntu Linux on Oracle VirtualBox. The setup includes:

  1. Ansible Master (Control Node) – ubuntu-vm1
  2. Ansible Client (Development) – ubuntu-vm2
  3. Ansible Client (Production) – ubuntu-vm3

The Ansible Master (ubuntu-vm1) is used to run playbooks on the other Ubuntu machines (ubuntu-vm2 and ubuntu-vm3).

Note: You can find the Ansible Playbook codes referenced in this article at my GitHub link: https://github.com/cjcheema/my_ansible_project

?

Understanding Built-in Facts

Ansible automatically collects system information from managed hosts when a playbook runs, storing them in built-in facts. For example, facts like ansible_hostname, ansible_os_family, and ansible_processor_count give details about the system. To see all built-in facts, you can run the following command:

ansible localhost -m setup        

This will output JSON data containing all gathered facts for the localhost.


Using Built-in Facts

You can reference these built-in facts within your playbooks to make tasks conditional or to configure resources based on system properties. Here’s an example:

- name: Example of using built-in facts
? hosts: all
? tasks:
??? - name: Print the operating system family
????? debug:
??????? msg: "Operating system family is {{ ansible_os_family }}."        



Creating Custom Fact Variables

Custom facts allow you to define additional facts that might be specific to your infrastructure, environment, or application requirements. Custom facts can be created in two main ways:


Method 1: Defining Custom Facts in Playbooks

You can define custom facts directly in playbooks using set_fact, which makes them available during the playbook's execution.


- name: Create custom fact variables
? hosts: Production
? tasks:
??? - name: Set custom fact for application environment
?????  set_fact:
??????? app_environment: "production"
??????? app_version: "v1.2.3"?
   
    - name: Display custom fact variables
????? debug:
??????? msg: "App Environment: {{ app_environment }}, Version: {{ app_version }}"        


In this example:

  • set_fact creates app_environment and app_version as custom fact variables, which you can use throughout the playbook.
  • The debug task demonstrates how to access and use these custom facts.


Method 2: Creating Custom Facts on Managed Hosts

Another approach is to place custom fact files on managed hosts. These files reside in the /etc/ansible/facts.d directory on each managed host and are written in JSON or INI format.

  • Create a custom fact file on the managed host:

sudo mkdir -p /etc/ansible/facts.d
echo '{"app_environment": "production", "app_version": "v1.2.3"}' | sudo tee /etc/ansible/facts.d/custom_app.fact        


  • Access the custom facts in a playbook:

- name: Using custom facts from managed host
? hosts: Production
? tasks:
??? - name: Display custom facts
????? debug:
??????? msg: "App Environment: {{ ansible_local.custom_app.app_environment }}, Version: {{ ansible_local.custom_app.app_version }}"        

In this case:

  1. Custom facts are stored in managed host or endpoint’s /etc/ansible/facts.d/custom_app.fact in JSON format.
  2. These facts are accessible through ansible_local and can be used throughout your playbook.



Using Conditional Statements with Custom Facts

Custom facts can be used in conditional statements to change task behavior based on the facts' values.

- name: Install packages based on app environment
? hosts: all
? become: yes
? tasks:
??? - name: Set custom app environment fact
????? set_fact:
??????? app_environment: "{{ app_env_var }}"


??? - name: Install production package
????? apt:
??????? name: apache2
??????? state: present
????? when: inventory_hostname in groups['Production'] and app_environment == "production"


??? - name: Install development package
????? apt:
??????? name: nginx
??????? state: present
????? when: inventory_hostname in groups['Development'] and app_environment == "development"        

How to execute this playbook:

  • During this playbook executing time, environment need to specify using the -e flag:

ansible-playbook your_playbook.yml -e "app_env_var=production"        


  • or for the development environment:

ansible-playbook your_playbook.yml -e "app_env_var=development"        

?

Explanation of this playbook:

  1. Set Custom Fact: The task set_fact assigns the value of app_env_var (provided during playbook execution) to the app_environment variable.
  2. Conditional Package Installation:

  • The when clause checks the value of app_environment based on the inventory group of each managed host.
  • If app_env_var is set to "production", the task to install apache2 will execute.
  • If app_env_var is set to "development", the task to install nginx will execute.


Creating Complex Facts with Jinja2

You can use Jinja2 expressions in set_fact to calculate values for custom facts. This allows for dynamically calculated facts that update based on other variables or facts in real-time.

- name: Create complex custom facts with Jinja2
? hosts: all
? tasks:
??? - name: Set server tier fact based on vCPU count
????? set_fact:
??????? server_tier: "{{ 'high' if ansible_processor_vcpus > 1 else 'standard' }}"


??? - name: Print server tier
????? debug:
??????? msg: "This server is classified as {{ server_tier }} tier based on vCPU count."        

In this example:

  • The server_tier fact is determined by evaluating the ansible_processor_vcpus fact. Servers with more than 2 virtual CPUs (in case of VM) are assigned to the "high" tier.


?

Registering Facts in Ansible for Later Use

You can use the register module to capture the output of a task and save it as a fact. This is helpful for dynamically created information, like command outputs or file contents.


- name: Register custom fact from command output
? hosts: all
? tasks:
??? - name: Get uptime information
????? command: uptime
????? register: uptime_info

??? - name: Print uptime
????? debug:
??????? msg: "The server uptime is: {{ uptime_info.stdout }}"        

?


Wrap Up!

  • Built-in facts are automatically gathered by Ansible and provide essential system details.
  • Custom facts can be created using set_fact or by placing fact files on managed hosts in /etc/ansible/facts.d.
  • Conditional facts can alter playbook tasks based on the fact's value.
  • Complex facts can be calculated with Jinja2 expressions and logic within set_fact.
  • Registered facts capture outputs of tasks for later use.

This approach to using both built-in and custom facts in Ansible enhances flexibility, making automation more adaptable to specific needs and conditions.

Harshit Mahajan

(RHCSA | CKA | TCA | EX374 ) I am always Interested in contributing meaningfully to simplify repetitive tasks.

4 个月

Its helpful

Indira Jois

Director @ Kyndryl India | Executive Leadership, Cloud Migration, Dark Data enthusiast, DEI Advocate, Wellness Advocate, POSH Champion

4 个月

Good one. Continue to publish Charanjit Singh Cheema

Bharani Ganesh S

Delivery Leader at Kyndryl

4 个月

Charanjit Singh Cheema another good one

要查看或添加评论,请登录

Charanjit Singh Cheema的更多文章

社区洞察

其他会员也浏览了