Resources and Recipes
Resources
A resource is a statement of configuration policy that describes the desired state of a node.
- Block of code, declares the desired state of a node.
- Resource type—such as package, template, or service.
Where a resource represents a piece of the system and the steps that are needed to bring that piece of the system from its current state into the desired state.
Recipes
- Collection of resources in a single file is called recipes.
- Recipes must be stored in a cookbook.
- One recipe may be included in another recipe.
- May use the results of a search query and read the contents of a data bag (including an encrypted data bag)
- Recipe must be added to a run-list before it can be used by the chef-client
- Is always executed in the same order as listed in a run-list
Writing our First recipe
Lets start creating a recipe file named as base.rb
, with the following resource specification
- Creating user
- deploy
- Removing user
- dojo
- Installing packages
- tree, git, ntp, wget, unzip
- Add content to motd file
- Start ntp
service
Before Writing a recipe lets have a look of available resources here[^chef_resources] to build of recipe.
- Our recipe start with creating a
user
resources, for creating a user calleddeploy
user 'deploy' do
action :create
end
- The above resource will create only user
deploy
to add more information to user resources, click here[^user_resources] - Let us create password for our user
deploy
, which need to be encrypted. - In terminal use this command and enter paswword twice to create a encrypted password
openssl passwd -l
user 'deploy' do
uid 5001
home '/home/deploy'
action :create
password '$1$Ze1eJK3R$j5I0NRP5WxbZAaeXcfYW7/'
end
Syntax Check
- To check the syntax of ruby file we use
ruby -c <file_name.rb>
where -c is used to "check syntax only".
ruby -c base.rb
Execute Recipe with Chef Client in Local Mode
- We will be using Chef-client command with
--local-mode
or-z
to run in localhost(chef workstation).
chef-client --local-mode --log_level info <file_name.rb>
or
chef-client -z -l <file_name.rb>
- In the above we use
--log_level info
info or-l
to get the detailed information onchef-client
run.
Using Why (Dry) Run
- Before applying recipe directly we will be using dry run mode to check what this recipe would do
- To use dry run and check what this recipe will do, we could use
--why-run
or-w
with chef-client command.
chef-client --local-mode --log_level info --why-run <file_name.rb>
or
chef-client -z -l -w <file_name.rb>
- By running
chef-client -z -l -w base.rb
tells thatuser deploy
would be created, and not really created, because of why run mode.
Running our first recipe
- After checking with dry run, we can apply our recipe to the local node.
chef-client --local-mode --log_level info base.rb
or
chef-apply base.rb
What it does?
- It creates user
deploy
with specified UID and home directory in local machine. - Run
id deploy
to check the details of user deploy.
Idempotence
Lets run chef-client again to reapply with same options
chef-client -z -l base.rb
What happened when we run again the chef-client command?
- It checks for the presence of user
deploy
and hence it Skipped executinguser
resources. - This is how, idempotent of chef works.
LAB Exercises
We created user deploy
now let us add the remaining resources to our base.rb
recipe.
- Removing user
- dojo
- Installing packages
- tree, git, ntp, wget, unzip
- Add content to motd file
- Start ntp
service
Common Functionality
Resources can have some common functionality like sharing properties, conditionals and relative actions.
Actions
action :nothing
The above common functionality can be used with any resource block to do nothing until notified by another resource to take action.
Notifications
This property is used to listens to other resources in the resource collection and then takes actions based on the notification type (notifies
or subscribes
).
The syntax for notifies is:
notifies :action, 'resource[name]', :timer
Timers
A timer specifies the point during the chef-client run at which a notification is run.
:before
Specifies that the action on a notified resource should be run before processing the resource block in which the notification is located.
:delayed
Default. Specifies that a notification should be queued up, and then executed at the very end of the chef-client run.
:immediate, :immediately
Specifies that a notification should be run immediately, per resource notified.
Resource with Guards
- To prevent the execute command from running again and again and providing idempotent to it, we use
gaurds
one of the common functionality along with the resource.
Gaurds
The following properties can be used to define a guard that is evaluated during the execution phase of the chef-client run:
-
not_if - Prevent a resource from executing when the condition returns true.
-
only_if - Allow a resource to execute only if the condition returns true.
Click here[^deploy_facebooc] for deploy_facebooc.rb recipe for common functionality, as shown below
package ['libsqlite3-dev', 'sqlite3']
execute 'download_facebooc_from_source' do
command 'wget https://github.com/jserv/facebooc/archive/master.zip'
cwd '/opt'
user 'root'
creates '/opt/master.zip'
notifies :run, 'execute[extract_facebook_app]', :immediately
end
execute 'extract_facebook_app' do
command 'unzip master.zip && touch /opt/.facebooc_compile'
cwd '/opt'
user 'root'
action :nothing
end
execute 'compile_facebooc' do
command 'make all && rm /opt/.facebooc_compile'
cwd '/opt/facebooc-master'
user 'root'
only_if 'test -f /opt/.facebooc_compile'
action :run
end
execute 'run_facebooc' do
command 'bin/facebooc 16000 &'
cwd '/opt/facebooc-master'
user 'root'
not_if 'netstat -an | grep 16000 | grep -i listen'
action :run
end
[^chef_resources]: Chef Resources - https://docs.chef.io/resource.html [^user_resources]: User Resources - https://docs.chef.io/resource_user.html [^deploy_facebooc]: Deploy_Facebooc Recipie - https://gist.github.com/initcron/eff10a8e5bde59b356a485539579d634