top of page

Ansible Custom Fact

In my previous blog we saw that what is Ansible Fact and why it is being used for.

Just to revise this again, Ansible fats are information about a host which ansible automatically gathers. It contains information about a host like IP Address, Partition details, Server architecture, ethernet card details, mac address etc...

But what if suppose you want to capture an information which is not a part of default ansible facts like version of package ?

Valid question right ? So to achieve this you can write your own custom fact to be available through ansible.


How to get this setup ?


To setup ansible custom fact we need to fulfill following prerequisites on remote server.

1. Create folder /etc/ansible/facts.d on remote servers.

2. Inside this folder write your custom fact script to generate an output in .json format.

The file extension of this script should ended with .fact only. So if you write a bash or python script make sure that file extension always to keep a .fact

3. This custom fact script should be executable, means it should have execute permission without any syntax / programmatic erros.


So lets start setting up above environment on local ansible tower server. After verifying on local server we can get this setup using separate playbook on remote servers.


1. Create folder /etc/ansible/facts.d

[root@siddhesh ~]# mkdir /etc/ansible/facts.d

2. Write a bash script to fetch version of redis & mariadb version in .json format and set executable permission.

[root@siddhesh ~]# cat /etc/ansible/facts.d/app_version.fact
#!/usr/bin/bash
#Custom script of fact
redis=$(redis-server --version | awk '{print $3}')
mariadb=$(mysql --version|awk '{print $2" "$3" "$4" "$5}' |awk -F',' '{print $1}')

cat << EOF
{ "Redis Version": "$redis",
  "Mariadb Version": "$mariadb"
}
EOF
[root@siddhesh ~]#

Set executable permission and run to see if it is generating expected output in .json format.

[root@siddhesh ~]# chmod +x /etc/ansible/facts.d/app_version.fact
[root@siddhesh ~]#/etc/ansible/facts.d/app_version.fact
{ "Redis Version: "v=3.2.3",
  "Mariadb Version: "Ver 15.1 Distrib 5.5.50-MariaDB"
}
[root@siddhesh ~]#

Lets create a same environment on all remote servers to capture this custom fact output.

So to create a same environment on remote server either you do this manual or use ansible it self to make this task more easier. I am going to use ansible playbook to perform above task on remote server.

I wrote below playbook to make this task automated.

[root@siddhesh ~]# cat custom_fact_deploy.yml
- hosts: dbserver
  tasks:
  - name: "Create facts.d directory"
    file:
        path: "/etc/ansible/facts.d"
        state: "directory"

  - name: "copy custom fact bash script"
    copy:
        src: /etc/ansible/facts.d/app_version.fact
        dest: /etc/ansible/facts.d/app_version.fact
        mode: 0755

[root@siddhesh ~]#

Lets execute this and verify changes on remote server.

[root@siddhesh ~]# ansible-playbook custom_fact_deploy.yml

PLAY [dbserver] *****************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************
ok: [node2.tecgeek.info]
ok: [node1.tecgeek.info]

TASK [Create facts.d directory] *************************************************************************************************************************************
changed: [node2.tecgeek.info]
changed: [node1.tecgeek.info]

TASK [copy custom fact bash script] *********************************************************************************************************************************
changed: [node2.tecgeek.info]
changed: [node1.tecgeek.info]

PLAY RECAP **********************************************************************************************************************************************************
node1.tecgeek.info         : ok=3    changed=2    unreachable=0    failed=0
node2.tecgeek.info         : ok=3    changed=2    unreachable=0    failed=0
[root@siddhesh ~]#

On Remote Server :

[root@node2 ~]# ll /etc/ansible/facts.d/app_version.fact
-rwxr-xr-x 1 root root 250 May 10 15:05 /etc/ansible/facts.d/app_version.fact
[root@node2 ~]# 

So we have now successfully setup environment on remote servers which is needed to capture a custom facts.


Lets run a setup module with filter enabled of ansible_local. All custom facts are getting stored under ansible_local filter.

[root@siddhesh ~]# ansible dbserver -m setup -a 'filter=ansible_local'
node2.tecgeek.info | SUCCESS => {
    "ansible_facts": {
        "ansible_local": {
            "app_version": {
                "Mariadb Version": "Ver 15.1 Distrib 5.5.50-MariaDB",
                "Redis Version": "v=3.2.3"
            }
        }
    },
    "changed": false
}
node1.tecgeek.info | SUCCESS => {
    "ansible_facts": {
        "ansible_local": {
            "app_version": {
                "Mariadb Version": "Ver 15.1 Distrib 5.5.50-MariaDB",
                "Redis Version": "v=3.2.3"
            }
        }
    },
    "changed": false
}
[root@siddhesh ~]# 

As you can see from above output that our requirement of capturing application details of redis & mariadb from remote server is accomplished successfully. By using similar method you can capture any details from remote servers.

bottom of page