我正在研究厨师食谱,我需要根据代码的结果更新一些包含一些信息的数据包。基本上我需要更新成功或失败的数据包。
代码如下所示:
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
块没有处理它。是否有意义?有什么帮助吗?
答案 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