Chef cookbooks and kitchen

Everyone wants to install always the same software in a specified version and configuration on their system. This mostly works with a script, but at some point, no one could ever read this or can be executed only once.

At this point Chef comes into the game and fixes this issue.

Chef is a DSL, which easily describes a desired state configuration in a ruby way (Yes, ruby is the language behind Chef). Chef is working with cookbooks and can contain several recipes, which are doing different things. To test such cookbooks, Chef uses kitchen.

To give you some insights about Chef cookbooks and kitchen testing, you’ll move on reading.

Kitchen

Kitchen is a part of the ChefDK, which includes several kitchen-plugins like kitchen-ec2, kitchen-vagrant or kitchen-vcenter. The idea behind kitchen is to test cookbooks based upon their creation containing tests and a predefined run_list.

General

We’re going into the materials, but have to do some prerequesites to move on with the cookbook generation and kitchen testing. I will describe in a short way, how to install Docker and ChefDK and how we’re going to start over with a cookbook creation. Followed by an easy recipe, which contains a single resource we’ll start with a test against kitchen.

So lets start!

Prerequesites

To run your first cookbook in a kitchen node, you have to have some prerequesites:

  • Docker installed and running
  • ChefDK installed
  • a cookbook generated with some content (an easy file resource might help you out)
  • defined the run_list you want to run in .kitchen.yml
  • defined a driver, which you want to use

Download und Installation

Docker

Go to “Get Started” and choose the wished download package of docker and install it.

To test, if everything works fine, just run a docker ps. If you’re receiving an error, docker isn’t running.

If the command works fine, we have created our base for creating kitchen nodes.

Download and install ChefDK

The easiest way do have the ChefDK installed is, to download it directly from Chef, but brew would also work: Option 1: Go to downloads.chef.io and download the appropriate package and install it Option 2 (mac only): Open terminal and type brew cask install chef/chef/chefdk

Both are currently installing the latest stable version of ChefDK. My preferred way is to use Option 1, as I can always define the version, I’d like to use without any special versioning in the brew installation. It also happened, that the brew cask version was several versions behind the official one.

Create cookbook with some content

Okay, we’ve installed the latest version of the ChefDK. Now let’s create a cookbook and add an easy small resource to it.

chef generate cookbook kitchen_testing

Then go into the cookbook directory kitchen-testing/recipes and edit the default.rb recipe.

vim kitchen_testing/recipes/default.rb

Add the following code and save the file

file "/tmp/mykitchentest.md" do
  owner 'root'
  group 'root'
  mode '0755'
  content 'made for cooking'
end

Let’s take a deeper look into the driver section. The name defines the kitchen driver, which will be used. The official list of all drivers can be found here.

---
driver:
  name: vagrant

provisioner:
  name: chef_zero
  always_update_cookbooks: true

verifier:
  name: inspec

platforms:
  - name: ubuntu-16.04
  - name: centos-7

suites:
  - name: default
    run_list:
      - recipe[kitchen_test::default]
    verifier:
      inspec_tests:
        - test/integration/default
    attributes:

kitchen configuration

Let’s take a look into the configuration of kitchen. First of all, you should have a file named .kitchen.yml in your root directory of the cookbook. For now, it’s configured to use vagrant. We will change this to docker. Edit the file .kitchen.yml with your preferred editor.

---
driver:
  name: docker

To check, if our configuration is fine, just run kitchen list. It will print out a short list with

Instance             Driver  Provisioner  Verifier  Transport  Last Action    Last Error
default-ubuntu-1604  Docker  ChefZero     Inspec    Ssh        <Not Created>  <None>
default-centos-7     Docker  ChefZero     Inspec    Ssh        <Not Created>  <None>

This points us out, that we have one suite, which is named default and two different OS (Ubuntu 16.04 and CentOS 7).

We will create only the ubuntu machine. Run the command kitchen create ubuntu. This will only download and creating a docker container (the hint behind that command is, that it’s using some regex, which only detects Ubuntu 16.04 as correct instance). Now run kitchen login ubuntu. You’ll see, that you can login into your instance. Do a short ls -la /tmp and see, that the file ‘mykitchentest.md’ isn’t present.

Okay, logout from that machine and let’s start converging that newly created instance. Run kitchen converge ubuntu.

You’ll see, that the file /tmp/mykitchentest.md has changed. So our converging step worked.

kitchen destroy will remove all our containers, which we used some seconds ago (only those, which are registered to the specified cookbook in kitchen).

-> This is the regular way of running kitchen. If you want to learn more about the kitchen configuration, you’ll have to read some additional entries about kitchen advanced configuration, kitchen-vcenter and more in my blog, which will follow up in the next time. So we’re finished here ;)