Facts et variables implicites
Objectif de cet atelier pratique
- Intégrer par la pratique le fonctionnement des facts et des variables implicites
Démarrer le labo
Placez-vous dans le répertoire du seizième atelier pratique :
Voici les quatre machines virtuelles de cet atelier :
| Machine virtuelle | Adresse IP |
|---|---|
ansible |
192.168.56.10 |
rocky |
192.168.56.20 |
debian |
192.168.56.30 |
suse |
192.168.56.40 |
Démarrez les VM :
Connectez-vous au Control Host :
L'environnement de cet atelier est préconfiguré et prêt à l'emploi :
-
Ansible est installé sur le Control Host.
-
Le fichier
/etc/hostsdu Control Host est correctement renseigné. -
L'authentification par clé SSH est établie sur les trois Target Hosts.
-
Le répertoire du projet existe et contient une configuration de base et un inventaire.
-
Direnv est installé et activé pour le projet.
-
Le validateur de syntaxe
yamllintest également disponible.
Rendez-vous dans le répertoire des playbooks :
$ cd ansible/projets/ema/playbooks/
direnv: loading ~/ansible/projets/ema/.envrc
direnv: export +ANSIBLE_CONFIG
Les facts et les variables implicites
Dans la configuration par défaut, Ansible va commencer par recueillir tout un
tas d'informations diverses et variées sur les hôtes lorsque vous exécutez un
playbook. Ce comportement est défini par le paramètre gather_facts, dont la
valeur par défaut est true.
Toutes ces informations sont soigneusement rangées dans un dictionnaire
ansible_facts et pourront être utilisées par la suite comme n'importe quelle
série de variables.
Pour avoir une première idée des facts, exécutez la commande ad hoc
suivante sur l'hôte debian :
Le résultat dépasse de loin la taille d'un écran. On va donc réitérer la commande comme ceci :
L'affichage des facts de notre hôte dépasse les 600 lignes :
En mode ad hoc, les facts peuvent être filtrés. Voici par exemple toutes les infos relatives à la distribution :
$ ansible debian -m setup -a "filter=ansible_distribution*"
debian | SUCCESS => {
"ansible_facts": {
"ansible_distribution": "Debian",
"ansible_distribution_file_parsed": true,
"ansible_distribution_file_path": "/etc/os-release",
"ansible_distribution_file_variety": "Debian",
"ansible_distribution_major_version": "12",
"ansible_distribution_minor_version": "4",
"ansible_distribution_release": "bookworm",
"ansible_distribution_version": "12"
},
"changed": false
}
Les informations affichées par le module setup peuvent nous induire en
erreur. À titre d'exemple, jetez un œil à la clé ansible_architecture avec
la valeur correspondante x86_64 :
$ ansible debian -m setup | head -n 12
debian | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.121.33",
"10.23.45.30"
],
"ansible_all_ipv6_addresses": [],
"ansible_apparmor": {
"status": "enabled"
},
"ansible_architecture": "x86_64",
"ansible_bios_date": "04/01/2014",
Si vous voulez utiliser ces informations dans un playbook, vous serez probablement tentés d'écrire quelque chose comme ceci :
--- # facts1.yml
- hosts: debian
tasks:
- debug:
var: ansible_facts.ansible_architecture
- debug: # alternative syntax
var: ansible_facts['ansible_architecture']
...
Malheureusement, les deux variantes ne vous affichent qu'une valeur
UNDEFINED :
TASK [debug] **********************************************************
ok: [debian] => {
"ansible_facts.ansible_architecture": "VARIABLE IS NOT DEFINED!"
}
TASK [debug] **********************************************************
ok: [debian] => {
"ansible_facts['ansible_architecture']": "VARIABLE IS NOT DEFINED!"
}
Essayez plutôt ceci :
--- # facts2.yml
- hosts: debian
tasks:
- debug:
var: ansible_facts.architecture
- debug: # alternative syntax 1
var: ansible_facts['architecture']
- debug: # alternative syntax 2
var: ansible_architecture
...
Voici ce que ça donne :
TASK [debug] ********************************
ok: [debian] => {
"ansible_facts.architecture": "x86_64"
}
TASK [debug] ********************************
ok: [debian] => {
"ansible_facts['architecture']": "x86_64"
}
TASK [debug] ********************************
ok: [debian] => {
"ansible_architecture": "x86_64"
}
Essayons de tirer une première conclusion :
-
Lorsque vous utilisez des facts dans le dictionnaire
ansible_facts, vous devez impérativement écrire la clé de premier niveau sans le préfixeansible_. -
Les clés de premier niveau sont également disponibles sous forme de variable directe avec le préfixe
ansible_.
En dehors des facts, vous avez également les variables implicites (magic vars) qui sont toujours disponibles :
-
inventory_hostname: le nom de l'hôte dans l'inventaire -
playbook_dir: répertoire dans lequel se trouve le playbook en cours -
inventory_dir: répertoire dans lequel se trouve l'inventaire -
etc.
Le meilleur moyen pour assimiler tout ce joyeux mélange de facts et de variables implicites, c'est de les utiliser dans des petits playbooks. C'est ce que nous allons faire. Commençons par afficher quelques infos sur les distributions Linux utilisées sur nos systèmes :
--- # distribution-info.yml
- hosts: all
tasks:
- name: Display distribution information
debug:
msg: >-
Host [{{inventory_hostname}}] is running {{ansible_distribution}}
version {{ansible_distribution_version}}
(family {{ansible_distribution_file_variety}}).
...
Résultat :
TASK [Display distribution information] *************************************
ok: [rocky] => {
"msg": "Host [rocky] is running Rocky version 9.3 (family RedHat)."
}
ok: [debian] => {
"msg": "Host [debian] is running Debian version 12 (family Debian)."
}
ok: [suse] => {
"msg": "Host [suse] is running openSUSE Leap version 15.5 (family SUSE)."
}
Ici on utilise deux variables implicites (magic vars) pour afficher les informations sur l'emplacement du playbook et de l'inventaire :
--- # playbook-info.yml
- hosts: all
tasks:
- name: Playbook information
debug:
msg: Your playbook is in {{playbook_dir}}.
run_once: true
- name: Inventory information
debug:
msg: Your inventory is in {{inventory_dir}}.
run_once: true
...
Le paramètre run_once évite que la tâche ne soit répétée pour chaque système
cible, ce qui n'aurait pas de sens ici :
TASK [Playbook information] *************************************************
ok: [rocky] => {
"msg": "Your playbook is in /home/vagrant/ansible/projets/ema/playbooks."
}
TASK [Inventory information] ************************************************
ok: [rocky] => {
"msg": "Your inventory is in /home/vagrant/ansible/projets/ema."
}
Voici un playbook qui affiche simplement la liste de tous les Target Hosts :
--- # hosts-info.yml
- hosts: all
tasks:
- name: Display host information
debug:
msg: "Your hosts are: {{groups.all}}"
run_once: true
...
Résultat :
TASK [Display host information] ************************
ok: [rocky] => {
"msg": "Your hosts are: ['rocky', 'debian', 'suse']"
}
Enfin, on va afficher les adresses IPv4 de chacun de nos systèmes cible :
--- # ip-info.yml
- hosts: all
tasks:
- name: Display IPv4 addresses
debug:
msg: "{{ansible_host}}'s IPv4 addresses: {{ansible_all_ipv4_addresses}}"
...
Résultat :
TASK [Display IPv4 addresses] ****************************************
ok: [rocky] => {
"msg": "rocky's IPv4 addresses: ['10.23.45.20', '192.168.121.82']"
}
ok: [debian] => {
"msg": "debian's IPv4 addresses: ['192.168.121.33', '10.23.45.30']"
}
ok: [suse] => {
"msg": "suse's IPv4 addresses: ['10.23.45.40', '192.168.121.109']"
}
À vous de jouer !
Écrivez trois playbooks pour afficher des informations sur chacun des Target Hosts :
-
pkg-info.ymlpour afficher le gestionnaire de paquets utilisé -
python-info.ymlpour afficher la version de Python installée -
dns-info.ymlpour afficher le(s) serveur(s) DNS utilisé(s)
Un peu de ménage
Quittez le Control Host :
Supprimez toutes les VM :
La rédaction de cette documentation demande du temps et des quantités significatives de café espresso. Vous appréciez ce site ? Offrez un café au rédacteur en cliquant sur la tasse.

