Aller au contenu

Gérer les tests Ansible avec Tox et Molecule

Mise à jour :

logo devops

Si vous avez parcouru mon guide sur l’écriture de rôles Ansible, vous savez déjà qu’un bon rôle, c’est plus qu’un simple tasks/main.yml. Et si vous avez jeté un œil à mon guide d’introduction à tox, vous avez vu comment ce petit outil peut devenir un vrai couteau suisse pour les tests automatisés.

Dans ce guide, on va assembler tout ça : **je vais vous montrer comment tester vos rôles Ansible avec tox. Pas besoin de magie noire — juste une config claire et des tests qui tournent tout seuls.

Pourquoi utiliser tox pour tester des rôles Ansible ?

Un rôle Ansible, ce n’est pas juste un script qui “marche sur ma machine”. Dès qu’on commence à le partager — que ce soit en interne, sur un dépôt Git, ou même sur Ansible Galaxy — il devient essentiel de garantir qu’il fonctionne, et qu’il continue de fonctionner au fil du temps.

Tester ses rôles, c’est :

  • éviter les régressions quand on modifie un handler, un var, ou une task ;
  • assurer la compatibilité avec plusieurs versions d’Ansible, surtout quand on les publie ;
  • valider les comportements sur différents systèmes cibles (Debian, CentOS, etc.) ;
  • vérifier la structure et les bonnes pratiques avec des outils comme ansible-lint.

C’est là qu’intervient Molecule.

Cet outil permet de simuler l’exécution complète d’un rôle dans un environnement isolé (via Docker, Podman, Vagrant, etc.). On y définit un scénario (avec converge.yml, verify.yml, etc.), et Molecule s’occupe de tout :

  • lancement de l’infra cible,
  • exécution du rôle,
  • validation du résultat.

Mais tout ça peut vite devenir lourd si on doit le faire à la main pour chaque version d’Ansible.

C’est là que tox entre en jeu : je l’utilise pour automatiser ces tests, sur plusieurs versions d’Ansible, sans effort. On définit les versions à tester, on configure les scénarios Molecule, et tox lance tout d’un coup. Résultat : un test rapide, reproductible, multi-environnement.

C’est le combo gagnant pour des rôles fiables et publiables.

Configurer tox pour tester un rôle Ansible avec Molecule

Voici comment je m’y prends pour automatiser les tests d’un rôle Ansible avec tox, sans utiliser pytest ni le plugin tox-ansible. L’objectif est simple : valider un rôle sur plusieurs versions d’Ansible, en utilisant Molecule comme moteur de test.

J’utilise un fichier tox.ini structuré de la façon suivante :

[tox]
envlist = ansible-2.{15,16,17,18}
skipsdist = true

Dans cette section, je définis les versions d’Ansible que je veux tester. Ici, je cible les versions 2.15 à 2.18 de ansible-core. Le paramètre skipsdist = true est là car je ne distribue pas de package Python : pas besoin de setup.py.

Ensuite, chaque environnement de test est défini de manière spécifique :

[testenv]
commands = molecule test
setenv =
TOX_ENVNAME={envname}
PY_COLORS=1
ANSIBLE_FORCE_COLOR=1
ANSIBLE_ROLES_PATH=../
passenv = *

Ce que ça fait concrètement :

  • commands = molecule test : c’est là que toute la magie opère. Cette commande exécute le scénario Molecule (molecule/default/converge.yml, etc.) du rôle.
  • ANSIBLE_ROLES_PATH=../ : j’indique à Ansible où chercher les rôles localement.
  • passenv = * : je laisse passer toutes mes variables d’environnement, utile si je teste dans des conteneurs Docker ou si j’utilise des tokens/accès externes.

Chaque version d’Ansible a ensuite son propre environnement dédié :

[testenv:ansible-2.15]
basepython = python3.9
deps =
-rrequirements.txt
ansible-core==2.15.*
ansible-lint==6.*

Je définis :

  • une version de Python compatible,
  • une version spécifique d’ansible-core,
  • ansible-lint pour vérifier la qualité du rôle avant exécution.

Même logique pour les versions 2.16, 2.17 et 2.18, que je configure avec des versions de Python plus récentes et les dernières versions d’ansible-lint.

Avec cette configuration, je peux lancer des tests sur plusieurs versions d’Ansible d’un simple tox, tout en bénéficiant de l’automatisation de Molecule. C’est simple, reproductible, et ça évite bien des surprises en production ou sur Ansible Galaxy.

Exemple concret : tests automatisés du rôle ansible-role-motd

Pour illustrer l’utilisation de tox avec Molecule dans un projet réel, prenons l’exemple de mon rôle Ansible ansible-role-motd. Ce rôle configure dynamiquement le message du jour (MOTD) sur des systèmes Debian et Ubuntu.

Structure du projet

Le dépôt suit une structure classique pour un rôle Ansible :

