Daniel Brennand

Testing Ansible Content with Molecule

Time for another blog post! 🚀

In this blog post, I will be discussing how to test Ansible content with Molecule ๐Ÿงช

What is Molecule?

Molecule aids in the development and testing of Ansible content: collections, playbooks and roles.

github.com/ansible-community/molecule1

Why do we need to test Ansible content?

Testing is an integral part of the software development lifecycle. It helps identify and prevent bugs from reaching production and in some cases, helps identify performance issues. When creating Ansible content we need to ensure that it works as expected and that we are not introducing any undesired behaviour. This is where Molecule comes in.

Molecule Terminology ๐Ÿ“š

Molecule has several terms that are used throughout the documentation. Let’s go over them now.

Instances & Drivers ๐Ÿš—

Molecule instances are what your Ansible content is executed against. Instances are created using a driver. Molecule has several drivers for handling the creation and destruction of instances. The drivers are currently located in ansible-community/molecule-plugins repository.

For example, the default Docker driver can be used to create a container instance and the Vagrant driver can create a virtual machine instance.

Scenarios ๐Ÿ“–

Molecule scenarios can be thought of as a test suite. Each scenario contains its own instances and configuration. For example, a scenario could be used to test an Ansible role against different distributions or test a specific configuration of a role.

There should always be a default scenario which is used to test Ansible content with its default configuration.

Molecule Directory Structure ๐Ÿ“

A basic Molecule directory structure is:

molecule
โ””โ”€โ”€ default
    โ”œโ”€โ”€ prepare.yml
    โ”œโ”€โ”€ converge.yml
    โ”œโ”€โ”€ verify.yml
    โ””โ”€โ”€ molecule.yml

Within the molecule directory is the default scenario directory which contains the prepare.yml, converge.yml and verify.yml playbooks, as well as the molecule.yml configuration file.

Prepare Playbook โ–ถ๏ธ

The prepare.yml playbook defines the preparation tasks to run before the converge.yml playbook. For example, this could be used configure the instance.

Converge Playbook โ–ถ๏ธ

The converge.yml playbook defines the Ansible content to be tested. This can be a playbook, role or collection.

Verify Playbook โ–ถ๏ธ

The verify.yml playbook is executed after the converge.yml playbook. This playbook contains verification tasks to check the Ansible content has been applied correctly.

Configuration File molecule.yml ๐Ÿ“

The molecule.yml file contains configuration for each Molecule component2:

ComponentDescription
Dependency ManagerMolecule uses Ansible Galaxy as the default manager for resolving role and collection dependencies.
DriverInstances & Drivers.
Platforms (Instances)Defines instances to be created by the driver for the scenario.
ProvisionerMolecule uses Ansible as the provisioner. The provisioner manages the life cycle of instances by communicating with the driver.
ScenarioMolecule’s default scenario configuration can be overridden for full control over each sequence.
VerifierMolecule uses Ansible as the verifier. The verifier uses the verify.yml playbook to check the state of the instance.

The example below shows a basic configuration using the Docker driver to create a Debian container instance.

 1---
 2dependency:
 3  name: galaxy
 4driver:
 5  name: docker
 6platforms:
 7  - name: instance
 8    image: geerlingguy/docker-debian10-ansible:latest
 9    pre_build_image: true
10provisioner:
11  name: ansible
12verifier:
13  name: ansible

Molecule Commands ๐Ÿ“œ

Molecule has several commands for performing different actions. The most common commands are:

Molecule CommandDescription
createCreates the instance defined in the molecule.yml file.
destroyDestroys the instance defined in the molecule.yml file.
loginSpawns a shell inside the instance. Useful for troubleshooting.
convergePerforms the converge sequence which includes creating the instance and executing the prepare.yml and converge.yml playbooks.
testPerforms a full test scenario. This includes the converge and idempotency sequences, executing the verify.yml playbook and destroying the instance.

Now that we have covered the basics, let’s test an Ansible playbook with Molecule! ๐Ÿงช

