In the previous article we discussed how to use Chef Solo, learned about knife, librarian and vagrant tools, which help us to use and test Chef Solo kitchen. In this article we will learn cookbook structure and will write own cookbook.
Cookbook
A cookbook is a collection of Chef recipes. All cookbooks like a Chef are written in Ruby. You already have seen how we get nginx cookbook and use “source” recipe from it to install nginx on our server. Let’s look at the structure of this cookbook:
A cookbook can have:
metadata.rb - a file, which contain all information about the cookbook (name, dependencies).
This is an important file, if you want to distribute your cookbook.
attributes - a folder, which contain files with default attributes for recipes. In the nginx cookbook you can find such default attributes:
As you remember we can redefine all these attributes in the node file.
definitions - a folder, which contain helpers from this cookbook. You can find this helper in the nginx cookbook:
The helper “nginx_site” can enable/disable configuration from the folder “site-available” and reload nginx. I will show you how to use this helper.
files - a folder, which contain files and these files just need to be copied on the server in the right place (it can be ssl keys, static configs, etc.)
recipes - a folder, which contain all recipes from this cookbook. Each recipe is in a separate Ruby file:
As you remember we added this to the run_list:
This is run the source.rb recipe from the nginx cookbook. If you change it with by this:
This is run default recipe from nginx cookbook (file default.rb in recipes folder).
templates - a folder, which contains Erb templates for this cookbook (these are nginx configs)
test - a folder, which contain tests for this cookbook
First cookbook
Let’s create our first cookbook. Our custom cookbooks should be in the folder “site-cookbooks” (the folder “cookbooks” is used for vendor cookbooks and managed by librarian, so we will add this folder in gitignore). If you look in solo.rb, you can see such settings:
This means what Chef will search needed cookbooks first in the site-cookbooks folder and nothing is found will try to search in the cookbooks folder. So if you create the nginx cookbook in site-cookbooks, Chef will try to use it first.
Let’s create a cookbook with named “tomatoes”:
And create the file default.rb in the recipes folder with content:
The command “package” is used to manage packages in the server. This command will install on server git package. For more info about this command you can read here: docs.opscode.com/chef/resources.html#package. Next, add our new recipe to the run list in our vagrant.json node:
And test our kitchen again:
As you can see the git package installed on the server. Let’s check this:
All works fine.
Сonfigure nginx through our cookbook
Let’s configure nginx for our application. First of all add new attributes in the vagrant node (file “nodes/vagrant.json”):
Next, create a nginx template (“tomatoes/templates/default/nginx.conf.erb”):
And create the index.html file in “tomatoes/files/default” (create this directory before) with content:
This we will use to check what nginx will show after setup of settings.
Finally add this content to “tomatoes/recipes/default.rb”:
As you can see in the recipe node attributes available for us in the “node” variable. You can get this attributes in several ways:
This always will give you the same value from the app.web_dir attribute.
As you can see in the recipe code we created 3 directories, created a new config for nginx, enabled this config by “nginx_site” helper (this helper automatically reloads nginx) and put “index.html” into the server directory. After the launch command, “vagrant provision”, you should see this in your browser with url “http://localhost:8085/”:
Ruby Power!
As you can see in our recipe we created 3 directories by 3 commands. Better DRY this code. But how to do this? Simple! This is all Ruby code, so you can use it to make your recipe more powerful (and beautiful, of course):
We collect all subfolders in a Ruby array and create it in one cycle.
Summary
In the current article we have learned the Chef cookbook structure and how to write a simple Chef cookbook. In the next article we will look at the usage of roles in your Chef kitchen.