In chef (therefor, ruby), I’ve seen two ways of declaring conditionals
resource 'foo' do
echo "Ubuntu"
end if node['platform'] == 'ubuntu'
and
resource 'foo' do
echo "Ubuntu"
only_if node['platform'] == 'ubuntu'
end
Don’t these effectively do the same thing? In the official docs, it seems "only_if" is the preferred way, and I can’t find many examples of the "end if", but just curious if they, as they seem, do the same thing (execute the block only if the conditional is true).
Thanks!
2
Answers
Chef Resource Guard Clauses vs. Expression Post-Conditions
only_if is a guard clause that’s part of the Chef DSL. However,
do...end if
is a Ruby modifier control expression (sometimes called a post-condition) applied to a block that functions the same way a normal Ruby if/then statement works. Note that even though theif
is placed after the expression to be evaluated, the post-condition is still evaluated first.Think of
only_if
as a Chef-specific resource statement. The other is just syntactic sugar supported by Ruby’s interpreter, and the example you cited (assuming it works in Chef outside a Ruby resource block; I didn’t bother to test it) is the same as writing the block inside a more standard if-statement like this one:Most Chef resources should follow the current style guides and DSL features, but post-conditions are very common in idiomatic Ruby because they emphasize the expression rather than the conditional and because they allow for more brevity of code.
There is a subtle difference in how
only_if
andend if
behave when a node is converged (in Chef speak). In simple terms, whenchef-client
starts, it compiles the cookbooks and creates a collection of resources that will converge on the node.For the sake of example, let’s say we have a cookbook
cookbook1
with only 1 resource in the recipe. When we run such cookbook in below scenarios:Scenario 1:
Using
do .. end if
:The resource is removed from the compilation when the condition is not matched. So there will be no resources to run. Example output from chef-client run when
node['platform']
is notubuntu
.Scenario 2:
Using
only_if
guardThe resource remains in the collection, but it is skipped when
node['platform']
is notubuntu
.In short, pure Ruby code, such as
if
conditions will run during "compile" phase itself. Chef resources run during the "converge" phase. See the Chef Infra Client documentation for details.