Using Molecule for Test Driven Development of Ansible Roles

  • August 21, 2019

Continuous testing is a DevOps best practice that helps ensure code quality. It implies that code is tested early, often and automatically, helping create a culture of test-driven development (TDD) and continuous integration (CI). While today’s blog isn’t a deep dive into TDD, we lean on the description of Kent Beck, who is credited with developing the technique, as one that encourages simple design and inspires confidence. 

While DevOps teams often excel at enabling application teams with better testing, in a case of “the cobbler’s children have no shoes” the DevOps community largely lags in the testing of their own code assets. Yet, the increasing complexity of infrastructure, configuration, and jobs among other assets make this situation increasingly untenable. For example, one of the most critical code assets created by a DevOps team is their server configuration. It is usually complex as it handles multiple interdependencies and requires long testing cycles. Clearly, a lack of proper DevOps security testing and TDD can prevent DevOps teams from realizing their potential. 

Our CTO has a simple mantra, “make it easy to do the right thing and harder to do the wrong thing.” Employing this mantra, we created a templatized framework to create Ansible roles with testing built-in using Molecule. We share our learnings with you today in this blog post.

Ease Testing Of Ansible Roles with Molecule

Scenarios, Testinfra

Molecule is designed to help develop and test Ansible roles. Providing support for multiple testing scenarios and frameworks, it was little surprise when Ansible announced that it was officially adopting Molecule and Ansible-Lint to test Ansible roles. This adoption unites the Ansible open source community behind a single framework, unifying the efforts. Hence, using Molecule and TestInfra as the framework of choice for Flux7 was a no-brainer.

Molecule can create different scenarios. By creating different scenarios for different test cases, we can test our Ansible roles against various platforms with different tests. Each scenario has its own platform defined, so when we run the Molecule test, the scenario automatically handles the creation of the testbench, running the Ansible role, orchestrating the different tests, and cleanup. The testbench can be bare-metal, virtual, cloud, containers, or any existing infrastructure. Molecule provides a high level of flexibility within steps and allows us to skip steps as appropriate.

For more information, refer to the Molecule Documentation.

Create Standard Templates For Reuse with Cookiecutter

Cookiecutter is a command-line utility that creates projects from project templates. Cookiecutter templates use the templating system Jinja2 to replace or customize folder and file names, along with file content. You can use Cookiecutter either with a Git repository, with a folder, any branch, or even a Zip file. It takes the source directory tree and copies it to your new project. Using Jinja allows us to create templates that are easy to read (variable substitution on all fields marked with ) and a high degree of flexibility (Jinja supports programming constructs like ‘if’ and ‘for’). Molecule has built-in support for creating new Ansible roles using Cookiecutter, so the use of CookieCutter was a natural choice.

For more information, refer to the Cookiecutter Documentation.

Bring It All Together

With our bias to action, we started by refactoring two roles and creating a Cookiecutter template. The roles were for managing a sample Nginx application and Jenkins. As Jenkins is core to a lot of work we do and is critical to our infrastructure., be on the lookout for an upcoming blog post specific to Jenkins. (Subscribe to our blog below to make sure you don’t miss it.)

We created a Molecule scenario which is a self-contained directory that has everything required to test the role in a specific way. The default scenario is named default, and every role contains a default scenario. In addition to the default scenario, we also created run tests for:

  1. Docker (these tests are designed torun quickly)
  2. AWS (these tests reflect a high fidelity environment)
  3. Use existing (tests on existing infrastructure)

Scenarios themselves allow a lot of flexibility and can support multiple usage models. Molecule scenarios enable us to split the parts of our test suites into two types. 

  1. Scenario-Specific Files – Define very specific scenarios like infrastructure provider-specific configurations, ensuring they are placed in separate directories.
  2. Common Files – Define common files that stay the same across all scenarios. Flux7 test cases are the best example.
    From here, we translate a skeleton role with best practices including Molecule tests into a Cookiecutter template to make it easy to deploy these best practices. This itself is a Molecule best practice as Molecule has the functionality to create roles from built-in Cookiecutter templates, saving time while enforcing defined standards.

From here, we translate a skeleton role with best practices including Molecule tests into a Cookiecutter template to make it easy to deploy these best practices. This itself is a Molecule best practice as Molecule has the functionality to create roles from built-in Cookiecutter templates, saving time while enforcing defined standards.

Cookiecutter Templates Ansible Role

How to Run Tests

To run a specific scenario use:

$ molecule  lint -s ${scenario_name}

To run the default scenario use:

$ molecule  lint 

Running these tests gives an output. This is an example of a Docker Scenario:

Molecule Lint

You are also able to skip some of the stages by just adding comment lines (#) in those stages.

Scenario Ansible Role Molecule

For information on running Molecule with a different matrix, refer to the Molecule Matrix.

How to Create Future Roles

First, you must configure your Molecule setup.  

To initialize a new generic role with Molecule, use:

$ molecule init role -r ${role_name}

This will create the Ansible role directory structure along with a Molecule directory inside the skeleton with the default scenario.

However, if, like us, you want to pre-populate particular paths, scenarios, and best practices, we recommend creating a template repo and using that as the basis for the roles you create, e.g. using a command like: 

$ molecule init template –url

Benefit DevOps Engineers

The Flux7 TDD solution has several benefits to DevOps engineers: 

  • Less Time to Create – As there is no need to create Ansible roles from scratch, it takes less time to create Ansible roles.
  • Fully Automated with Best Practices – The process is now fully automated and roles are created automatically with best practices to save engineer’s time.
  • Less Time for Test – Tests are triggered from Jenkins so that whenever a user makes a code commit, a test gets triggered and scans for lint-related errors, checks functionalities and performs unit testing. Only after that can a pull request be passed for approval and merged to master.
  • Fully Customizable – This level of customization allows us to add many new features. 
  • Manage Multiple Environment Roles – It is easy to have your role run inside any type of virtual environment you need as Molecule works with VirtualBox, Docker, or even AWS EC2 instances.
  • No Need to Learn Best Practices – No prior knowledge of best practices is required as everything required for testing is available in one place in the framework.
  • Faster Feedback Cycle – With the Flux7 TDD, engineers get a fast feedback loop, quickly seeing if a change is successful or not. This allows you to quickly make additional changes, easily following the loop until you are satisfied with the outcome.
  • Prevents Code Bugs – As pre-commit hooks to check basic code errors are embedded, you get a warning and cannot push the code until errors are resolved. 
  • Security Updates – Ansible role development is more secure as third-party library or component updates are reflected.
  • Quick and Easy – Run only one command to test an Ansible role once it is ready.

Continuous testing is a DevOps best practice as it helps you evaluate code quality at every step, identifying problems early and ultimately speeding time to market. While TDD increases developer productivity, it places a strong emphasis on the tests you write to ensure that they identify what you expect from code. With Flux7’s Molecule Framework for testing Ansible roles,  you can improve the quality of your Ansible roles using best practices, while ensuring integration with your CI/CD processes. 

Interested in improving your TDD processes? Let us help. Reach out today:

Subscribe to our blog


Related Blog Posts