Hello my dear friends. Today we will continue to talk about Chef. But today my article will be about Chef cookbooks by TDD. If you don’t know what is Chef and how to use it, then you should better start with my articles about it. All code examples you can find here: github.com/le0pard/chef-tdd-monit.
Chef testing tools
First, let’s look what tools exist to test Chef cookbooks today.
Foodcritic is a lint tool for your Opscode Chef cookbooks. Foodcritic has two goals:
To make it easier to flag problems in your Chef cookbooks that will cause Chef to blow up when you attempt to converge. This is about faster feedback. If you automate checks for common problems you can save a lot of time.
To encourage discussion within the Chef community on the more subjective stuff - what does a good cookbook look like? Opscode have avoided being overly prescriptive which by and large I think is a good thing. Having a set of rules to base discussion on helps drive out what we as a community think is good style.
On main site you can find list of rules. Also you can define own list of rules (if you need this). Foodcritic is like jslint for cookbooks. At the bare minimum, you should run foodcritic against all your cookbooks.
Ohai is a tool that is used to detect attributes on a node, and then provide these attributes to the chef-client at the start of every chef-client run. Ohai is required by the chef-client and must be present on a node. It’s awesome, but this can be problem for testing. What is why exist Fauxhai. Fauxhai is a gem for mocking out ohai data in your chef testing. Example:
ChefSpec is a unit testing framework for testing Chef cookbooks. ChefSpec makes it easy to write examples and get fast feedback on cookbook changes without the need for virtual machines or cloud servers. Example:
Cucumber-chef is a library of tools to enable the emerging discipline of infrastructure as code to practice test driven development. It provides a testing platform within which Cucumber tests can be run which provision virtual machines, configure them by applying the appropriate Chef roles to them, and then run acceptance and integration tests against the environment.
Chef Zero is a simple, easy-install, in-memory Chef server that can be useful for Chef Client testing and chef-solo-like tasks that require a full Chef Server. Because Chef Zero runs in memory, it’s super fast and lightweight. This makes it perfect for testing against a “real” Chef Server without mocking the entire Internet.
Enough words. Let’s start with the practice
First of all you should have installed Ruby and Rubygems. Let’s create monit cookbook by TDD. I generated structure of coobook by berkshelf:
Now we need to add gems in Gemfile, which we will use for testing:
And you should to execute “bundle” command to install this gems.
Using ChefSpec
First of all we should create tests for our monit cookbook:
File: spec/spec_helper.rb
File: spec/unit/recipes/default_spec.rb
Of course tests failed:
Let’s fix these tests by writing cookbook code:
File: attributes/default.rb
File: templates/default/monitrc.erb
File: recipes/default.rb
First test should pass:
Perfect! Let’s fix rest of the tests:
File: recipes/default.rb
And again I will check tests:
Ok, tests passed.
Checking by Foodcritic
Now we need to check our cookbook by foodcritic:
We have a few warnings in the code. Let’s fix them:
FC002: Avoid string interpolation where not required: ./templates/default/monitrc.erb:31
FC019: Access node attributes in a consistent manner: ./attributes/default.rb:8
Now I will show how to work with different operating systems. I will add such default attributes in our attributes :
And I will change tests:
Now we should fix tests in recipe:
And we again will check tests:
Working with Fauxhai
In default attributes we have such attribute:
where “fqdn” is attribute from ohai. Let’s check by Fauxhai is this attribute will work corrently. Add this test:
And run tests:
May be this example is not perfect for Fauxhai (because we couldn’t change “fqdn” using method “mock”), but this should help you to understand how you can use it.
Using test-kitchen, bats and minitest
Now let’s begin testing using test-kitchen. First we need to initialize it:
This command will create file “.kitchen.yml”, which contains all settings for test-kitchen:
About this setting you can read here this page. Let’s add integration tests. I use them for this bats:
It is not neccessary to use bats and minitests together in the same cookbook. I use both in this cookbook to show simple example.
Finaly, run command “kitchen test” to begin testing:
Of course my tests are not designed to work on different types of systems (on CentOS they will fail), my goal was to show how you can test environment after your cookbook. More about test-kitchen you can read here.
Summary
In this article I covered how to write Chef cookbook by TDD. Hope it will help you to write better cookbooks for Chef. All code examples you can find here: github.com/le0pard/chef-tdd-monit.
That’s all folks! Thank you for reading till the end.