Ansible Molecule is a tool used for testing and validating Ansible roles and playbooks in multiple scenarios. It helps automate the testing of Ansible code and ensures that it will work as intended when applied to target servers. With Molecule, you can test roles and playbooks across different environments and platforms. supports different virtualization and containerization technologies such as Docker, Podman, Vagrant, and cloud providers such as Amazon Web Services, Microsoft Azure, and Google Cloud Platform.
Ansible Molecule is a powerful tool for automating and streamlining the testing and validation of Ansible roles and playbooks. It uses a testing framework such as pytest and provides an environment for the role or playbook to run in.
In this tutorial, you will learn how to set up and test Ansible Roles automatically via Molecule and Docker. You will install Ansible, Docker, and Molecule at the same time, then you will learn how to create an Ansible Roles boilerplate with Molecule and set up automatic testing of Ansible Roles via Docker containers.
Prerequisites
To complete this tutorial, you must have the following requirements:
- A Linux system – This example uses the latest version of Ubuntu 22.04 server with hostname ‘ansible-test‘.
- A non-root user with sudo/root administrator privileges – This example uses a user called ‘alice‘.
- Understanding of Ansible and Ansible Roles.
Installing Dependencies
In the first section, you will install package dependencies that will be used in the following guide. This includes Python3, Pip, Ansible, and Docker CE (Community Edition). Before you start, run the following command to update and refresh your package index.
sudo apt update
Once the package index is updated, enter the following command to install Python3, Pip3, Virtualenv, and Ansible.
sudo apt install python3 python3-pip python3-venv ansible ca-certificates curl gnupg lsb-release
Input y when prompted and press ENTER to proceed.
After Python3, Pip3, Virtualenv, and Ansible are installed, you will be installing the Docker CE (Community Edition) via the official Docker Repository.
Enter the following command to create a new directory ‘/etc/apt/keyrings‘ and download the GPG key of the Docker repository.
sudo mkdir -m 0755 -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
Next, add the Docker CE repository to your system using the below command.
echo
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Then update and refresh your ubuntu package index to apply the changes.
sudo apt update
Now install Docker CE packages via the following ‘apt‘ command below. When prompted, input y to confirm and press ENTER to proceed.
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
With the Docker CE installed, add your current user to the group ‘docker‘ using the following command. This will allow your user to run Docker containers.
sudo usermod -aG docker $USER
You can now verify the Docker configuration using the command below. This will download and run the container ‘hello-world’ on your system.
docker run hello-world
If the user can execute Docker containers, you should see the output of the ‘hello-world‘ container as below.
With this, you have now installed package dependencies such as Python3, Pip3, Virtualenv, Ansible, and Docker. In the next section, you will install Molecule within the Python virtual environment.
Installing Molecule
In this section, you will create a new Python virtual environment that will be used for the development environment of Ansible Roles. You will also install Molecule and the Docker driver.
Run the following command to create a new Python virtual environment called ‘ansible-venv‘. Once the virtual environment is created, you should see the new directory ‘ansible-venv‘ on your current working directory.
python3 -m venv ansible-venv
Next, run the below command to activate your Python virtual environment. Once activated, your prompt shell will become like this: ‘(ansible-venv) [email protected]:…‘.
source ansible-venv/bin/activate
Now move your working directory to ‘ansible-venv‘, then install Python packages Molecule and the Molecule Docker driver using the ‘pip3‘ command as below.
cd ansible-venv/
pip3 install wheel molecule 'molecule-plugins[docker]'
Below you can see the installation process of Molecule and the Docker driver.
After the Molecule and Docker driver are installed, you will next create a new Ansible Role via Molecule.
Initializing Ansible Role with Molecule
After installing Molecule and the Docker driver, you will now create new Ansible Roles via molecule. In this example, you will create roles that will be used to install basic LEMP Stack (Linux, Nginx, MariaDB, and PHP-FPM) packages and ensure that LEMP Stack services are running and enabled.
First, run the following command to generate the Ansible Role boilerplate called ‘test.lemp‘ with the driver ‘docker‘. This will create a new directory called ‘lemp‘ on your current working directory.
molecule init role test.lemp --driver-name docker
Move to the ‘lemp’ directory using the below command.
cd lemp
Open the file ‘tasks/main.yml’ using the nano editor and define some tasks for your role.
nano tasks/main.yml
Add the following lines to the file. With this, you will create tasks for installing LEMP Stack packages and verifying LEMP services.
---
- name: "Installing LEMP Stack"
apt:
name: "{{ pkg_list }}"
state: present- name: "Ensure LEMP Services is running"
service:
name: "{{ item }}"
state: started
enabled: true
with_items: "{{ svc_list }}"
Save and close the file when finished.
Now open the file ‘vars/main.yml‘ using the nano editor and add variables for your Ansible roles.
nano vars/main.yml
Add the following lines to the file. In this example, you will define the variable ‘pkg_list‘ that contains package names of the LEMP stack, and the variable ‘svc_list’ that contains the services name of the LEMP Stack.
---
pkg_list:
- nginx
- mariadb-server
- php-fpm
- php-cli
svc_list:
- nginx
- mariadb
- php8.1-fpm
Save the file and exit the editor when finished.
Setting Up Instance for Testing
After creating Ansible roles, you will need to set up the instance that will be used to test Ansible roles. This example will be using the Docker image ‘mipguerrero26/ubuntu-python3‘, which by default contains the Python3 package. You can use different Docker images, but you must ensure that Python is installed.
First, run the following command to download the Docker image ‘mipguerrero26/ubuntu-python3‘.
docker pull mipguerrero26/ubuntu-python3
Once downloaded, verify the list of images using the below command. You should see the Docker image ‘mipguerrero26/ubuntu-python3‘ is downloaded and available on your system.
docker images
Now run the following command to run a temporary container and execute bash in the attached mode.
docker run -it mipguerrero26/ubuntu-python3 /bin/bash
Once logged in to the container, enter the following command to verify the Python and Ubuntu version.
python3 --version
cat /etc/lsb-release
You should receive an output like this – In this example, the image ‘mipguerrero26/ubuntu-python3‘ is based on Ubuntu 22.04 and comes with Python.
Type ‘exit‘ to log out from the container shell.
Next, open the default Molecule configuration ‘molecule/default/molecule.yml‘ using the nano editor.
nano molecule/default/molecule.yml
On the ‘platform’ section, change the name and the default image that will be used for testing. Also, add the setting ‘privileged: true‘. In this example, the instance for testing will be named ‘instance-ubuntu22.04’ with the image ‘mipguerrero26/ubuntu-python3‘.
platforms:
- name: instance-ubuntu22.04
image: mipguerrero26/ubuntu-python3
privileged: true
Save the file and exit the editor.
Now run the ‘molecule’ command below to verify the list of instances within your Molecule test project. You should see the instance called ‘instance-ubuntu22.04‘ with the driver ‘Docker‘.
molecule list
Running Molecule Test Converge
With the Molecule instance created, you can now run the test by simply invoking the command ‘molecule converge‘ as below. This ‘converge‘ parameter allows you to test and verify Ansible roles against the instance that is available on your Molecule project. In this example, the Ansible role ‘lemp‘ will be run against the instance ‘instance-ubuntu22.04‘ via Docker.
molecule converge
Below is an output when the Molecule is running.
The Molecule task is to create a new instance via Docker for testing.
Once the instance is created, the Ansible roles will be applied against the instance.
At this point, the Ansible role ‘lemp‘ is applied to the instance ‘instance-ubuntu22.04‘, which is running via Docker. Enter the following command to verify the running container on your system.
docker ps
You should see the container called ‘instance-ubuntu22.04’, which is matched with the Molecule instance name.
Now log in to the container ‘instance-ubuntu22.04‘ using the following command.
docker exec -it instance-ubuntu22.04 /bin/bash
Then verify the list of open ports on the container using the below command. You should see port 80 used by Nginx, port 3306 used by MariaDB, and the PHP-FPM running with the sock file ‘/run/php/php8.1-fpm.sock‘. This confirms that the role ‘lemp’ is running successfully.
ss -tulpn
ss -pl | grep php
Lastly, run the following command to clean up your environment. This will destroy and remove the container ‘instance-ubuntu22’ from your system.
molecule destroy
If you check the list of running containers on your system, there will be no running container, because the instance ‘instance-ubuntu22‘ is removed.
docker ps
docker ps -a
Create Test Script with testInfra Python Module
In this section, you will create the test script scenario that will be used to verify the state of the Molecule instance and ensure that roles are applied. This can be done with Python script with the module testInfra.
First, run the following pip3 command to install the testInfra module.
pip3 install pytest-testinfra
Once the testinfra module is installed, create a new directory ‘molecule/default/tests/‘, and create a new test file ‘molecule/default/tests/test_default.py‘ using the following nano editor command.
mkdir -p molecule/default/tests/
nano molecule/default/tests/test_default.py
Add the following Python script to the file. With this, you will test the Ansible Molecule instance to ensure that LEMP Stack packages are installed and running.
import os
import pytest
import testinfra.utils.ansible_runnertestinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')@pytest.mark.parametrize('pkg', [
'nginx',
'mariadb-server',
'php-fpm'
])
def test_pkg(host, pkg):
package = host.package(pkg)assert package.is_installed
@pytest.mark.parametrize('svc', [
'nginx',
'mariadb',
'php8.1-fpm'
])
def test_svc(host, svc):
service = host.service(svc)assert service.is_running
assert service.is_enabled
Save and close the file when finished.
Next, open the Molecule config file ‘molecule/default/molecule.yml’ using the nano editor to define the test.
nano molecule/default/molecule.yml
On the ‘verifier’ section, change the name to ‘testinfra‘ and add the parameter ‘directory: tests’. This means that the test script will be taken from the directory ‘tests‘.
verifier:
name: testinfra
directory: tests
Save the file and exit the editor.
Now execute the following command to run the test with all scenarios from start to end. The ‘molecule test‘ command will start testing by creating the instance, applying for the Ansible role, running the test, then destroying everything to clean up.
molecule test
Below is the screenshot when the ‘test‘ command is initialized, the Ansible Molecule will destroy the existing instance if available.
Now the process of creating an instance for new testing.
Then the Ansible role will be applied against the instance.
When the roles are applied, the test or verifier will begin. When successful, you should get an output such as ‘collected 6 items – 6 passed in …‘.
Lastly, the Molecule will destroy the instance when the test is finished.
Ansible Molecule Process in Development
When first developing roles, you must ensure that the role is generated via Molecule. Then, you can add tasks and others components to your Ansible role, define the instance for testing, then set up the test script to ensure that the desired state is applied to the target instance.
So, when you have finished the configuration of an Ansible role and defined the instance, run the following command to test the implementation of the Ansible role in your test instance.
molecule converge
Now after creating the test script and defining the test on the Molecule configuration, run the following command to apply the test.
molecule verify
When the test was successful, you can now destroy everything and retest using the command below.
molecule destroy
molecule test
You can check the detailed available paramaters of Ansible Molecule via the command below.
molecule --help
Conclusion
In this tutorial, you have learned the installation of Ansible Molecule that allows you to perform end-to-end testing of Ansible role and playbook via multiple scenarios. You have also learned how to create roles via Molecule and run testing of the Ansible role with Docker. Lastly, you have also learned how to create a Python test script with module testInfra that can be used to verify the state of desired machines/servers.
In the end, you now better understand how to test Ansible roles and work with Molecule and Docker. Learn more about Ansible Molecule by visiting the official documentation of Ansible Molecule.