Ruby code blocks and Chef
If you come from another language (not Ruby), this syntax might seem very strange. Let's break down things.
When calling a method with parameters, in most cases the parentheses are optional:
foo(bar)
is equivalent tofoo bar
foo(bar, baz)
is equivalent tofoo bar, baz
A Ruby block of code can be wrapped in curly braces ({}
) or inside a do..end
block and can be passed to a method as its last parameters (but note that there's no comma and if you're using parentheses it goes after them. Some examples:
foo(bar) { # code here }
foo(bar) do
# code here
end
foo bar do
# code here
end
foo do
# code here
end
In some cases, code blocks can receive parameters, but in Chef the resources' blocks never do. Just for reference, the syntax for that is:
foo(bar) do |baz, qux|
baz + qux
end
Specifically about Chef resources, their syntax is usually:
resource_type(name) do
attribute1 value1
attribute2 value2
end
This means that, when you say:
log "a debug string" do
level :debug
end
you're actually creating a log
resource whose name
attribute is set to "a debug string"
. It can later be referred to (in other resources, for example) using log[a debug string]
.
AFAIK, the name
attribute is mandatory for every Chef resource type as it's what makes it unique, and allows you to, among other things, call actions on it after it has been declared.
Side note: The ruby block is usually optional for a Chef resource. If you do something like:
directory "/some/path"
Chef will compile that resource using its default attributes (among which is action :create
), and try to create the named directory using those.
How prevent chef failure on ruby code?
You didn't show where title
comes from so they best I can say is to put your code in a ruby_block
resource and use the ignore_failure
property. You can also use normal Ruby rescue
blocks for imperative code but be aware of how that interacts (or rather, doesn't) with resources, see https://coderanger.net/two-pass/ for some details on the loading process Chef uses.
Ruby blocks as used in Chef, trouble understanding syntax
I answered the same question at https://stackoverflow.com/a/20569738/123527
# Call the method directory passing the path and a block
# containing some code to be evaluated in the given context
template "/etc/profile.d/golang.sh" do
# Use the ERB template defined at "golang.sh.erb"
source "golang.sh.erb"
# chown the file to the user root
owner "root"
group "root"
# set the permissions to 0555
mode "0755"
end
Blocks are a convenient way to specify a group of operations (in this case create, set permissions, etc) to be evaluated in a single context (in this case in the context of that path).
template
, source
, owner
, group
, etc are all Ruby methods.
Chef - run install block based on variable condition
The problem is Chef's two-pass model. See https://coderanger.net/two-pass/ for the full explanation for for this you just need to move the condition check in to the only_if
block itself since that is delayed until converge time: only_if { ::File.directory?('/opt/MyPkg/conf') }
.
Using the fatal
log level is also probably not a good idea as this isn't actually a fatal error as written.
How to use a Ruby block to assign variables in chef recipe
Your problem is compile time versus converge time. Your block will be run at converge time but at this time the node['host']
in the execute resource has already been evaluated.
The best solution in this case would be to use lazy evaluation so the variable will be expanded when the resource is converged instead of when it is compiled:
execute "Enable on hosts" do
command lazy { "#{path}/command --enable -N #{node['hosts']}" }
end
Here's a little warning though, the lazy operator has to include the full command
attribute text and not only the variable, it can work only as first keyword after the attribute name.
Related Topics
Unknown Ruby Interpreter Version (Do Not Know How to Handle): Ruby_Version
Ruby: How to Load a File into Interactive Ruby Console (Irb)
Ruby - Elegantly Convert Variable to an Array If Not an Array Already
Generating Unique, Hard-To-Guess "Coupon" Codes
Rails 3/Ruby: Activerecord Find Method in Condition Array to Parameters Single Quote Issue
Why Is Safe Navigation Better Than Using Try in Rails
Undefined Method '>' for Nil:Nilclass <Nomethoderror>
Sidekiq Configuration for Multiple Environments
Generate All Possibles Combinations of an Array with a Length Within a Given Range
Mailer Unable to Access Reset_Token in User Model
File.Open, Open and Io.Foreach in Ruby, What Is the Difference
How to Convert a JSON Formatted Key Value Pair to Ruby Hash with Symbol as Key
Rails Authentication Across Apps/Servers
How to Suppress the Output of Return Value in Irb/Rails Console