Managing Cookbooks with Berkshelf - Reliably Deploying Rails Applications: Hassle free provisioning, reliable deployment (2014)

Reliably Deploying Rails Applications: Hassle free provisioning, reliable deployment (2014)

6.1 - Managing Cookbooks with Berkshelf

Overview

We finished the previous chapter by observing that a majority of chef repositories will contain a mixture of our own bespoke cookbooks and community ones from third parties.

It’s also fair to say you’ll eventually end up with a fair few different chef repositories relating to different projects. If you’ve written your recipes well, you’ll often be able to re-use them across projects, further increasing the overall time saved. This principal “Don’t Repeat Yourself” (DRY) will be familiar to any ruby developer used to extracting re-usable functionality into standalone gems or using such functionality provided in gems by others.

Ruby has bundler which allows us to define the gems and the versions of these gems which we need in a Gemfile. a quick bundle install will then take care of pulling in these gems from their remote sources and making them available to our Ruby application.

Bundler then generates a Gemfile.lock which contains details of all the gems (including dependencies) installed and their exact versions. When our colleagues run bundle install as long as they have this Gemfile.lock file present, they will get the same versions of all gems as we did.

Berkshelf provides exactly this functionality for chef Cookbooks. In a Berksfile we can define the cookbooks our chef repository is dependent on and the versions of these. We can then use berks install to grab all of these cookbooks. If any individual cookbook specifies its own dependencies using depends in its metadata.rb, Berkshelf will take care of installing these as well.

Like bundler, Berkshelf generates a .lock file (Berksfile.lock) with the relevant versions for each cookbook. As long as we share this with our colleagues (for example by checking it into our version control system), they will get the same versions that we have when they run berks install.

If you want to update a cookbook you can use berks update cookbook_name and Berkshelf will attempt to update the latest version of that cookbook and resolve any new/ existing dependencies appropriately.

warning

Berksfile.lock

When troubleshooting a provisioning failure, a lot of forums will contain advice along the lines of “try just deleting your Berksfile.lock”. This is generally a really bad idea (as would be deleting Gemfile.lock to fix a Rails app). It’s far safer - and more likely to solve the problem - to work through the cookbooks in the Berksfile, updating them one by one, so that any new problems introduced by breaking changes between versions can be managed.

How Berkshelf works with knife solo

By default Berkshelf installs cookbooks to a folder within ~/.berkshelf. The integration with knife solo means that when we run knife solo cook, the cookbooks we need are automatically copied into the cookbooks Directory.

It’s important to recognise therefore that the cookbooks folder should not be used by us for anything because changes to it will not be persisted when knife solo cook is run.

Instead, any repository specific cookbooks should be stored in site-cookbooks.

Getting Started

Structure of a Berksfile

Begin by cloning the example chef repository:

1 git clone https://github.com/TalkingQuickly/rails-server-template.git

Then cd into the rails-server-template directory, you’ll see a folder structure exactly as described in section 5 and like the example configuration we created.

Open Berksfile and you’ll see something that looks like this:

1 site :opscode

2

3 cookbook 'build-essential', git: 'https://github.com/opscode-cookbooks/build-e\

4 ssential'

5 cookbook 'sudo', git: 'https://github.com/opscode-cookbooks/sudo.git'

6 cookbook 'basic-security-tlq', git: 'git@github.com:TalkingQuickly/basic_secur\

7 ity-tlq.git'

8 cookbook 'look-and-feel-tlq', git: 'git@github.com:TalkingQuickly/look_and_fee\

9 l-tlq.git'

10 cookbook 'users', git: 'https://github.com/opscode-cookbooks/users.git'

11 cookbook 'chef-solo-search', git: 'https://github.com/edelight/chef-solo-searc\

12 h'

The first line site :opscode is the default source for cookbooks, in the same way Ruby Gems provides a central package index for gems, opscode provides a similar index for packages.

The simplest definition would be:

1 cookbook 'cookbook_name'

This would tell Berkshelf to look for the cookbook “cookbook_name” in the opscode index and download it and any dependencies.

You can also use bundler style version definitions so:

1 cookbook 'cookbook_name', '~> x.x.x'

You’ll see in our example Berksfile the format is generally:

1 cookbook 'cookbook_name', git: 'https://github.com/user/repo'

Again, like bundler, this allows you to specify a git repository to download the recipe from. I tend to specify git repositories over using the Opscode index. This is entirely personal preference as I regularly refer back to the repositories and their authors.

Finally you can also provide an SHA-1 commit hash to ensure a particular revision of the cookbook is used like so:

1 cookbook “cookbook_name”, git: 'https://github.com/user/repo', ref: “eef7e6580\

2 6e7ff3bdbe148e27c447ef4a8bc3881”

Berkshelf like bundler is extremely powerful and it’s worth spending some time reading the documentation available at: http://berkshelf.com/

Installing from the Berksfile

To install the cookbooks, execute the following command in the root of our example configuration folder:

1 bundle exec berks install

As explained above, when knife solo cook is run later, Berkshelf will copy the cookbooks automatically into the cookbooks directory. Since this won’t happen until the first time we apply the configuration to a node, the cookbooks source isn’t initially available in the cookbooks directory. To get around this we can have Berkshelf ‘vendor’ the cookbooks into the cookbooks folder with the following command:

1 bundle exec berks install --path cookbooks

Now if you look in the cookbooks folder you’ll see that for each of the cookbooks listed in the Berksfile, as well as some additional dependencies, there’s a directory containing a cookbook structured as per section 5.1.

Remember though, any changes made to the cookbooks in the cookbooks directory directly, will not be saved. The contents of this Directory is refreshed every time knife solo cook is run.

Any repository specific custom cookbooks should go in site-cookbooks instead.

The following chapters will cover each of the key system elements in detail.