Best Practices for Writing Chef Cookbooks

Overview and Objectives

This post features a recipe on how to write good quality Chef cookbooks and to keep your cookbooks up to date. You’ll learn how to use Test Kitchen, Cookstyle, Foodcritic and ChefSpec to create a well documented Chef Cookbook which you can publish on Chef Supermarket.


In order to complete this walkthrough, you need to be set up for local development. It involves verifying your work on local test infrastructure before you deploy any changes out to production. Follow steps below, to setup your local development environment.

About Chef

Chef is a very popular, open sourced(very recently) and powerful infrastructure automation platform which transforms infrastructure to easily manageable and versioned code blocks. With Chef, you can automate how your infrastructure will be configured, deployed and managed across your network. It can work both in the cloud and on-premises no matter its size.

  • Chef workstation is the location where users communicate with Chef. This is the development and testing environment for cookbooks and publishing them to Chef server for production use. You can also configure the organizational policies such as roles and environments to separate the responsibilities.
  • Chef server is the center for configuration data. It stores our cookbooks, the policies about the nodes, and informations about the nodes that are being managed by that server. Nodes communicate with Chef Server for configuration details.
  • Chef client node is the machine that are configured and managed by Chef Server. After configuring the Chef client on a node, it connects to Chef server to configure itself to its desired state.

About Cookbooks

Chef uses cookbooks to communicate with nodes in order to pass the configurations and policies. Inside of a cookbook, there are

  • recipes that specify the resources to use and the order in which they are to be applied,
  • files which can be transferred to nodes,
  • attributes which can be used to override the default settings on a node,
  • metadata which provides information that helps client and server correctly deploy it,
  • libraries to allow arbitrary Ruby code to be included in the cookbook,
  • templates which are an Embedded Ruby(ERB) template that is used to dynamically generate static text files,
  • tests to improve the quality of our cookbooks.

Why It’s Important to Update Cookbooks

Chef usually releases a backwards-compatible update of Chef client each month. However, each year they release a new major version which may include some deprecations for old functionalities. For example, Chef 13 was released in April 2017, Chef 14 was released in April 2018. You can see from here the upcoming update has some deprecations.

How Teams Update Their Cookbooks

Depends on the size and structure of the organizations, some teams perform periodic maintenance on their notebooks every month or quarter whereas other teams updates less frequently. It all depends how big is your organization, how many cookbooks your team maintains and how often your team add features to your cookbooks. But it’s crucial to remove legacy part from your cookbooks to ensure you have healthy infrastructure when you deploy on production.

  • Remove files that you no longer need.
  • Run Foodcritic and Cookstyle tests.
  • Use Test Kitchen to verify your cookbook succeeds locally.
  • Create passing unit and integration tests
  • Add appropriate metadata and documentation.

Clone custom_apache Cookbook

Let’s start by cloning the custom_apache cookbook from Github to your Chef workstation.

$ git clone

Remove Files That No Longer Needed

We use Vagrantfile to run and verify our cookbook on a temporary VM that runs on Virtual Box. Before Test Kitchen, we had to use a separate Vagrantfile to achieve testing. However, Test Kitchen is creating and managing the Vagrantfile. Therefore, we can remove this file from the cookbook contents.

$ rm Vagrantfile

Run Foodcritic and Cookstyle Tests

Foodcritic and Cookstyle are two popular linting tool for cookbooks. Linting tools help you to ensure that your code adheres to standart style guidelines that are followed for the language you write to avoid common problems. As both tools do not involve the creation of a test instance, they provide a faster way to validate the correctness of your cookbook.

