Managing Ansible Facts & Creating Ansible Custom Facts

What Is Ansible Fact

In summary, Ansible facts are system properties information.

These system properties information or rather, facts are gathered by the Ansible control node. The control node uses the setup module to gather these facts from the managed hosts, and these facts are used as variables, hence, Ansible facts are also variables.

The setup module in newer Ansible version always run by default and it is the first task to run when one runs a playbook. With the aid of this setup module, all managed hosts facts are being gathered on the control node by default.

To understand Ansible facts better, from our previous lessons, we have been running several playbooks, below is a screen-shot of one of the playbooks we have ran in one of our previous lessons.

ansible facts

From the screen shot, you can see that the first task of a play when one runs a playbook is “Gathering Facts“. You can also see that the name of the hosts the facts are gathered from are also displayed.

Gathering facts is a simple and easy way to get information or system properties that can help to determine what action to take based on the state of a managed host. They are just convenient way of fetching information of the managed hosts.

These gathered facts can be used in a playbook just as you would use variables or conditional loops in a playbook. In short, facts are just other form of variables.

How do you get all the facts in Ansible

The setup module can be used to get all the gathered facts on the Ansible control node.

To get or gather all the facts of a managed host or a group of hosts, use the command,

[lisa@drdev1 ~]$ ansible <managed-host> -m setup 

For example, to get all the facts of hqdev1.tekneed.com, use the command,

[lisa@drdev1 ~]$ ansible hqdev1.tekneed.com -m setup

hqdev1.tekneed.com | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.170.141",
            "192.168.122.1"
...........

You might want to pipe the output of the command to more or less due lots of information/facts that are gathered. You can also search for specific facts.

You can see that the output of the command is displayed in JSON format. You can also see that some of the gathered facts includes, IP address, host name, kernel version, operating system version and architecture, NICs, storage configuration, network configuration, etc.

Going forward, One can also run a playbook to get all the Ansible facts instead of using the Ansible ad hoc as used above. To run a playbook to get facts, follow the steps below.

*create a simple playbook with the debug module

[lisa@drdev1 ~]$ vim play5.yml
- name: gather facts
  hosts: hqdev1.tekneed.com
  tasks:
    - name: gather all facts for hqdev1
      debug:
        var: ansible_facts

*Run the playbook

[lisa@drdev1 ~]$ ansible-playbook play5.yml

