Testing Ansible playbooks on localhost

How to develop and test Ansible playbooks on your local machine with Docker and some shell scripting.

Zakhar Shapurau
Xeneta
Published in
3 min readNov 2, 2016

--

Ansible playbooks are an extremely powerful tool for managing complex multi-server setups. But when you are developing playbooks, you can not just run them towards your production environment to test them.

In this article we present a method for testing playbooks locally with Docker containers as targets.

Overview

We are going to create several Docker containers and use them as Ansible targets.

We will also alias IP addresses to the loopback interface and expose container SSH ports on those. This is mostly a workaround for macOS because it does not have Docker network interface.

Structure

The setup fits into one folder with a few files, and Docker is the only requirement apart from Ansible.

Test inventory

In the dev/inventory file we put the Ansible hosts config with *.ans.local hostnames. This is how it looks in our setup:

When dev/test.sh is run, we first parse the test inventory file to get hostnames of test targets.

Docker interface workaround for macOS

Docker on macOS does not have docker0 interface, so you can not access containers via the network from the host without exposing their ports on host IP.

We could expose SSH on 127.0.0.1 with different port for each container, but Ansible does not see the difference between 127.0.0.1:1234 and 127.0.0.1:5555, so we still need unique hostnames. Another problem with using different ports is that it complicates the Ansible run configuration - we would have to set ansible_port for each target.

To circumvent these limitations, we alias IP addresses to the loopback interface for each hostname from dev/inventory and put the hostname for the alias in /etc/hosts. This way we get unique IP addresses, unique hostnames for Ansible, and the same exposed SSH port on each container.

Test containers

We build the Docker image with SSH server and our public test key in it.

Now we can start the Docker containers for each test target. We are going to assign hostname as a name of container to reference them easily when needed. We are exposing port 22 on the corresponding aliased IP in each container.

Running Ansible

Now we are all set to run our Ansible playbook towards the test targets.

Cleaning up

After Ansible is done, we remove the IP aliases from the loopback interface and test target hostnames from /etc/hosts.

Demo project

I made a demo project that illustrates the approach described in this article. It contains a simple Ansible playbook and setup for testing it locally. You can clone it and follow instructions in README to try it out.

The demo project can be found here: https://github.com/xeneta/ansible-local-dev

Using Linux?

Everything is much easier. You can skip IP setup and cleanup steps, and instead map hostnames to Docker container IP addresses on docker0 interface - you can find them with docker inspect.

ifconfig is deprecated on Linux now: you can use ip link to add and remove alias IP addresses instead.

--

--