How to Master Managing Facts in Ansible: The Ultimate Guide

Managing Facts in Ansible - Playbook Example

In this tutorial, You will learn how to manage facts in ansible and why managing facts in Ansible is critical for dynamic inventory

Table of Contents

Objectives

After completing this section, you should be able to reference data about managed hosts using Ansible facts, and configure custom facts on managed hosts.

Why **Managing Facts in Ansible** is Essential for Automation

Ansible facts are pieces of information automatically collected from managed hosts. They behave like normal variables and can be used in tasks, conditions, templates, or loops.

Examples of facts collected:
  • Hostname

  • Kernel version

  • Network interfaces

  • IP addresses

  • Operating system version

  • Environment variables

  • Number of CPUs

  • Memory availability

  • Disk space

Facts help you make decisions during play execution. For example:

  • Restarting a server only if the kernel version changes

  • Adjusting MySQL configuration based on available memory

  • Setting IP addresses dynamically in templates

Ansible gathers facts automatically using the setup module before running tasks.

Normally, every play runs the setup module automatically before the first task in order to gather facts. This is reported as the Gathering Facts task in Ansible 2.3 and later, or simply as setup in older versions of Ansible. By default, you do not need to have a task to run setup in your play. It is normally run automatically for you.

One way to see what facts are gathered for your managed hosts is to run a short playbook that gathers facts and uses the debug module to print the value of the ansible_facts variable.

- name: Fact dump
hosts: all
tasks:
- name: Print all facts
debug:
var: ansible_facts

When you run the playbook, the facts are displayed in the job output:

