Chef

Just Enough Ruby for ChefΒΆ

Chef uses Ruby as its reference language. Ruby is a simple programming language that Chef uses to define the patterns that are found in resources, recipes, and cookbooks. In many cases, just using these patterns is enough to configure, deploy, and manage nodes across the network. Ruby is also a powerful and complete programming language. You can use the full power of the Ruby programming language to make decisions about what should happen to specific resources and recipes or to extend Chef in any manner that your organization requires.

The chef-client uses Ruby as its reference language for creating cookbooks and defining recipes, with an extended DSL (domain-specific language) that is used for specific resources. These settings are saved as Ruby files and are stored in the chef-repo. When these files are uploaded to the Chef server, they are converted to JSON. Each time the chef-repo is refreshed, the contents of all domain-specific Ruby files are re-compiled to JSON and are re-uploaded to the Chef server.

Many people who are new to Ruby often find that it doesn’t take very long to get up to speed with the basics. For example, it’s useful to know how to check the syntax of a Ruby file, such as the contents of a cookbook named my_cookbook.rb:

$ ruby -c my_cookbook_file.rb

to return:

Syntax OK

Here is a quick rundown of some basic Ruby commands.

Anything after a # is a comment.

# This is a comment.

Assign a local variable:

x = 1

Do some basic arithmetic:

1 + 2           # => 3
2 * 7           # => 14
5 / 2           # => 2   (because both arguments are whole numbers)
5 / 2.0         # => 2.5 (because one of the numbers had a decimal place)
1 + (2 * 3)     # => 7   (you can use parens to group expressions)

Work with strings:

'single quoted' # => "single quoted"
"double quoted" # => "double quoted"
'It\'s alive'   # => "It's alive!"
"1 + 2 = 5"     # => "1 + 2 = 5" (numbers surrounded by quotes may exhibit string-like behavior)

Embed Ruby in a string:

x = "Bob"
"Hi, #{x}"      # => "Hi, Bob"
'Hello, #{x}'   # => "Hello, \#{x}" Notice that single quotes don't work with #{}

Work with basic truths:

true            # => true
false           # => false
nil             # => nil
1 == 1          # => true ( == tests for equality )
1 == true       # => false ( == tests for equality )

Work with basic untruths (! means not!):

!true           # => false
!false          # => true
!nil            # => true
1 != 2          # => true (1 is not equal to 2)
1 != 1          # => false (1 is not not equal to itself)

Convert something to either true or false (!! means not not!!):

!!true          # => true
!!false         # => false
!!nil           # => false (when pressed, nil is false)
!!0             # => true (zero is NOT false).

Create lists using arrays:

x = ["a", "b", "c"] # => ["a", "b", "c"]
x[0]                # => "a" (zero is the first index)
x.first             # => "a" (see?)
x.last              # => "c"
x + ["d"]           # => ["a", "b", "c", "d"]
x                   # => ["a", "b", "c"] ( x is unchanged)
x = x + ["d"]       # => ["a", "b", "c", "d"]
x                   # => ["a", "b", "c", "d"]

A Hash is a list with keys and values. Sometimes they don’t have a set order:

h = {
"first_name" => "Bob",
"last_name"  => "Jones"
}

And sometimes they do. For example, first name then last name:

h.keys              # => ["first_name", "last_name"]
h["first_name"]     # => "Bob"
h["last_name"]      # => "Jones"
h["age"] = 23
h.keys              # => ["first_name", "age", "last_name"]
h.values            # => ["Jones", "Bob", 23]

Use Perl-style regular expressions:

"I believe"  =~ /I/                       # => 0 (matches at the first character)
"I believe"  =~ /lie/                     # => 4 (matches at the 5th character)
"I am human" =~ /bacon/                   # => nil (no match - bacon comes from pigs)
"I am human" !~ /bacon/                   # => true (correct, no bacon here)
/give me a ([0-9]+)/ =~ "give me a 7"     # => 0 (matched)

Use conditions! For example, an if statement

if false
  # this won't happen
elsif nil
  # this won't either
else
  # code here will run though
end

or a case statement:

x = "dog"
case x
when "fish"
 # this won't happen
when "dog", "cat", "monkey"
  # this will run
else
  # the else is an optional catch-all
end

Define a method (or a function, if you like):

def do_something_useless( first_argument, second_argument)
  puts "You gave me #{first_argument} and #{second_argument}"
end

do_something_useless( "apple", "banana")
# => "You gave me apple and banana"
do_something_useless 1, 2
# => "You gave me 1 and 2"
# see how the parens are optional if there's no confusion about what to do

Call a method on something with .method_name():

x = "My String"
x.split(" ")            # => ["My", "String"]
x.split(" ").join(", ") # => "My, String"

To learn more about Ruby, see the following: