Data Driven Cookbooks
Code vs Data
- once the data is taken out of the code then cookbook become generic.
- Generic cookbook can be used with any OS and environments.
- Reusability helps in reducing tonnes and tonnes of time.
Node Object
- It is the representation of each node on chef server in
JSON
format. - If we run a
chef-client
it generates a node object in chef server in case of nodes or in workstation (/nodes/*.json
) in case of running locally in workstation.
Attributes
It is used to specify a detail about node.
- Attributes are used by the chef-client to understand;
- The current state of the node
- What the state of the node was at the end of the previous chef-client run
- What the state of the node should be at the end of the current chef-client run
- Attributes
are taken in precedence, according to the place where we specify them, as follows;
System Defined Attributes
OHAI
- It installs along with
chef-client
. - It helps in getting all the information about nodes
- Finding information on node with ohai
ohai
ohai ipaddress
ohai hostname
ohai memory
ohai memory/total
ohai cpu/model_name
- Referring attributes
node['ipaddress']
node['hostname']
node['memory']['total']
node['cpu']['model_name']
User Defined Attributes
- User defined attributes are located in four places as follows
- Attributes file
- Recipes
- Roles
- Environments
Attribute File
- How the attribute file looks like?
- Precedence is defined
-
Attribute and its value is defined as per the above format.
-
Now we can access these attributes in
recipe
ortemplate
as shown below.
Example
template node['tomcat']['config'] do
source 'tomcat.conf.erb'
owner node['tomcat']['user']
group node['tomcat']['group']
mode '0644'
action :create
notifies :restart, "service[#{node['tomcat']['service']}]", :delayed
end
Parameterizing Tomcat Configurations
- Now let us start creating attribute file
- Use
chef generate
to create a file in tomcat cookbook
chef generate attribute cookbooks/tomcat default
- It will create a file as follows
cookbooks/tomcat/attributes/default.rb
- Now we add the attributes and its value in
default.rb
- Path: cookbooks/tomcat/attributes/default.rb
default['tomcat']['user'] = 'tomcat'
default['tomcat']['group'] = 'tomcat'
default['tomcat']['config'] = '/etc/tomcat/tomcat.conf'
default['tomcat']['packages'] = [ 'tomcat', 'tomcat-webapps' ]
default['tomcat']['service'] = 'tomcat'
- Now call these attributes in the following recipes
- tomcat::config will be changed as follows
cookbook_file node['tomcat']['config'] do
source 'tomcat.conf'
owner node['tomcat']['user']
group node['tomcat']['group']
mode '0644'
action :create
notifies :restart, "service[#{node['tomcat']['service']}]", :delayed
end
- tomcat::install will be changed as follows
package node['tomcat']['packages']
- tomcat::service will be changed as follows
service node['tomcat']['service'] do
action [ :start, :enable]
end
- Now apply it using
kitchen converge
and then verify usingkitchen verify
.
Platform Specific cookbooks
- Let us convert our first created
base.rb
recipe into a cookbook. - Create a cookbook using
chef generate
chef generate cookbook cookbooks/base
- Now move the
base.rb
todefault.rb
of base cookbook.
mv /workspace/chapter3/base.rb cookbooks/base/recipes/default.rb
- Add
base::default
recipe to the run_list
knife node run_list add app1 "recipe[base]"
- Apply on node1
ssh devops@node1
sudo chef-client
- It fails because the service name for rhel/centos is
ntpd
and not ntp as like debian.
- To overcome this we use attribute for platform specific.
- We use system defined attribute
platform_family
to do this.
Example for ohai platform_family
is
root@ws:/workspace/myapp# ohai platform_family
[
"debian"
]
root@ws:/workspace/myapp# kitchen login
Last login: Thu May 4 05:50:20 2017 from 172.17.0.1
[kitchen@9af3a004e202 ~]$ ohai platform_family
[2017-05-04T05:58:19+00:00] INFO: The plugin path /etc/chef/ohai/plugins
does not exist. Skipping...
[
"rhel"
]
[kitchen@9af3a004e202 ~]$ logout
Connection to localhost closed.
root@ws:/workspace/myapp#
- Now let us create a create a default attribute file for base cookbook using
chef generate
chef generate attribute cookbooks/base default
- Now add the following content to attribute file
- Path: cookbooks/base/attributes/default.rb
case node['platform_family']
when 'rhel'
default['ntp']['service'] = 'ntpd'
else
default['ntp']['service'] = 'ntp'
end
- Call the attributes in
cookbooks/base/recipes/default.rb
recipe
service node['ntp']['service'] do
action [ :start, :enable ]
end
- Now apply again using kitchen
ssh devop@node1
sudo chef-client
- It is successful now and service is started based on platform.
Nano Project - Add some tests for recipes in base cookbook for different platform.
Templates
- A cookbook template is an Embedded Ruby (ERB) template that is used to dynamically generate static text files.
- Templates are great way to manage configuration files for different environment.
- ERB or ERUBIS
- Contains text with dynamic ruby code
- Uses tags to mark dynamic code
- ERB Tags
- Code wrapped in
<% %>
or<% -%>
is a statement that is evaluated. - Code wrapped in
<%= %>
is code that is evaluated and the result is placed into the file. - Harcoded strings dont have to be wrapped in erb tags if they are constant, but Ruby code must be wrapped in erb tags if you want the result of that code to go into your file.
Templatize MOTD
- Generate
motd
template for base cookbook.
chef generate template cookbooks/base motd
- Add the following content to the template file motd.erb.
- Path: cookbooks/base/templates/default/motd.erb
This server is a property of <%= node['org']['name'] %>
SYSTEM INFO:
HOSTNAME : <%= node['hostname'] %>
IP ADDRESS : <%= node['ipaddress'] %>
MEMORY : <%= node['memory']['total'] %>
- Now add organization name as a user defined attribute in attribute file
- Path: cookbooks/base/attributes/default.rb
default['org']['name'] = "XYZ Inc."
- Complete attribute
default.rb
ofbase cookbook
is as follows
case node['platform_family']
when 'rhel'
default['ntp']['service'] = 'ntpd'
else
default['ntp']['service'] = 'ntp'
end
default['org']['name'] = "XYZ Inc."
- Now add template resource to the
cookbooks/base/recipes/default.rb
recipe file.
template '/etc/motd' do
source 'motd.erb'
owner 'root'
group 'root'
mode 0644
end
- Apply using
kitchen converge
.
Attributes Precedence
- Declaring attributes in various places takes precedence one over another.
- Let us take an example of declaring port as follows
- Now let us define organization name in recipe file, before calling attribute in any resource of a recipe.
- Path: cookbooks/base/recipes/default.rb
node.default['org']['name'] = "School of Devops"
- Complete recipe
default.rb
ofbase cookbook
is as follows
user 'deploy' do
uid 5001
home '/home/deploy'
action :create
password '$1$Ze1eJK3R$j5I0NRP5WxbZAaeXcfYW7/'
end
user 'dojo' do
action :remove
end
package 'ntp' do
action :install
end
package ['tree', 'unzip', 'wget'] do
action :install
end
package 'git'
service node['ntp']['service'] do
action [ :start, :enable ]
end
node.default['org']['name'] = "School of Devops Inc"
template '/etc/motd' do
source 'motd.erb'
owner 'root'
group 'root'
mode 0644
end
- Now apply using
kitchen converge
Templatizing Tomcat Cookbook (LAB Exercise)
- Generate a
tomcat.conf.erb
template for tomcat cookbook.
chef generate template cookbooks/tomcat tomcat.conf
- Generate a
default.rb
attribute for tomcat cookbook.
chef generate attribute cookbooks/tomcat default
- Add the following content to attribute file.
- Path: /workspace/myapp/cookbooks/tomcat/attributes/default.rb
default['tomcat']['user'] = 'tomcat'
default['tomcat']['group'] = 'tomcat'
default['tomcat']['config'] = '/etc/tomcat/tomcat.conf'
default['tomcat']['packages'] = [ 'tomcat', 'tomcat-webapps' ]
default['tomcat']['service'] = 'tomcat'
default['tomcat']['user'] = 'tomcat'
default['tomcat']['group'] = 'tomcat'
default['tomcat']['java_home'] = '/usr/lib/jvm/jre'
default['tomcat']['catalina_home'] = '/usr/share/tomcat'
default['tomcat']['java_opts'] = '-Xms32m -Xmx64m -XX:MaxPermSize=64M \
-Djava.security.egd=file:/dev/./urandom'
- Add the below content to
tomcat.conf.erb
template. - Path: /workspace/myapp/cookbooks/tomcat/templates
TOMCAT_CFG_LOADED="1"
JAVA_HOME="<%= node['tomcat']['java_home'] %>"
JAVA_OPTS="<%= node['tomcat']['java_opts'] %>"
CATALINA_BASE="/usr/share/tomcat"
CATALINA_HOME="<%= node['tomcat']['catalina_home'] %>"
JASPER_HOME="/usr/share/tomcat"
CATALINA_TMPDIR="/var/cache/tomcat/temp"
TOMCAT_USER="<%= node['tomcat']['user'] %>"
SECURITY_MANAGER="false"
SHUTDOWN_WAIT="30"
SHUTDOWN_VERBOSE="false"
CATALINA_PID="/var/run/tomcat.pid"
- Now update
tomcat::config
recipe as mentioned below - Path: /workspace/myapp/cookbooks/tomcat/recipes/config.rb
template node['tomcat']['config'] do
source 'tomcat.conf.erb'
owner node['tomcat']['user']
group node['tomcat']['group']
mode '0644'
action :create
notifies :restart, "service[#{node['tomcat']['service']}]", :delayed
end
-
Apply using
kitchen converge
-
Now change the values of
JAVA_OPTS
in attribute file and then apply again for verifying the changes using template and attribute. -
Also verify using
kitchen login
and runps auwwx
command.