Skip to end of metadata
Go to start of metadata


Recipes are the fundamental configuration in Chef. Recipes encapsulate collections of resources which are executed in the order defined to configure the system

Recipes are an internal Ruby domain-specific language (DSL), but you do not need to have experience with Ruby to write recipes.

Most things in Chef recipes will be resources to configure. Some things in recipes will be Ruby syntax and helper code.


Basic Recipe Rules

When writing recipes, keep a few things in mind.

1. Recipes are stored in Cookbooks.
2. Resources are executed in the order they appear.
3. Recipes are evaluated as Ruby code on the node to find resources to execute. See Anatomy of a Chef Run for more information.
4. Recipes from other Cookbooks can be included with include_recipe.
5. All the attributes of the current Node are available via the node object.

Using Recipes

Recipes are used by assigning them to a node or role run list. They are assigned using the appropriate name. Recipes are stored in cookbook directories, and namespaced by the cookbook. The namespacing is used when assigning recipes to be run by a node. For example for a directory structure like:

There are two recipes: apache2 and apache2::mod_ssl. On a node, these are assigned to the node's run_list. For example:

(See Guide to Creating A Cookbook and Writing A Recipe for a simple example.)



Just Enough Ruby for Chef

Ruby is a language designed to be easy to read and to behave exactly as you'd expect, so it shouldn't take you too long to get up to speed. See Just Enough Ruby for Chef for a starting point.

Applying Recipes to Nodes

If you are using Chef with client/server, use knife to add the recipe to the node's run list, then run Chef client on the node.

If you are using Chef Solo, use a JSON file passed to chef-solo -j:

/etc/chef/dna.json

Then run chef-solo:

The cookbooks must be available in the cookbook_path on the system running chef-solo. See the Chef Solo page for more information.

Resources

Chef manages Resources on the node. Resources can be many things:

  • packages
  • services
  • users
  • files
  • directories

And more. They are the bread and butter of recipes. Chef's Providers do the heavy lifting that configure resources, based on the platform of the node. Chef's providers take idempotent actions to configure the resource as it is declared in the recipe.

Composition

Resources have four components:

  • type
  • name
  • parameter "attributes"
  • action(s)

For example:

This resource is a Ruby block. Its type is "package". Its name is "tar". It has a single parameter attribute "version". It defines a single action, ":install".

Parameter attributes are not the same as node Attributes. Context is important. These parameters specify various ways the resource should be configured. Each kind of resource in Chef has different parameters, and some have default values. If you want the default, you do not need to specify that parameter. Likewise, each type of resource has a default action. You do not need to specify the action if you want the default.

See the Resources page for documentation on each resource that comes with Chef and the default parameters and actions.

Meta Parameters

A variety of "meta" parameters are available to all resources. These are most commonly used to send notifications to other resources or set up conditional execution rules.

Meta parameters are documented in detail in the Meta section of the Resources page.

Custom Lightweight Resource Providers (LWRPs)

As discussed above, Resources represent a piece of system state and Providers are the underlying implementation which brings them into that state. For example, all database vendors support the abstract concept of database creation, but the underlying implementation is different for each. While typical Resources and Providers are implemented in Chef's core using Ruby classes, creating custom Lightweight Resources and Providers (LWRP) requires less Ruby knowledge than their heavier counterparts.

For the Light-weight Resources and Providers (LWRPs) that are used in Opscode's public open source cookbooks, see Opscode LWRP Resources.

Node Object

Recipes are executed in the context of the Chef node object, called node. A feature of Chef is using data about the Node, called Attributes in recipes to configure the system in particular ways based on that data.

Accessing Node Attributes

The node's attributes are like a Ruby hash. They are accessed with:

This will use the value of 'some_attribute'. A number of attributes are detected automatically by ohai when the node runs Chef. Node attributes are a nested key/value store, so there can be sub-keys too:

New custom attributes can be created in Cookbook Attributes and Roles. See below for creating new attributes in Recipes.

Common Automatic Attributes

Ohai detects attributes on the node based on its own plugin system. The most commonly accessed attributes are:

  • node['platform'] - The node's platform. This determines what Providers are used by Resources.
  • node['platform_version'] - The node's platform version. This may be used in determining Providers as well.
  • node['ipaddress'] - The node's ipaddress is IPV4 address of the interface that has the default route. If the node does not have a default route, this attribute will be nil. Using the IP of the interface with the default route is deemed the most sane default.
  • node['macaddress'] - The node's macaddress, from the interface detected for ipaddress above.
  • node['fqdn'] - The fully qualified domain name, for example from hostname -f on Unix/Linux systems. This is also used as the node name unless otherwise set.
  • node['hostname'] - The hostname is the first field from splitting the FQDN on "." (dot).
  • node['domain'] - The domain is the rest of the FQDN after splitting on "." (dot).
  • node['recipes'] - The node's Run List is expanded for roles and recipes, and recipes are stored in this attribute.
  • node['roles'] - The node's Run List is expanded for roles and recipes, and roles are stored in this attribute.
  • node['ohai_time'] - Not commonly used in recipes, but this value is the time epoch of the node when ohai was run, and gets saved to the Chef Server. It is also used in the Knife "status" sub command.

