When you want to test the integration of your snowflake data into your environments you should consider KitchenCI.

You should understand Test Driven Development with RSpec and Chef to such a degree that you have exhausted it as a resource. In that post we created a set of acceptance criteria and tests that support a user generating a file at a specific location containing a specific string of text. We are at a state where we can rely on the mechanics of the recipe … we know we can pass a string and have it show up in the intended file.

These RSpec tests provide assertions against generic data that we don’t want in production. When it comes time to validate the data that you will be using in a production or staging environment you hit scenarios where the data is unique per environment. These are our data separation principles in action. We can build seemingly unique environments simply by replacing data into the consistent structure. Test Kitchen helps us tremendously with these tasks.

Create a Test

The integration tests get stored in a slightly different location than the tests we wrote previously. A good first step is creating a spec helper file at test/integration/slogan/serverspec/spec_helper.rb. Executing the command serverspec-init generates the content of the file for us.

require 'serverspec'

include SpecInfra::Helper::Exec
include SpecInfra::Helper::DetectOS

RSpec.configure do |c|
    require 'highline/import'
    c.sudo_password = ask("Enter sudo password: ") { |q| q.echo = false }
    c.sudo_password = ENV['SUDO_PASSWORD']

With the helper file in place, we can now address the previous two assertions.


As a result, we want to ensure the new tests that we add are unique in focus. Most code will travel through multiple environments like development, qa, staging, production etc. Our next test will be the equivallent of “Writes the slogan file to my development location.” The test is saved as test/integration/slogan/serverspec/slogan_spec.rb.

require 'spec_helper'

describe file('/etc/development_slogan') do
  it { should be_file }


Kitchen Testing Suites

KitchenCI contains testing suites, which are a collection of meta data specific to that test. It has several ways of exposing data to your tests that can include the use of roles, data bags that can tie into your production chef servers or directly through json in a .kitchen.yml file. This functionality helps distributed teams work intelligently by integrating tightly with “real” data.

The data integration is why we are here, but let’s start with the basics and get to a state where we can run our failing test. Add the following to .kitchen.yml.

