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!
CodePudding user response:
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 the if
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:
if node['platform'] == 'ubuntu'
resource 'foo' do
echo "Ubuntu"
end
end
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.
CodePudding user response:
There is a subtle difference in how only_if
and end if
behave when a node is converged (in Chef speak). In simple terms, when chef-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 not ubuntu
.
Compiling Cookbooks...
Converging 0 resources
Scenario 2:
Using only_if
guard
The resource remains in the collection, but it is skipped when node['platform']
is not ubuntu
.
Compiling Cookbooks...
Converging 1 resources
Recipe: cookbook1::default
* resource[foo] action run (skipped due to only_if)
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.