test-kitchen config hijinks part 1

In part 1 we will look at DRYing up chef zero configs for test-kitchen and chef cookbooks.

A few things become apparent while making test-kitchen work in all your chef cookbooks, there is a chuck of this which is repeated and would be best to do once and reference everywhere.

Most notably the chef zero environments, data bags, nodes, etc stubs you need to service cookbooks that search and use data bags and all do all the things. This is what we will look at here.

The ‘.kitchen.yml’ config file is not only yaml, its also parsed by a Ruby template engine. This lets us do interesting things.

First, we need a common place to refer to from all the test-kitchen configs, lets for example make a new Git repo for this task called ‘kitchen_shared’.

Inside kitchen_shared repo make a simple directroy structure.

kitchen_shared/
├── data_bags
│   └── users
├── environments
└── nodes

Now place inside those directories files representing the appropriate subject. Here are some examples:

# cat kitchen_shared/data_bags/users/bob.json
{
  "id"       : "bob",
  "comment"  : "Bob Smith",
  "action"   : "create",
  "ssh_keys" : [
    "ssh-rsa thiskeyiswaaaayshortAAAAB3NzaC1yc2EAAARCV/g9OK1Oc0X04DPV0MiECguZmH/FqS13 bob@foo.local"
  ],
  "password" : "wooooooosekret!"
}

$ cat kitchen_shared/environments/database.json
{
  "name": "database",
  "default_attributes": {
  },
  "json_class": "Chef::Environment",
  "description": "kitchen database env",
   "cookbook_versions": {
  },
  "chef_type": "environment"
}
$ cat kitchen_shared/nodes/database01.json
{
  "name": "database01",
  "chef_type": "node",
  "json_class": "Chef::Node",
  "chef_environment": "database",
  "run_list": [],
  "automatic": {
    "ipaddress": "1.1.1.1",
    "hostname": "database01"
  }
}

Thses match what you would get from knife if you did a show on a node or an environment etc. They aren’t special, they are legit configs that match whats in a real server, they are just loaded into chef zero instead.

Add the appropriate things for your needs, the above are just random examples.

The .kitchen.yml docs show how to reference locations for this info, but relative to the current path and for a typically local and unique to each cookbook set of data. Ex:

provisioner:
  name: chef_zero
  nodes_path: '../../nodes'
  data_bags_path: '../../data_bags'
  environments_path: '../../environments'

So now to share this we can start using the Ruby template-fu.

Add an environment variable which contains the path to where the kitchen_shared repo is checked out to your shell so its always set through whatever means appropriate, Ex:

$ echo "export kitchen_shared=~/repos/kitchen_shared" >> ~/.bash_profile
$ . .bash_profile

Now use that to reference the paths in the kitchen_shared repo from your .kitchen.yml like this:

provisioner:
  name: chef_zero
  nodes_path: '<%= ENV['kitchen_shared'] %>/nodes'
  data_bags_path: '<%= ENV['kitchen_shared'] %>/data_bags'
  environments_path: '<%= ENV['kitchen_shared'] %>/envs'

Update your cookbook creation procedure to include this as standard and your set.

Now you have one consistent and shared set of data to populate the test-kitchen chef zero servers. Make a change there, push the repo, and everyone working on chef as well as any CI/CD processes can track that repo and use and expand and be DRY.

More to come in part 2.

Leave a Reply