Automated Ansible Testing with Molecule
Infrastructure testing provides some challenges just because of the mere fact you are building machines and not just compiling code. To test Ansible, I used to run Ansible with
--list-tasks. For roles I would run local tests with Vagrant using the tests/ directory in the role. The tests had Ansible test itself with the uri module or other checks. This is ok for simple checks but can be cumbersome and time consuming as it doesn’t catch everything.
Molecule has made this very simple. Install Molecule with pip install molecule. Create your role with
molecule init --role-name role --driver-name driver. The current drivers are Docker, OpenStack, Vagrant, EC2, GCE, LXC, LXD, and a few others with Docker being the default. It’s not absolutely required to build the role with molecule init but it adds the molecule dir with default testing and the .yamllint file.
Rather than rewrite their documentation, I’ll just go through what I have set up to test my roles. Currently I’m using the Vagrant driver with a CentOS 7 box ( I don’t do much with non RHEL distros) and the libvirt provider for Vagrant. So here’s what my molecule/molecule.yml file looks like:
--- dependency: name: galaxy driver: name: vagrant provider: name: libvirt lint: name: yamllint platforms: - name: bind box: centos/7 provisioner: name: ansible lint: name: ansible-lint scenario: name: default verifier: name: testinfra options: sudo: True lint: name: flake8
Molecule also uses testinfra to run automated tests against the Vagrant box. Here’s a simple example to check a firewalld role:
import os import testinfra.utils.ansible_runner testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all') def test_firewall_installed(host): package = host.package("firewalld") assert package.is_installed def test_firewall_service(host): service = host.service("firewalld") assert service.is_running assert service.is_enabled def test_firewall_config(host): config = host.file("/etc/firewalld/zones/public.xml") assert config.exists assert config.contains('<service name="http"/>') assert config.contains('<service name="https"/>') assert config.contains('<service name="ssh"/>')
Testinfra will check that the package firewalld is installed, the service is running and enabled, and that the /etc/firewalld/zones/public.xml file contains the services defined.
To start your molecule testing you can run molecule test.
Here’s a video running this setup against a firewalld role: