Ansible - les modules assert et validate_argument_spec peuvent tout controler !
Publié le : 22 mars 2023 | Mis à jour le : 22 mars 2023Table des matières
Introduction
Au début du lancement de l’exécution d’un playbook Ansible, il peut parfois
être nécessaire de réaliser des contrôles de conformité avant d’exécuter
d’autres actions. Un des premiers contrôles est de vérifier la conformité des
variables transmis. C’est là qu’interviennent les modules assert
et
validate_argument_spec
.
Contrôle des variables
Utilisation du module assert
Le module assert permet de vérifier si des expressions sont vrais.
---
- name: Playbook de test
hosts: all
become: true
gather_facts: true
tasks:
- name: Check my_param
ansible.builtin.assert:
that:
- my_param <= 100
- my_param >= 0
fail_msg: "'my_param' must be between 0 and 100"
success_msg: "'my_param' is between 0 and 100"
Pour des cas simples assert peut faire l’affaire. Pour valider des structures
plus complexes, nous allons utiliser le module validate_arugment_spec
.
Utilisation du module validate_arugment_spec
Introduit avec la version 2.11 d’Ansible, le module validate_arugment_spec
est
à la base utilisée pour valider des variables de rôles. Nous allons voir qu’il
est possible de s’en servir dans un playbook :
---
# Description
- name: Description of the playbook
hosts: all
gather_facts: true
tasks:
- name: Verify vars needed for this task file are present when included
ansible.builtin.validate_argument_spec:
argument_spec: '{{required_data}}'
vars:
required_data:
stuff:
description: stuff
type: str
choices: ['who', 'knows', 'what']
default: what
but:
description: test
type: str
required: true
Ici, nous définissons deux valeurs : stuff
et but
. stuff
est une string pouvant
prendre les valeurs : ‘who’, ‘knows’, ‘what’.
Si nous lançons son exécution en utilisant des extra vars avec stuff = ‘toto’.
ansible-playbook -i localhost, -c local playbook.yml -e but=test -e stuff=toto
...
TASK [Verify vars needed for this task file are present when included] *********
fatal: [localhost]: FAILED! => changed=false
argument_errors:
- 'value of stuff must be one of: who, knows, what, got: toto'
argument_spec_data:
but:
description: test
required: true
type: str
stuff:
choices:
- who
- knows
- what
default: what
description: stuff
type: str
msg: |-
Validation of arguments failed:
value of stuff must be one of: who, knows, what, got: toto
validate_args_context: {}
PLAY RECAP **********
Pour un exemple de validation de dictionnaire, reportez-vous au billet sur l’écriture des roles.
Des contrôles plus poussés
Inutile de lancer un playbook complet pour le voir échouer à cause d’un bête manque de place sur un filesystem non ?
Il est tout à fait possible de lancer des contrôles sur la machine sans utiliser le module command. Je vais prendre comme exemple un check de l’espace disque du filesystem root :
---
- name: Playbook de test
hosts: all
become: true
gather_facts: true
vars:
max_rate_occupation_disk: 0.8
tasks:
- name: Check / usage
ansible.builtin.assert:
that:
- item.size_available > item.size_total|float * (1 - max_rate_occupation_disk/100)
when: item.mount == "/"
with_items:
- "{{ ansible_mounts }}"
Une boucle with_items
couplée à une condition vwhen
permet de limiter le
champ de test au seul filesystem root. Ici j’utilise les facts ansible
qui contient toutes sortes d’informations dont les filesystems. Bien sur, il ne
faut pas avoir désactivé la collecte de ces facts au démarrage du playbook !
Une autre solution pour limiter la collecte des facts au strict minimum est
le désactiver et faire appel ensuite appel au module setup en limitant la
collecte avec le paramètre gather_subset
:
---
- name: Playbook de test
hosts: all
become: true
gather_facts: false
tasks:
- name: collect facts
ansbile.builtin.setup:
gather_subset: !all,!min
- name: Check / usage
ansible.builtin.assert:
that:
- item.size_available > item.size_total|float * (1 - my_disk_slash_space_max/100)
when: item.mount == "/"
with_items:
- "{{ ansible_mounts }}"
Point important, pour éviter de recourir systématiquement au module
commande, je vous conseille d’utiliser les custom_facts
que je vous ai exposé
dans un précédent billet. En effet, il est possible d’utiliser un langage plus
évolué que du bash pour les créer. On peut tout imaginer !