Cookbook development in a nutshell

There are many ways to setup a cookbook - knife cookbook create, berks init, etc. The problem is after that, you’ve also got to setup a whole suite of other tools to make sure your cookbooks are decent quality. These tools include rubocop, foodcritic, chefspec, test-kitchen, and more. Here’s a quick breakdown of the tools we use, and the order they should be used in:

Chefspec - Write your tests first. You’re unlikely to go back after you’ve written your cookbook to add tests, and it can help you stay a bit more organized if you outline it with tests first.

Rubocop/Foodcritic - These are both linting tools. Rubocop checks for ruby style plus complexity and a few other markers. Foodcritic checks specifically for cookbook style. Both these tools are useful for making sure your cookbooks are readable and that you are using proper syntax.

Chefspec - Now that you’ve written your cookbook (or at least part of it) and you’ve made sure it meets the style guidelines, you’ll want to run those tests you wrote earlier!

Test-kitchen - If those chefspec tests pass, you’ll run your cookbook through test-kitchen. This will actually spin up a virtual machine and run your cookbook. If chef converges properly, your cookbook is complete! In addition to running chef, test-kitchen has the ability to run other testing suites like bats, mini-test, Serverspec, etc. These are more ways for you to verify your cookbook’s output is what you are expecting.

We actually wrap these tools in another tool - Guard. Guard essentially just watches your cookbook directory for changes and then runs whatever you tell it to when a file changes. So we have it run rubocop, foodcritic, etc for us every time we make a change. That way if we make a mistake, it will alert us right away (normally through terminal output, but with some additional gems, you can get a growl/notification center alert).

So now that you’ve got all those tools set up for one cookbook, you’ve got to replicate them each time you make a new cookbook. We used to do this by hand - when we had a repo with working tools, we would copy and paste those configs to the new cookbook, and then manually change values as needed. We also had problems with older repos getting out of date - managing all these additional dependencies can be very difficult. That’s where kitchen-cabinet comes in.

cabinet is a tool that replaces knife cookbook create/berks init/etc. It creates a cookbook with all these tools already configured for you to use! You can also say cabinet update to update your old cookbooks.

So, you’ve got this cookbook now. How do you get it to your chef server? The simplest answer for our setup was berks upload, but that leads so some problems. Hopefully you have your cookbooks under some form of version control, so you have to remember to commit AND push to your chef server. If you have multiple people working on cookbooks, this can get messy. If someone pushes to the chef server but forgets to commit to git, the next person to clone the cookbook will have a hell of a time getting things to work properly.

In order to solve this problem, (and to ensure that our tests have been run/are passing) we put our cookbooks into Jenkins! We make changes (and write chefspec tests for our changes), bump the cookbook version, and then push to git. Our jenkins job watches for commits, and once it pulls up our new code it runs rubocop, foodcritic, and chefspec tests against it. If those tests are all successful, it does an automatic berks upload to our chef server!

Assuming that everything was successful, that cookbook is now available for chef to run on our nodes! From there, we simply need to iterate and update our cookbooks so they stay up to date. kitchen-cabinet helps by allowing us to keep our testing environment up to date in each cookbook.

And that’s about it, in a nutshell!

 
5
Kudos
 
5
Kudos

Now read this

Migrating User Home Folders

Today at work I developed a script to migrate users to a new home folder. This was done with automation in mind – every user will now have the same home folder name (but individual RealNames) so that scripts can be deployed without... Continue →