Setting up Puppet module testing from scratch: Part III, Travis CI

In Parts I & II we have looked at setting up Puppet-syntax, Puppet-lint, Rspec-puppet, and Beaker. In today’s post we look at how to automatically run these tests in the Travis CI build pipeline.

Note that Travis CI is only freely available for open source projects.  If it’s the paid-for service you need, consult their pricing plan, or perhaps look at other options like Jenkins.

I must thank Mark McKinstry for showing me how to do this when he sent in a pull request to add the Travis CI configuration to one of my own Puppet Modules. One of the wonderful things about maintaining open source projects is that people sometimes turn up randomly and teach you things, and that’s what happened here.

Anyhow, let’s begin.

Setting up Travis CI

Changes to Gemfile

One of the advantages of using Travis CI is that it is easy to test Puppet modules against a matrix of Ruby and Puppet versions. This is a great advantage when maintaining a Puppet Forge module, as it allows us to easily test and advertise the versions of Puppet that we support, and we can ensure that our module is also tested against the standard set of Ruby versions.

But in order to test against different Puppet versions, our Gemfile needs to be modified to accept the Puppet Gem version as a variable.

Here’s what we’re going to do. We’ll delete the line …

gem 'puppet'

… and replace it with a block:

if puppetversion = ENV['PUPPET_GEM_VERSION'] gem 'puppet', puppetversion, :require => false else gem 'puppet', :require => false end read more

Setting up Puppet module testing from scratch: Part II, Beaker for module testing

In our previous post we covered the py_puppetlabs_spec_helper, a kind of front-end to a bunch of tools including puppet-syntax, puppet-lint, and rspec-puppet.

Today we will be looking at how to set up the Beaker framework for module testing. Beaker is the Puppet community’s preferred acceptance test harness.

Before proceeding, I must call out some of the materials that I found useful when I learnt Beaker, especially Liam J. Bennett’s great three part series, Testing puppet with Beaker, Part 2: the Windows Story, and Part 3: testing roles.  There is also a great 1-hour presentation by Puppet’s David Schmidt online here, which covers a lot of the material we look at in this post and in the previous post (the Beaker-related material starts at around 40 minutes).

Once again, my focus is on helping new people to quickly stand up the Beaker framework, while assuming as little as possible by way of Ruby and any other prior knowledge; I am less concerned about writing a proper tutorial on writing Beaker and Serverspec tests.  And as before, I use the real life example throughout of the Spacewalk module we are developing.

Let’s dive right into it.

Installing and configuring Beaker

Prerequisites

To get started, we’ll need to ensure we have our prerequisites installed. In addition to Ruby Gems and Bundler, which were discussed in Part I, we’ll also need to install Vagrant.  I assume that my readers have used Vagrant before; if not, it’s well worth spending 15 minutes doing the Vagrant tutorial.

Otherwise, let’s continue.

Gemfile additions

As we discussed in Part I, the Gemfile is a file that specifies Ruby dependencies to be installed in our ‘bundle’ by Bundler, a Ruby app that manages dependencies in Ruby projects.

To install Beaker, we will add a new system testing Gem group to the Gemfile:

group :system_tests do gem 'beaker', :require => false gem 'beaker-rspec', :require => false gem 'beaker-puppet_install_helper', :require => false end read more

Setting up Puppet module testing from scratch: Part I, Puppet-syntax, Puppet-lint and Rspec-puppet

It was brought to my attention that there’s demand for a post on how to set up Beaker from scratch. Then, after looking into it, I realised there’s a case for a whole series on how to set up Puppet modules as well as Puppet roles & profiles for testing.

In this series I am going to look at setting up all of the following components for Puppet module testing: Puppetlabs_spec_helper, Puppet-syntax, Puppet-lint, and Rspec-puppet (this post); Beaker for modules (part II); Travis CI (part III), Puppet Blacksmith and additional set up required for publishing your module on the Forge (part IV); and using ModuleSync to keep all of this set up in sync when you support many modules or code bases (part V).

My aim is not to provide tutorials on how to write Rspec or Rspec-puppet or Beaker tests; there are many of those out there already. My focus is simply how to set up the various frameworks, assuming no prior knowledge from the reader.

Example module

By way of example, we will look at adding the testing of the puppet-spacewalk module that my colleague is working on.  As such, this is a real-life example.

