I have been working toward my Chef certification here lately, and my husband came up with this really cool kata that I’ve been working on lately to study up for my first exam. A kata is something that you do over and over for training and for the purpose of bringing the broken parts of the process to light. It’s origins are in karate, and I’m sure you’ve heard of how it was implemented at Toyota with their famous Toyota-kata.
I really love this kata that Michael created because I can:
- copy and paste the tasks into my Checkvist,
- create a base cookbook,
- create a branch,
- run through the kata, knocking out each task on my Checkvist as I go,
- and then create another branch off of the base cookbook the next time I go through the kata.
It’s been perfect for me. It causes the things that I just don’t understand to really stand out so that I can focus on them a little more. So one of those things that kept getting me stuck was custom resources. For me, the documentation just wasn’t enough. So I’m going to explicitly explain this one custom resource that I had to make so that I can come back to this and remember. Maybe it’ll help some of you, too!
Why I wasn’t getting it
Here’s what the Chef docs say:
Honestly, when it all came down to it, I realized that I didn’t understand the documentation because I didn’t know the proper names for all the parts of the resource. My understanding now of a very basic resource declaration is this:
resource 'name' do
property value
action :value
end
resource
is the type of the resource.
name
is the name of the resource. This can also be the value of a property if you don’t assign one.
property
is any word that you give to the property for use in the resource and not in quotes so that you can use it as
a variable.
action
is a property of the resource that tells chef-client
what to do.
value
is the value that you’re giving to property
.
My Recipe’s Starting Point
Some of the tasks in the kata are:
- Run the command
echo ran command > /var/website/command.txt
- Don’t run the command the second time Chef converges (i.e. make it idempotent)
- If the command does run, do a
git pull
of the architect repository into/var/website/architect
. It shouldn’t pull the repository every time. - Refactor your command and pull into a custom resource called
chef_training_website
.
Okay, so those first three tasks leave me with these two resources (note: I did change the repo that he gave as an example):
execute 'ran' do
command 'echo ran command > /var/website/command.txt'
not_if { ::File.exist?('/var/website/command.txt') }
end
git 'chefkata' do
destination '/var/website/chefkata'
repository 'https://github.com/mhedgpeth/chef-by-example.git'
action :nothing
subscribes :sync, 'execute[ran]', :immediately
end
There are a couple of reasons we’d want to make a custom resource.
- So that we can simplify the recipe for better readability
- So that we can call this resource in a simple manner elsewhere in the cookbook, possibly with variables in it which change it
So how do I make that whole block (above) into one custom resource? First, I’m going to show you what I ended up with, and then I’m going to show you what each thing means.
My Custom Resource
Sibling to my recipes
directory, I created a resources
directory. Within that, I created a Ruby file that was just
for that one custom resource that I wanted to create. I called it chefkata.rb
, and put this in it.
resource_name :chefkata
property :kata, String, name_property: true
action :create do
execute 'ran' do
command 'echo ran command > /var/website/command.txt'
not_if { ::File.exist?('/var/website/command.txt') }
end
git 'chefkata' do
destination '/var/website/chefkata'
repository kata_repo
action :nothing
subscribes :sync, 'execute[ran]', :immediately
end
end
chefkata
is the name of the resource that I called in my recipe after this was created.
kata_repo
is the property, which is just like what command
is in the execute resource (execute
being the
resource_name).
name_property
is the thing that you put in quotes after the resource_name
. It’s marked as true
so that you can
call the resource without the name_property
(in this case kata_repo
).
For example, these two resource calls are the same:
directory 'website' do
path '/var/website'
end
and…
directory '/var/website'
By omitting the path
, which is the name_property
for the directory
resource, Chef will set the path
property
to /var/website
because that’s what I set the name
to. So really, each resource has a different
default name_property
that you can find in docs.chef.io.
In the recipe
After that was finished, I was able to then call that resource in my recipe, which looked simply like this:
chefkata 'https://github.com/mhedgpeth/chef-by-example.git'
As you can see, I substituted the name
for the kata_repo``property
. I could have also written it like this:
chefkata 'example' do
kata_repo 'https://github.com/mhedgpeth/chef-by-example.git'
end
Concluding Thoughts
I have to admit that the way resources are created doesn’t feel all that intuitive to me just yet. It could very well be that I just haven’t used Chef enough for it to be intuitive yet; that’s what Michael says, anyway. But that’s what this kata is for - to practice over and over until it is ingrained.