自定义厨师处理程序

Custom Chef handlers

我正在尝试了解有关 Custom Handlers 的 Chef 文档。

这些步骤看起来很简单,但我仍然不明白它是如何工作的。

  1. 下载 chef_handler 食谱
  2. 创建自定义处理程序
  3. 使用 chef_handler 资源编写食谱
  4. 将该配方添加到节点的 运行-列表,通常作为该 运行-列表
  5. 中的第一个配方

不再需要第 1 步,因为 chef_handler 食谱现在是 Chef 的一部分。

第 2 步创建处理程序。给出的例子是

require 'net/smtp'

module OrgName
  class SendEmail < Chef::Handler
    def report
      if run_status.failed? then
        message  = "From: sender_name <sender@example.com>\n"
        message << "To: recipient_address <recipient@example.com>\n"
        message << "Subject: chef-client Run Failed\n"
        message << "Date: #{Time.now.rfc2822}\n\n"
        message << "Chef run failed on #{node.name}\n"
        message << "#{run_status.formatted_exception}\n"
        message << Array(backtrace).join('\n')
        Net::SMTP.start('your.smtp.server', 25) do |smtp|
          smtp.send_message message, 'sender@example', 'recipient@example'
        end
      end
    end
  end
end

现在是第 3 步,我不明白,将以下内容添加到食谱中

send_email 'blah' do
  # recipe code
end

当我 运行 我的食谱时,它只是产生了我期望以以下开头的错误消息:

FATAL: NoMethodError: undefined method `send_email` for cookbook: test, recipe: default :Chef::Recipe

这应该如何运作?还有其他简单但有效的自定义处理程序示例吗?

厨师 15.0.300

我认为文档中的第 3 步是错误的。应该是这样的:

# recipe:
chef_handler 'OrgName::SendEmail' do # Full class name
  # relative path to your handler
  source ::File.expandpath('../../files/default/handlers/send_mail.rb', __FILE__)
  arguments() # Hash or Array to pass to handler constructor
end

在 cookbook 的 files/default/handlers/ 目录中存储处理程序很常见,这就是为什么 source 属性是这样的。 arguments 在您的情况下不是必需的,因为处理程序中的 initialize 方法不需要任何参数。

有关 Chef 处理程序的文档乍一看确实有点不清楚。查看更多细节,一件事很清楚。 chef_handler 是 Chef 资源(自 Chef 客户端 14 起)。它默认支持两个处理程序 - JsonFileErrorReport.

custom handlers 上有更多文档。这表明我们需要为自定义处理程序安装一些 chef_gem 才能工作(除了上述两个)。

Simple Email

A handler that collects exception and report handler data and then uses pony to send email reports that are based on Erubis templates.

连接点...然后我们应该有一个安装 chef_gem 并启用处理程序的方法。我创建了一个单独的食谱,可以被其他食谱重复使用。

在下面的例子中,我有一本食谱 my_handlers:

recipes/json.rb
recipes/error_report.rb
recipes/email.rb
libraries/send_mail.rb

my_handlers/recipes/email.rb中:

chef_gem 'chef-handler-mail'

chef_handler 'MailHandler' do
  source 'chef/handler/mail'
  arguments :to_address => 'root'
  action :enable
end

my_handlers/libraries/send_mail.rb中:

require 'net/smtp'

module HandlerSendEmail
  class Helper

    def send_email_on_run_failure(node_name)
      message = "From: Chef <chef@chef.io>\n"
      message << "To: Grant <grantmc@chef.io>\n"
      message << "Subject: Chef run failed\n"
      message << "Date: #{Time.now.rfc2822}\n\n"
      message << "Chef run failed on #{node_name}\n"
      Net::SMTP.start('your.smtp.server', 25) do |smtp|
        smtp.send_message message, 'chef@chef.io', 'grantmc@chef.io'
      end
    end
  end
end

现在我有一些东西可以在其他食谱中重复使用,并选择我想要启用的处理程序。

假设我有一本食谱 cookbook1,我想在其中使用失败时的电子邮件处理程序:

cookbook1/metadata.rb中:

depends 'my_handlers'

recipes/default.rb中:

# Enable the Chef email handler by calling "my_handler"
include_recipe 'my_handlers::email'

Chef.event_handler do
  on :run_failed do
    HandlerSendEmail::Helper.new.send_email_on_run_failure(Chef.run_context.node.name)
  end
end

# Usual resource declarations

ruby_block 'fail the run' do
  block do
    fail 'deliberately fail the run'
  end
end

如果发生故障(故意如上),将调用 Chef 电子邮件处理程序并触发一封指示失败的电子邮件。