Running test-kitchen with Docker

With some configurability, Docker is a great choice to test chef recipes in a cookbook. While there are a few small gotchas, I’ve marked my journey below. I configured this to work successfully on a set of existing cookbooks I inherited and the production instance they run on. Most of the following info involves spinning up a new cookbook and a boilerplate recipe, but the content I pulled directly from my solutions. Feel free to reach out to me on twitter about questions, corrections, or comments.

Pre-Setup

To start it’s expected you have the most recent version of these tools already installed on your workstation.

Setup

Start by generating a new cookbook

$ chef generate cookbook new-cookbook-name

This will generate a new directory named after the supplied cookbook name (or new-cookbook-name if you copy/pasted). You can enter this directory and poke around. It’s a bare cookbook with a default recipe that currently doesn’t do anything.

Next we’ll want to list our ruby dependencies into a Gemfile in our cookbooks.

Using test-kitchen as our testing harness we can utilize most kitchen settings. We specify kitchen-docker as a VM and kitchen-inspec as our testing framework. Using Docker keeps all results of the recipes from affecting our workstation and helps clean up sticky situations.

We’ll also want to specify the testing config in a .kitchen.yml file. (You might have to override an existing .kitchen.yml file!)

Next we need a recipe and a test for the recipe. The first snippet below is a source file for our recipe and the second is our default recipe. This is what we’ll be testing, and while it’s a silly, lightweight example, it gives us a clear use case.

# new-cookbook-name/files/default/log.sh#!/bin/bashecho"this is the log.sh"

# new-cookbook-name/test/recipes/default_test.rbdescribedirectory("/etc/testbook")doit{shouldexist}enddescribefile("/etc/testbook/log.sh")doit{shouldexist}its('content'){shouldmatch/echo "this is the log.sh"/}end

To wrap up the setup, we’ll install all ruby gems and create the kitchen. Be sure Docker is running locally.

$ bundle install
$ kitchen create

This will create a .kitchen directory in your cookbook. This directory can be ignored for now - it contains the definition of our VM, the connection keys to SSH in, and our logs.

Next up we’ll want to create the VM and run our defined commands in suites::run_list in the .kitchen.yml using converge.

$ kitchen converge

Once that’s complete, we’re ready to test the output of our recipes - the files they create or processes they start. We’ll use the verify command for this.