require 'spec_helper'
  - name: slogan
      - recipe[nmdbase::slogan]
    attributes: {
      "nmdbase": {
        "slogan": {
          "path": "/etc/development_slogan"


Executing kitchen list shows us that the slogan suite is now available:

$ bundle exec kitchen list
Instance                 Driver   Provisioner  Last Action
slogan-ubuntu-1204       Vagrant  ChefSolo     
default-ubuntu-1204      Vagrant  ChefSolo     
ldap-ubuntu-1204         Vagrant  ChefSolo     
yubico-ubuntu-1204       Vagrant  ChefSolo     
yubico-ldap-ubuntu-1204  Vagrant  ChefSolo     


Kitchen Converge


When Kitchen performs a converge, it gathers all of your latest code, cookbooks, data, etc and creates a vagrant instance for each suite specified that has this information available to chef. It tells chef to perform a client run and configure the VM accordingly. Executing kitchen commands directly will leave the instance running for you to access. Executing kitchen commands from Rake will destroy the instance making it a suitable approach for continuous integration efforts. If you are familiar with vagrant, this is the equivalent of a vagrant up followed by a vagrant provision.

$ bundle exec kitchen converge slogan-ubuntu-1204
-----> Starting Kitchen (v1.2.1)
-----> Converging ...
       Preparing files for transfer
       Resolving cookbook dependencies with Berkshelf 2.0.16...
       Removing non-cookbook files before transfer
       Transfering files to 
[2014-05-12T16:50:43+00:00] INFO: Forking chef instance to converge...
Starting Chef Client, version 11.10.4
[2014-05-12T16:50:43+00:00] INFO: *** Chef 11.10.4 ***
[2014-05-12T16:50:43+00:00] INFO: Chef-client pid: 20426
[2014-05-12T16:50:43+00:00] INFO: Setting the run_list to ["recipe[nmdbase::slogan]"] from JSON
[2014-05-12T16:50:43+00:00] INFO: Run List is [recipe[nmdbase::slogan]]
[2014-05-12T16:50:43+00:00] INFO: Run List expands to [nmdbase::slogan]
[2014-05-12T16:50:43+00:00] INFO: Starting Chef Run for slogan-ubuntu-1204
[2014-05-12T16:50:43+00:00] INFO: Running start handlers
[2014-05-12T16:50:43+00:00] INFO: Start handlers complete.
Compiling Cookbooks...
Converging 1 resources
Recipe: nmdbase::slogan
  * template[/etc/development_slogan] action create[2014-05-12T16:50:44+00:00] INFO: Processing template[/etc/development_slogan] action create (nmdbase::slogan line 21)
[2014-05-12T16:50:44+00:00] INFO: template[/etc/development_slogan] created file /etc/development_slogan

    - create new file /etc/development_slogan[2014-05-12T16:50:44+00:00] INFO: template[/etc/development_slogan] updated file contents /etc/development_slogan

    - update content in file /etc/development_slogan from none to 081034
        --- /etc/development_slogan 2014-05-12 16:50:44.040987721 +0000
        +++ /tmp/chef-rendered-template20140512-20426-16ghydx 2014-05-12 16:50:44.040987721 +0000
        @@ -1 +1,4 @@
        +# This file was generated by Chef for slogan-ubuntu-1204.vagrantup.com
        +# Do NOT modify this file by hand!
        +I am verifying variables are used properly.[2014-05-12T16:50:44+00:00] INFO: template[/etc/development_slogan] owner changed to 0
[2014-05-12T16:50:44+00:00] INFO: template[/etc/development_slogan] group changed to 0
[2014-05-12T16:50:44+00:00] INFO: template[/etc/development_slogan] mode changed to 644

    - change mode from '' to '0644'
    - change owner from '' to 'root'
    - change group from '' to 'root'

[2014-05-12T16:50:44+00:00] INFO: Chef Run complete in 0.101614243 seconds

Running handlers:
[2014-05-12T16:50:44+00:00] INFO: Running report handlers
Running handlers complete

[2014-05-12T16:50:44+00:00] INFO: Report handlers complete
Chef Client finished, 1/1 resources updated in 0.465135306 seconds
       Finished converging  (0m5.16s).
-----> Kitchen is finished. (0m6.23s)


Looking at kitchen list reflects the new status of this instance.

bundle exec kitchen list
Instance                 Driver   Provisioner  Last Action
slogan-ubuntu-1204       Vagrant  ChefSolo     Converged
default-ubuntu-1204      Vagrant  ChefSolo     
ldap-ubuntu-1204         Vagrant  ChefSolo     
yubico-ubuntu-1204       Vagrant  ChefSolo     
yubico-ldap-ubuntu-1204  Vagrant  ChefSolo     


At this point we have full access to the instance, as it is configured. We can log in and poke around to our hearts content. Being able to do this is a total distraction from our TDD approach, but it’s good to know that you have the option if you need it.

bundle exec kitchen login slogan-ubuntu-1204
Welcome to Ubuntu 12.04.4 LTS (GNU/Linux 3.11.0-15-generic i686)

 * Documentation:  https://help.ubuntu.com/
Last login: Mon May 12 16:52:54 2014 from

root@slogan-ubuntu-1204:/home/vagrant# ls -l /etc/development_slogan
-rw-r--r-- 1 root root 150 May 12 16:52 /etc/development_slogan


Kitchen Verify

Once the server is converged we can verify that it is configured the way we expect.

$ bundle exec kitchen verify slogan-ubuntu-1204
-----> Starting Kitchen (v1.2.1)
-----> Verifying ...
       Removing /tmp/busser/suites/serverspec
Uploading /tmp/busser/suites/serverspec/slogan_spec.rb (mode=0644)
Uploading /tmp/busser/suites/serverspec/spec_helper.rb (mode=0644)
-----> Running serverspec test suite
/opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/suites/serverspec/slogan_spec.rb --color --format documentation

File "/etc/development_slogan"
  should be file

Finished in 0.0327 seconds
1 example, 0 failures
       Finished verifying  (0m1.34s).
-----> Kitchen is finished. (0m2.39s)



This shows you how to work with your infrastructure from an integration perspective. The next step will continue on these concepts by introducing data_bags.

Let’s Create Something Great Together!

Our team is highly motivated and inventive thinkers and tinkerers — designers, developers, engineers & more.

Plan a Project

Hire Us

Join the Team

Work With Us