Section Objectives:
- Properties of the Chef::Node object
- Common attributes from ohai
- Original location of node attributes
- Node's run list
- Methods available in recipes
- Use
knife
andshef
to examine nodes
.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.
The first class citizen in Chef is the Chef::Node
. The server stores
a copy of the node, and indexes it for search.
Ultimately, the node itself is the authority for its own
configuration. The Chef::Node
object contains the run list and
attributes about the node itself.
An instance of Chef::Node
is created for the Chef run, available in
recipes, templates and other cookbook components as "node
".
Every node has a name which must be unique. By default, Chef will use the node's fully-qualified domain name, since that is fairly safe.
You can override the name using node_name
in the client config, or
by passing -N NAME
to chef-client
.
The Chef::Node
object has a method, name
to return the node's
name.
@@@ruby
# In some recipe...
node.name # => "www1.example.com"
Node's have attributes, which are data about the node itself. Attributes can come from a variety of sources in Chef. Most commonly:
- Automatic (ohai)
- Cookbooks (attributes or recipes)
- Roles
Other locations are available, but they are out of scope for this course.
Ohai determines many node attributes automatically for Chef. This is the first thing that Chef does when it runs.
Values such as platform
, platform_version
, ipaddress
, hostname
are determined by Ohai.
These are "automatic" attributes and cannot be overridden.
You can find the attributes of a node by running "ohai".
The exact attributes will vary by node based on the platform and the available plugins. The following list is an abbreviated example from an Ubuntu Linux node. Each of these may have values that are strings, arrays or hashes.
chef_packages
- version information about Chef and Ohaicpu
- information about installed processor(s)current_user
- UID of the processdmi
- ifdmi_decode
is installed, DMI information is availabledomain
- the node's domain, e.g., the non-hostname portion of thefqdn
.etc
- users and groups on the systemfilesystem
- mounted/available filesystems
fqdn
- fully qualified domain name, e.g.hostname -f
hostname
- first portion offqdn
.ipaddress
- IP address of the interface with the default routekeys
- host SSH keyslanguages
- information about programming languageslsb
- Linux systems with LSB packages may have information heremacaddress
- the MAC address of the interface with the default route.memory
- memory statistics/informationnetwork
- information about all the installed network interfacesohai_time
- the Unix Epoch when Ohai was called
os
- the operating system kernelos_version
- the OS kernel versionplatform
- the platform/distributionplatform_version
- the version of the platform/distributionrecipes
- all the recipes appearing in the expanded run listroles
- all the roles appearing in the expanded run listuptime
- the system's uptimeuptime_seconds
- uptime in seconds, useful for calculationvirtualization
- if the node is virtualized, additional information is avaialble
Node attributes can be used in recipes and templates.
Access node attributes like Ruby hash keys.
@@@ruby
node["fqdn"] # => "www1.example.com"
node["chef_packages"]["chef"]["version"] # => "0.10.8"
Attributes can be used to set up conditional checks using Ruby "if", "unless" and "case" statements.
This is commonly done to match a node's platform.
@@@ruby
case node["platform"]
when "debian", "ubuntu"
package "apache2-doc" do
action :install
end
end
package "apache2" do
case node["platform"]
when "centos","redhat"
package_name "httpd"
end
action :install
end
The platform?
method will return true
if one of the parameters
matches the node["platform"]
attribute. The method takes a comma
separated list of platform names (lower-case).
@@@ruby
# on an ubuntu system:
platform?("ubuntu") # => true
This isn't a Chef::Node
method, but worth mentioning here as an
alternate way to check the node's platform.
Use Ruby's #{} string interpolation to embed an attribute in a string. For example, we can set an attribute where the Apache directory is, and write a configuration file there dynamically.
@@@ruby
template "#{node["apache"]["dir"]}/ports.conf" do
# ...
end
Templates can take a parameter attribute called variables
. These
variables become available to the template. This allows us to shortcut
typing longer attributes.
variables
is a hash, each key must be a symbol (starting with :
), and the value can be
anything. Here we use a node attribute:
@@@ruby
template "#{node["apache"]["dir"]}/ports.conf" do
# ...
variables :apache_listen_ports => node["apache"]["listen_ports"]
end
When referring to the variables in the actual template, we must use a
class instance variable (starting with @
).
#This file generated via template by Chef.
<% @apache_listen_ports.each do |port| -%>
Listen <%= port %>
NameVirtualHost *:<%= port %>
<% end -%>
We can also use node attributes directly.
ServerRoot "<%= node["apache"]["dir"] %>"
# ...
<% if node["platform"] == "debian" || node["platform"] == "ubuntu" -%>
Node attributes used in a template can come from the cookbook itself, or one auto detected by chef such as "platform".
.notes We do not need to use the @
symbol on the node.
Node attributes can come from cookbooks.
Use an attributes file in a cookbook to set defaults.
These default values are to ensure that some value is set.
All the attributes files in all cookbooks on the node are loaded and all attributes are applied to the node object.
Use the "default" keyword to set the attributes.
The node object is implied, default
is a method of Chef::Node.
default["apache"]["listen_ports"] = [ "80","443" ]
default["apache"]["contact"] = "ops@example.com"
default["apache"]["timeout"] = 300
Setting attributes is the same as calling a method on the node object, and this can also be done in a recipe.
Do this when you want to calculate a value for the attribute.
Calculated values can come from Ruby expressions, searches, external data sources and more.
When setting attributes in recipes, use the node.set method.
This allows additional overrides to be used, but has higher priority
than cookbook attributes files "default" and "set" and role
"default_attributes
" values.
@@@ruby
node.set['unicorn']['workers'] = node['cpu']['total'].to_i * 4
Node attributes can be set in roles using "default_attributes
".
This overrides the attributes set using "default" in the cookbook's attributes file.
name "webserver"
description "Systems that serve HTTP traffic"
run_list(
"recipe[apache2]",
"recipe[apache2::mod_ssl]"
)
default_attributes(
"apache" => {
"listen_ports" => [ 80, 443, 8080 ]
}
)
The Chef::Node#attribute?
method can be used to check if the node
has a given attribute. Use it with a top-level key to find sub-keys.
@@@ruby
node.attribute?("fqdn") # => true
node.attribute?("aaaaa") # => false
node['chef_packages'].attribute?("chef") # => true
The run list is an array of roles and/or recipes to apply on the node.
The run list is expanded during run time to determine the cookbooks to download (by recipe name).
The expanded list of roles are stored in the attribute
node["roles"]
.
The expanded list of recipes are stored in the attribute
node["recipes"]
.
Recipes that are included via include_recipe
method are not expanded.
The run list is an array, which means it is ordered by numeric index of the elements it contains.
The expanded run list's recipes are in the order they appear in run list elements (node itself or in roles).
Recipes are applied on the node in the order specified.
The Chef::Node#role?
method will check if the node's run list has
the specified role.
@@@ruby
node.role?("base")
Use the Chef::Node#recipe?
method to check if the node has a given
recipe or not.
First, the run list is consulted for the named recipe. Second, the
node's run state is checked for recipes Chef has seen via include_recipe
.
@@@ruby
node.recipe?("webserver")
When Chef runs, it stores ephemeral information about the node in the
run_state
. This is per-run data that is not persisted to the Chef
Server.
run_state
is a method of the node object that returns its contents.
An example of content in the run state is the list of recipes that Chef has seen as they are loaded.
Every node has an environment. If you do not explicitly set one,
_default
is used.
Chef environments allow you to set cookbook version constraints to nodes in a particular environment, e.g. "production".
Retrieve the value of the node's environment with the
Chef::Node#chef_environment
method.
@@@ruby
node.chef_environment # => "_default"
We will discuss Chef Environments later.
Use knife node list
to list all the node objects on the Chef Server.
> knife node list
Use knife node show
to display a node object on the Chef Server.
> knife node show i-2b58ad4a
Node Name: i-2b58ad4a
Environment: _default
FQDN: domU-12-31-39-07-D5-65.compute-1.internal
IP: 107.20.14.15
Run List: role[base], role[webserver]
Roles: base, webserver
Recipes: apt, chef-client, webserver
Platform: ubuntu 10.04
knife node show
has several options to modify the output of the node
object. We can show only the run list:
> knife node show i-2b58ad4a -r
run_list:
role[base]
role[webserver]
The Chef environment:
> knife node show -E i-2b58ad4a
chef_environment: _default
Or a specific attribute:
> knife node show i-2b58ad4a -a ec2.public_hostname
ec2.public_hostname: ec2-107-20-14-15.compute-1.amazonaws.com
The Chef::Node
is actually a JSON object but the format returned is
a bit nicer for humans to read. Show the data in another format with
-F
and specify a format. Valid alternate formats are JSON ("j"),
YAML ("y") or Text (default, or "t")
> knife node show i-2b58ad4a -Fj
> knife node show i-2b58ad4a -r -Fj
> knife node show i-2b58ad4a -a ec2 -Fj
We can use shef
to examine properties of the Chef::Node
object. Similar to chef-client
, shef
loads a node
object on
startup, including attributes from Ohai.
> shef
loading configuration: none (standalone shef session)
Session type: standalone
...
Ohai2u jtimberman@localhost.localdomain!
chef >
Show the Chef::Node
object itself:
chef > node
=> <Chef::Node:0xb75b9c @name="localhost.localdomain">
Show the node's name:
chef > node.name
=> "localhost.localdomain
Show the node's environment and run list:
chef > node.chef_environment
=> "_default"
chef > node.run_list
=>
Show some attributes about the node:
chef > node['ipaddress']
=> "10.0.0.100"
chef > node['platform']
=> "ubuntu"
chef > node['platform_version']
=> "11.10"
- Properties of the Chef::Node object
- Common attributes from ohai
- Original location of node attributes
- Node's run list
- Methods available in recipes
- Use
knife
andshef
to examine nodes
- In a recipe, how do you get the node's name?
- What are some commonly available attributes?
- Where can attributes come from?
- What kind of attributes should be set in a cookbook attributes file?
- When should attributes be set from a recipe?
- Are recipes included with
include_recipe
in thenode["recipes"]
attribute? - What order are recipes applied to the node by Chef?
- What is the node's run state? Is it saved on the server?
- http://wiki.opscode.com/display/chef/Nodes
- http://wiki.opscode.com/display/chef/Attributes
- http://wiki.opscode.com/display/chef/Environments
Chef Node
- View the node object on the Chef Server with knife
- Create new attributes on the node with a cookbook and role.
- Use node attributes in a conditional in the recipe.