[user@demo ~]$ ansible-playbook facts.yml
PLAY [Fact dump] ***************************************************************
TASK [Gathering Facts] *********************************************************
ok: [demo1.example.com]
TASK [Print all facts] *********************************************************
ok: [demo1.example.com] => {
"ansible_facts": {
"all_ipv4_addresses": [
"172.25.250.10"
],
"all_ipv6_addresses": [
"fe80::5054:ff:fe00:fa0a"
],
"ansible_local": {},
"apparmor": {
"status": "disabled"
},
"architecture": "x86_64",
"bios_date": "01/01/2011",
"bios_version": "0.5.1",
"cmdline": {
"BOOT_IMAGE": "/boot/vmlinuz-3.10.0-327.el7.x86_64",
"LANG": "en_US.UTF-8",
"console": "ttyS0,115200n8",
"crashkernel": "auto",
"net.ifnames": "0",
"no_timer_check": true,
"ro": true,
"root": "UUID=2460ab6e-e869-4011-acae-31b2e8c05a3b"
},

The playbook displays the content of the ansible_facts variable in JSON format as a hash/ dictionary of variables. You can browse the output to see what facts are gathered, to find facts that you might want to use in your plays.

The following table shows some facts which might be gathered from a managed node and may be useful in a playbook:

Examples of Ansible Facts

FACT VARIABLE
Short host name ansible_facts['hostname']
Fully qualified domain name ansible_facts['fqdn']
Main IPv4 address (based on routing ansible_facts['default_ipv4']['address']
List of the names of all network interfaces ansible_facts['interfaces']
Size of the /dev/vda1 disk partition ansible_facts['devices']['vda']['partitions'] ['vda1']['size']
List of DNS servers ansible_facts['dns']['nameservers']
Version of the currently running kernel ansible_facts['kernel']

Note:

Remember that when a variable’s value is a hash/dictionary, there are two syntaxes that can be used to retrieve the value. To take two examples from the preceding table:

• ansible_facts[‘default_ipv4’][‘address’] can also be written

ansible_facts.default_ipv4.address

• ansible_facts[‘dns’][‘nameservers’] can also be written

ansible_facts.dns.nameservers

When a fact is used in a playbook, Ansible dynamically substitutes the variable name for the fact with the corresponding value:

---
- hosts: all
tasks:
- name: Prints various Ansible facts
debug:
msg: >
The default IPv4 address of {{ ansible_facts.fqdn }}
is {{ ansible_facts.default_ipv4.address }}

The following output shows how Ansible was able to query the managed node and dynamically use the system information to update the variable. Facts can also be used to create dynamic groups of hosts that match particular criteria.

[user@demo ~]$ ansible-playbook playbook.yml
PLAY ***********************************************************************
TASK [Gathering Facts] *****************************************************
ok: [demo1.example.com]
TASK [Prints various Ansible facts] ****************************************
ok: [demo1.example.com] => {
"msg": "The default IPv4 address of demo1.example.com is
172.25.250.10"
}
PLAY RECAP *****************************************************************
demo1.example.com : ok=2 changed=0 unreachable=0 failed

TURNING OFF FACT GATHERING

Sometimes, you do not want to gather facts for your play. There are a couple of reasons why this might be the case. It might be that you are not using any facts and want to speed up the play or reduce load caused by the play on the managed hosts. It might be that the managed hosts cannot run the setup module for some reason, or need to install some prerequisite software before gathering facts.

To disable fact gathering for a play, set the gather_facts keyword to no:

---
- name: This play gathers no facts automatically
hosts: large_farm
gather_facts: no

Even if gather_facts: a task that uses the setup module: no is set for a play, you can manually gather facts at any time by running

tasks:
- name: Manually gather facts
setup:
...output omitted.

CREATING CUSTOM FACTS

Administrators can create custom facts which are stored locally on each managed host. These facts are integrated into the list of standard facts gathered by the setup module when it runs on the managed host. These allow the managed host to provide arbitrary variables to Ansible which can be used to adjust the behavior of plays.

Custom facts can be defined in a static file, formatted as an INI file or using JSON. They can also be executable scripts which generate JSON output, just like a dynamic inventory script.

Custom facts allow administrators to define certain values for managed hosts, which plays might use to populate configuration files or conditionally run tasks. Dynamic custom facts allow the values for these facts, or even which facts are provided, to be determined programmatically when the play is run.

By default, the setup module loads custom facts from files and scripts in each managed host’s /etc/ansible/facts.d directory. The name of each file or script must end in .fact in order to be used. Dynamic custom fact scripts must output JSON-formatted facts and must be executable.

This is an example of a static custom facts file written in INI format. An INI-formatted custom facts file contains a top level defined by a section, followed by the key-value pairs of the facts to define:

[packages]
web_package = httpd
db_package = mariadb-server
[users]
user1 = joe
user2 = jane

The same facts could be provided in JSON format. The following JSON facts are equivalent to the facts specified by the INI format in the preceding example. The JSON data could be stored in a static text file or printed to standard output by an executable script:

{
"packages": {
"web_package": "httpd",
"db_package": "mariadb-server"
},
"users": {
"user1": "joe",
"user2": "jane"
}
}

Custom facts are stored by the setup module in the ansible_facts.ansible_local variable. Facts are organized based on the name of the file that defined them. For example, assume that the preceding custom facts are produced by a file saved as /etc/ ansible/facts.d/custom.fact on the managed host. In that case, the value of ansible_facts.ansible_local[‘custom’][‘users’][‘user1’] is joe. You can inspect the structure of your custom facts by running the setup module on the managed hosts with an ad hoc command.

[user@demo ~]$ ansible demo1.example.com -m setup
demo1.example.com | SUCCESS => {
"ansible_facts": {
...output omitted...
"ansible_local": {
"custom": {
"packages": {
"db_package": "mariadb-server",
"web_package": "httpd"
},
"users": {
"user1": "joe",
"user2": "jane"
}
}
},
...output omitted...
},
"changed": false
}

Custom facts can be used the same way as default facts in playbooks:

[user@demo ~]$ cat playbook.yml

---
- hosts: all
tasks:
- name: Prints various Ansible facts
debug:
msg: >
The package to install on {{ ansible_facts['fqdn'] }}
is {{ ansible_facts['ansible_local']['custom']['packages']['web_package'] }}
[user@demo ~]$ ansible-playbook playbook.yml
PLAY ***********************************************************************
TASK [Gathering Facts] *****************************************************
ok: [demo1.example.com]
TASK [Prints various Ansible facts] ****************************************
ok: [demo1.example.com] => {
"msg": "The package to install on demo1.example.com is httpd"
}
PLAY RECAP *****************************************************************
demo1.example.com : ok=2 changed=0 unreachable=0 failed=0

USING MAGIC VARIABLES

Some variables are not facts or configured through the setup module, but are also automatically set by Ansible. These magic variables can also be useful to get information specific to a particular managed host.

Four of the most useful are:

hostvars

Contains the variables for managed hosts, and can be used to get the values for another managed host’s variables. It does not include the managed host’s facts if they have not yet been gathered for that host.

group_names

Lists all groups the current managed host is in.

groups

Lists all groups and hosts in the inventory.

inventory_hostname

Contains the host name for the current managed host as configured in the inventory. This may be different from the host name reported by facts for various reasons.

There are a number of other “magic variables” as well. For more information, see https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable. One way to get insight into their values is to use the debug module to report on the contents of the hostvars variable for a particular host:

[user@demo ~]$ ansible localhost -m debug -a 'var=hostvars["localhost"]'
localhost | SUCCESS => {
"hostvars[\"localhost\"]": {
"ansible_check_mode": false,
"ansible_connection": "local",
"ansible_diff_mode": false,
"ansible_facts": {},
"ansible_forks": 5,
"ansible_inventory_sources": [
"/home/student/demo/inventory"
],
"ansible_playbook_python": "/usr/bin/python2",
"ansible_python_interpreter": "/usr/bin/python2",
"ansible_verbosity": 0,
"ansible_version": {
"full": "2.7.0",
"major": 2,
"minor": 7,
"revision": 0,
"string": "2.7.0"
},
"group_names": [],
"groups": {
"all": [
"serverb.lab.example.com"
],
"ungrouped": [],
"webservers": [
"serverb.lab.example.com"
]
},
"inventory_hostname": "localhost",
"inventory_hostname_short": "localhost",
"omit": "__omit_place_holder__18d132963728b2cbf7143dd49dc4bf5745fe5ec3",
"playbook_dir": "/home/student/demo"
}
}

 

 

 

You can refer also Ansible public documentation page https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_vars_facts.html  to get more information about Ansible Facts.

 

Please visit our official website https://linuxgktech.com/ansible/ to know more about Ansible. 

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top