Vous avez un role Ansible qui tourne "chez vous". Vous le poussez en prod, et ca casse. Le serveur DNS ne résout plus, le firewall bloque le SSH, ou pire : le role est idempotent sur Ubuntu mais pas sur Rocky Linux. En clair : si vous ne testez pas vos roles, vous jouez à la roulette russe avec votre infrastructure.
Molecule existe pour régler ce problème. C''est le framework de test standard pour Ansible. Il crée un environnement isolé, exécute votre role, vérifie le résultat, et détruit tout. Reproductible, automatisable, intégrable en CI/CD.
Arretons de tourner autour du pot : voici comment le mettre en place.
Installation
Molecule s''installe via pip. Si vous utilisez déjà Ansible, vous avez Python et pip, donc c''est une affaire de secondes.
# Installation de base avec le driver Docker
pip install molecule molecule-plugins[docker]
# Vérification
molecule --version
Le driver Docker est le plus courant : Molecule crée un conteneur, exécute le role dessus, vérifie, puis détruit le conteneur. Pas besoin de VM, pas de cout cloud, exécution en quelques secondes.
Si vous préférez tester sur des VM (Vagrant, EC2), les drivers correspondants existent, mais Docker couvre 90% des cas.
Initialiser un scenario de test
Molecule travaille avec des "scenarios". Un scenario, c''est un contexte de test complet : quel driver utiliser, quel OS cible, quelles étapes exécuter.
# Depuis la racine de votre role
cd roles/mon_role
molecule init scenario
Ca crée cette structure :
molecule/
default/
converge.yml # Le playbook qui applique votre role
molecule.yml # Configuration du scenario
verify.yml # Tests de vérification (Ansible verify)
Configuration du scenario
Le fichier molecule.yml définit tout le contexte :
---
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: instance-debian
image: debian:12
pre_build_image: true
command: /sbin/init
tmpfs:
- /run
- /tmp
- name: instance-rocky
image: rockylinux:9
pre_build_image: true
command: /sbin/init
tmpfs:
- /run
- /tmp
provisioner:
name: ansible
verifier:
name: ansible
En clair : Molecule va lancer deux conteneurs (Debian 12 et Rocky Linux 9), exécuter votre role sur les deux, puis vérifier le résultat. Tester sur plusieurs distributions, c''est le minimum quand on distribue des roles via Galaxy.
Le playbook de convergence
Le fichier converge.yml est le playbook qui applique votre role :
---
- name: Converge
hosts: all
become: true
roles:
- role: mon_role
vars:
mon_role_param: 'valeur_test'
Écrire des tests : deux approches
Ansible verify (défaut depuis Molecule 6)
Depuis Molecule 6, le vérificateur par défaut est Ansible lui-meme. Vous écrivez vos assertions dans verify.yml avec des modules Ansible classiques :
---
- name: Verify
hosts: all
gather_facts: false
tasks:
- name: Check nginx is installed
ansible.builtin.package:
name: nginx
state: present
check_mode: true
register: nginx_check
- name: Assert nginx is installed
ansible.builtin.assert:
that:
- nginx_check is not changed
fail_msg: 'nginx is not installed'
- name: Check nginx is running
ansible.builtin.service:
name: nginx
state: started
check_mode: true
register: nginx_service
- name: Assert nginx is running
ansible.builtin.assert:
that:
- nginx_service is not changed
fail_msg: 'nginx is not running'
- name: Check nginx config syntax
ansible.builtin.command: nginx -t
register: nginx_syntax
changed_when: false
- name: Assert nginx config is valid
ansible.builtin.assert:
that:
- nginx_syntax.rc == 0
L''avantage : vous restez dans l''écosystème Ansible, pas besoin de connaitre Python. L''inconvénient : les assertions sont plus verbeuses et moins expressives que Testinfra.
Testinfra : tests Python
Testinfra permet d''écrire des tests d''infrastructure en Python avec pytest. C''est plus puissant et plus lisible pour des vérifications poussées.
# Installation
pip install pytest-testinfra
Créez le fichier molecule/default/tests/test_default.py :
"""Tests pour le role mon_role."""
import pytest
def test_nginx_installed(host):
"""Vérifie que nginx est installé."""
nginx = host.package("nginx")
assert nginx.is_installed
def test_nginx_running(host):
"""Vérifie que nginx tourne."""
nginx = host.service("nginx")
assert nginx.is_running
assert nginx.is_enabled
def test_nginx_listening(host):
"""Vérifie que nginx écoute sur le port 80."""
socket = host.socket("tcp://0.0.0.0:80")
assert socket.is_listening
def test_nginx_config(host):
"""Vérifie la configuration nginx."""
config = host.file("/etc/nginx/nginx.conf")
assert config.exists
assert config.user == "root"
assert oct(config.mode) == "0o644"
def test_custom_vhost(host):
"""Vérifie que le vhost custom est déployé."""
vhost = host.file("/etc/nginx/sites-enabled/mon_site.conf")
assert vhost.exists
assert vhost.contains("server_name mon_site.example.com")
Pour utiliser Testinfra comme vérificateur, modifiez molecule.yml :
verifier:
name: testinfra
En clair : si votre équipe est à l''aise avec Python, Testinfra est supérieur. Sinon, Ansible verify fait le travail.
Le cycle de vie Molecule
Molecule exécute une séquence d''étapes. molecule test lance le cycle complet :
dependency → create → prepare → converge → idempotence → verify → destroy
Chaque étape peut etre exécutée individuellement pendant le développement :
# Créer les conteneurs sans exécuter le role
molecule create
# Appliquer le role (sans détruire après)
molecule converge
# Relancer le role pour vérifier l''idempotence
molecule converge
# Exécuter les tests
molecule verify
# Se connecter au conteneur pour debug
molecule login -h instance-debian
# Tout nettoyer
molecule destroy
Le test d''idempotence est fondamental : Molecule relance le role une seconde fois et vérifie qu''aucune tache ne retourne "changed". Si votre role n''est pas idempotent, il n''est pas pret pour la production.
Intégration CI/CD
Tester en local c''est bien. Tester automatiquement à chaque push, c''est non négociable. Voici une configuration GitLab CI fonctionnelle :
---
stages:
- test
molecule:
stage: test
image: python:3.12-slim
services:
- docker:27-dind
variables:
DOCKER_HOST: 'tcp://docker:2375'
DOCKER_TLS_CERTDIR: ''
PY_COLORS: '1'
ANSIBLE_FORCE_COLOR: '1'
before_script:
- pip install ansible molecule molecule-plugins[docker]
- pip install pytest-testinfra # si vous utilisez Testinfra
script:
- cd roles/mon_role
- molecule test
only:
changes:
- roles/mon_role/**/*
Points importants :
- Docker-in-Docker (dind) : nécessaire pour que Molecule crée des conteneurs dans le runner GitLab CI.
only: changes: ne lance les tests que si le role a été modifié. Sur un repo avec 50 roles, ca évite de tout retester à chaque commit.PY_COLORSetANSIBLE_FORCE_COLOR: pour avoir des logs lisibles dans la CI.
Pour une intégration plus poussée avec AWX, vous pouvez déclencher les tests Molecule avant chaque synchronisation de projet.
Bonnes pratiques
Testez sur plusieurs distributions
Si votre role cible Debian et RHEL, testez sur les deux. Un apt qui marche ne garantit pas que le dnf équivalent fonctionne.
platforms:
- name: debian-12
image: debian:12
pre_build_image: true
- name: rocky-9
image: rockylinux:9
pre_build_image: true
- name: ubuntu-2404
image: ubuntu:24.04
pre_build_image: true
Testez les cas d''erreur
Un role qui installe nginx, c''est bien. Un role qui gère correctement le cas ou nginx est déjà installé dans une version différente, c''est mieux. Créez des scenarios séparés :
molecule init scenario --scenario-name upgrade
molecule init scenario --scenario-name broken_config
Gardez les tests rapides
Un test Molecule qui prend 10 minutes, personne ne le lance. Utilisez des images Docker légères, limitez les dépendances Galaxy, et parallélisez les scenarios quand c''est possible.
Versionnez vos scenarios
Les fichiers Molecule font partie du role. Ils vivent dans le meme répertoire, versionnés dans le meme dépot. Un role sans scenario Molecule est un role incomplet.
Ce qu''il faut retenir
Molecule n''est pas un luxe, c''est un filet de sécurité. Le cout d''écriture des tests est négligeable face au cout d''un role cassé en production à 3h du matin. Installez Molecule, écrivez un verify.yml basique, branchez-le dans votre CI, et itérez.
Si vous débutez avec Ansible, commencez par les fondamentaux, puis structurez vos roles avec Galaxy. Molecule vient naturellement après, quand vous réalisez que "ca marche chez moi" n''est pas une stratégie de déploiement.