$ foodcritic ~/cookbooks/custom_apache
Checking 5 files
FC019: Access node attributes in a consistent manner: ./recipes/default.rb:13
FC019: Access node attributes in a consistent manner: ./recipes/default.rb:14
FC019: Access node attributes in a consistent manner: ./recipes/default.rb:15
FC064: Ensure issues_url is set in metadata: ./metadata.rb:1
FC065: Ensure source_url is set in metadata: ./metadata.rb:1
FC066: Ensure chef_version is set in metadata: ./metadata.rb:1
FC067: Ensure at least one platform supported in metadata: ./metadata.rb:1
supports 'ubuntu'
issues_url ''
source_url ''
chef_version '>= 12' if respond_to?(:chef_version)
# Load from node attributes some variables we'll need.
site_name = node['site']['name']
content_owner = node['site']['content']['owner']
content_group = node['site']['content']['group']
$ foodcritic ~/cookbooks/custom_apache
Checking 5 files
$ cookstyle -a ~/cookbooks/custom_apache
Inspecting 8 files
8 files inspected, 12 offenses detected, 12 offenses corrected

Use Test Kitchen to Verify Your Cookbook Succeeds Locally

Test Kitchen automatically test your cookbook across any combination of platforms and test suites defined in a kitchen.yml file. Here, we'll use its vagrant driver to test our cookbook in a test VM. To apply the cookbook to the Ubuntu virtual machine as defined in kitchen.yml file run kitchen converge as shown below.

$ kitchen converge
-----> Creating <default-ubuntu-1604>...
==> vagrant: A new version of Vagrant is available: 2.2.4!
==> vagrant: To upgrade visit:
Deprecated features used!
Cloning resource attributes for apt_package[install libapache2 package] from prior resource
Previous apt_package[install libapache2 package]: /tmp/kitchen/cache/cookbooks/custom_apache/recipes/default.rb:32:in `block in from_file'
Current apt_package[install libapache2 package]: /tmp/kitchen/cache/cookbooks/custom_apache/recipes/default.rb:32:in `block in from_file' at 1 location:
- /tmp/kitchen/cache/cookbooks/custom_apache/recipes/default.rb:32:in `block in from_file'
See for further details.
supports { manage_home: true } on the user resource is deprecated and will be removed in Chef 13, set manage_home true instead at 1 location:
- /tmp/kitchen/cache/cookbooks/custom_apache/recipes/default.rb:52:in `block in from_file'
See for further details.
supports { non_unique: false } on the user resource is deprecated and will be removed in Chef 13, set non_unique false instead at 1 location:
- /tmp/kitchen/cache/cookbooks/custom_apache/recipes/default.rb:52:in `block in from_file'
See for further details.
Chef Client finished, 11/16 resources updated in 30 seconds
Finished converging <default-ubuntu-1604> (0m53.43s).
deprecations_as_errors: true
package "install libapache2 package #{p}" do
manage_home true
non_unique false

Create Passing Unit and Integration Tests

ChefSpec is an extension of Ruby’s RSpec a behaviour driven development framework for Ruby. ChefSpec is a framework that tests resources and recipes as part of a simulated chef-client run. In our example cookbook, there is already a few tests defined in spec/unit/recipes/default_spec.rb. Let's try to run them without error.

$ chef exec rspec ~/cookbooks/custom_apache
WARNING: you must specify a 'platform' and 'version' to your ChefSpec Runner and/or Fauxhai constructor, in the future omitting these will become a hard error. A list of available platforms is available at
runner = 'ubuntu', version: '16.04')
$ chef exec rspec ~/cookbooks/custom_apache
Finished in 0.53752 seconds (files took 2.17 seconds to load)
3 examples, 0 failures

Add Appropriate Metadata and Documentation

It is important to provide appropriate metadata and documentation that helps other team members understand what your cookbook does and how to use it. To do that, make sure you have at least update

  • Copyright in the files
  • Detailed description of your cookbook in metadata
  • Latest version of the cookbook
  • file with some more details about how to use the cookbook
  • file about the latest changes

Original Source



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Alibaba Cloud

Alibaba Cloud

Follow me to keep abreast with the latest technology news, industry insights, and developer trends. Alibaba Cloud website: