
Molecule crée des machines de test, y joue votre rôle, vérifie le résultat, puis détruit tout. Cette page installe l'outil, produit un premier scénario, puis règle les quatre points qui séparent le scénario généré d'un scénario réellement fonctionnel. Elle se termine par les commandes de la CLI Molecule, qui sont votre interface quotidienne avec l'outil.
L'obstacle qui attend tout le monde est contre-intuitif : le scénario généré passe au vert sans avoir rien testé. Comprendre pourquoi, et le corriger, est le cœur de ce guide.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Installer Molecule et le plugin correspondant à votre moteur de conteneurs.
- Créer un scénario, et identifier les cinq fichiers déposés.
- Lire un
molecule.ymlmoderne, qui n'a plus la structure décrite par la plupart des tutoriels. - Rendre ce scénario fonctionnel, jusqu'à un rôle réellement joué dans un conteneur.
- Utiliser les commandes de la CLI, du cycle complet au diagnostic pas à pas.
Prérequis
Section intitulée « Prérequis »- Python et
ansible-coreinstallés. - Un moteur de conteneurs, Podman de préférence, ou Docker.
- Un rôle existant, par exemple celui de Créer son premier rôle.
Installer Molecule
Section intitulée « Installer Molecule »Molecule est un outil Python indépendant d'ansible-core. L'installer avec pipx l'isole dans son propre environnement, ce qui évite de mélanger ses dépendances avec celles de votre système. Le plugin de driver s'ajoute ensuite dans ce même environnement, car Molecule seul ne sait pas fabriquer de conteneur.
# Molecule, puis le plugin Podman dans le même environnement isolépipx install molecule==26.4.0pipx inject molecule "molecule-plugins[podman]"La vérification donne bien plus qu'un numéro de version : elle liste les plugins détectés et la version d'ansible-core que Molecule utilisera, qui n'est pas forcément celle de votre shell.
$ molecule --versionmolecule 26.4.0 using python 3.12 ansible:2.20.5 podman:25.8.12 from molecule_plugins docker:25.8.12 from molecule_pluginsSi la ligne ansible: n'apparaît pas, Molecule ne trouve pas de moteur Ansible utilisable et rien ne fonctionnera ensuite. Si aucun plugin n'est listé, l'injection a échoué et la création de machines restera impossible.
La commande molecule drivers confirme ce que l'installation met à disposition. Elle liste les drivers connus, podman et docker en tête pour un usage local.
Créer un scénario
Section intitulée « Créer un scénario »La commande s'exécute depuis la racine du rôle, et non depuis un répertoire quelconque. Un scénario est un dossier de configuration autonome : vous en aurez plusieurs le jour où vous testerez sur plusieurs distributions.
cd monrolemolecule init scenarioElle dépose exactement cinq fichiers dans molecule/default/ :
molecule/default/├── molecule.yml # la configuration du scénario├── create.yml # comment fabriquer les machines de test├── destroy.yml # comment les détruire├── converge.yml # le playbook qui appelle votre rôle└── verify.yml # les vérifications après convergenceLe nom default est celui du scénario. Vous pouvez en créer d'autres en passant un nom en argument, sujet traité dans Scénarios multi-distributions.
Lire le molecule.yml généré
Section intitulée « Lire le molecule.yml généré »Ce fichier surprend quiconque a lu un tutoriel écrit avant 2025. Il ne contient aucune section driver: ni platforms:, qui étaient pourtant le cœur de la configuration des versions précédentes. Voici ses blocs significatifs.
dependency: name: galaxy options: role-file: requirements.yml requirements-file: requirements.yml
ansible: cfg: defaults: host_key_checking: false verbosity: 1
executor: backend: ansible-playbook args: ansible_playbook: - --diff - --force-handlers - --inventory=/path/to/inventory.yml
playbooks: converge: converge.yml verify: verify.yml
scenario: name: default test_sequence: - dependency - cleanup - destroy - syntax - create - prepare - converge - idempotence - side_effect - verify - cleanup - destroyQuatre blocs le composent. dependency installe les rôles et collections déclarés dans un requirements.yml avant chaque test. ansible configure le moteur pour la durée du scénario, en écrivant un ansible.cfg temporaire. executor liste les arguments passés à ansible-playbook. scenario énumère les étapes que molecule test enchaînera dans l'ordre.
Deux détails de ce fichier généré méritent votre attention immédiate. La ligne --inventory=/path/to/inventory.yml est un exemple laissé en place, pas un chemin valide. Surtout, la création des machines n'est plus décrite ici, elle est déléguée à create.yml, et c'est ce déplacement qui explique la section suivante.
Pourquoi un scénario neuf ne teste rien
Section intitulée « Pourquoi un scénario neuf ne teste rien »Ouvrez create.yml, et le diagnostic tient dans son commentaire d'ouverture :
- name: Create hosts: localhost connection: local gather_facts: false tasks: # TODO: Developer must implement and populate 'server' variable
- name: Create instance config when: server.changed | default(false) | bool # noqa no-handler block: - name: Populate instance config dict # noqa jinja ansible.builtin.set_fact: instance_conf_dict: {}Le fichier est un squelette à compléter. La variable server n'est jamais définie, donc la condition vaut faux, donc toutes les tâches de création sont ignorées. Aucune machine n'est fabriquée. Le # noqa no-handler en fin de ligne fait taire une règle d'ansible-lint : Molecule annote son propre squelette pour qu'il passe le linter, ce qui confirme qu'il est destiné à être remplacé.
La conséquence à l'exécution est déroutante :
INFO [default > create] Executingskipping: [localhost] => {"false_condition": "server.changed | default(false) | bool"}localhost : ok=0 changed=0 unreachable=0 failed=0 skipped=3INFO [default > create] Executed: SuccessfulLe PLAY RECAP affiche ok=0, et Molecule annonce pourtant Successful. Le cycle complet se termine avec un code de retour nul alors qu'aucune instance n'existe et que votre rôle n'a jamais été joué.
Rendre le scénario fonctionnel
Section intitulée « Rendre le scénario fonctionnel »Le plugin installé plus haut fournit ses propres playbooks de création et de destruction, éprouvés et maintenus. Le travail consiste donc à lui laisser la place, en quatre gestes qui se tiennent.
Le premier est le moins intuitif : supprimez les squelettes locaux. Tant que create.yml et destroy.yml existent dans le dossier du scénario, Molecule les utilise et ignore ceux du driver. Leur simple présence suffit à les faire gagner.
rm molecule/default/create.yml molecule/default/destroy.ymlLe deuxième déclare le driver et les machines voulues. Les sections driver: et platforms: sont absentes du fichier généré, mais le driver Podman les attend, et c'est là que vous choisissez votre image de test.
---driver: name: podman
platforms: - name: instance image: quay.io/centos/centos:stream9@sha256:3714c89f1903dac5a5e1eb6c02d84189ff6d962a0c18df01feba0a5406856926Le troisième rend votre rôle visible. Molecule n'ajoute pas le répertoire parent du rôle au chemin de recherche, ce qui provoque un échec sec au converge. La variable MOLECULE_PROJECT_DIRECTORY pointe sur la racine du rôle, donc son parent est le répertoire qui contient vos rôles.
ansible: cfg: defaults: roles_path: ${MOLECULE_PROJECT_DIRECTORY}/.. host_key_checking: falseProfitez-en pour retirer la ligne --inventory=/path/to/inventory.yml du bloc executor, qui pointe vers un fichier inexistant.
Le quatrième corrige le nom du rôle. Le converge.yml généré référence un rôle fictif, et l'oublier donne l'erreur the role 'yournamespace.yourcollection.yourrole' was not found.
---- name: Converge hosts: all gather_facts: true tasks: - name: Apply role under test ansible.builtin.include_role: name: monroleLe hosts: all désigne l'inventaire produit par le driver, pas votre inventaire de production. Molecule le construit à la volée et l'oublie à la destruction.
Le résultat se vérifie en une commande, et cette fois le recap est parlant :
TASK [monrole : Deposer un fichier temoin] *************************************instance : ok=3 changed=1 unreachable=0 failed=0 skipped=0Un conteneur instance existe, votre rôle y a exécuté ses tâches, et molecule list le confirme en affichant Created: true et Converged: true.
Les commandes de la CLI Molecule
Section intitulée « Les commandes de la CLI Molecule »Le cycle complet s'obtient avec molecule test, qui enchaîne toute la test_sequence puis détruit l'instance, y compris en cas de succès. C'est la commande de l'intégration continue, et la plus mauvaise compagne du développement : elle repart de zéro à chaque appel et ne laisse rien à inspecter.
molecule testAu quotidien, vous utiliserez plutôt les étapes séparément. Elles conservent l'instance entre deux appels, ce qui rend la boucle de correction rapide.
molecule create # fabriquer l'instance et s'arrêter làmolecule converge # jouer le rôle sur l'instance existantemolecule idempotence # rejouer le converge, échoue si quelque chose changemolecule verify # exécuter les vérifications de verify.ymlmolecule destroy # détruire l'instanceL'étape idempotence mérite d'être connue pour elle-même : elle rejoue le converge et échoue si une tâche se déclare modifiée au second passage. Molecule vérifie donc gratuitement une propriété fondamentale de vos rôles, sans que vous ayez une seule assertion à écrire.
Trois commandes servent au diagnostic quand quelque chose résiste. molecule list affiche l'état des instances, molecule login ouvre un shell dans l'instance pour constater l'état réel du système, et molecule reset efface les fichiers temporaires de Molecule quand son état interne ne correspond plus à la réalité.
molecule list # instances, driver, créée et convergée ou nonmolecule login # shell interactif dans l'instancemolecule reset # purger l'état temporaire de MoleculeDeux dernières commandes s'exécutent sans rien créer, donc instantanément. molecule syntax contrôle la syntaxe des playbooks et molecule matrix affiche la liste des étapes qu'une commande donnée déclencherait, ce qui répond une bonne fois à la question de savoir ce que molecule test fait exactement.
molecule syntaxmolecule matrix testVous avez maintenant un scénario qui fabrique une instance, y joue un rôle et vérifie l'idempotence. La suite consiste à écrire les tests avant le code du rôle, méthode détaillée dans Le cycle TDD complet, qui construit un rôle users en trois cycles successifs sur cette base.
Trois blocages au premier lancement
Section intitulée « Trois blocages au premier lancement »Ces messages arrivent presque toujours, dans cet ordre, et aucun n'est un défaut de votre travail. Les reconnaître fait gagner beaucoup de temps.
Le premier survient avant même que Molecule ne démarre, si votre rôle vient d'être créé par ansible-galaxy role init :
InvalidPrerequisiteError: Computed fully qualified role name of monrole does notfollow current galaxy requirements.Molecule exige un nom pleinement qualifié, que le squelette généré ne fournit pas. Deux lignes dans meta/main.yml règlent la question :
galaxy_info: role_name: monrole namespace: demoLe deuxième frappe au converge, et c'est celui que le roles_path de la section précédente corrige :
[ERROR]: the role 'monrole' was not found in .../molecule/default/roles:/home/bob/.ansible/roles:/usr/share/ansible/rolesLe chemin de recherche affiché ne contient pas le répertoire de votre rôle. Ansible ne cherche jamais ailleurs, d'où l'échec immédiat.
Le troisième est un simple avertissement de fin d'exécution, et beaucoup le prennent à tort pour une erreur :
WARNING Molecule executed 1 scenario (1 missing files)Le molecule.yml référence des playbooks facultatifs comme prepare.yml, cleanup.yml ou side_effect.yml que init ne génère pas. Leur absence n'empêche rien, les étapes correspondantes sont sautées. Créez-les si vous en avez besoin, ignorez l'avertissement sinon.
Mettre en pratique
Section intitulée « Mettre en pratique »Un scénario généré passe au vert sans avoir rien testé : ce lab part de ce constat pour le combler. Vous y ajoutez un prepare.yml et un requirements.yml, personnalisez les instances par host_vars, déclarez une test_sequence qui inclut l'étape d'idempotence, et activez profile_tasks pour voir où part le temps. La correction relit le scénario produit et refuse un molecule.yml resté au squelette d'origine.
Pièges courants
Section intitulée « Pièges courants »| Symptôme | Cause | Solution |
|---|---|---|
molecule test réussit mais rien n'a tourné | Les squelettes create.yml et destroy.yml sont toujours là | Les supprimer et déclarer driver: plus platforms: |
the role 'monrole' was not found | Le rôle parent n'est pas dans le chemin de recherche | Ajouter roles_path: ${MOLECULE_PROJECT_DIRECTORY}/.. |
yournamespace.yourcollection.yourrole was not found | Le converge.yml généré cite un rôle fictif | Y mettre le nom réel de votre rôle |
Computed fully qualified role name au démarrage | meta/main.yml sans namespace ni role_name | Ajouter les deux clés |
1 missing files en fin d'exécution | Playbooks facultatifs non générés | Sans conséquence, ou créer les fichiers concernés |
Aucun plugin listé par molecule --version | L'injection dans l'environnement pipx a échoué | Rejouer pipx inject molecule "molecule-plugins[podman]" |
À retenir
Section intitulée « À retenir »molecule init scenariodépose cinq fichiers, dontcreate.ymletdestroy.ymlqui sont des squelettes non fonctionnels.- Un scénario neuf réussit sans rien tester, avec un code de retour nul et un
PLAY RECAPàok=0. - Supprimer les squelettes locaux est ce qui laisse le driver Podman fournir ses propres playbooks de création.
roles_path: ${MOLECULE_PROJECT_DIRECTORY}/..rend votre rôle visible depuis le scénario.molecule testdétruit tout à la fin : préférezcreate,convergeetverifyséparément pendant le développement.- L'étape
idempotencerejoue le converge et échoue si quelque chose change au second passage.
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Scenarios multi-distro : ajouter des plateformes au
molecule.ymlque vous venez de configurer. - Tests avec testinfra : changer de verifier quand
verify.ymlne suffit plus aux assertions. - CI GitHub Actions : rejouer le scénario sur un runner, avec la même configuration.