Facts + Implicit Variables¶
Objectif
Découvrir les facts (informations collectées automatiquement sur les hôtes) et les magic variables (variables implicites fournies par ansible), puis les utiliser dans des playbooks.
Durée
~40 minutes (exploration facts + 4 mini-playbooks)
Commandes de l'atelier¶
Les commandes pour initialiser le lab.
J'affiche les facts récupérés de la machine Debian avec le module ansible.builtin.setup (souvent abrégé setup).
L'objectif du module est de récupérer des informations pertinentes d'un hôte pour en faire des variables utilisables par ansible.
# sur le control host
cd ansible/projets/ema/playbooks
ansible debian -m setup
!! | less # ansible debian -m setup | less
^less^wc -l # ansible debian -m setup | wc -l

Pour filtrer par contenu d'une liste (fnmatch), le filtre par défaut est [] (donc rien).

Dans le guide playbook_vars_facts, il est précisé que les facts peuvent être récupérés dans le dictionnaire ansible_facts, avec une clé comme architecture (i.e.ansible_facts.architecture).
Il est aussi possible de pouvoir récupérer les facts dans une variable avec le préfix ansible_, pour reprendre l'exemple au dessus : ansible_architecture. C'est possible car les associations dictionnaire-clés récupérées sont aussi poussées individuellement comme variable, avec un nom unique dans le namespace principal.
Si je cite le paramètre INJECT_FACTS_AS_VARS :
Facts are available inside the ansible_facts variable, this setting also pushes them as their own vars in the main namespace. Unlike inside the ansible_facts dictionary where the prefix ansible_ is removed from fact names, these will have the exact names that are returned by the module.
Par défaut, ce paramètre est à true. Donc les facts sont disponibles en dictionnaire et en variables globales injectées. Si ce paramètre est à false, alors uniquement le dictionnaire fonctionne.
De ce que j'ai compris, historiquement toutes les variables étaient injectées dans le namespace mais ansible a décidé de passer au dictionnaire ansible_facts. Mais le paramétrage de INJECT_FACTS_AS_VARS reste à true par retro-compatibilité.
J'ai pas réussi à trouver la release note, PR ou issues pointant directement vers ce changement. Mais de ce que j'ai lu sur les forums c'est sûrement apparu entre la version 2.2 et 2.3.
C'est drôle de voir que ça dure depuis plus de 5 ans.
Pour utiliser les variables dans un playbook, je préfère donc utiliser les clés du dictionnaire ansible_facts par compatibilité et démarche actuelle... Avec la syntaxe ressemblant aux FQCN par uniformité (même si ça peut porter à confusion).
La notation par crochets serait plus efficace si des clés avaient des caractères spéciaux par exemple...
| facts2.yml | |
|---|---|

Si je récupère les informations sur les OS des Target Hosts. Pour s'entrainer à utiliser les magic vars.
Ici est utilisée la magic vars inventory_hostname, tout le reste étant des ansible_facts.
| distribution-info.yml | |
|---|---|

Si on cherche à utiliser playbook_dir...
| playbook-info.yml | |
|---|---|

Utiliser groups...
| hosts-info.yml | |
|---|---|

Et enfin, pour les addresses IPv4.
| ip-info.yml | |
|---|---|

À vous de jouer !¶
Je vais ajouter le paramètre INJECT_FACTS_AS_VARS dans le fichier ansible.cfg
Gestionnaire de paquets¶
Pour ensuite chercher la clé qui me donnera le gestionnaire de paquet.

avec ansible_facts.ansible_pkg_mgr, j'ai le nom du gestionnaire de paquets des Target Hosts.
Si je rédige un playbook pour vérifier le nom sur chacun d'entre eux.
Je donne un nom au playbook entier, quand il se lance on voit l'action qu'il va faire (ici Gather Package Manager).
J'utilise aussi la restriction gather_subset.

Version de Python¶
Je vais utiliser la variable ansible_facts.python_version.
| python-info.yml | |
|---|---|

DNS utilisés¶

Je retiens
ansible_factsest le dictionnaire centralisé des facts. Le préfixeansible_(ex :ansible_distribution) est une injection rétro-compatible contrôlée parINJECT_FACTS_AS_VARS.gather_subsetlimite la collecte aux catégories nécessaires (min,network,distribution...) pour accélérer l'exécution.- Les magic variables (
inventory_hostname,playbook_dir,groups...) ne sont pas des facts mais des variables fournies paransiblelui-même. run_once: trueexécute une tâche une seule fois pour tout le play, utile pour les infos globales.
Cheatsheet¶
| Symptôme | Cause probable | Correction |
|---|---|---|
{{ ansible_distribution }} → undefined variable |
gather_facts: false dans le play, ou INJECT_FACTS_AS_VARS = false dans ansible.cfg |
Réactiver gather_facts: true ou accéder au dictionnaire ansible_facts.distribution |
ansible debian -m setup -a "filter=architecture" ne retourne rien |
Le filtre utilise fnmatch et la clé exacte est ansible_architecture (format d'affichage) le glob architecture ne matche rien |
Utiliser un glob : filter=ansible_architecture ou filter=*architecture* |
| Les playbooks deviennent très lents sur un gros parc | gather_facts: true collecte tout par défaut (all), beaucoup de données réseau |
Restreindre avec gather_subset: ["!all", "min"] (ou ajouter seulement ce dont on a besoin : network, distribution…) |
ansible_facts.dns.nameservers → undefined |
Le subset network n'est pas collecté |
Ajouter gather_subset: ["!all", "min", "network"] |
groups.testing → undefined |
Pas de groupe testing dans l'inventaire courant |
Vérifier l'inventaire effectif avec ansible-inventory --graph |
Après inject_facts_as_vars = false, tous les playbooks cassent |
Les anciennes références ansible_<fact> ne résolvent plus |
Migrer vers ansible_facts.<fact> (préférable à long terme) |
Sources (principales)¶
- Docs
ansibleDiscovering variables: facts and magic variables - Docs
ansibleSpecial variables (magic vars) - Docs
ansibleansible.builtin.setupmodule (source des facts) - Docs
ansiblegather_subsetparameter - Docs
ansibleINJECT_FACTS_AS_VARSconfiguration - Docs
ansibleFact caching (accélérer les plays répétés) - Docs
ansibleCustom facts (/etc/ansible/facts.d/) - Reddit
ansible_distributionvsansible_facts.distribution(discussion historique)
Précédent : Stored Variables Suite : Heterogeneous Targets