如何捕获Chef异常

时间:2013-08-20 17:39:58

标签: ruby chef chef-recipe

我正在研究厨师食谱,我需要根据代码的结果更新一些包含一些信息的数据包。基本上我需要更新成功或失败的数据包。

代码如下所示:

begin
     node[:fileDeploy].each do |f|
        if f[:deploy]
          cookbook_file "#{f[:subdirectory]}/#{f[:targetFilename]}" do
             owner users['tomcatUser']
             group users['tomcatGroup']
             mode "0755"
             cookbook node[:cookbookName]
             source "#{f[:sourceFilename]}"
          end
        end
     end
     # Update data bag: succeeded
rescue Chef::Exceptions::FileNotFound => e
     # Update data bag: failed
end

问题在于,即使文件丢失,救援区也不会被取消,数据包也不会相应更新。 因此,当我在服务器上运行命令sudo chef-client时,它最终会遇到异常Chef::Exceptions::FileNotFound,但rescue块没有处理它。是否有意义?有什么帮助吗?

1 个答案:

答案 0 :(得分:5)

您的救援块没有捕获异常,因为引发异常的代码不会在异常处理程序的范围内执行。

在您的代码中,您声明了cookbook_file资源。声明正常,资源计划在收敛阶段执行。您的救援块可以捕获在资源声明期间发生的异常,而不是在实际执行时发生的异常。

请参阅About the chef-client Run以了解有关厨师运行的两个阶段的更多信息,即资源收集的生成和后来的收敛。

现在,为了得到您想要的结果,您可以在收敛期间检查源文件存在的条件并做出相应的决定。

一般来说,Chef的处理错误相当困难。这是设计的,因为您通常应该设计您的系统,使其独立于其他部分。因此,如果您需要存在目录或文件,则应使用适当的资源明确创建该目录或文件。然后,如果当前资源“已更改”(无论对特定资源意味着什么),您都可以使用notifications通知其他资源运行某个操作。

下面的代码尝试实现类似于您显然想要的东西。在收敛期间它仍然没有捕获异常,但是尝试不首先引发异常,但检查所需的条件并运行适当的资源。

node[:fileDeploy].each do |f|
  if f[:deploy]
    cookbook_file "#{f[:subdirectory]}/#{f[:targetFilename]}" do
      owner users['tomcatUser']
      group users['tomcatGroup']
      mode "0755"
      cookbook node[:cookbookName]
      source f[:sourceFilename]
      only_if{ Dir.exist?(File.base_name(f[:sourceFilename]) }
      notifies :run, "execute[success #{f[:sourceFilename]}]", :immediately
    end

    # This one gets notified (and run) when the cookbook_file is successful
    execute "success #{f[:sourceFilename]}" do
      action :nothing
      command "do whatever you like"
    end

    # This one runs only if f[:sourceFilename] doesn't exist by now
    execute "error #{f[:sourceFilename]}" do
      action :run
      command "do whatever you like"
      creates f[:sourceFilename]
    end
  end
end