Ansible

How to Use Ansible Custom Facts

Facts are like variables in Ansible. Ansible generates a lot of facts, depending on the host it automates. If you need, you can also define custom facts/variables in Ansible.

You can define three types of custom facts in Ansible.

1) Global facts: These facts are accessible from every host in your inventory file.
2) Group facts: These facts are only accessible from a specific set of hosts or a host group.
3) Host facts: These facts are only accessible from a particular host.

In this article, I am going to show you how to work with Ansible custom facts. So, let’s get started.

Prerequisites:

If you want to try out the examples of this article,

1) You must have Ansible installed on your computer.
2) You must have at least 6 Linux hosts configured for Ansible automation.

There are many articles on LinuxHint dedicated to Installing Ansible and configuring hosts for Ansible automation. You may check them out if needed.

Setting Up a Project Directory:

Before we get started, let’s create a project directory so that we can organize our project files.

To create a project directory custom-facts/ in your HOME directory, run the following command:

$ mkdir -pv custom-facts/{playbooks,host_vars,group_vars}

Now, navigate to the custom-facts/ directory as follows:

$ cd custom-facts/

Create an Ansible configuration file ansible.cfg in your project directory as follows:

$ nano ansible.cfg

Type in the following lines your ansible.cfg file.

[defaults]
inventory           = hosts
host_key_checking   = False

Once you’re done, press <Ctrl> + X followed by Y and <Enter> to save the ansible.cfg configuration file.

Now, create an Ansible inventory file hosts in your project directory as follows:

$ nano hosts

Type in the following lines in your host’s inventory file.

vm1.nodekite.com
vm2.nodekite.com
[web]
vm3.nodekite.com
vm4.nodekite.com
[database]
vm[5:6].nodekite.com

Once you’re done, press <Ctrl> + X followed by Y and <Enter> to save the hosts inventory file.

To list all the available hosts in your inventory file, run the following command:

$ ansible all --list-hosts

As you can see, I have six hosts in my inventory file.

To list the hosts available in the web group of your inventory file, run the following command:

$ ansible web --list-hosts

As you can see, I have two hosts (vm3.nodekite.com and vm4.nodekite.com) in the web group of my inventory file.

To list the hosts available in the database group of your inventory file, run the following command:

$ ansible database --list-hosts

As you can see, I have two hosts (vm5.nodekite.com and vm6.nodekite.com) in the database group of my inventory file.

Working with Ansible Global Facts:

In this section, I am going to show you how to define Ansible global facts/variables in your inventory file and access them from your Ansible playbooks. I will also show you how to define global facts/variables in a separate file.

First, open the host’s inventory file with the following command:

$ nano hosts

Now, add the marked lines in your host’s inventory file. Once you’re done, press <Ctrl> + X followed by Y and <Enter> to save the file.

You add global facts in the all:vars section. Here, I have added the web_url global fact.

Now, create a new playbook print_global_fact.yaml in the playbooks/ directory as follows:

$ nano playbooks/print_global_fact.yaml

Then, type in the following lines in the print_global_fact.yaml file.

- hosts: all
  user
: ansible
  tasks
:
    - name
: Print the value of global fact 'web_url'
      debug
:
        msg
: 'Web URL: {{web_url}}'

The purpose of this playbook is to print the web_url global fact.

Once you’re done, press <Ctrl> + X followed by Y and <Enter> to save the print_global_fact.yaml file.

Now, run the print_global_fact.yaml playbook as follows:

$ ansible-playbook playbooks/print_global_fact.yaml

As you can see, all the hosts in my inventory file can access the global fact web_url.

You can also add global facts in a separate file. This way, you can keep the inventory file clean. Let’s see how to do it.

First, let’s remove the global facts from the host’s inventory file.

$ nano hosts

Now, remove the marked lines from the inventory file and press <Ctrl> + X, followed by Y and <Enter> to save the inventory file.

Then, create a new file all in the group_vars/ directory as follows:

$ nano group_vars/all

To add the global fact web_url, type in the following line in the group_vars/all file.