Automatic Attributes lists all the automatic node attributes detected by Ohai. Additional attributes and sub-attributes can be viewed on a particular node by running ohai. This returns data as JSON.

Setting Node Attributes

Node attributes can be set in recipes. This use of node attributes should do done when you want to calculate a derived value, or store some data on the node that should be persisted the next time Chef runs. Use the "set" method on the node.

Attributes are applied in precedence order; node attributes are automatic and have the highest precedence. As these automatic attributes will be re-written with each Ohai run - Chef doesn't provide any way to modify them. See Setting Attributes for more detail on the attribute types and precedences.

Including Recipes

Recipes from other cookbooks can be included in a recipe with the include_recipe keyword. The included recipe's resources will be inserted in order, at the point where include_recipe was called. For example:

Will include the resources defined in recipe apache2::mod_ssl. Note, however, that subsequent calls to include_recipe for the same recipe will have no effect.

You can also pass data from various recipes to one definition. This would be useful if you'd like to update your /etc/aliases, /etc/sudoers, or something similar, with entries from multiple recipes in a single chef run.

Dependencies

When using Chef client/server, you must use cookbook Metadata to declare dependencies on cookbooks' recipes included with include_recipe. This is specified with the "depends" keyword in the metadata.rb of the cookbook.

For example, if the above inclusion of apache2::mod_ssl was in a recipe in the "my_app" cookbook then cookbooks/my_app/metadata.rb would have:

This is not required in Chef Solo because all the cookbooks the node will use must be available since Solo doesn't use a Chef Server to distribute cookbooks.



Command-line Cookbook Dependency Solving with Knife Exec

Need to replicate a node setup elsewhere, and aren't sure of all the cookbook dependencies? Or, just want to validate that you've uploaded all the cookbooks that are stated as being required?

Community member Stephen Nelson-Smith has a blog post on Dependency Solving using Knife Exec.

Other Data Sources

The Chef Server has core features that are useful in Recipes to build fully automated dynamic infrastructure.

* Search Indexes
* Data Bags
* Encrypted Data Bags

The Chef Recipe DSL has keywords for using each of these features.

Search

A basic search query in a recipe looks like this:

Searches can be assigned to variables and then used elsewhere in a recipe. For example, we could search for all nodes with the role "webserver" assigned, then render a template with them.

For more information on using search in recipes, and search queries in general, see the Search documentation. For more information on the Template resource, see its section on the Resources#Template page.

Data Bags

The Chef Server can have arbitrary stores of JSON data called Data Bags, which can also be Encrypted Data Bags. Each bag is a container of one or more items. These items can be loaded in recipes. Given the bag "apps", and the following item "my_app":

We can access the item in a recipe:

The item's keys and values can be accessed like a Ruby Hash.

Other Recipe DSL Methods

There are other methods available in the Recipe DSL.

platform?

The platform? method will return true if one of the parameters matches the node 'platform'. This method takes a comma separated list of platforms.

attribute?

The node.attribute? method will return true if the specified node attribute is defined.

value_for_platform

The value_for_platform method uses a hash to select a particular value based on the node 'platform' and node 'platform_version'.

value_for_platform syntax

For example, the following will set the package_name Ruby variable to "httpd" on Red Hat family distributions, or "apache2" on Debian family distributions.

value_for_platform example

Tags

To use tags in your recipe simply

If you want to test if a machine is tagged

will return true or false. tagged? Takes an array as an argument.

To remove a tag

So all in all

Will output

Ruby in Recipes

Regular Ruby code can also be used in Chef Recipes.

Variables

Assign values to variables in recipes using the assignment operator, "="

Conditionals

Common conditionals can be used to check for true/false. Note that in Ruby, only nil and false are false, everything else is true.

Case

Select a particular package name for a resource based on the platform. This is similar to the example above.

If/Unless

If statements check for true or false values.

Unless is the opposite of if.

Loops

Use the .each method to an Enumerable object (typically an Array or Hash)

Array

Iterate over an array of package names and install them.

Hash

Iterate over a hash of gem package names with specific versions.

Further Reading







Metadata


Creating a "First Run Only" Resource



Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Jan 23, 2012

    It would be nice to add something about how to handle errors and logging. Like whats the appropriate way to generate an error exception or exit if the recipe test decides that something is bad and should immediately exit the chef-client run.

    Another case that I always forget how to do in Chef is to stop processing a recipe but not be an error. Just short-circuit that recipe to return/exit and allow the chef-client run to continue.

    And it might be good to put in this recipes page how to do logging with Chef::Log as well as any other normal non-resource but Chef specific things like logging and exception generation...