Demo ๐Ÿ“บ

I’ve created a demo repository which contains a simple playbook to install nginx on a Debian container instance. You’ll need to have Docker and Python installed to use the repository.

Begin by cloning the repository:

1git clone https://github.com/dbrennand/molecule-demo.git && cd molecule-demo

Inspect the files and notice the default molecule scenario with the playbooks and molecule.yml configuration file. The converge.yml playbook calls the main playbook.yml two directories above.

Next, install Molecule and the Docker driver. I recommend using a virtual environment:

1mkdir -pv ~/.virtualenvs
2python3 -m venv ~/.virtualenvs/molecule-demo
3source ~/.virtualenvs/molecule-demo/bin/activate
4pip install -r requirements.txt

Now we can run the molecule test command to perform a full test scenario:

1molecule test

The output should look similar to the following:

 1INFO     Running default > create
 2
 3PLAY [Create] ******************************************************************
 4
 5TASK [Create molecule instance(s)] *********************************************
 6changed: [localhost] => (item=instance)
 7
 8...
 9
10INFO     Running default > prepare
11
12PLAY [Prepare] *****************************************************************
13
14TASK [Gathering Facts] *********************************************************
15ok: [instance]
16
17TASK [Update apt cache] ********************************************************
18changed: [instance]
19
20...
21
22INFO     Running default > converge
23
24PLAY [Converge] ****************************************************************
25
26TASK [Gathering Facts] *********************************************************
27ok: [instance]
28
29PLAY [Playbook | Install nginx] ************************************************
30
31TASK [Gathering Facts] *********************************************************
32ok: [instance]
33
34TASK [Install nginx] ***********************************************************
35changed: [instance]
36
37PLAY RECAP *********************************************************************
38instance                   : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
39
40INFO     Running default > idempotence
41
42PLAY [Converge] ****************************************************************
43
44TASK [Gathering Facts] *********************************************************
45ok: [instance]
46
47PLAY [Playbook | Install nginx] ************************************************
48
49TASK [Gathering Facts] *********************************************************
50ok: [instance]
51
52TASK [Install nginx] ***********************************************************
53ok: [instance]
54
55PLAY RECAP *********************************************************************
56instance                   : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
57
58INFO     Idempotence completed successfully.
59INFO     Running default > side_effect
60WARNING  Skipping, side effect playbook not configured.
61INFO     Running default > verify
62INFO     Running Ansible Verifier
63
64PLAY [Verify] ******************************************************************
65
66TASK [Gathering Facts] *********************************************************
67ok: [instance]
68
69TASK [Gather package list] *****************************************************
70ok: [instance]
71
72TASK [Verify nginx is installed] ***********************************************
73ok: [instance] => {
74    "changed": false,
75    "msg": "All assertions passed"
76}
77
78PLAY RECAP *********************************************************************
79instance                   : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
80
81INFO     Verifier completed successfully.
82INFO     Running default > cleanup
83WARNING  Skipping, cleanup playbook not configured.
84INFO     Running default > destroy
85
86PLAY [Destroy] *****************************************************************
87
88TASK [Wait for instance(s) deletion to complete] *******************************
89FAILED - RETRYING: [localhost]: Wait for instance(s) deletion to complete (300 retries left).
90changed: [localhost] => (item=instance)
91
92PLAY RECAP *********************************************************************
93localhost                  : ok=3    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

Tada! You’ve just tested an Ansible playbook with Molecule! โœจ๐ŸŽ‰

We now have peace of mind that our playbook works as expected! :slight_smile:

Conclusion ๐Ÿ“

In this blog post, we covered the basics of using Molecule and how to test Ansible content. I recommend checking out the Molecule documentation for more information.

I hope you found this post useful and if you have any questions or feedback, feel free to reach out to me on Twitter or via email.

Until next time, happy testing! ๐Ÿงช 👋

References

<< Previous Post

|

Next Post >>

#Ansible #Testing #Molecule