在某些情况下,我需要使用非零状态代码中止/结束 Chef 运行,然后它将通过我们的部署链传播回并最终传播到 Jenkins,从而产生一个又大又肥的红球。
做这个的最好方式是什么?
在某些情况下,我需要使用非零状态代码中止/结束 Chef 运行,然后它将通过我们的部署链传播回并最终传播到 Jenkins,从而产生一个又大又肥的红球。
做这个的最好方式是什么?
对于将来可能不熟悉 Chef 的读者来回答这个问题,Chef 运行“聚合”节点,或使其符合它正在运行的配方中声明的策略。这也称为“收敛”。这有两个阶段,“编译”和“执行”。编译阶段是 Chef 评估(“编译”)食谱的 Ruby 代码,寻找要添加到资源集合中的资源。完成后,它会“执行”每个资源的操作以将其置于所需的状态。运行系统命令等。
Erik Hollensbe在 2013 年写了一篇关于其工作原理的精彩演练。
现在,为了答案:
有几种方法可以结束 Chef 运行或退出 Chef 配方,具体取决于您想要如何进行,因为 Chef 配方是 Ruby 代码。
如果您的目标是根据条件停止处理配方,但继续运行其余部分,请使用return
Ruby 关键字。例如:
file '/tmp/ponies' do
action :create
end
return if platform?('windows')
package 'bunnies-and-flowers' do
action :install
end
我们假设如果系统是 Windows,它没有可以安装 bunnies-and-flowers 包的包管理器,所以我们从哪里回来。
如果您希望完全中止 Chef 运行
Tl;博士:使用raise
。如果出现错误情况,最好中止 Chef 运行。
也就是说,如果在运行中的任何地方遇到未处理的异常,chef-client 就会退出。例如,如果模板资源找不到它的源文件,或者如果运行 chef-client 的用户没有权限执行诸如创建目录之类的操作。这就是为什么 usingraise
也可以结束运行的原因。
你把raise
事情放在哪里。如果在ruby_block
资源中使用它,它只会在收敛的执行阶段引发。如果您在return
上面示例的资源之外使用它,它将在编译阶段发生。
file '/tmp/ponies' do
action :create
end
raise if platform?('windows')
package 'bunnies-and-flowers' do
action :install
end
也许我们在 Windows 上确实有一个包管理器,我们希望安装这个包。加注将导致 Chef 致命地退出并提供堆栈跟踪。
在过去的几年里,另一种方法是使用Chef::Application.fatal!
- 正如我在这个答案中所写的那样。时代变了,不推荐这样做。不要再这样做了。如果您正在这样做,请切换到raise
并如前所述,如果您的需求更复杂,请编写自己的异常处理程序(见下文)。
更优雅的错误处理
由于配方是 Ruby,您还可以使用begin..rescue
块优雅地处理错误情况。
begin
dater = data_bag_item(:basket, "flowers")
rescue Net::HTTPServerException
# maybe some retry code here?
raise "Couldn't find flowers in the basket, need those to continue!"
end
data_bag_item
对 Chef 服务器上的数据包发出 HTTP 请求,Net::HTTPServerException
如果服务器出现问题(404 未找到、403 未授权等),将返回 a。我们可能会尝试重试或做一些其他处理,然后回退到raise
.
报告错误
如果您从命令行运行 Chef,只需退出并抛出堆栈跟踪就可以了。但是,如果您在cron
几台甚至几十台或数百台机器上运行它或作为守护程序运行它,那么当出现问题时,这并不是保持理智的好方法。
输入Chef 的报告/异常处理程序功能。您可以为 Chef 运行使用处理程序。所有报告处理程序都在 Chef 运行结束时运行。异常处理程序在中止的 Chef 运行结束时运行。运行的状态被跟踪,并且可以在处理程序中检查,因此您可以编写一个处理两种运行(成功/完成或不成功/中止)的程序。
该文档告诉您如何编写一个。它还包括可用于各种服务的可用开源处理程序列表,包括:
还有很多。
中止或编辑 Chef 运行的推荐方法是引发异常。这是一个例子:
ruby_block "some tricky operation" do
block do
OperationFoo
raise "Operation Foo Failed" if some_condition
end
end
厨师::Application.fatal!应该做你想要的。这是我们代码库中的一个示例,可能会有所帮助。
cipher = case key.length
when 16 then "AES-128-ECB"
when 24 then "AES-192-ECB"
when 32 then "AES-256-ECB"
else
Chef::Application.fatal!("AES Key must be 16, 24, or 32 characters in length but key #{key} has length of #{key.length}")
end
chef
当您想在某些操作后完成时,只需使用以下语句:
throw :end_client_run_early
它将退出而没有任何错误。
要在 chef-solo 运行期间执行不干净的退出,请尝试以下操作:
bash 'exit' do
code 'killall -9 chef-solo'
end