0

I want to abort a recipe at the run time based on a certain condition but use raise or Chef::Application.fatal! as described in this post How do you abort/end a Chef run? my recipe is exiting at the compilation time only.

Here is what I am trying (a part of my script):

execute "Execute somehthing" do
  cwd node['abc']['dir']
  command "something >> #{results}"
  node.default['success'] = "false"
  notifies :run, "ruby_block[jobFailure]", :delayed
  not_if "cd #{node['abc']['dir']} && somecommand >> #{results}"
end

ruby_block "jobFailure" do
  raise "Exiting the script as the job has failed" if (node.default['success'] == "false")
  action :nothing
end

But while running the above script I am getting the error as Chef is exiting at the compilation time only giving the below error:

Running handlers:
[2014-10-27T17:17:03+00:00] ERROR: Running exception handlers
Running handlers complete
[2014-10-27T17:17:03+00:00] ERROR: Exception handlers complete
[2014-10-27T17:17:03+00:00] FATAL: Stacktrace dumped to c:/Users/manish.a.joshi/
.chef/local-mode-cache/cache/chef-stacktrace.out
Chef Client failed. 0 resources updated in 12.400772 seconds
[2014-10-27T17:17:03+00:00] FATAL: RuntimeError: Exiting the script as the job has failed

Can anyone let me know if there is a way to only execute the raise command based on a condition?

Community
  • 1
  • 1
Manish Joshi
  • 2,512
  • 1
  • 18
  • 29
  • It's not clear what your condition is. Can you please edit your question to clarify what the condition is that you're checking? – Tejay Cardon Oct 27 '14 at 23:27

2 Answers2

3

So first off Chef doesn't work like this and this code won't work as you expect regardless, but you have to put the code in actual block for the ruby_block:

ruby_block "jobFailure" do
  block do
    raise "Exiting the script as the job has failed" if (node.default['success'] == "false")
  end
  action :nothing
end

The node.default['success'] = "false" that you have in the execute resource will happen regardless of the status of the command and will happen at compile time. Chef resources do not have return values in this manner.

coderanger
  • 44,716
  • 4
  • 39
  • 59
  • You could add an only_if to the job_failure `ruby_block` and test your success condition there. – Tejay Cardon Oct 27 '14 at 19:13
  • That wouldn't change anything, the success or failure of execute resource isn't something you can communicate to another resource easily. If the execute resource fails, Chef will abort. To do this kind of thing you need to write an LWRP generally, and use shell_out directly. – coderanger Oct 27 '14 at 19:31
  • I'm well aware, but I don't think OP was planning to do that. My impression was that the exit condition and the result of the execute are two distinct things. The execute could succeed while the "condition" still failed. If that's the case, then the condition could be tested as condition on the ruby block. – Tejay Cardon Oct 27 '14 at 23:25
  • The above answer worked for me.. Since the command I am executing is "some command" >> "output.file" so even if the command fails due to some reason it gets captured in the output file, but chef doesn't exit as for chef, the command was to put the result in the output file. And then based on the execute block I am executing `raise` at the end of chef recipe, because I know that if execute block was run by chef it means the not_if command in there was failed and hence I need to abort my script... Thanks for the answer @coderanger – Manish Joshi Oct 28 '14 at 10:51
1

It sounds like you only want to execute your execute block if your condition has failed. If that's the case, you could use a single resource to accomplish both tasks.

execute "Execute somehthing" do
  cwd node['abc']['dir']
  command "something >> #{results} && exit 1"
  node.default['success'] = "false"
  notifies :run, "ruby_block[jobFailure]", :delayed
  not_if "cd #{node['abc']['dir']} && somecommand >> #{results}"
end

Adding the && exit 1 will cause the execute resource to fail and thus terminate the chef run.

Of course, this only works if you want to terminate immediately. Your current code uses a :delayed notification, which means your chef run will continue until all resources have executed, and then fail during the delayed notifications. This may nor may not be what you intended.

If you really do want to terminate during the notifications, then try this (notice that setting the node attribute is not helpful)

execute "Execute somehthing" do
  cwd node['abc']['dir']
  command "something >> #{results}"
  notifies :run, "ruby_block[jobFailure]", :delayed
  not_if "cd #{node['abc']['dir']} && somecommand >> #{results}"
end

ruby_block "jobFailure" do
  block
    raise "Exiting the script as the job has failed"
  action :nothing
end
Tejay Cardon
  • 3,993
  • 1
  • 13
  • 29
  • Thanks, I really wanted to terminate the session after all chef resources have been run, and thus I have used `:delayed`, but I like your idea of using `&& exit 1;` because in one of my other recipes I was trying to use `:immediately` for calling the ruby section immediately if the condition fails but it was not working.. Seems a different question, but do you have idea why `immediately` was not calling the ruby block immediately but only at the end much like `delayed`? – Manish Joshi Nov 05 '14 at 17:31
  • I'd need more info. There's no reason why an :immediate notification wouldn't be immediate. – Tejay Cardon Nov 05 '14 at 22:45