Ansible utilise en arrière plan un dictionnaire contenant de nombreuses variables.
Pour s’en rendre compte on peut lancer :
ansible <hote_ou_groupe> -m debug -a "msg={{ hostvars }}"
Ce dictionnaire contient en particulier:
ansible_user
par exemple)ansible_facts
, c’est à dire des variables dynamiques caractérisant les systèmes cible (par exemple ansible_os_family
) et récupéré au lancement d’un playbook.On peut définir et modifier la valeur des variables à différents endroits du code ansible:
vars:
du playbook.vars_files:
group_vars
, host_vars
defaults
des roles (cf partie sur les roles)set_facts
.--extra-vars "version=1.23.45 other_variable=foo"
Lorsque définies plusieurs fois, les variables ont des priorités en fonction de l’endroit de définition. L’ordre de priorité est plutôt complexe: https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable
En résumé la règle peut être exprimée comme suit: les variables de runtime sont prioritaires sur les variables dans un playbook qui sont prioritaires sur les variables de l’inventaire qui sont prioritaires sur les variables par défaut d’un role.
https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html
Les plus utiles:
ansible_facts
: faits récoltés par Ansible (Ansible Facts) sur l’hôte en courshostvars
: dictionaire de toute les variables rangées par hôte de l’inventaire.ansible_host
: information utilisée pour la connexion (ip ou domaine).inventory_hostname
: nom de la machine dans l’inventaire.groups
: dictionnaire de tous les groupes avec la liste des machines appartenant à chaque groupe.Pour explorer chacune de ces variables vous pouvez utiliser le module debug
en mode adhoc ou dans un playbook :
ansible <hote_ou_groupe> -m debug -a "msg={{ ansible_host }}" -vvv
Attention, les facts ne sont pas relevés en mode ad-hoc. Il faut donc utiliser le module debug
.
Vous pouvez exporter les ansible_facts en JSON pour plus de lisibilité :
ansible all -m setup --tree ./ansible_facts_export
Puis les lire avec cat ./ansible_facts_export/votremachine.json | jq
(il faut que jq soit installé, sinon tout ouvrir dans VSCode avec code ./ansible_facts_export
).
Les facts sont des valeurs de variables récupérées au début de l’exécution durant l’étape gather_facts et qui décrivent l’état courant de chaque machine.
ansible_os_family
est un fact/variable décrivant le type d’OS installé sur la machine. Elle n’existe qu’une fois les facts récupérés.Lors d’une commande adhoc ansible les facts ne sont pas récupérés : la variable ansible_os_family
ne sera pas disponible.
La liste des facts peut être trouvée dans la documentation et dépend des plugins utilisés pour les récupérés: https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_vars_facts.html
when:
Elle permet de rendre une tâche conditionnelle (une sorte de if
)
- name: start nginx service
systemd:
name: nginx
state: started
when: ansible_os_family == 'RedHat'
Sinon la tâche est sautée (skipped) durant l’exécution.
loop:
Cette directive permet d’exécuter une tâche plusieurs fois basée sur une liste de valeurs :
https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html
exemple:
- hosts: localhost
tasks:
- name: exemple de boucle
debug:
msg: "{{ item }}"
loop:
- message1
- message2
- message3
On accéde aux différentes valeurs qu’elle prend avec {{ item }}
.
On peut également contrôler cette boucle avec quelques paramètres:
- hosts: localhost
vars:
messages:
- message1
- message2
- message3
tasks:
- name: exemple de boucle
debug:
msg: "message numero {{ num }} : {{ message }}"
loop: "{{ messages }}"
loop_control:
loop_var: message
index_var: num
Cette fonctionnalité de boucle était anciennement accessible avec le mot-clé with_items:
qui est maintenant déprécié.
La plupart des fichiers Ansible (sauf l’inventaire) sont traités avec le moteur de template python Jinja2.
Ce moteur permet de créer des valeurs dynamiques dans le code des playbooks, des roles, et des fichiers de configuration.
Les variables écrites au format {{ mavariable }}
sont remplacées par leur valeur provenant du dictionnaire d’exécution d’Ansible.
Des filtres (fonctions de transformation) permettent de transformer la valeur des variables: exemple : {{ hostname | default('localhost') }}
(Voir plus bas)
Pour transformer la valeur des variables à la volée lors de leur appel on peut utiliser des filtres (jinja2) :
{{ hostname | default('localhost') }}
La liste complète des filtres ansible se trouve ici : https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html
Les fichiers de templates (.j2) utilisés avec le module template, généralement pour créer des fichiers de configuration peuvent contenir des variables et des filtres comme les fichier de code (voir au dessus) mais également d’autres constructions jinja2 comme:
if
: {% if nginx_state == 'present' %}...{% endif %}
.for
: {% for host in groups['appserver'] %}...{% endfor %}
.{% include 'autre_fichier_template.j2' %}
Il est possible d’importer le contenu d’autres fichiers dans un playbook:
import_tasks
: importe une liste de tâches (atomiques)import_playbook
: importe une liste de play contenus dans un playbook.Les deux instructions précédentes désignent un import statique qui est résolu avant l’exécution.
En général, on utilise import_*
pour améliorer la lisibilité de notre dépôt.
Au contraire, include_tasks
permet d’intégrer une liste de tâches dynamiquement pendant l’exécution.
En général, on utilise include_*
pour décider quelles tâches, quelles variables ou quels rôles seront inclus au run d’un playbook.
Par exemple :
vars:
apps:
- app1
- app2
- app3
tasks:
- include_tasks: install_app.yml
loop: "{{ apps }}"
Ce code indique à Ansible d’exécuter une série de tâches pour chaque application de la liste. On pourrait remplacer cette liste par une liste dynamique. Comme le nombre d’imports ne peut pas facilement être connu à l’avance on doit utiliser include_tasks
.
Documentation additionnelle :
Avec Ansible on dispose d’au moins trois manières de debugger un playbook :
Rendre la sortie verbeuse (mode debug) avec -vvv
.
Utiliser une tâche avec le module debug
: debug msg="{{ mavariable }}"
.
Utiliser la directive debugger: always
ou on_failed
à ajouter à la fin d’une tâche. L’exécution s’arrête alors après l’exécution de cette tâche et propose un interpreteur de debug.
Les commandes et l’usage du debugger sont décrits dans la documentation: https://docs.ansible.com/ansible/latest/user_guide/playbooks_debugger.html
Command | Shortcut | Action |
---|---|---|
p | Print information about the task | |
task.args[key] = value | Update module arguments | |
task_vars[key] = value | Update task variables (you must update_task next) | |
update_task | u | Recreate a task with updated task variables |
redo | r | Run the task again |
continue | c | Continue executing, starting with the next task |
quit | q | Quit the debugger |