56

在某些情况下,我需要使用非零状态代码中止/结束 Chef 运行,然后它将通过我们的部署链传播回并最终传播到 Jenkins,从而产生一个又大又肥的红球。

做这个的最好方式是什么?

4

5 回答 5

117

对于将来可能不熟悉 Chef 的读者来回答这个问题,Chef 运行“聚合”节点,或使其符合它正在运行的配方中声明的策略。这也称为“收敛”。这有两个阶段,“编译”和“执行”。编译阶段是 Chef 评估(“编译”)食谱的 Ruby 代码,寻找要添加到资源集合中的资源。完成后,它会“执行”每个资源的操作以将其置于所需的状态。运行系统命令等。

Erik Hollensbe在 2013 年写了一篇关于其工作原理的精彩演练。

现在,为了答案:

有几种方法可以结束 Chef 运行或退出 Chef 配方,具体取决于您想要如何进行,因为 Chef 配方是 Ruby 代码。

如果您的目标是根据条件停止处理配方,但继续运行其余部分,请使用returnRuby 关键字。例如:

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 运行结束时运行。运行的状态被跟踪,并且可以在处理程序中检查,因此您可以编写一个处理两种运行(成功/完成或不成功/中止)的程序。

文档告诉您如何编写一个。它还包括可用于各种服务的可用开源处理程序列表,包括:

  • 通过 SMTP 发送电子邮件
  • 国税局
  • 石墨
  • 嘻哈聊天

还有很多。

于 2013-01-12T13:58:31.193 回答
8

中止或编辑 Chef 运行的推荐方法是引发异常。这是一个例子:

ruby_block "some tricky operation" do
  block do
    OperationFoo
    raise "Operation Foo Failed" if some_condition
  end
end
于 2013-01-12T04:59:50.713 回答
2

厨师::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
于 2013-05-02T20:35:18.047 回答
-2

chef当您想在某些操作后完成时,只需使用以下语句:

throw :end_client_run_early

它将退出而没有任何错误。

于 2018-01-19T09:20:02.440 回答
-5

要在 chef-solo 运行期间执行不干净的退出,请尝试以下操作:

bash 'exit' do
    code 'killall -9 chef-solo'
end
于 2016-02-01T19:44:03.937 回答