Over the last few years I have written a number of Ansible roles that I have published on Galaxy. When I wrote them, I followed the Jeff Geerling’s pattern for testing ansible roles with Travis CI so that I could put a badge in Galaxy that they were working. When I was introduced to Molecule earlier this year, I decided to migrate my current roles to use molecule as the testing framework. It has a lot more features available to it, including being able to actually test it before you check it in, not afterwards like with the Travis CI setup.

Initialize the Scenario

Since the role already exists, we need to initialize a scenario with Molecule, rather than a role (which does essentially the same think as ansible-galaxy init does). So the first step is to check out the role from source control.

git clone git@github.com:austincloudguru/ansible-role-splunk-forwarder.git

Once the code is checked out, you need to change directories into the role and run the  molecule init scenario command to create the molecule scenario.

cd ansible-role-splunk-forwarder
molecule init scenario —scenario-name default —role-name ansible-role-splunk-forwarder -d docker

This will create the scaffolding for molecule inside the role using docker as the default driver. There are multiple drivers and you can have multiple scenarios. I have one set of roles that includes docker as the default, but also can be tested in scenarios configured with AWS and GCP (this can be useful since each cloud provider image can have different packages and settings).

Configuring Molecule

For all the roles that I create, I make some changes to the default Molecule files. I add a yamllint.yml file that contains the following to make some changes to the default yamllint settings.

---
extends: default
rules:
  line-length:
  max: 120
  level: warning
  truthy: disable

I also update the dockerfile.j2 file and add some additional packages (iproute2 systemd unzip) to the apt-get blocks. This allows me to pull down base images directly from providers (ubuntu, centos) instead of building my own base images and then having molecule build on top of them.

#ubuntu
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates iproute2 systemd unzip && apt-get clean; \

Finally, I update the molecule.yml file to use the yamllint.yml file and configure the docker containers (platforms) that I want to run the molecule tests against.

---
dependency:
  name: galaxy
driver:
  name: docker
lint:
  name: yamllint
  options:
  config-file: molecule/default/yamllint.yml
platforms:
  - name: ubuntu-18.04
  image: ubuntu:18.04
  privileged: True
  command: /sbin/init
  - name: centos-7
  image: centos:7
  privileged: True
  command: /sbin/init
provisioner:
  name: ansible
  lint:
  name: ansible-lint
scenario:
  name: default
verifier:
  name: testinfra
  lint:
  name: flake8

Running Tests

Before you run your first full test of the role, I suggest you run molecule lint to make sure everything passes. This will allow you to quickly see the issues without having to scroll back up. Once you have validated that the linting is good, you can run `molecule test</code> and see if you have any other errors or issues around idempotence.

You can also add some additional tests in the test_default.py file that you can run after the ansible is complete. The following validates that the user and group is setup and that the service is enabled and running.

import os

import testinfra.utils.ansible_runner

testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
  os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')


def test_splunk_group_exists(host):
  splunk_group = host.group("splunk")
  assert splunk_group.exists


def test_splunk_user_exists(host):
  splunk_user = host.user("splunk")
  assert splunk_user.exists


def test_splunk_is_running(host):
  splunk_service = host.service('splunkd')
  assert splunk_service.is_running
  assert splunk_service.is_enabled

Continuous Integration

If you would like to still test the role with TravisCI or be able to post back to Ansible Galaxy that the build is passing, you can run the Molecule tests via TravisCI by replacing your current .travis.yml file with the following.

---
sudo: required
language: python
cache: pip

branches:
  only:
  - master
services:
  - docker
before_install:
  - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
  - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
  - sudo apt-get update
  - sudo apt-get -y install docker-ce
install:
  - pip install molecule docker
script:
  - molecule test

notifications:
  webhooks: https://galaxy.ansible.com/api/v1/notifications/

That’s all there is to it. Now you can run the molecule test command locally prior to checking in your code to validate that it works properly as well as have it run in TravisCI so that it can update the status on Ansible Galaxy.