Terminal window
tree
ansible-role-motd/
├── defaults/
├── files/
├── handlers/
├── meta/
├── molecule/
└── default/
├── tasks/
├── templates/
├── vars/
├── .ansible-lint
├── .gitignore
├── .yamllint
├── README.md
└── tox.ini

La présence du dossier molecule/default/ indique que des scénarios de test sont définis pour valider le rôle dans des environnements isolés.

Configuration de tox

Le fichier tox.ini est configuré pour tester le rôle avec différentes versions d’Ansible :

[tox]
envlist = ansible-2.{15,16,17,18}
skipsdist = true
[testenv]
commands = molecule test
setenv =
TOX_ENVNAME={envname}
PY_COLORS=1
ANSIBLE_FORCE_COLOR=1
ANSIBLE_ROLES_PATH=../
passenv = *
[testenv:ansible-2.15]
basepython = python3.9
deps =
-rrequirements.txt
ansible-core==2.15.*
ansible-lint==6.*
[testenv:ansible-2.16]
basepython = python3.10
deps =
-rrequirements.txt
ansible-core==2.16.*
ansible-lint==24.*
[testenv:ansible-2.17]
basepython = python3.10
deps =
-rrequirements.txt
ansible-core==2.17.*
ansible-lint==24.*
[testenv:ansible-2.18]
basepython = python3.13
deps =
-rrequirements.txt
ansible-core==2.18.*
ansible-lint==24.*

Chaque environnement (ansible-2.15, ansible-2.16, etc.) spécifie :

  • Une version spécifique de Python compatible avec la version d’Ansible ciblée.
  • Les dépendances nécessaires, notamment ansible-core et ansible-lint.

Exécution des tests

Pour lancer les tests sur toutes les versions configurées :

Terminal window
tox

Pour exécuter les tests sur une version spécifique d’Ansible :

Terminal window
tox -e ansible-2.17
ansible-2.17: commands[0]> molecule test
WARNING The scenario config file ('/home/bob/Projets/ansible-role-motd/molecule/default/molecule.yml') has been modified since the scenario was created. If recent changes are important, reset the scenario with 'molecule destroy' to clean up created items or 'molecule reset' to clear current configuration.
WARNING Driver docker does not provide a schema.
INFO default scenario test matrix: dependency, cleanup, destroy, syntax, create, prepare, converge, idempotence, side_effect, verify, cleanup, destroy
INFO Performing prerun with role_name_check=0...
INFO Running default > dependency
WARNING Skipping, missing the requirements file.
WARNING Skipping, missing the requirements file
...
INFO Running default > prepare
PLAY [Afficher la version d'Ansible] *******************************************
TASK [Afficher la version d'Ansible] *******************************************
changed: [localhost]
TASK [Affichage version] *******************************************************
ok: [localhost] => {
"version_ansible.stdout_lines": [
"ansible [core 2.17.10]",
" config file = /home/bob/.ansible/tmp/molecule.hf4h.default/ansible.cfg",
" configured module search path = ['/home/bob/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']",
" ansible python module location = /home/bob/Projets/ansible-role-motd/.tox/ansible-2.17/lib/python3.10/site-packages/ansible",
" ansible collection location = /home/bob/.ansible/collections:/usr/share/ansible/collections",
" executable location = /home/bob/Projets/ansible-role-motd/.tox/ansible-2.17/bin/ansible",
" python version = 3.10.17 (main, Apr 14 2025, 11:09:18) [GCC 13.3.0] (/home/bob/Projets/ansible-role-motd/.tox/ansible-2.17/bin/python)",
" jinja version = 3.1.6",
" libyaml = True"
]
}
...
PLAY RECAP *********************************************************************
localhost : ok=3 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
INFO Pruning extra files from scenario ephemeral directory
ansible-2.17: OK (79.70=setup[0.06]+cmd[79.65] seconds)
congratulations :) (79.77 seconds)

Cette commande :

  1. Crée un environnement virtuel avec la version spécifiée d’Ansible.
  2. Installe les dépendances définies.
  3. Exécute le scénario Molecule (molecule test) pour valider le rôle.

Avantages de cette approche

  • Automatisation complète : Les tests sont lancés automatiquement pour chaque version d’Ansible définie.
  • Détection précoce des incompatibilités : En testant sur plusieurs versions, on identifie rapidement les problèmes de compatibilité.
  • Intégration continue facilitée : Cette configuration s’intègre aisément dans des pipelines CI/CD, assurant une qualité constante du rôle.

En résumé, cette configuration tox permet de garantir que le rôle ansible-role-motd fonctionne correctement sur différentes versions d’Ansible, tout en automatisant les tests grâce à Molecule.

Conclusion

Avec tox, je peux tester mes rôles Ansible de manière simple et efficace. Je n’ai plus à jongler avec des versions d’Ansible, des environnements virtuels ou des configurations complexes. Tout est automatisé, et je peux me concentrer sur l’écriture de code propre et fonctionnel.