DevOps

Ansible Molecule : tester ses roles avant de casser la prod

23 mars 2026

7 min de lecture

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_COLORS et ANSIBLE_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.

Sources

Besoin d'aide sur ce sujet ?

Notre équipe d'experts est là pour vous accompagner dans vos projets d'infrastructure et d'infogérance.

Contactez-nous

Articles similaires