5

Is there a way to return from Chef recipe without rising an exception?

Say I have a long recipe. I want to add a ruby block to it's beginning which will check some condition (for example directory presence) and stop processing this recipe (but continue to execute the rest of run_list) without raising an exception if condition succeeds.

Conditional execution (only_if/not_if) doesn't solve the problem because I have to add the condition to every resource call in the recipe while there may be very many of them.

There is a comment in Opscode's wiki where the commenter asks about the same but no answer.

HUB
  • 6,322
  • 3
  • 22
  • 22

2 Answers2

3

The way to abort run of a recipe (e.g. due to some condition) is to use a 'return' statement. A thorough discussion appears in jtimberman's answer to a parallel StackOverflow question.

yoniLavi
  • 150
  • 7
  • Can you please elaborate on the `return` syntax - is it just `return`, or is it `return [value]`, or how? The linked answer uses `return if ...` type of syntax – vikingsteve Aug 16 '16 at 10:52
  • No need to return a value. Just a regular "return". Assuming you only want to return in some cases, use an "if" or "unless" guard to only return when needed. Concerning the syntax itself, any valid Ruby code will work in Chef recipes. – yoniLavi Aug 16 '16 at 10:58
1

I would break up that recipe into two pieces and use include_recipe inside an if statement. For example in cookbooks/foo/default.rb:

some_condition = File.exists?("/etc/whatever") # Your specific check here

if some_condition
    include_recipe "foo::conditional_bit"
end

Put your conditional recipe in cookbooks/foo/recipes/conditional_bit.rb and add recipe[foo] to the appropriate node's run list.

Note that the order of execution will be slightly different to if you had specified a ruby block. The condition will be checked during the "compile" phase of the chef-client run, not the "execute" phase. See the Anatomy of a Chef Run page for details.

Tim Potter
  • 1,754
  • 15
  • 15
  • Not too elegant but may be a working solution. I've used only_if in my case because there were not too many repeat-sensetive resources. Anyway you answer may be useful for someone. – HUB Jul 02 '12 at 12:02