Serverspec testing a puppet module
Upon joining TeamQuest, I started finding places to make myself useful as fast as possible. One such place was adding integration tests to existing puppet modules. I have done this a lot for Chef in the past, using vagrant and/or test-kitchen.
It must be said, that any information, or opinions espoused here, is mine, not TeamQuest’s. This is a personal blog, and the information provided here is provided “AS IS”, with no warranties.
So here’s what I’ve got working.
Vagrantfile
- uses the vanilla
centos-6.7
bento box - installs puppet 3.8
- lands puppet module dependencies using this trick
- “installs” the module under test
- provisions the VM with a test manifest
- verifies the provision with serverspec tests
A few peculiarities
Serverspec from Windows to Linux
The fact that I wanted to test a CentOS box from a Windows local machine seemed to confound serverspec. I am writing this from a Mac, where it works as well, but I finally landed on using the Rakefile pattern generated by serverspec-init
to solve issues with CRLFs and EOFs. Now it handles connecting and running the tests over SSH.
Module naming and custom class definitions
In my module under test, I have a custom class called tqjenkins
. It wraps uses of the Puppet Forge hosted rtyler/jenkins
, so in order to not conflict, it has a unique name. But the module it is in, just like rtyler/jenkins
, isn’t named tqjenkins
, but is prefixed with the company name. So my module teamquest-tqjenkins
provides a class called tqjenkins
. You with me?
Well the puppet apply
provisioner in Vagrant doesn’t like this. It thinks I am just crazy, even though this is how puppet generates module layouts. It can’t find the class definition, and fails during puppet provision with the NoClassDefFoundError equivalent, of:
Error: Puppet::Parser::AST::Resource failed with error ArgumentError: Invalid resource type tqjenkins::production
To make a short story longer, shout out to Volcane in #puppet
on Freenode, he/she led me down this path. I saw that if I renamed my folder teamquest-tqjenkins
to just tqjenkins
, everything worked correctly, but that still didn’t feel good. So instead, I use a Vagrant synced_folder
to install the module, thus stripping the prefix. Voilà!
config.vm.synced_folder "teamquest-tqjenkins", "/etc/puppet/modules/tqjenkins"
Here is my Vagrantfile in entirety, in case you’re curious:
unless Vagrant.has_plugin?("vagrant-puppet-install")
raise "Plugin 'vagrant-puppet-install' is required.
Run 'vagrant plugin install vagrant-puppet-install'"
end
Vagrant.configure(2) do |config|
config.vm.box = "bento/centos-6.7"
# uses vagrant plugin vagrant-puppet-install
config.puppet_install.puppet_version = "3.8.3"
# install dependencies (go ahead, mock me copying this from the metadata)
# a better way to do this would be use something like librarian-puppet
config.vm.provision :shell do |shell|
shell.inline = "mkdir -p /etc/puppet/modules;
puppet module install puppetlabs-stdlib;
puppet module install rtyler/jenkins;
puppet module install puppetlabs/concat"
end
config.vm.network "forwarded_port", guest: 8080, host: 9090
# Because we're not "puppet module install" installing our module under test,
# we need to rename it on the VM so it looks like a typical module
config.vm.synced_folder "teamquest-tqjenkins", "/etc/puppet/modules/tqjenkins"
# provision jenkins with puppet
config.vm.hostname = "teamquest-tqjenkins.example.com"
config.vm.provision :puppet do |puppet|
puppet.manifest_file = "test.pp"
puppet.manifests_path = "test_manifests"
puppet.module_path = "./"
puppet.facter = { 'fqdn' => config.vm.hostname }
# You want more logs? this is how you get more logs
puppet.options = "--verbose --debug"
end
end
Leave a Comment