Voici le quatorzième article de la formation Ansible. Dans mon précédent article, je vous ai présenté les variables enregistrées et les possibilités qu’elles offrent dans un playbook. Aujourd’hui, nous allons nous intéresser à deux autres types de variables dont nous allons nous servir assez régulièrement dans nos playbooks.
Atelier pratique
Placez-vous dans le répertoire du seizième atelier pratique :
$ cd ~/formation-ansible/atelier-16
Voici les quatre machines virtuelles de cet atelier :
Machine virtuelle | Adresse IP |
---|---|
ansible |
10.23.45.10 |
rocky |
10.23.45.20 |
debian |
10.23.45.30 |
suse |
10.23.45.40 |
Démarrez les VM :
$ vagrant up
Connectez-vous au Control Host :
$ vagrant ssh ansible
L’environnement de cet atelier est préconfiguré et prêt à l’emploi :
- Ansible est installé sur le Control Host.
- Le fichier
/etc/hosts
du 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
yamllint
est é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
.
TASK [Gathering Facts] **************************************
ok: [debian]
ok: [suse]
ok: [rocky]
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
:
$ ansible debian -m setup
Le résultat dépasse de loin la taille d’un écran. On va donc réitérer la commande comme ceci :
$ ansible debian -m setup | less
L’affichage des facts de notre hôte dépasse les 600 lignes :
$ ansible debian -m setup | wc -l 607
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’inventaireplaybook_dir
: répertoire dans lequel se trouve le playbook en coursinventory_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']"
}
Exercice
Écrivez trois playbooks pour afficher des informations sur chacun des Target Hosts :
pkg-info.yml
pour afficher le gestionnaire de paquets utilisépython-info.yml
pour afficher la version de Python installéedns-info.yml
pour afficher le(s) serveur(s) DNS utilisé(s)
Quittez le Control Host :
$ exit
Supprimez toutes les VM :
$ vagrant destroy -f
Lire la suite : Cibles hétérogènes
La rédaction de cette documentation demande du temps et des quantités significatives de café espresso. Vous appréciez ce blog ? Offrez un café au rédacteur en cliquant sur la tasse.
0 commentaire