Chef Speak
Express yourself completely,
then keep quiet.
Perhaps the biggest hurdle to overcome when learning Chef, especially for those new to configuration management software, is the terminology. Learning the language is an absolute necessity for understanding Chef and being able to explain problems when they arise. The difficulty in learning Chef’s language, I think, has two root causes: firstly, Chef’s abstractions of system configuration concepts appear novel to users unfamiliar with them—users might be learning the abstractions with little frame of reference; and secondly, it’s hard to find authoritative definitions of what the terms mean in Chef. This makes it more difficult to learn Chef by reading the wiki, since you won’t know what to look at until you know what the words mean. Luckily, Chef’s concepts are pretty intuitive, so learning to speak like a chef won’t be difficult. Here we go:
Resource
A resource is usually a cross platform abstraction of the thing you’re configuring on the host. For example, packages may be installed via apt, yum, or the BSD ports and packages systems, but the package resource abstracts these differences away so you can specify that a package should be installed in a cross-platform way. Chef’s resources are mostly just containers for data, with some basic validation functionality.
Attribute (On a Resource)
As I just noted, resources are mostly containers for data. Attributes are the pieces of data that resources contain. In the case of managing a package, this might be the name of the package you want to install, the version you want to install, or options to pass to the package manager.
NOTE: The Chef developers have discussed renaming these “properties” or something similar, to avoid overloading the term “attribute,” which is also used to describe data associated with nodes and roles, described below. For now, though, the documentation says “attribute,” so that’s what I’m using here.
Action
The action is what you want Chef to do with the resource: should the package be installed? Upgraded to the latest version? Removed? Actions are usually specific to the resource, but all resources support the nothing action, which does what its name suggests.
Provider
The provider is the specific implementation of what the resource abstracts. On Red Hat or CentOS, a package resource will use the yum package provider to get the package installed, but on Debian and Ubuntu, the apt package provider will be used. Providers contain most of the intelligence: they’re responsible for making Chef idempotent by checking if an action needs to be taken and issuing the commands to the system to take that action. In the case of package providers, they first check if the desired version of a package is installed and run the yum, apt-get, or or other package manager commands to install or upgrade as needed. When working with Chef, you normally don’t need to worry about providers. For the occasions when you do, Chef provides “shortcut” resources which will always use the desired provider. The dpkg_package and rpm_package resources allow you to install packages directly from the filesystem, using providers specific to these package managers, for example.
Templates
Templates, as one would expect, are files with all of the important data substituted with code so we can fill them in later. You can use templates to create any kind of file you like, though the most common use is to create configuration files with host-specific parameters filled in dynamically. Using templates involves a template resource, which Chef backs with a template provider, and the template file itself.
Chef templates use ERb (Embedded Ruby) syntax, though Chef uses the erubis implementation of ERb for speed.
Recipe
Recipes are the files where you write your resources. Recipes can also contain arbitrary ruby code, but you need to understand a little bit about how Chef runs to make productive use of this. Each Chef run is a two stage process: in the first step, usually called the compilation step, Chef evaluates the recipe files, building up a list of the resources. In the next step, Chef executes the desired action for each resource on the provider for that resource. Any arbitrary code in a recipe will be run during the compilation step, not the execution step. To defer execution until the execution phase of the Chef run, use the ruby_block resource.
Node
A node is a host that runs Chef. The primary features of a node, from Chef’s point of view, are its attributes and its run list. In the distant future, Chef may support a “virtual node” concept, where the Chef client runs on one host but configures another, such as a router or switch that can’t run ruby. For now, though, the Chef client is assumed to be running on the node it configures. This means that every host you want to manage with chef will need ruby and the Chef client installed.
Role
A role provides a means of grouping similar features of similar nodes. At web scale, you almost never have just one of something, so you can use roles to express the parts of the configuration that are shared by a group of nodes. Roles consist of the same parts as a node: attributes and a run list. When the Chef client runs, it merges its own attributes and run list with those of any roles it has been assigned.
Attribute (On a Node or Role)
Nodes and roles have associated attributes, which are a structure of nested key–value pairs. Node and role attributes are commonly used as inputs for resource attributes. For example, your production boxes might be using one version of nginx, but you’d like to install a newer version on your staging servers for testing. By using a node or role attribute to specify the version, you can use the same recipe in both environments.
Chef allows attributes to be set in attribute files (among other myriad ways). Code in these files accesses the node chef is running on, and manages attributes on that node directly. In ruby terms, the value of self within attribute files is the node. Using attribute files, you can rely on a node having a sane value for an attribute when writing a recipe without having to worry that the node may not have defined that attribute.
Advanced Chef users often make heavy use of attributes defined in roles to manage attributes on many nodes at once.
Cookbook
A cookbook is a collection of the various related files, such as recipes, templates, and attributes files that chef uses to configure a system, plus metadata. Cookbooks are typically grouped around configuring a single package or service. The MySQL cookbook, for instance, contains recipes for both client and server, plus an attributes file to ensure the attributes used in the recipes are available if they haven’t been defined on the node in some other way.
Metadata
Cookbooks often rely on other cookbooks for pre-requisite functionality. In order for the server to know which cookbooks to ship to a client, a cookbook that depends on another one needs to express that dependency somewhere. That “somewhere” is in its metadata. Dependency tracking is the most visible part of metadata, but metadata also can contain information about authorship, licensing, a description of the cookbook, what platforms the cookbook is expected to work on, and whether or not a cookbook plays nice with other cookbooks. At the moment, Chef supports many more fields for metadata than it actually uses, but maintaining accurate dependency information is absolutely essential, since nodes may not get all of the cookbooks they need if this information is incomplete.
Run List
In the simplest case, the run list is just an ordered list of the recipes that a node should run. Assuming the cookbook metadata is correct, you can put just the recipes you want to run in the run list, and dependent recipes will be run automatically as needed.
In the more complicated case, the run list will include roles that a node has been assigned along with any recipes set on the node explicitly. In this case, when the Chef client runs, the run list is “expanded” into a list of recipes by replacing the role’s entry in the run list with the list of recipes the role specifies in its run list.