The puppetlabs_spec_helper

It makes sense to begin with the puppetlabs_spec_helper gem, a wrapper around quite a number of other tools, including:

  • Puppet-syntax
  • Puppet-lint
  • Rspec-puppet

And many others.

Prerequisites

To install and configure up the puppetlabs_spec_helper gem we need to firstly have RubyGems, and Bundler installed.  This is well-documented in the links provided.  Once these are installed you should find these commands in your path:

$ bundler -v Bundler version 1.10.5 $ gem -v 2.0.14 read more

Speeding up Beaker on a Mac using SquidMan

Update: Thanks to Steven Bambling for pointing out that SquidMan is also available as a Homebrew Cask.

If you have used Beaker extensively for system testing your Puppet roles and profiles, you will have no doubt had some coffees while waiting for RPMs to download that you may well have downloaded before.

I was pleasantly surprised to find that setting up a Squid Cache using SquidMan on my Mac OS X Yosemite laptop and then having Beaker point at it was fairly straightforward. Still, there are a few gotchas to justify a blog post on the subject.

Thanks go to Alexander Rumyantsev for his post on Using squid to cache RedHat/CentOS yum repositories, and also to My Private Network for their post on Setting up Squid Man.

Installing and configuring SquidMan

I downloaded SquidMan 3.6 from here, and installed as with any other DMG file (although, to be sure, I had to manually drag and drop the app into my /Applications folder).

Having started I went to its Preferences and entered the following config:

Screen Shot 2016-04-27 at 12.13.11 am

 

That is, I set the port to 3128, increased the maximum object size to 256MB in case I need to deal with large RPMs, and set the cache size to 4GB, and then I went to the Clients tab:

Screen Shot 2016-04-25 at 8.28.37 pm

And here I allowed Beaker to connect from whatever network it happens to be on, i.e. all. (Limit that as your needs for security dictate.)  (If you forget this step, Beaker will error out during a Yum install with a 403 Forbidden error.)

After starting Squid, you can find its config file using:

$ ps -ef |grep squid 501 2955 1 0 8:17pm ?? 0:03.64 /Applications/SquidMan.app/Contents/Ma cOS/SquidMan 501 7283 1 0 8:28pm ?? 0:00.00 /usr/local/squid/sbin/squid -f /Users/ alexharvey/Library/Preferences/squid.conf 501 7285 7283 0 8:28pm ?? 0:00.08 (squid-1) -f /Users/alexharvey/Library /Preferences/squid.conf 501 13310 96095 0 8:43pm ttys003 0:00.00 grep squid read more

Rspec testing a simple Ruby script

While writing a simple Ruby script recently, I discovered that it is difficult to find any internet documentation that discusses the simplest use-case for Rspec, namely to test a short, simple Ruby script. By that I mean a script that has methods, but no classes.  This post intends to fill that gap.

Following along

If you’d like to follow along with the code, you can clone this repo. Note that I have added tags so that you can checkout the code in stages that will closely follow the examples in the text. Where I say, “checkout 0.0.1” in the text, I mean run a

$ git checkout 0.0.1

and you’ll have the code matching where you’re up to in the text.

Project structure

To begin (checkout 0.0.1) we create a new project that illustrates expected file locations.

$ mkdir example $ cd example $ mkdir bin spec read more

Building a highly available ELK solution with Puppet, Part III: Elasticsearch backend

NOTE: this series is a work-in-progress that will be finished in due course.  I leave it up here because the code and approach is likely to be nonetheless useful to people engaged in building a similar ELK / Puppet solution.

Introduction

Elasticsearch is a Java-based open-source search engine built on top of Apache Lucene, and released under the terms of the Apache license. It provides a distributed, multitenant-capable search engine behind a convenient RESTful JSON API. Today, it is the most popular enterprise search engine in the world.

In this third part of our series, ‘Building a highly available ELK solution with Puppet’, we look at how to build an Elasticsearch 2.2 cluster using the latest Elasticsearch, the latest Puppet 4, and the latest Elastic.co Elasticsearch Puppet module.

