Writing a Chef Cookbook, or writing your first cookbook
In continuation to a Chef Introduction session we had last week on meetup, I thought a blog post was called for in order to emphasize the process of writing a recipe. And/Or working with chef in general as a buy product of that.
I will be using the basic “ntp” example Opscode uses on their wiki, but in order to understand the components of a recipe I will stretch it a bit further in order to show the true power of Attributes and Templates.
At the end of this post [or now if you really insist] you can clone https://github.com/tikalk/chef-intro-repo and see the ntp recipe alongside other stuff which was presented in the meetup.
Prequisets:
- A Chef server [see: http://www.tikalk.com/alm/blog/installing-chef-server if you want and set one up …]
- Configured Knife workstation
Step 1: Install the service you want to recipe …
1 2 |
|
Identify:
- package name you wish to install
- Files which are template candidates [which chef will need to populate with your data]
I found the following:
- service name “ntpd” [ init file name: /etc/rc.d/init.d/ntpd ]
- configuration file our tempalte candidate “/etc/ntp.conf” [ also found via rpm -ql ]
Step 2: Setup a git repository [clone opscode’s “template” repository]
1
|
|
Step 3: Create a cookbook [named ntp]
1 2 |
|
The knife command above will create the foloowing structure [under cookbooks directory]:
1 2 3 4 5 6 7 8 9 10 |
|
We won’t be using all of these in this tutorial … highlighted are the ones we are going to use (at this stage)
Step 4: Create the recipe
1
|
|
Add the following ruby code [link]:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
The first block of code will use chefs built-in packadge installer providor to use the os’s package manager (in our case yum/rpm) and use the service name “ntp” the one we located whilst installing the package in step1 above.
Step 5: Create a template
1
|
|
Unlike files which are placed by chef “as is” files under templates folder ending with erb are interpolated and created on the node during a chef-client run.
The content of the file [link]:
1 2 3 4 5 6 7 8 |
|
In this simple use case line #7 from cookbooks/ntp/recipes/default.rb will be the one setting the ntp_server parameter for the tempalte file in line #5 of the template above.
At this stage you could create a role add this recipe to arun_list and it will just work … until you try to apply this recipe on ubuntu for example, there you will find an issue with the service name … and whilst were at it , let’s add support for more than one ntp server [in case the single one we added is down :(].
1
|
|
Will reveal the issue I just mentioned and
1 2 |
|
will give us the list of files [ /etc/ntp.conf ] and service name [ ntp ] => notice in this case there is no “d” at the end.
Step 6: Improovment #1 – adding service name resolution to our recipe
Add an attributes file:
1
|
|
With the following content:
1 2 3 4 5 6 7 8 |
|
This case statement will help our recipe in the service name resolution for redhat / centos & other rpm based distros “ntpd” for ubutnu / debian use “ntp”.
Let’s tell our recipe to respect this attribute …:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
The diff is in line #7 & line #12 which now uses the node:[ntp][:service] attribute we defined in the attributes.rb file above.
Step 7: Add support for more than 1 ntp server
In cookbooks/ntp/attributes/default.rb file add the following array:
1
|
|
And in our template file let’s add support for more than one line of ntp server:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
As you can see I marked out linet #5 which is our old ntp decleration
and added lines# 7-10:
1 2 3 4 |
|
chef will itterate over the array and inject the vlaues in our case whilst using defaults we will recieve the following:
1 2 3 4 5 6 7 8 |
|
That’s it all is left is to upload this cookbook to your chef server and add it to one of your nodes and you are good to go.
1
|
|
(you might want to bump the version up just so it becomes a habbit – edit the metadata.rb file under the recipies directory).
Coming up [hopefully in the next few days] a test environment for chef cookbooks – I will be taking this example and present how to setup an environment for testing combining Chef-Solo (in case you don’t have a chef server), Vergrant & VirtualBox
Fell free to comment / remark :)