web_url: https://www.linuxhint.com

Once you’re done, press <Ctrl> + X followed by Y and <Enter> to save the group_vars/all file.

To check whether you can access the global fact web_url, run the print_global_fact.yaml playbook again as follows:

$ ansible-playbook playbooks/print_global_fact.yaml

As you can see, all the hosts in my inventory file can access the global fact web_url.

Working with Ansible Group Facts:

In this section, I am going to show you how to define Ansible group facts/variables in your inventory file and access them from your Ansible playbooks. I will also show you how to define group facts/variables in a separate file.

First, open the host’s inventory file with the following command:

$ nano hosts

If you have a host group group1, then you add group facts/variables for that host group in a group1:vars section of your inventory file.

[group1]

[group1:vars]
variable1=value1
variable2=value2

For example, to add the group facts/variables domain_name and database_backends for the web host group, you can type in the marked lines in your inventory file.

Once you’re done, press <Ctrl> + X followed by Y and <Enter> to save the inventory file.

To print and test whether we can access the group facts, create a new playbook print_group_facts.yaml in the playbooks/ directory as follows:

$ nano playbooks/print_group_facts.yaml

 

Type in the following lines in your print_group_facts.yaml file.

- hosts: web
  user
: ansible
  tasks
:
    - name
: Print group facts
      debug
:
        msg
: 'Domain Name: {{domain_name}} Database Backend: {{database_backend}}'

Once you’re done, press <Ctrl> + X followed by Y and <Enter> to save the print_group_facts.yaml file.

Now, run the print_group_facts.yaml playbook as follows:

$ ansible-playbook playbooks/print_group_facts.yaml

As you can see, the hosts in the web group can access the domain_name and database_backend group facts/variables.

Now, let’s clean up the inventory file and see how to add group facts/variables in a separate file.

First, open the host’s inventory file as follows:

$ nano facts

Remove the marked lines from the host’s inventory file. Once you’re done, press <Ctrl> + X followed by Y and <Enter> to save the hosts inventory file.

As we are adding group variables for the web host group, create a new file web (same as the group name) in the group_vars/ directory as follows:

$ nano group_vars/web

To add the group facts domain_name and database_backend for the web host group, add the following lines in the group_vars/web file.

domain_name: web.linuxhint.com
database_backend
: pgsql

Once you’re done, press <Ctrl> + X followed by Y and <Enter> to save the group_vars/web file.

To check whether the hosts in the web group can access the group facts, run the print_group_facts.yaml playbook as follows:

$ ansible-playbook playbooks/print_group_facts.yaml

As you can see, the hosts in the web group can access the domain_name and database_backend group facts/variables.

Working with Ansible Host Facts:

In this section, I am going to show you how to define Ansible host facts/variables in your inventory file and access them from your Ansible playbooks. I will also show you how to define host facts/variables in a separate file.

First, open the host’s inventory file with the following command:

$ nano hosts

You can add host facts/variables after the DNS name or IP address of the host in your inventory file as follows:

www.domain1.com      variable1=value1       variable2=value2
192.168.22.2         variable1=value3       variable2=value4

For example, you can add host facts/variables domain_name and database_backend for the hosts vm3.nodekite.com and vm4.nodekite.com, as marked in the screenshot below.

Notice that the value of the domain_name and database_backend facts/variables are different for each host.

Once you’re done adding the host facts/variables, press <Ctrl> + X, followed by Y and <Enter> to save the host’s inventory file.

As I have added the same facts/variables as in the group facts/variables example, we can use the print_group_facts.yaml playbook to test the accessibility of these facts/variables as well.

Run the print_group_facts.yaml playbook as follows:

$ ansible-playbook playbooks/print_group_facts.yaml

As you can see, the host facts/variables are accessible to their specified host. The values are different for each host as well.

As each of the hosts are in a separate line in my inventory file, I could easily add host facts/variables in my inventory file. But, if you use ranges to define hosts in your inventory file as marked in the screenshot below, you can’t add host facts/variables like that.

