Test First Infrastructure Development (With Chef)

In this blog post and the next, we will build a simplistic test-driven infrastructure from environments to cookbooks involving different components of Chef.

Chef’s Recipe:

  1. Specify Environments
  2. Add Nodes to the Environments
  3. Write Platform Tests using Test Kitchen
  4. Write Server Tests Using ServerSpec
  5. Write Unit Tests Using ChefSpec
  6. Deploy on to the node and run System Tests

We will see Steps 1,2 and 3 in this post and the remaining steps in the next.

Step 0 – Set up Editor:

The below knife commands are going to create JSON files which need an editor to open. Please set the environment variable $EDITOR or add the below line to chef-repo/.chef/knife.rb. Please use the editor executable of your choice.

knife[:editor] = “/usr/bin/vi”


  • All knife command shoule be executed in chef-repo
  • Make sure the EDITOR variable is set to an editor of your choice. I used “/usr/bin/vi”.
  • Make sure the sticky bit on “/tmp” or “/temp” is set and these directories are writable.

Step 1 – Specify Environments:

Firstly, take a look at the environments in your Chef Server

knife environment list

Add a new environment dev.

knife environment create dev

A JSON file like below would be opened in the editor.

“name”: “dev”,
“description”: “Dev Environment”,
“cookbook_versions”: {
“json_class”: “Chef::Environment”,
“chef_type”: “environment”,
“default_attributes”: {
“override_attributes”: {

Fill in the values as above and save it.

Step 2 – Add nodes to the environment:

The next step is to create a node “all-in-one” and associate it with dev environment. The below command creates a node configuration and pushes it to Chef-Server.

knife node create all-in-one

A JSON file like below would open up in editor. Change the “chef_environment” attribute to “dev” and save the file.

“name”: “all-in-one”,
“chef_environment”: “dev”,
“normal”: {
“run_list”: [


Note: There is no need to write any tests at the environment level (To Verify Again).

Step 3 – Write Platform Tests using Test Kitchen:

Before we start coding the infrastructure, let us verify if we have all the test frameworks ready. We will use Test Kitchen for Platform Testing, ServerSpec for System testing and ChefSpec for Unit testing of cookbooks. All these three frameworks are provided by Chef out of the box. So, you can use them directly.

Test Kitchen is a Platform testing framework which integrates with ServerSpec. It essentially runs your tests across different machines and makes sure that the infrastructure developed works as expected. These machines can be configured with Test Kitchen through different driver plugins like Vagrant, Amazon EC2, Docker. The machine configuration is specified in “platforms” section in .kitchen.yml file. The test suites’ information is specified in “suites” section.

Let us start with writing some platform tests. As you can see, we are writing the tests top to bottom so that the inner layers of infrastructure could be developed as per the specifications.

Firstly, setup kitchen for our project with the below command.

kitchen init

The above command creates .kitchen.yml file and test/integration/default directory to hold tests.

We should now add the platforms we should be supporting for our mysql component. Assuming that we need to support our DB installation on both CentOS 6.4 and Ubuntu 12.0.4, let us go ahead and add the platforms.

In .kitchen.yml file, change the platforms section to

– name: ubuntu-12.04
box: ubuntu12.0.4
– name: centos-6.4
box: centos64

Note: Ensure that there are vagrant base box “ubuntu12.0.4” and “centos64” in your vagrant environment.

Now, we need to specify which infrastructure should be configured with the platforms. For this, use the suites section to specify the details.

– name: default
run_list: recipe[mysql::install]

The name “default” specifies the suite name in test/integration folder. “run_list” specifies the cookbooks that need to be installed. Please note that “provisioner” name is “chef_solo” which is a Chef mock server.

Let us now try to run the “kitchen setup”. This command which runs the configuration code against the platforms in their current state.

kitchen setup

This command should fail with the below output.

Cookbook mysql not found. If you’re loading mysql from another cookbook, make sure you configure the dependency in your metadata

… which is expected since we have not yet written “mysql” cookbook. Let us now go and add the cookbook. To add a cookbook, we will take the help of Berkshelf which can manage cookbook dependencies. (Berkshelf comes installed with Chef Development Kit) In chef-repo/cookbooks, run the below command.

berks cookbook mysql

The above command creates mysql directory with several files in it. Now, add an empty file install.rb in mysql/recipes and run “kitchen converge”

kitchen converge

The empty cookbook is executed against both the platforms CentOS 6.4 and Ubuntu 12.0.4 and the below output is given.

—–> Starting Kitchen (v1.2.1)
—–> Setting up <default-ubuntu-1204>…
Finished setting up <default-ubuntu-1204> (0m0.00s).
—–> Setting up <default-centos-64>…
Finished setting up <default-centos-64> (0m0.00s).
—–> Kitchen is finished. (0m0.40s)

We have successfully added platform test coverage to our test framework. We should now add System specification and unit specification which we will see in the next post.

Test First Infrastructure Development (With Chef)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s