Ansible Role Testing
Molecule
Creating a minimal Ansible role is as simple as creating <role_name>/tasks/main.yml. But how do you know that the role does what you think? And, as the underlying OS and other dependencies are updated and change, how can you know that your role maintains compatibility (e.g., Apache httpd deprecated configuration directives)? Clearly there's a need for testing and that's where Molecule comes in.
Molecule is a harness for testing Ansible roles. You need to have Molecule installed and then a set of configurations in a molecule sub-directory in your role (molecule init scenario). With those things in place you can run molecule test to test your role.
A typical Molecule configuration will specify multiple container images, representing the various deployment targets for your role, as well as one or more tests that get run against each container.
Development
Molecule allows for test-driven development, which might look something like this:
- Run
molecule createto create the testing containers - Edit
molecule/default/verify.ymlto create a test case - Edit your role to make the change to satisfy the test case
- Run
molecule convergeto apply your role to the test containers - Run
molecule verifyto test your role's changes - Go to 3 until the test passes
Continuous Testing
The single largest advantage to this paradigm is having your role continuously tested by incorporating continuous integration. As your target platforms evolve, your daily pipeline runs can allow you to remain confident that your role still works and is safe to use as underpinnings for important infrastructure. Additionally, Ansible itself often introduces deprecations and breaking changes that your pipeline can provide advanced warning for.
Role Template
Rather than manually performing this setup all the time, I just maintain a role template that allows me to quickly hammer out production-quality roles.
molecule/default/molecule.yml
---
role_name_check: 1
driver:
name: docker
platforms:
- name: CHANGEME_ROLE_NAME_role-ubuntu_2604
image: docker.io/markcaudill/ubuntu-2604:latest
pre_build_image: true
privileged: true
tmpfs:
- /run
- /tmp
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
cgroupns_mode: host
command: /lib/systemd/systemdThe key elements are:
tmpfs: ['/run', '/tmp']volumes: ['/sys/fs/cgroup:/sys/fs/cgroup:rw'](you could probably get away with:rowhich would be more secure)command: '/lib/systemd/systemd'cgroupns_mode: host
molecule/default/verify.yml
---
- name: Verify
hosts: all
gather_facts: false
vars_files:
- ../../defaults/main.yml
- ../../vars/main.yml
tasks:
- name: Gather package facts
ansible.builtin.package_facts:
manager: auto
- name: Ensure some things
ansible.builtin.assert:
that: 'true == true'If your role installs a certain package, for example, adding a test case like 'package_name' in ansible_facts.packages might be good here.
Container Images
These are images that I maintain and use for Ansible role testing using Molecule, but you can probably use vendor-supplied images just as well.
| Repository | Pipeline | Docker Hub |
|---|---|---|
| Debian 11 | ||
| Debian 12 | ||
| Debian 13 | ||
| Ubuntu 22.04 | ||
| Ubuntu 24.04 | ||
| Ubuntu 26.04 |
I find the Ansible ecosystem documentation terribly cumbersome to sift through for some reason, so it's possible or even likely that there are newer and better ways to do this.
Note: this is all derivative of or directly copied from Jeff Geerling's work.