........
TASK [gather all facts for hqdev1] ******************************************************
ok: [hqdev1.tekneed.com] => {
    "ansible_facts": {
        "all_ipv4_addresses": [
            "192.168.122.1",
            "192.168.170.141"
        ],
        "all_ipv6_addresses": [
            "fe80::ad03:2f76:22a3:99dc"

Having understood what Ansible facts is and how to display facts, let’s also see how you can refer to facts in a playbook just as you would refer to variables in a playbook.

In the playbook below, facts about FQDN and kernel version will be referred to as ansible_facts[‘fqdn’] and ansible_facts[‘kernel’].

Let’s do this, step by step

*create the playbook

[lisa@drdev1 ~]$ vim play8.yml
---
- name: gather facts
  hosts: hqdev1.tekneed.com
  tasks:
    - name: gather hqdev1 facts
      debug:
        msg: >
          My kernel version is {{ ansible_facts['kernel'] }}
          and my FQDN is {{ ansible_facts['fqdn'] }}

*Run the playbook

[lisa@drdev1 ~]$ ansible-playbook play8.yml

........
TASK [gather hqdev1 facts] **************************************************************
ok: [hqdev1.tekneed.com] => {
    "msg": "My kernel version is 4.18.0-240.15.1.el8_3.x86_64 and my FQDN is hqdev1.tekneed.com\n"
}

Creating an Ansible Custom Facts

Custom facts are the Ansible facts created by users. These facts are not available by default and can be stored locally on managed hosts.

To create a custom fact, the directory, “/etc/ansible/facts.d” must be created on the Ansible control node or on the managed hosts, and the custom facts file must have the .fact extension.

To create a custom facts file on the control node, follow the steps below.

1. make the /etc/ansible/facts.d directory

[lisa@drdev1 ~]$ mkdir -p /etc/ansible/facts.d/
[lisa@drdev1 ~]$ sudo vim /etc/ansible/facts.d/httpd.fact
[basic]
package=httpd
service=httpd
state=started
enabled=true

2. use the setup module to verify the custom facts and search for “ansible_local” string.

"ansible_local": {
            "httpd": {
                "basic": {
                    "enabled": "true",
                    "package": "httpd",
                    "service": "httpd",
                    "state": "started"

Now you can see that the custom facts has been created on the control node.

Similarly, you will do the same to create custom facts on managed hosts.

To create custom facts on hqdev1.tekneed.com for example, follow the steps below

1. make the /etc/ansible/facts.d directory

[root@hqdev1 ~]# mkdir -p /etc/ansible/facts.d/
[root@hqdev1 ~]# vim /etc/ansible/facts.d/httpd.fact
[basic]
package=httpd
service=httpd
state=started
enabled=true

2. From the ansible control node, use the setup module to verify the custom facts and search for “ansible_local” string.

[lisa@drdev1 ~]$ ansible hqdev1.tekneed.com -m setup |less
 "ansible_local": {
            "httpd": {
                "basic": {
                    "enabled": "true",
                    "package": "httpd",
                    "service": "httpd",
                    "state": "started"

Now you can see the custom facts created on the managed host.

Ansible facts file can be written in INI or JSON format but cannot be written in YAML format.

Having understood how to create custom facts, let’s look at how to use playbooks with custom facts

To use a playbook with the custom facts we have created above, follow the steps below.

*create a playbook

[lisa@drdev1 ~]$ vim play9.yml
---
- name: Install httpd
  hosts: hqdev1.tekneed.com
  tasks:
    - name: Install httpd
      yum:
        name: "{{ ansible_facts['ansible_local']['httpd']['basic']['package'] }}"
        state: latest

    - name: Start and enable httpd
      service:
        name: "{{ ansible_facts['ansible_local']['httpd']['basic']['service'] }}"
        state: "{{ ansible_facts['ansible_local']['httpd']['basic']['state'] }}"
        enabled: "{{ ansible_facts['ansible_local']['httpd']['basic']['enabled'] }}"

*Run the playbook

[lisa@drdev1 ~]$ ansible-playbook play9.yml

PLAY [Install httpd] *************************************************************************************

The custom fact created on hqdev1.tekneed.com host above was manually created. In real life environment, it is smart to create /etc/ansible/fact.d/httpd using a playbook. This activity will be done as a class activity.

How do you stop Ansible gathering facts

If there are many inventories a user’s playbook will execute against, it is apparent that the ansible control node will have to gather facts from all the managed hosts specified in the inventory file.

This can elongate the ansible playbook operation time, especially if the playbook contains many tasks, hence, one can stop the ansible control node from gathering facts on the managed hosts.

To stop the ansible control node from gathering facts, add the syntax, “gather_facts: false” in the playbook.

For example, to stop the ansible control node from gathering facts in a simple playbook as below, use the syntax as it is used below.

---
 - name: Install, start and enable httpd
   hosts: group1
   gather_facts: false
   tasks:
     - name: Install httpd
       yum:
         name: httpd

*Run the playbook

You can see that the ansible control node did not gather facts because it was set to false. The value can also be set to no or 0, it is how you choose to define your boolean, they all mean the same thing.

One thing you must also know is that setting the gather_facts directive to false for some ansible tasks will result to error. An example is the playbook with the custom facts that we created above.

Setting the gather_facts directive to false will defeat the purpose of the task, hence the playbook will result to error when you run it.

Magic Variables

Magic variables are special variables that cannot be set directly by a user neither by facts but automatically set by ansible by default. Magic variables is also useful to gather information of managed hosts.

There are numbers of magic variables but the most common ones are hostvars, groups, group_names, inventory_hostname, etc. Click here to see other magic variables in Ansible

Let’s use play5.yml we created above as an example of one of the ways to refer to a magic variable in a playbook.

[lisa@drdev1 ~]$ vim play5.yml
- name: gather facts
  hosts: hqdev1.tekneed.com
  tasks:
    - name: gather all facts for {{ inventory_hostname }}
      debug:
        var: ansible_facts

To show that you have understood this lesson, you can take on the class activity below.

Class Activity

Create a custom fact on hqdev1.tekneed.com host with a playbook. The playbook must contain a custom fact syntax and may contain variables to install the httpd package.

If you like this article, you can support us by

1. sharing this article.

2. Buying the article writer a coffee (click here to buy a coffee)

3. Donating to move our project to the next level. (click here to donate)

If you need personal training, send an email to info@tekneed.com

Click Here To Watch Video On Managing Ansible Facts

RHCE / EX294 Exam Practice Question On Managing Ansible Facts

Your feedback is welcomed. If you love others, you will share with others

Be the first to comment

Leave a Reply

Your email address will not be published.


*