One of the easiest ways to get started is by using Berkshelf but here is also where most of the problems come in - so I decided to write a blog post on it and do a presentation on my findings.
It might be easy to get berkshelf via chef-dk but that’s not much fun for few reasons: not a clear understanding how bits fit together, locked into a concrete version of berkshelf - things can start to break if updated on their own, not the latest, bleeding edge version by definition - which is not much fun.
Here it goes. To start we need latest stable ruby version (2.2.2 at the time of writing).
Now that we have berkshelf installed lets install virtualbox, vagrant and test-kitchen so that we can start writing infrastucture code.
Lets scaffold our cookbook called hello-infra
and pull in dependecies.
Lets change defaults to use chef-zero instead of chef-solo and use debian instead of ubuntu. Vagrant will work faster with debian than ubuntu since it’s server distro and less stuff comes with it pre-installed.
Test-kitchen comes with handy commands to see if we got the configuration right.
Lets create the box, converge and verify to make sure we have everything set up correctly and good to start writing infrastructure code.
The initial .kitchen.yml file should look like this:
To demonstrate test-kitchen lets build a simple nodejs app powered by supervisor and reverse proxied by nginx iteratively using TDD cycle. Lets create our first failing infrastructure test.
And run tests.
To make the test pass we need to make changes to these files.
Now after running kitchen converge the tests pass and nodejs is installed on server. We repeat these TDD steps for creating a simple hello-world nodejs app, installing nginx, and configuring supervisor service. The resulting file tree structure looks like this:
The contents of the test files are:
The contents of files are:
To demonstrate chefspec I’ve also added spec/default_spec.rb for recipe.
Chefspec can come in handy when testing combinations of data bags and commands running on multiple platforms, however I would only use them if something’s hard or takes very long time to test using integration tests. Integration tests give the most confidence and aren’t tied to implementation - verifies that implementation fulfils the contract. This makes implemtation easy to change without breaking tests.
All code commits for this example can be found on github presentation on slidshare and screencast on youtube.