I initially discovered test kitchen through Chef, but having worked in many different DevOps environments have found that although popular in Chef has been adapted to work with Puppet, albeit with some minor configuration.
The handy thing about test kitchen is the ability to switch environments, e.g. from Vagrant to AWS EC2, etc for being able to start up and perform server testing on virtual nodes. It also makes the use of Rake easier since you don't have to worry about the configuration of the Rakefile, or VM files, e.g. Vagrantfile. All configuration is made in the .kitchen.yml file, and inside a fixtures directory to inform Kitchen where the dependent modules and the module to test are.
The project directory;
The above diagram shows how the .kitchen.yml file maps to the directory structure of our project. Since we are serverspec testing we are less interested in the code, but need access to the configuration management environment so that Kitchen can provision the nodes we require.
This example shows only 1 test suite, called default, which has a corresponding directory in the
test/integration directory. Each test
suite is named and associated to particular nodes. As part of the
suites section you can target specific tests to specific hosts by adding a
driver section and
vm_hostname as per the below example;
suites:
- name: web
mainfests: site.pp
driver:
vm_hostname: web1.tps-services.ltd.uk
- name: database
manifests: site.pp
driver:
vm_hostname: db1.tps-services.ltd.uk
Each test in this example makes use of the site.pp, which contains node definitions such as;
node /^web/ {
}
node /^db/ {
}
These will then be picked up and the Puppet configuration applied.
The
web and
database suite names will then have corresponding directories in the
test/integration directory.
Each test suite then has a serverspec directory containing a spec_helper.rb and hostname, IP addres or localhost directories which will contain the tests relevant to each host. For Kitchen tests only localhost would be required.
Preparing for serverspec testing
To create the test/integration layout you should make use of the kitchen init command. To do this you will need to run the following commands;
- bundle init
- This will create a Gemfile for you
- echo -e "test-kitchen\nkitchen-puppet" >>Gemfile
- Add the test kitchen tools to the project Gemfile
- bundle install
- Will install kitchen into your environment
Once kitchen is installed you can then create the directory structure using;
- kitchen init
- Creates the relevant directory and files for kitchen test in your project
- This would include .kitchen.yml and all kitchen files
- This should be done at the root of your Puppet environment, e.g. where the manifests and modules directory would show in a listing.
- bundle install
- This is done again to ensure we have all the necessary modules
The .kitchen.yml file
The core file for defining the configuration of Kitchen to build, provision and test VMs is done in the file called .kitchen.yml
The driver section defines the VM platform you will be using, so possible to have automated testing systems build and test our provisioning for us. The provisioner part tells the system how we will be provisioning, e.g. Puppet, Ansible, Chef, etc. The platforms defines the type of VM image that will be required and its configuration to the driver software, and the suites are where the starting point of the provisioner are and also any testing.
Example file using Vagrant:
---
driver:
name: vagrant
provisioner:
name: puppet_apply
manifests_path: manifests
modules_path: modules
hierdata_path: hierdata
require_puppet_collections: true
puppet_yum_collections_repo: https://yum.puppetlabs.com/puppetlabs-release-pc1-el-7.noarch.rpm
# See - https://github.com/neillturner/kitchen-puppet/blob/master/provisioner_options.md for more options
platforms:
- name: centos-7.2
driver_plugin: vagrant
driver_config:
box: bento/centos-7.2
verifier:
ruby_bindir: '/usr/bin/'
suites:
- name: default
manifests: site.pp
driver:
vm_hostname: web1.tps-services.ltd.uk
The .kitchen.yml file should be at the root of your environment directory that you wish to perform tests in.
Example file using AWS ec2
---
driver:
name: ec2
aws_ssh_key_id: steveshilling
region: eu-west-2
availability_zone: b
instance_type: t2.micro
iam_profile_name: ee_kitchen
security_group_ids: ["sg-6d30b304"]
provisioner:
name: puppet_apply
manifests_path: manifests
modules_path: modules
hierdata_path: hierdata
platforms:
- name: centos-7.2
driver:
image_id: ami-9c363cf8
transport:
username: ec2-user
ssh_key: ~/.ssh/id_rsa
verifier:
ruby_bindir: '/usr/bin/'
suites:
- name: default
manifests: site.pp
driver:
vm_hostname: web1.tps-services.ltd.uk
Adding the serverspec test directory
To be able to write your serverspec tests, you could create the directory structure and files yourself, or you could create the initial structure as follows, and then add the rest of your files.
- /opt/puppetlabs/puppet/bin/gem install serverspec
Note that we are using the Puppet gem command not the system one, since we want this to work with Puppet.
The command that will create the initial test directory structure and the spec_helper.rb file for a host. When you run this command you will be asked whether you are testing local or SSH. For kitchen you can chose local.
This will generate a spec_helper.rb file under test/integration/default/localhost which will contain;
require 'serverspec'
set :backend, :exec
After running this command you will have the following structure;
test
└── integration
└── default
└── serverspec
├── localhost
| └── sample_spec.rb
└── spec_helper.rb
You can now write your serverspec tests under the localhost directory, and create further directories based on the name of your tests. The sample_spec.rb is an example set of tests, so you would define files based on the types of test you wish to carry out, to which you may have multiple files in the localhost folder.
Example serverspec test file
require 'spec_helper'
describe package('nginx') do
it { should be_installed }
end
describe service('nginx') do
it { should be_enabled }
it { should be_running }
end
describe port(80) do
it { should be_listening }
end
Running your tests
Once you have your tests ready you can perform a test run by typing;
This will build the VMs, run the configuration management and then the serverspec tests for each suite. If you have dependencies on other VMs being built then you should order the
suites section correctly, since it is sequential. If your web nodes rely on a database node, then the database node should be in the list first and tested.
If all tests complete successfully then the VMs will all be destroyed. If there is a failure then those VMs that have completed their testing will still be running, including the one that failed. To remove the VMs simply run;
If you only want to build and configure VMs but not test then you can run;