Aller au contenu principal

Ansible et les assertions

· 4 minutes de lecture
Stéphane ROBERT

logo ansible

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 ansible 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 assertions peut faire l'affaire. Pour valider des structures plus complexes, nous allons utiliser le module validate_argument_spec.

Utilisation du module validate_argument_spec

Introduit avec la version 2.11 d'Ansible, le module validate_argument_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 rôles.

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 when 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 !