Aller au contenu principal

Utiliser les customs facts Ansible

· 4 minutes de lecture
Stéphane ROBERT
Consultant DevOps

Petit rappel : Chaque fois que vous exécutez un playbook Ansible, la première tache qui est exécuté est la collecte des facts. A moins que vous l'ayez désactivé avec le paramètre de playbook gather_facts: false.

Cette collecte rassemble toute une série d'informations présentes sur la ou les machines distantes : adresses IP, liste des disques, version du système d’exploitation, etc. Dans le langage Ansible on appelle ça des « facts ».

Mais, saviez-vous que vous pouvez également ajouter vos propres facts qu'Ansible collectera de la même manière que vous pourrez utiliser ensuite dans les conditions ou comme paramètre de module. On les appelle les customs facts.

Les customs facts bien qu'évoqué dans le module setup, celui qui est appelé implicitement et contrôlé par le paramètre gather_facts, ne sont pas très documenté et c'est cela que je vous propose de vous exposer.

Où créer des customs facts ?

Les customs facts sont en fait assez faciles à mettre en œuvre. Sur chaque noeud de votre inventaire Ansible, il suffit de créer un répertoire dans lequel vous pourrez déposer un ou plusieurs fichiers nommés avec l'extension .fact.

Lors de l'exécution implicite du module setup Ansible cherche ses fichiers de facts dans le répertoire /etc/ansible/facts.d/. Il est pour le moment impossible de lui indiquer un autre chemin.

Par contre, vous pouvez désactiver cette collecte implicite et exécuter le module setup de manière contrôlé et là en lui indiquant le chemin où se trouve ces fichiers facts. Il suffit d'utiliser le paramètre fact_path.

Voici comment écrire une telle invocation :

---
- name: Update OS of servers
  hosts: webservers
  become: true
  gather_facts: false

  tasks:
  - name: Collects facts
    ansible.builtin.setup:
      fact_path: /custom/facts/path/
      gather_subset: !all,min

En utilisant ce pattern, vous pouvez optimiser le temps d'exécution de vos playbooks en ne collectant que les facts nécessaires à sa bonne exécution. En effet, la collecte des facts est assez consommatrice et c'est pour cela qu'il est possible d'utiliser un mécanisme de cache avec divers outils spécialisés.

Que mettre dans ces fichiers de customs facts ?

Les fichiers de facts doivent afficher des données au format json ou ini. Donc il est tout à fait possible d'utiliser un script bash, python, ou tout autre langage.

Le format ini

Par exemple si vous créer le fichier preference.fact dans le dossier /etc/ansible/facts.d avec ce contenu :

[general]
function=War
family=Destruction

Lors de la collecte des facts vous devriez les voir apparaître ainsi :

        "ansible_local": {
            "preference": {
                "general": {
                    "family": "Destruction",
                    "function": "War"
                }
            }
        },

Vous pouvez le tester sur votre machine en créant le fichier et en exécutant le module setup de cette manière :

all -m setup -a 'gather_subset=!all,min' -c local -i localhost,all

Un script qui retourne du json

On peut tout à fait utiliser un script écrit dans le langage de votre choix tant qu'il retourne de l'information sous le format json ou ini :

Exemple de script bash :

#!/bin/bash
DATE=$(date)
echo {\"date\" : \"${DATE}\"}

Lançons le playbook et voyons ce qu'il retourne :

        "ansible_local": {
            "date": {
                "date": "mer. 20 avril 2022 07:42:23 CEST"
            },
            "preference": {
                "general": {
                    "family": "Destruction",
                    "function": "War"
                }
            }
        },

Donc, vous voyez qu'il suffit de créer des fichiers qui retournent des données dans le format de votre choix. Vous les retrouverez dans la liste ansible_local ou chaque fichier est une liste portant de son fichier sans l'extension.

Quand et comment créer ses fichiers de customs facts ?

Le plus simple est de le créer au moment où vous provisionnez vos machines. Par exemple si vous utilisez Terraform, créer les avec un provisionner de type file. Vous pouvez aussi utiliser Ansible pour les créer avec ce contenu qui pourrait devenir par la suite un rôle :

---
- name: Update OS of servers
  hosts: webservers
  become: true
  gather_facts: false
  tasks :
    - name: "Create custom fact directory"
      ansible.builtin.file:
        path: "/etc/ansible/facts.d"
        state: "directory"
    - name: "Insert custom fact file"
      ansible.builtin.copy:
        src: files/date.fact
        dest: /etc/ansible/facts.d/custom.fact
        mode: 0755

Ces fichiers pourraient être aussi créé par des scripts qui s'exécuteraient de régulièrement via des jobs cron, ou des workflows AWX.

Plus loin

Tout est envisageable. Je l'ai mis en oeuvre par exemple pour mettre en place un système de patch d'OS automatique. La mise à jour des packages de l'OS ne s'exécutait que si le paramètre gel_applicatif se trouvait à false. D'autres paramètres contrôlaient le jour de la semaine et l'heure à laquelle cette mise à jour pouvait s'appliquer...

Il y a plein de cas d'usage possible de ces customs facts comme alimenter les données d'une CMDB. On n'y pense pas assez souvent, mais plus maintenant !