TL;DR
- Molecule proporciona testing automatizado para roles de Ansible con contenedores Docker, escenarios multi-plataforma y verificaciones de idempotencia integradas
- El ciclo de vida de testing (
create → converge → idempotence → verify → destroy) detecta deriva de configuración y tareas no idempotentes antes de producción- Usa Docker para iteración rápida durante desarrollo; cambia a Vagrant solo cuando necesites probar parámetros del kernel o características específicas de systemd
Ideal para: Equipos con 5+ roles de Ansible que quieren infraestructura reproducible e integración CI/CD No recomendado si: Solo tienes playbooks simples (ansible-lint puede ser suficiente) Tiempo de lectura: 20 minutos
Cuando tus playbooks de Ansible se despliegan en producción, ¿qué tan seguro estás de que funcionarán correctamente? Aquí es donde entra Molecule—un framework de testing diseñado específicamente para roles de Ansible que transforma el desarrollo de infraestructura de “funcionó en mi máquina” a “está probado en Ubuntu 20.04, 22.04 y Debian 11.”
En este tutorial, aprenderás todo desde testing básico de roles hasta validaciones complejas de múltiples escenarios con integración CI/CD. Ya sea que estés gestionando un puñado de servidores u orquestando miles de nodos, Molecule transformará cómo desarrollas y mantienes tu infraestructura como código.
El testing de infraestructura como código es parte de un ecosistema más amplio de prácticas DevOps. Si estás trabajando con otras herramientas de IaC, te recomendamos explorar nuestras estrategias de testing y validación de Terraform. Para entender mejor los entornos contenedorizados donde Molecule ejecuta sus pruebas, consulta nuestra guía sobre contenedorización para testing. Además, integrar estas pruebas en tu flujo de trabajo automatizado es esencial—aprende más en nuestra guía de optimización de pipelines CI/CD para equipos QA.
Enfoques Asistidos por IA
Los asistentes de IA modernos pueden acelerar el desarrollo y depuración de flujos de trabajo de Molecule. Aquí hay prompts prácticos para tareas comunes:
Generar tests verify.yml desde tareas del role:
Analiza el tasks/main.yml de este role de Ansible y genera tests
comprehensivos para verify.yml de Molecule. Para cada tarea, crea
aserciones que verifiquen:
1. Estados de instalación de paquetes
2. Estado de servicios (running/enabled)
3. Existencia y permisos de archivos
4. Validación de contenido de configuración
5. Estados de puertos escuchando
Tareas del role:
[pega tu tasks/main.yml]
Depurar fallos de idempotencia:
Mi test de idempotencia de Molecule muestra estas tareas como "changed"
en la segunda ejecución:
[pega la salida de las tareas]
Explica por qué cada tarea no es idempotente y proporciona alternativas
idempotentes usando los módulos apropiados de Ansible (lineinfile,
template, blockinfile, etc.)
Crear escenarios multi-plataforma:
Genera una configuración molecule.yml que pruebe mi role en:
- Ubuntu 20.04, 22.04 y 24.04
- Debian 11 y 12
- Rocky Linux 8 y 9
Incluye:
- Imágenes Docker apropiadas con soporte systemd
- Variables específicas por plataforma para diferencias de gestor de paquetes
- Sugerencias de ejecución paralela para optimización en CI
Generar tests Testinfra desde verify.yml existente:
Convierte estas aserciones de verify.yml de Ansible a tests de Python
con Testinfra. Mantén la misma cobertura de tests pero usa la sintaxis
más Pythonica de Testinfra. Incluye fixtures apropiados y parametrización
donde corresponda.
verify.yml actual:
[pega tu verify.yml]
Integración de pipeline CI/CD:
Genera un workflow de GitHub Actions para mi role de Ansible probado
con Molecule que:
1. Ejecute ansible-lint y yamllint
2. Pruebe en matriz de Ubuntu y Debian
3. Pruebe múltiples escenarios de Molecule
4. Cachee dependencias de pip entre ejecuciones
5. Publique en Ansible Galaxy al hacer push de tags
Estructura actual del role: [describe tu role]
Cuándo Usar Molecule
Framework de Decisión de Migración
| Tu Situación | Recomendación | Por qué |
|---|---|---|
| 1-3 playbooks simples, sin roles | Quedarte con ansible-lint | El overhead no justifica el tiempo de configuración |
| 5+ roles, desarrollador individual | Empezar con Molecule | ROI en detectar errores antes de producción |
| Equipo de 3+, roles compartidos | Molecule + CI obligatorio | Previene problemas de “funciona en mi máquina” |
| Roles de infraestructura crítica | Molecule + multi-escenario | Probar upgrades, casos edge, rollbacks |
| Publicando en Ansible Galaxy | Molecule obligatorio | Expectativa de la comunidad, genera confianza |
Considera Molecule Cuando
- Tienes roles reutilizables: Molecule brilla al probar roles que se despliegan en múltiples proyectos o entornos
- Necesitas soporte multi-OS: Probar en Ubuntu, Debian y RHEL simultáneamente detecta problemas específicos de OS temprano
- Existe integración CI/CD: Testing automatizado en cada commit previene regresiones
- Colaboración en equipo: Múltiples ingenieros modificando los mismos roles necesitan validación consistente
- Requisitos de compliance: Resultados de tests auditables prueban que la infraestructura cumple estándares
Considera Alternativas Cuando
- Playbooks únicos: Scripts simples que se ejecutan una vez no necesitan el overhead
- Aprendiendo lo básico de Ansible: Enfócate en fundamentos de Ansible primero antes de agregar complejidad de testing
- Roles extremadamente simples: Un role que instala un paquete podría estar sobre-probado con Molecule
- Testing a nivel de kernel necesario: Vagrant o testing bare-metal puede ser más apropiado para módulos de kernel, namespaces de red o características específicas de systemd
- CI con recursos limitados: Los contenedores de Molecule agregan overhead; ansible-lint solo puede ser suficiente para validación simple
Prerequisitos
Antes de sumergirte en Molecule, asegúrate de tener configurado lo siguiente:
Herramientas Requeridas:
- Python 3.8 o superior
- Ansible 2.10 o superior
- Docker (para testing basado en contenedores)
- pip (gestor de paquetes de Python)
Requisitos de Conocimiento:
- Experiencia básica con Ansible (roles, tareas, handlers)
- Familiaridad con sintaxis YAML
- Comprensión de conceptos de Docker
- Competencia en línea de comandos
Configuración del Entorno: Recomiendo crear un entorno virtual de Python dedicado para evitar conflictos de dependencias:
python3 -m venv molecule-env
source molecule-env/bin/activate # En Windows: molecule-env\Scripts\activate
Paso 1: Instalar Molecule
La instalación de Molecule es directa con pip. Necesitarás instalar Molecule junto con el driver de Docker, que usaremos para nuestros escenarios de testing.
# Instalar Molecule con soporte para Docker
pip install "molecule[docker,lint]"
# Verificar instalación
molecule --version
Salida Esperada:
molecule 5.0.1 using python 3.11
ansible:2.15.4
default:5.0.1 from molecule
docker:2.1.0 from molecule_plugins.docker
La instalación incluye varios componentes:
- Core de Molecule: El framework de testing en sí
- Driver de Docker: Habilita testing basado en contenedores
- Herramientas de lint: Ansible-lint y yamllint para calidad de código
Punto de Verificación: Ejecuta molecule --version y confirma que todos los componentes estén instalados. Si falta el driver de Docker, reinstala con el extra [docker].
Paso 2: Inicializar un Nuevo Role
Vamos a crear un ejemplo práctico: un role de servidor web Nginx. Molecule se integra perfectamente con la estructura de roles de Ansible Galaxy.
# Crear un nuevo role con testing de Molecule incorporado
molecule init role nginx --driver-name docker
# Navegar al directorio del role
cd nginx
Este comando genera una estructura completa de role:
nginx/
├── defaults/
│ └── main.yml
├── files/
├── handlers/
│ └── main.yml
├── meta/
│ └── main.yml
├── molecule/
│ └── default/
│ ├── converge.yml
│ ├── molecule.yml
│ └── verify.yml
├── tasks/
│ └── main.yml
├── templates/
├── tests/
└── vars/
└── main.yml
Directorios Clave:
molecule/default/: Contiene la configuración de tu escenario de testingtasks/main.yml: Donde van tus tareas de Ansiblehandlers/main.yml: Para reinicios de servicios y notificaciones
Paso 3: Entender la Estructura de Molecule
El directorio molecule/default/ contiene tres archivos críticos:
molecule.yml - El archivo de configuración principal:
---
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: instance
image: geerlingguy/docker-ubuntu2204-ansible:latest
pre_build_image: true
provisioner:
name: ansible
verifier:
name: ansible
Desglose de Configuración:
dependency: Gestiona dependencias de roles de Ansible Galaxydriver: Especifica Docker para crear instancias de pruebaplatforms: Define entornos de prueba (OS, imagen, recursos)provisioner: Usa Ansible para aplicar tu roleverifier: Ejecuta tests de verificación después de la convergencia
converge.yml - Aplica tu role a las instancias de prueba:
---
- name: Converge
hosts: all
become: true
tasks:
- name: "Include nginx"
include_role:
name: "nginx"
verify.yml - Contiene aserciones para validar el comportamiento del role:
---
- name: Verify
hosts: all
gather_facts: false
tasks:
- name: Example assertion
ansible.builtin.assert:
that: true
Paso 4: Escribir tu Primera Prueba
Vamos a construir un role funcional de Nginx con pruebas apropiadas. Comienza definiendo las tareas del role.
tasks/main.yml:
---
# Instalar servidor web Nginx
- name: Install Nginx package
ansible.builtin.apt:
name: nginx
state: present
update_cache: yes
notify: Start nginx
- name: Ensure Nginx is started and enabled
ansible.builtin.service:
name: nginx
state: started
enabled: yes
- name: Deploy custom index.html
ansible.builtin.copy:
content: |
<html>
<head><title>Ansible Managed</title></head>
<body><h1>Deployed with Ansible</h1></body>
</html>
dest: /var/www/html/index.html
owner: www-data
group: www-data
mode: '0644'
handlers/main.yml:
---
- name: Start nginx
ansible.builtin.service:
name: nginx
state: started
Ahora crea pruebas de verificación significativas en molecule/default/verify.yml:
---
- name: Verify
hosts: all
gather_facts: true
tasks:
- name: Check if Nginx is installed
ansible.builtin.package_facts:
manager: auto
- name: Assert Nginx package is present
ansible.builtin.assert:
that:
- "'nginx' in ansible_facts.packages"
fail_msg: "Nginx package is not installed"
success_msg: "Nginx package is correctly installed"
- name: Check if Nginx service is running
ansible.builtin.service_facts:
- name: Assert Nginx service is active
ansible.builtin.assert:
that:
- "ansible_facts.services['nginx.service'].state == 'running'"
- "ansible_facts.services['nginx.service'].status == 'enabled'"
fail_msg: "Nginx service is not running or not enabled"
success_msg: "Nginx service is active and enabled"
- name: Check if Nginx is listening on port 80
ansible.builtin.wait_for:
port: 80
timeout: 5
- name: Verify custom index.html content
ansible.builtin.uri:
url: http://localhost
return_content: yes
register: webpage
- name: Assert webpage contains expected content
ansible.builtin.assert:
that:
- "'Deployed with Ansible' in webpage.content"
fail_msg: "Custom index.html was not deployed correctly"
success_msg: "Custom index.html is correctly deployed"
Paso 5: Ejecutar las Pruebas
Molecule proporciona un ciclo de vida de testing completo. Aquí está cómo ejecutar las pruebas:
# Ejecutar la secuencia completa de testing
molecule test
# O ejecutar pasos individuales:
molecule create # Crear instancias de prueba
molecule converge # Aplicar tu role
molecule verify # Ejecutar pruebas de verificación
molecule destroy # Limpiar instancias
La Secuencia Completa de Testing:
Cuando ejecutas molecule test, Molecule ejecuta estas fases:
- Dependency: Instalar dependencias de roles desde Ansible Galaxy
- Lint: Verificar sintaxis y mejores prácticas
- Cleanup: Eliminar instancias de prueba anteriores
- Destroy: Asegurar estado limpio
- Create: Crear contenedores de prueba
- Prepare: Pasos opcionales de pre-configuración
- Converge: Aplicar tu role
- Idempotence: Re-ejecutar para asegurar que no ocurran cambios
- Verify: Ejecutar pruebas de aserción
- Destroy: Limpiar recursos
Salida Esperada (abreviada):
--> Test matrix
└── default
├── dependency
├── cleanup
├── destroy
├── create
├── prepare
├── converge
├── idempotence
├── verify
└── destroy
--> Scenario: 'default'
--> Action: 'converge'
PLAY [Converge] ********************************************************
TASK [Include nginx] ***************************************************
included: /Users/user/nginx/tasks/main.yml
TASK [Install Nginx package] *******************************************
changed: [instance]
TASK [Ensure Nginx is started and enabled] *****************************
changed: [instance]
PLAY RECAP *************************************************************
instance: ok=3 changed=2 unreachable=0 failed=0
--> Scenario: 'default'
--> Action: 'verify'
TASK [Assert Nginx service is active] **********************************
ok: [instance] => {
"msg": "Nginx service is active and enabled"
}
Consejo de Flujo de Desarrollo: Durante el desarrollo, usa molecule converge repetidamente para aplicar cambios sin destruir instancias. Solo ejecuta el molecule test completo cuando estés listo para validar todo.
Paso 6: Probar con Diferentes Escenarios
La infraestructura del mundo real rara vez se ejecuta en un solo OS. Los escenarios de Molecule te permiten probar en múltiples plataformas simultáneamente.
Crea un escenario multi-plataforma modificando molecule/default/molecule.yml:
---
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: ubuntu-20-04
image: geerlingguy/docker-ubuntu2004-ansible:latest
pre_build_image: true
- name: ubuntu-22-04
image: geerlingguy/docker-ubuntu2204-ansible:latest
pre_build_image: true
- name: debian-11
image: geerlingguy/docker-debian11-ansible:latest
pre_build_image: true
provisioner:
name: ansible
playbooks:
converge: converge.yml
verify: verify.yml
verifier:
name: ansible
Crear Escenarios Nombrados:
También puedes crear escenarios de prueba completamente separados para diferentes casos de uso:
# Crear un escenario tipo producción
molecule init scenario production
# Crear un escenario para probar actualizaciones
molecule init scenario upgrade
Esto crea:
molecule/
├── default/
│ ├── converge.yml
│ ├── molecule.yml
│ └── verify.yml
├── production/
│ ├── converge.yml
│ ├── molecule.yml
│ └── verify.yml
└── upgrade/
├── converge.yml
├── molecule.yml
└── verify.yml
Ejecutar Escenarios Específicos:
# Probar solo el escenario de producción
molecule test -s production
# Converger múltiples escenarios
molecule converge --all
Paso 7: Integración CI/CD
Molecule se integra perfectamente con pipelines de integración continua. Aquí está cómo configurarlo con GitHub Actions.
.github/workflows/molecule.yml:
---
name: Molecule Tests
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
scenario:
- default
- production
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install "molecule[docker,lint]"
pip install ansible
- name: Run Molecule tests
run: molecule test -s ${{ matrix.scenario }}
Configuración de GitLab CI (.gitlab-ci.yml):
---
stages:
- test
molecule:
stage: test
image: geerlingguy/docker-ubuntu2204-ansible:latest
services:
- docker:dind
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
before_script:
- pip install "molecule[docker,lint]"
script:
- molecule test --all
only:
- merge_requests
- main
Punto de Verificación: Empuja tu role a un repositorio Git y verifica que el pipeline de CI se ejecute exitosamente. Verifica que todos los escenarios pasen y que el pipeline falle en caso de errores de prueba.
Ejemplos del Mundo Real
Ejemplo 1: Probar un Role de Servidor Web
Vamos a extender nuestro role de Nginx con configuración SSL y virtual hosts.
tasks/main.yml (extendido):
---
- name: Install Nginx and SSL dependencies
ansible.builtin.apt:
name:
- nginx
- openssl
state: present
update_cache: yes
- name: Create SSL directory
ansible.builtin.file:
path: /etc/nginx/ssl
state: directory
mode: '0755'
- name: Generate self-signed SSL certificate
ansible.builtin.command:
cmd: >
openssl req -x509 -nodes -days 365 -newkey rsa:2048
-keyout /etc/nginx/ssl/nginx.key
-out /etc/nginx/ssl/nginx.crt
-subj "/C=US/ST=State/L=City/O=Org/CN=localhost"
creates: /etc/nginx/ssl/nginx.crt
- name: Deploy SSL virtual host configuration
ansible.builtin.template:
src: vhost-ssl.conf.j2
dest: /etc/nginx/sites-available/default
mode: '0644'
notify: Reload nginx
- name: Ensure Nginx is started
ansible.builtin.service:
name: nginx
state: started
enabled: yes
templates/vhost-ssl.conf.j2:
server {
listen 80;
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
molecule/default/verify.yml (extendido):
---
- name: Verify
hosts: all
gather_facts: true
tasks:
- name: Check SSL certificate exists
ansible.builtin.stat:
path: /etc/nginx/ssl/nginx.crt
register: ssl_cert
- name: Assert SSL certificate is present
ansible.builtin.assert:
that:
- ssl_cert.stat.exists
- ssl_cert.stat.mode == '0644'
- name: Verify Nginx is listening on HTTPS
ansible.builtin.wait_for:
port: 443
timeout: 5
- name: Test HTTPS connection
ansible.builtin.uri:
url: https://localhost
validate_certs: no
return_content: yes
register: https_response
- name: Assert HTTPS is working
ansible.builtin.assert:
that:
- https_response.status == 200
Ejemplo 2: Probar Configuración de Base de Datos
Aquí está cómo probar un role de PostgreSQL con Molecule.
molecule/default/molecule.yml:
---
platforms:
- name: postgres-instance
image: geerlingguy/docker-ubuntu2204-ansible:latest
pre_build_image: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
privileged: true
command: /lib/systemd/systemd
tasks/main.yml (role de PostgreSQL):
---
- name: Install PostgreSQL
ansible.builtin.apt:
name:
- postgresql
- postgresql-contrib
- python3-psycopg2
state: present
update_cache: yes
- name: Ensure PostgreSQL is started
ansible.builtin.service:
name: postgresql
state: started
enabled: yes
- name: Create application database
become_user: postgres
community.postgresql.postgresql_db:
name: appdb
state: present
- name: Create database user
become_user: postgres
community.postgresql.postgresql_user:
name: appuser
password: "{{ db_password | default('changeme') }}"
db: appdb
priv: ALL
state: present
molecule/default/verify.yml:
---
- name: Verify
hosts: all
become: true
tasks:
- name: Check PostgreSQL service status
ansible.builtin.service_facts:
- name: Assert PostgreSQL is running
ansible.builtin.assert:
that:
- "ansible_facts.services['postgresql.service'].state == 'running'"
- name: Verify database exists
become_user: postgres
community.postgresql.postgresql_query:
db: appdb
query: SELECT 1
register: db_check
- name: Assert database is accessible
ansible.builtin.assert:
that:
- db_check is succeeded
- name: Test database connection with user
become_user: postgres
community.postgresql.postgresql_query:
db: appdb
login_user: appuser
query: CREATE TABLE test (id serial PRIMARY KEY, name varchar(50))
register: table_creation
- name: Assert user has correct privileges
ansible.builtin.assert:
that:
- table_creation is succeeded
Ejemplo 3: Probar Hardening de Seguridad
Los roles de seguridad requieren pruebas exhaustivas para asegurar que no rompan funcionalidad.
molecule/default/verify.yml (hardening de seguridad):
---
- name: Verify Security Hardening
hosts: all
gather_facts: true
tasks:
- name: Check if SSH password authentication is disabled
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^PasswordAuthentication'
line: 'PasswordAuthentication no'
state: present
check_mode: yes
register: ssh_config
- name: Assert SSH is properly configured
ansible.builtin.assert:
that:
- not ssh_config.changed
fail_msg: "SSH password authentication is not disabled"
- name: Verify firewall is active
ansible.builtin.command: ufw status
register: ufw_status
changed_when: false
- name: Assert firewall is enabled
ansible.builtin.assert:
that:
- "'Status: active' in ufw_status.stdout"
- name: Check for unattended upgrades
ansible.builtin.stat:
path: /etc/apt/apt.conf.d/50unattended-upgrades
register: unattended_upgrades
- name: Assert automatic updates are configured
ansible.builtin.assert:
that:
- unattended_upgrades.stat.exists
- name: Verify root login is disabled
ansible.builtin.command: passwd -S root
register: root_status
changed_when: false
- name: Assert root account is locked
ansible.builtin.assert:
that:
- "'L' in root_status.stdout"
fail_msg: "Root account is not locked"
Mejores Prácticas
Organización de Pruebas
Mantén las pruebas enfocadas y modulares:
# Mal: Un archivo de verificación gigante
verify.yml # 500 líneas de pruebas
# Bien: Tareas de verificación separadas
molecule/default/
├── molecule.yml
├── converge.yml
├── verify.yml
└── verify/
├── test_installation.yml
├── test_configuration.yml
├── test_security.yml
└── test_networking.yml
El verify.yml principal incluye pruebas específicas:
---
- name: Verify
hosts: all
tasks:
- name: Run installation tests
include_tasks: verify/test_installation.yml
- name: Run configuration tests
include_tasks: verify/test_configuration.yml
- name: Run security tests
include_tasks: verify/test_security.yml
Gestión de Escenarios
Usa escenarios estratégicamente:
default: Pruebas básicas de funcionalidadproduction: Entorno tipo producción con todas las característicasupgrade: Probar rutas de actualización desde versiones anterioresmulti-node: Pruebas de sistemas distribuidos
No crees escenarios para variaciones menores. En su lugar, usa variables:
# molecule/default/converge.yml
- name: Converge
hosts: all
vars:
# Sobrescribe estas en escenarios específicos
enable_ssl: "{{ scenario_ssl | default(true) }}"
enable_monitoring: "{{ scenario_monitoring | default(false) }}"
roles:
- nginx
Pruebas de Idempotencia
La idempotencia es crítica: ejecutar tu role múltiples veces no debería causar cambios después de la primera ejecución.
Molecule prueba esto automáticamente. Asegúrate de que tus tareas sean idempotentes:
# Mal: Siempre reporta cambios
- name: Configure application
ansible.builtin.shell: echo "config=true" >> /etc/app.conf
# Bien: Configuración idempotente
- name: Configure application
ansible.builtin.lineinfile:
path: /etc/app.conf
line: "config=true"
create: yes
Monitorea la salida de la prueba de idempotencia:
PLAY RECAP *****************************************************************
instance: ok=10 changed=0 unreachable=0 failed=0
Si changed es mayor que 0 en la segunda ejecución, tienes problemas de idempotencia.
Docker vs Vagrant
Docker (Recomendado para la mayoría de casos):
- Rápido: Los contenedores inician en segundos
- Eficiente en recursos: Ejecuta muchas instancias simultáneamente
- Amigable con CI: Funciona en la mayoría de entornos de CI
- Limitaciones: No puede probar módulos del kernel, peculiaridades de systemd, o cualquier cosa que requiera VM completa
Vagrant (Para escenarios complejos):
- VMs completas: Sistema operativo completo
- Systemd: Soporte completo del sistema init
- Testing de kernel: Puede probar parámetros y módulos del kernel
- Compensaciones: Más lento (minutos para iniciar), pesado en recursos, más difícil en CI
Cuándo usar Vagrant:
# molecule/vagrant/molecule.yml
---
driver:
name: vagrant
platforms:
- name: ubuntu-vm
box: ubuntu/jammy64
memory: 2048
cpus: 2
provisioner:
name: ansible
Usa Vagrant cuando pruebes roles que:
- Modifican parámetros del kernel (
sysctl) - Requieren características específicas de systemd
- Instalan módulos del kernel
- Necesitan stack de red completo
Errores Comunes
Limitaciones de Contenedores
Problema: Systemd no funciona apropiadamente en contenedores estándar.
Solución: Usa imágenes pre-construidas con soporte para systemd:
platforms:
- name: instance
image: geerlingguy/docker-ubuntu2204-ansible:latest
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
privileged: true
command: /lib/systemd/systemd
Las imágenes Docker de Jeff Geerling están construidas específicamente para testing de Ansible con systemd funcional.
Problemas de Privilegios
Problema: Las tareas fallan con errores de permisos.
Solución: Usa become apropiadamente en tu playbook de convergencia:
# molecule/default/converge.yml
---
- name: Converge
hosts: all
become: true # Ejecutar tareas con sudo
tasks:
- name: Include role
include_role:
name: nginx
Evita requerir become: yes en el role mismo cuando sea posible. Deja que el usuario decida la escalada de privilegios.
Gestión de Dependencias
Problema: El role depende de otros roles, pero no están disponibles durante el testing.
Solución: Define dependencias en meta/main.yml:
# meta/main.yml
---
dependencies:
- role: geerlingguy.security
- role: geerlingguy.firewall
Molecule instala estas automáticamente antes de probar si tienes habilitado el gestor de dependencias de Galaxy:
# molecule/default/molecule.yml
dependency:
name: galaxy
options:
role-file: requirements.yml
Crea requirements.yml para dependencias externas:
# requirements.yml
---
roles:
- name: geerlingguy.security
version: 2.3.0
- name: geerlingguy.firewall
version: 3.1.0
Inestabilidad de Pruebas
Problema: Las pruebas ocasionalmente fallan sin razón aparente.
Causas comunes:
- Timeouts de red
- Condiciones de carrera en el inicio de servicios
- Tiempos de espera insuficientes
Solución: Agrega esperas y reintentos apropiados:
- name: Wait for service to be ready
ansible.builtin.wait_for:
port: 80
delay: 2
timeout: 30
- name: Check endpoint with retry
ansible.builtin.uri:
url: http://localhost/health
register: health_check
until: health_check.status == 200
retries: 5
delay: 3
Herramientas e Integración
Testinfra para Verificación
Aunque Molecule usa Ansible para verificación por defecto, también puedes usar Testinfra (testing basado en Python):
pip install testinfra
molecule/default/tests/test_default.py:
import os
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']
).get_hosts('all')
def test_nginx_is_installed(host):
nginx = host.package("nginx")
assert nginx.is_installed
def test_nginx_running_and_enabled(host):
nginx = host.service("nginx")
assert nginx.is_running
assert nginx.is_enabled
def test_nginx_listening(host):
assert host.socket("tcp://0.0.0.0:80").is_listening
def test_index_html_content(host):
content = host.file("/var/www/html/index.html").content_string
assert "Deployed with Ansible" in content
Configurar Testinfra en molecule.yml:
verifier:
name: testinfra
options:
v: 1
Integración GitLab/GitHub CI
GitHub Actions avanzado con testing de matriz:
---
name: Ansible Role Testing
on:
push:
branches: [main]
pull_request:
schedule:
- cron: '0 0 * * 0' # Semanal
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: pip install ansible-lint yamllint
- name: Lint Ansible role
run: ansible-lint .
- name: Lint YAML files
run: yamllint .
test:
needs: lint
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
distro:
- ubuntu2004
- ubuntu2204
- debian11
scenario:
- default
- production
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install Molecule
run: pip install "molecule[docker,lint]" ansible
- name: Run Molecule test
run: molecule test -s ${{ matrix.scenario }}
env:
PY_COLORS: '1'
ANSIBLE_FORCE_COLOR: '1'
MOLECULE_DISTRO: ${{ matrix.distro }}
Integración con Ansible Galaxy
Al publicar roles en Ansible Galaxy, incluye pruebas de Molecule para aumentar credibilidad:
# .github/workflows/release.yml
---
name: Release to Galaxy
on:
push:
tags:
- 'v*'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Test with Molecule
run: |
pip install "molecule[docker,lint]"
molecule test
release:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Release to Galaxy
uses: robertdebock/galaxy-action@1.2.0
with:
galaxy_api_key: ${{ secrets.GALAXY_API_KEY }}
Enlaza a tu badge de CI en README.md:
# Ansible Role: Nginx
[](https://github.com/username/ansible-role-nginx/actions)
[](https://galaxy.ansible.com/username/nginx)
Probado con Molecule en:
- Ubuntu 20.04
- Ubuntu 22.04
- Debian 11
Conclusión
Molecule transforma el desarrollo de roles de Ansible de un proceso manual y propenso a errores en un flujo de trabajo robusto y automatizado. Al implementar estrategias de testing comprehensivas—desde verificaciones básicas de funcionalidad hasta escenarios multi-plataforma—aseguras que tu código de infraestructura sea confiable, mantenible y listo para producción.
Puntos Clave:
- Siempre prueba tus roles en múltiples sistemas operativos y escenarios
- Aprovecha el testing de idempotencia para prevenir deriva de configuración
- Integra Molecule en tu pipeline de CI/CD para validación continua
- Usa Docker para velocidad durante desarrollo, Vagrant para testing complejo a nivel de sistema
- Escribe pruebas de verificación claras y enfocadas que actúen como documentación viva
Próximos Pasos:
- Explora escenarios avanzados: Implementa testing multi-nodo para sistemas distribuidos (aprende más en nuestra guía de Mejores Prácticas de Gestión de Contenedores Docker)
- Integra con tu pipeline de CI/CD: Agrega pruebas de Molecule a tus pipelines existentes (revisa Estrategias de Optimización de Pipeline CI/CD)
- Contribuye a la comunidad: Comparte tus roles probados en Ansible Galaxy
- Aprende herramientas complementarias de testing: Explora Testinfra, InSpec y ServerSpec para validación más profunda de infraestructura
Para más sobre automatización de infraestructura y mejores prácticas de DevOps, explora nuestra guía completa sobre Infraestructura como Código con Terraform o sumérgete en Estrategias de Despliegue en Kubernetes para testing de infraestructura cloud-native.
Recursos Adicionales:
- Documentación Oficial de Molecule
- Guía de Estrategias de Testing de Ansible
- Serie de Testing de Ansible de Jeff Geerling
Comienza a probar tu código de infraestructura hoy—tu yo futuro (y tu equipo) te lo agradecerán cuando los despliegues se vuelvan predecibles, confiables y libres de estrés.
Ver También
- Testing de Infrastructure as Code - Estrategias de validación para Terraform y Ansible
- Testing Continuo en DevOps - Integra testing de infraestructura en pipelines CI/CD
- Estrategias de Testing de Terraform - Enfoques complementarios de testing IaC
- Estrategias de Testing en Kubernetes - Testing de orquestación de contenedores para infraestructura cloud-native
- Optimización de Pipelines CI/CD - Optimiza tests de Molecule en tu pipeline de entrega
