.notes These course materials are Copyright © 2010-2012 Opscode, Inc. All rights reserved. This work is licensed under a Creative Commons Attribution Share Alike 3.0 United States License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/us; or send a letter to Creative Commons, 171 2nd Street, Suite 300, San Francisco, California, 94105, USA.
At completion of this unit you should...
- Understand how knife handles merging multiple cookbooks.
- Understand recipe ordering.
- Apply multiple recipes to a node through a role.
- Be able to create a new cookbook and start writing simple recipes.
Getting More Cookbooks
Knife can download more cookbooks.
knife cookbook site install apt knife cookbook site install apache2
When using Git, multiple cookbooks are committed to the repository.
Git Commit Log
% git log commit 49e45373f294ace0c721a98f2155d4d2b558fee8 Author: jtimberman <email@example.com> Date: Tue Apr 26 15:27:53 2011 -0600 Import apt version 1.1.1 commit 5ead5af876235c0e7bc37972ea22134cd10af7ba Author: jtimberman <firstname.lastname@example.org> Date: Tue Apr 26 12:45:57 2011 +0000 Import fail2ban version 1.0.0
% git branch chef-vendor-apt chef-vendor-fail2ban
% git tag chef-vendor-apt-1.1.1 chef-vendor-fail2ban-1.0.0
Infrastructure as Code
This is a source code repository.
Treat it like one!
We can go back to any point in time, any version of a cookbook, and inspect differences.
git checkout chef-vendor-apt git checkout chef-vendor-fail2ban-1.0.0 git diff master
Use Your VCS
Knife currently integrates with Git in the “cookbook site install” command.
You can use any version control system you like.
There will be additional steps required to untar cookbooks, branch/merge, etc, depending on your tool.
Open Source contributions welcome!
Recipes applied to a node are processed in the order specified.
Recipes are specified in a Role or Node run list.
Run lists are ordered lists (Ruby/JSON arrays).
Recipes can include other recipes, too. Use “include_recipe”
Chef will process the included recipe in place, adding its resources to the resource collection.
Included recipes from other cookbooks require metadata dependency.
Cookbook dependencies are implied when using part(s) of one cookbook in another, such as recipe inclusion.
Cookbook dependencies are explicitly defined in metadata.
Use the “depends” keyword in the metadata.
The metadata defines the additional cookbooks required that might not appear in the run list explicitly.
The server reads the metadata as JSON, it does not parse the recipes (which are Ruby).
This is a security feature, the Chef Server does not execute the Ruby code.
During the initial part of the Chef run the node’s run list is expanded. Roles' run lists are expanded.
Chef uses the expanded run list to determine what recipes are included, and which cookbooks to download from the server.
Dependencies in the metadata are also downloaded.
Cookbooks are versioned. If the node has a Chef Environment, and the environment specifies cookbook versions, those versions will be downloaded.
We typically apply multiple related recipes to a node via a role.
A base role is a great place to apply the 'fail2ban' recipe, and also a recipe to update the APT cache on Debian/Ubuntu systems.
Simple Base Role
@@@ruby name "base" description "Base role is applied to all systems" run_list( "recipe[apt]", "recipe[fail2ban]" )
We’ll put apt before fail2ban to make sure the package cache is updated.
The default action in the fail2ban package resource is upgrade, so apt will ensure we always have the latest version including security fixes.
Upload Base Role
Use knife to upload the base role.
knife role from file base.rb
This will look for the role file (base.rb) in the roles sub-directory of the Chef Repository.
Apply Role to a Node
First remove the fail2ban recipe, it will be applied via the base role.
knife node run list remove NODE ‘recipe[fail2ban]’
Then add the role to the node.
knife node run list add NODE ‘role[base]’
Running Chef on the target node will cause the APT recipe to be applied, then fail2ban.
Since fail2ban was applied previously, it will not actually take any action on the node (unless there’s a new package version!).
New cookbooks can be created with Knife.
This will create a skeleton directory structure with all the components of a cookbook.
knife cookbook create
% knife cookbook create webserver ** Creating cookbook webserver ** Creating README for cookbook: webserver ** Creating metadata for cookbook: webserver
Default Cookbook Contents
tree cookbooks/webserver cookbooks/webserver ├── README.rdoc ├── attributes ├── definitions ├── files │ └── default ├── libraries ├── metadata.rb ├── providers ├── recipes │ └── default.rb ├── resources └── templates └── default
Knife pre-generates some information in the cookbook.
The values used come from configuration options in the knife cookbook create command.
Knife is not configured for creating new cookbooks by default. It has three settings that can customize the pre-filled content.
knife cookbook create
cookbook_copyright "Opscode, Inc." -C, --copyright COPYRIGHT cookbook_license "apachev2" -I, --license LICENSE cookbook_email "email@example.com" -E, --email EMAIL
Used to prefill default recipe, README and metadata
cookbook_* goes in knife.rb, and corresponds to command-line options
Licenses available: apachev2, gplv2, gplv3, mit, none
Note About Software Licenses
Cookbooks are distributable, be careful about the software license you choose.
You can use whatever you like.
Be aware of what you include in your cookbook, though!
Opscode uses Apache 2.0 Software License. Use the license you prefer.
- This is not legal advice, ask a lawyer if unsure.
Modifying the Cookbook
Once the cookbook is created, it is time to start modifying it to do something meaningful.
Typically, this will involve editing the default recipe.
Edit this with your favorite text editor.
Not all the cookbook components are used.
They are created so you don’t have to remember them all.
Remove the ones you know you don’t want.
Common Cookbook Components
The most common cookbook components:
- README :)
- files and / or templates
Cookbook attributes files set up sane defaults to be used in the cookbook.
We will cover them in depth next unit.
Most things in Chef recipes will be resources to configure.
Some things in Recipes will be pure Ruby syntax and helper code.
Your first recipes will be simple.
A DSL is a domain-specific language
- Recipes are a pure Ruby DSL
- Recipes are processed in two phases
- Compilation and Execution happen in the order specified.
Attributes in Recipes
The node object is available in recipes, and we can access the attributes like a Ruby hash key.
Attributes can come from cookbook files, roles, or the node itself.
Common Chef Resources
Chef supports a couple dozen resources, but a few are most commonly used. We’ll mostly work with the common ones.
- template, cookbook_file, remote_file
Common Resources: Package
@@@ruby package "tar" do action :install end package "tar" do version "1.16.1-1" action :install end package "tar" do action :upgrade end package "tar" do action :remove end
Common Resources: Service
@@@ruby service "example_service" do supports :status => true, :restart => true, :reload => true action [ :enable, :start ] end
.notes Recall the 'supports' meta-parameter controls the way the service's provider is going to work with the service on the system. :status => true, Chef will use the built in status command for the provider to check if the service is running. Commonly this is like '/etc/init.d/SERVICE status.' :restart => true, Chef will use the built in restart command for the provider to restart the service. Commonly this is like '/etc/init.d/SERVICE restart.' :reload => true, Chef can send a reload action to a service only if it supports reload. Chef will use the reload command for the provider usually to tell the daemon about a configuration change. Commonly this is like '/etc/init.d/SERVICE reload.'
Common Resources: Template
@@@ruby # Config file from a template template "/tmp/config.conf" do source "config.conf.erb" end # Config file from a template with variable map template "/tmp/config.conf" do source "config.conf.erb" variables( :config_var => node["configs"]["config_var"] ) end
Common Resources: Cookbook File
@@@ruby cookbook_file "/usr/local/bin/apache2_module_conf_generate.pl" do source "apache2_module_conf_generate.pl" mode 0755 owner "root" group "root" end
Common Resources: Remote File
@@@ruby remote_file "/tmp/testfile" do source "http://www.example.com/tempfiles/testfile" mode "0644" checksum "08da002l" end
Common Resources: User
@@@ruby user "random" do comment "Random User" uid "1000" gid "users" home "/home/random" shell "/bin/zsh" password "$1$JJsvHslV$szsCjVEroftprNn4JHtDi." end # System User user "systemguy" do comment "system guy" system true shell "/bin/false" end
.notes For password setting, you need to generate the password appropriate for your system.
Common Resources: Execute
@@@ruby execute "generate-module-list" do command "/usr/local/bin/apache2_module_conf_generate.pl /usr/lib/httpd/modules /etc/httpd/mods-available" action :run end
The command parameter calls a cookbook_file dropped off by an earlier example.
Providers Take Idempotent Actions
Providers know how to run the right commands or API calls to configure a resource by taking the appropriate action.
Providers should be written so they are idempotent and don’t configure the resource if it is in the declared state.
Providers are sometimes platform specific (apt, yum, useradd, chkconfig, etc).
- Information about the cookbook
- Instructs server what to distribute (dependencies)
- Specifies the version
- “Packaging” information
Use metadata to define dependencies.
Dependencies are required when using a cookbook’s components in another cookbook.
@@@ruby maintainer "YOUR_COMPANY_NAME" maintainer_email "YOUR_EMAIL" license "All rights reserved" description "Installs/Configures webserver" version "0.0.1" depends "apache2"
Cookbooks have two kinds of assets that aren’t strictly Ruby code that can be distributed.
- Files (
- Templates (
Cookbook Assets: Files
- Static assets
- For directories,
- File specificity
.notes "file" is a basic resource that manages the properties of a file - owner, mode, and basic content.
cookbook_file" is a file distributed from the cookbook.
remote_file" is a file downloaded from a remote source.
An early common development pattern is to start using
cookbook_file for static configuration files.
Cookbook Assets: Templates
- ERB (embedded ruby)
- Access to
- template resource
- File specificity
.notes Templates are dynamically rendered by Chef during convergence. The content of the rendered template is compared via SHA256 checksum to the target file. Variables can be passed into the template resource as a parameter. The node object is accessible in a template as well.
File specificity is how Chef determines source file for files and templates
Directory locations under files or templates
File Specificity Example
% ls cookbooks/classroom/files/* host-www.example.com/thing.conf ubuntu-10.04/thing.conf ubuntu/thing.conf default/thing.conf
You should now be able to...
- Explain how knife handles merging multiple cookbooks.
- Describe recipe ordering through inclusion.
- Apply multiple recipes to a node through a role.
- Create a new cookbook and understand the components.