Mocking with rspec-puppet-utils

This post came out of a question that I answered at ask.puppet.com.

I decided to write some Rspec-puppet tests for a class that used the razorsedge/network module, and along the way decided to mock some of the functions that are normally delivered by it.

It was an excuse to try out Tom Poulton‘s rspec-puppet-utils project.

In this post I’m going to show how to use Tom’s project to mock functions; how to mock the Hiera function; how to test template logic; and also how to validate Hiera data directly.

If you’d like to follow along, I have this code at Github here.

The problem

In the example, the question that prompted me to set all this up involved use of the network::hiera interface of the razorsedge/network module.

So, we have the following class:

manifests/init.pp:

class profiles::network { include network::hiera } read more

Integration testing using Ansible and Test Kitchen

Introduction

I recently wrote a master-slave BIND 9 solution using Ansible and in this post I describe a multi-node integration testing approach for the solution using Test Kitchen and Neill Turner‘s Kitchen-Ansible extensions.

To be sure, Test Kitchen lacks proper support for multi-node integration testing, and its maintainers have explained the reasons for the lack of multi-node support in this thread here. Suffice to say, Puppet’s Beaker had multi-node support some five or six years ago, as did Puppet’s earlier, now retired, Rspec-system project.

This lack of multi-node support is, indeed, a quite serious limitation in an otherwise excellent framework. I am encouraged that the team has an issue open to track adding multi-node support here.

General approach

The aforementioned limitation aside, it is still possible to do rudimentary integration testing, as long as we tolerate a few manual steps and design our tests so that all testing on the first node can be completed before testing on the subsequent nodes begins.

In the case of my BIND 9 solution, this means that I’ll write one test suite for the DNS master, a second suite for the first DNS slave, and a third suite for the second DNS slave.  The first suite will prove that the DNS master has the BIND 9 packages installed, zone files and other files in place, that the BIND 9 service runs, and that name resolution works.  The second suite will prove that a DNS slave is build, and receives a zone transfer as soon as it comes online.  The third suite simply proves that more than one DNS slave can be handled by the solution.

The approach would fall short if we had a requirement, say, to add a new DNS record after the master was created, update its serial number, and see that all the slaves received the update.  But as I say, it’s a lot better than nothing.

I must acknowledge Maxim Chernyak for documenting the Kitchen hack that this work is based on.

BIND 9 solution

The Ansible role that we will be testing configures a simple BIND 9 system with a single master that is also a master for all of its zones, and one or more slaves that receive the zone tranfers and respond to recursive DNS queries.

The following figure shows the high-level architecture:

Screen Shot 2016-06-12 at 7.56.37 pm

Ansible role

The code for this solution is available online at Github here.  It’s not my intention here to discuss the Ansible code itself, except where it is relevant to the integration testing procedure.

Kitchen config

To learn more about my Kitchen config, please see my earlier post where I described the general config.

The .kitchen.yml file

The .kitchen.yml I have for the role is as follows:

--- driver: name: vagrant platforms: - name: centos-7.2 driver_plugin: vagrant driver_config: box: puppetlabs/centos-7.2-64-nocm provisioner: name: ansible_playbook hosts: test-kitchen ansible_verbose: false ansible_verbosity: 2 require_ansible_repo: false require_ansible_omnibus: true require_chef_for_busser: false verifier: name: serverspec bundler_path: '/usr/local/bin' rspec_path: '/usr/local/bin' suites: - name: master verifier: patterns: - roles/ansible-bind/test/integration/master/serverspec/master_spec.rb driver_config: network: - ['private_network', {ip: '10.0.0.10'}] - name: slave1 verifier: patterns: - roles/ansible-bind/test/integration/slave1/serverspec/slave1_spec.rb driver_config: network: - ['private_network', {ip: '10.0.0.11'}] - name: slave2 verifier: patterns: - roles/ansible-bind/test/integration/slave2/serverspec/slave2_spec.rb driver_config: network: - ['private_network', {ip: '10.0.0.12'}] read more