Here we look at the profiles profile::jdk, profile::elasticsearch, and profile::elasticsearch::data_node. We will discuss Hiera data for a single-node and clustered configuration. This will involve configuring Yum; installing the JDK; managing the elasticsearch user and group; configuring an LVM volume for Elasticsearch data; installing and configuring the Elasticsearch application; and configuring the firewall. We will discuss in passing some of our views on Puppet programming best practices, and justify some of the choices we have made.

Puppetfile configuration

We add the following modules to our Puppetfile for the Elasticsearch cluster:

forge 'https://forgeapi.puppetlabs.com' mod 'thias/sysctl', :git => 'https://github.com/thias/puppet-sysctl.git' mod 'elasticsearch/elasticsearch', :git => 'https://github.com/elastic/puppet-elasticsearch.git' ... read more

Building a highly available ELK solution with Puppet, Part II: The base profile

NOTE: this series is a work-in-progress that will be finished in due course.  I leave it up here because the code and approach is likely to be nonetheless useful to people engaged in building a similar ELK / Puppet solution.

Introduction

In this second part of our series, ‘Building a highly available ELK solution with Puppet’, we look at our example base profile.

The example is artificially simple, and provides an illustration of the concepts for readers who are new to the roles and profiles pattern, and allows me to make some general points about writing roles and profiles that inform my decisions in subsequent ELK-related posts. Most readers will already have their own base profile, and if not, will probably have requirements that go beyond this contrived example.

If you are already familiar with the roles and profiles pattern, you may want to read the section about the yum configuration, and you may be interested in the firewall_multi module.

As mentioned in part I, the source code is available at Github. It is licensed under the MIT license.

Configuring the Puppetfile

Before we can write the base profile we need to install the Puppet Forge modules that it will depend upon, and to do that, we must set up our Puppetfile. If you have not used a Puppetfile before, have a look at the documentation here.

Why Librarian-puppet

It should be noted that I am using Tim Sharpe’s Librarian-puppet, the original Puppetfile processor and, in my opinion, still the best. Many users will be using r10k both to install modules as specified in Puppetfile, and also to deploy their code into target environments. Meanwhile, Puppet Enterprise users may be using Code Manager, which uses r10k under the hood.

The advantage of Librarian-puppet is that it is simpler, and it resolves dependencies. And if you, like me, intend to deploy your code onto Puppet Masters using the deployment capabilities of your CI/CD system, you may find that Librarian-puppet is still the right choice.

Puppetfile config for base profile

Our base profile requires the following modules:

We therefore add the following lines to our Puppetfile (source code):

forge 'https://forgeapi.puppetlabs.com' mod 'puppetlabs/stdlib' mod 'puppetlabs/ntp' mod 'alexharvey/firewall_multi' read more

Dumping the catalog in rspec-puppet

I always knew there was a better way.

In a previous post I documented a procedure for compiling a catalog without logging onto a Puppet Master.  The procedure is useful but also complicated.

Some would ask, why can’t Rspec-puppet just dump the catalogs it compiles during unit testing?

It can; I just found a bit of the answer here, and the rest of it inside a debugger.

How to dump the catalog in Rspec-puppet

I assume we have Rspec-puppet set up already.  If not, try the Rspec-puppet tutorial.

Imagine we have a simple test as follows:

require 'spec_helper' describe 'myclass' do it { is_expected.to compile.with_all_deps } end read more

Parallelising rspec-puppet

I recently migrated a client away from Andrew Cunningham’s puppet-validator – an open source project that simply compiles catalogs based on configurable fact values – to rspec-puppet.

The advantages of rspec-puppet are many and, obviously, being able to do more than just compile catalogs is one advantage.  However, Andrew’s project also had some advantages; in particular it used threads to parallelise catalog compilation.  This meant that some 100 catalogs could be compiled and tested on my 8 CPU-core laptop in less than 3 minutes.  After setting up rspec-puppet, however, I found that the same tests were now taking over 20 minutes.

It seems to me that the Puppet community has thus far tolerated rspec-puppet’s slowness.  To illustrate, I’ll focus in this post on the very mature Puppet Labs Apache module and show how parallelising its rspec-puppet tests by setting up Michael Grosser’s parallel_tests would get the current execution time of about 30 minutes (on my laptop) down to under three.

Running the rspec tests in puppetlabs/apache

To get started, let’s clone the puppetlabs/apache module:

$ cd /tmp $ git clone https://github.com/puppetlabs/puppetlabs-apache.git read more