You can add host facts/variables in a separate file, just like you have done for the global and group facts/variables.

To add host facts/variables for the vm5.nodekite.com host, create a new file vm5.nodekite.com (same as the host DNS name) in the host_vars/ directory as follows:

$ nano host_vars/vm5.nodekite.com

You can add the host facts/variables db_port and db_name for the host vm5.nodekite.com with the following lines.

db_port: 3306
db_name: demo1

Once you’re done, press <Ctrl> + X followed by Y and <Enter> to save the vm5.nodekite.com file.

The same way, to add host facts/variables for the host vm6.nodekite.com, create a new file vm6.nodekite.com in the host_vars/ directory as follows:

$ nano host_vars/vm6.nodekite.com

You can add the host facts/variables db_port and db_name for the host vm6.nodekite.com with the following lines.

db_port: 8877
db_name
: app1

Once you’re done, press <Ctrl> + X followed by Y and <Enter> to save the vm6.nodekite.com file.

To print and test whether we can access the host facts/variables, create a new playbook print_host_facts.yaml in the playbooks/ directory as follows:

$ nano playbooks/print_host_facts.yaml

Now, type in the following lines in the print_host_facts.yaml file.

- hosts: database
  user
: ansible
  tasks
:
    - name
: Print host facts
      debug
:
        msg
: 'Database Name: {{db_name}} Database Port: {{db_port}}'

Once you’re done, press <Ctrl> + X followed by Y and <Enter> to save the print_host_facts.yaml file.

To check whether the host vm5.nodekite.com and vm6.nodekite.com can access the host facts/variables, run the print_host_facts.yaml playbook as follows:

$ ansible-playbook playbooks/print_host_facts.yaml

As you can see, the hosts vm5.nodekite.com and vm6.nodekite.com can access the db_name and db_port host facts/variables.

Putting it All Together: Ansible Facts Precedence

In this section, I am going to talk about Ansible fact/variable precedence. So, let’s get started.

Before we get started, let’s clean up the inventory file.

Open the host’s inventory file with the following command:

$ nano hosts

Remove the marked section from the inventory file.

This is how your inventory file should look at this point.

Now, add the marked line in your inventory file. These lines add the global facts/variables fact_scope and port.

Then, add the marked lines in your inventory file. These lines add the fact_scope and port facts/variables for the hosts in the database group.

Finally, add the fact_scope and port host facts/variables for the vm3.nodekite.com and vm4.nodekite.com hosts, as marked in the screenshot below.

Once you’re done, press <Ctrl> + X followed by Y and <Enter> to save the inventory file.

To print the value of the global, group and host facts/variables, create a new playbook fact_precendence.yaml in the playbooks/ directory as follows:

$ nano playbooks/fact_precedence.yaml

Type in the following lines in the fact_precedence.yaml file.

- hosts: all
user
: ansible
tasks
:
- name
: Print all facts
debug
:
msg
: 'Fact Scope: {{fact_scope}}    Port: {{port}}'

Once you’re done, press <Ctrl> + X followed by Y and <Enter> to save the fact_precedence.yaml file.

To print the global, group, and host facts/variables, run the fact_precedence.yaml playbook as follows:

$ ansible-playbook playbooks/fact_precedence.yaml

As you can see, the global, group, and host facts/variables are printed.

Notice that the group facts/variables replaced the global facts/variables (1). Also, notice that the host facts/variables replaced both the group and global facts/variables (2).

The fact/variable precedence of Ansible is as follows:

Host fact > Group fact > Global fact

Conclusion:

After reading this article, you should be able to comfortably work with Ansible global, group, and host facts/variables. Remember the Ansible custom fact precedence. It will help you debug your Ansible playbooks more easily.

About the author

Shahriar Shovon

Freelancer & Linux System Administrator. Also loves Web API development with Node.js and JavaScript. I was born in Bangladesh. I am currently studying Electronics and Communication Engineering at Khulna University of Engineering & Technology (KUET), one of the demanding public engineering universities of Bangladesh.