问题描述
我有一个似乎无法找到解决方案的 catch-22。我可以成功地做到这一点:
#
# Cookbook:: core_unix_base_cmcb
# Recipe:: email_on_fail
email_hash = node.default['core_unix_base_cmcb']['email_hash']
email_hash['mailserver'] = node['postfix']['main']['relayhost']
email_hash['subject'] = "Subject: Chef-client run Failed on #{email_hash['hostname']}"
email_hash['message'] = "A Chef-client run Failed on #{email_hash['hostname']}."
email_hash['recipient'] = [ 'someone@somewhere.com' ]
Chef.event_handler do
on :run_Failed do
SendEmail::Helper.new.send_email(email_hash)
end
end
require 'net/smtp'
module SendEmail
class Helper
def send_email(email_hash)
msg = "From: #{email_hash[:sender]} < #{email_hash[:sender]}@#{email_hash[:hostname]}\n"
msg << "To: #{email_hash[:recipient].join('; ')}\n"
msg << "#{email_hash[:subject]}\n"
msg << "Date: #{Time.Now.rfc2822}\n\n"
msg << "#{email_hash[:message]}\n"
sender = 'chef-client-noreply@somewhere.com'
Net::SMTP.start(email_hash[:mailserver],25) do |smtp|
smtp.send_message msg,sender,email_hash[:recipient]
end
end
end
end
但是 - 我需要消息包含厨师客户端 run_status。 如果添加
msg << "#{run_status.formatted_exception}\n"
msg << Array(backtrace).join('\n')
对于上面的例子,run_status 没有定义。
我能找到的唯一示例是使用报告界面的自定义处理程序和chef_handler 资源声明。所以我尝试了这个(从我发现的一个例子中):
chef_handler 'SendEmailOnFail::SendEmail' do # Full class name
# relative path to your handler
source ::File.expand_path('../../files/default/handlers/email_on_fail_helper.rb',__FILE__)
# source 'email_on_fail_helper.rb'
arguments email_hash # Hash or Array to pass to handler constructor
end
require 'net/smtp'
module SendEmailOnFail
class SendEmail < Chef::Handler
def report(email_hash)
if run_status.Failed?
msg = "From: #{email_hash[:sender]} < #{email_hash[:sender]}@#{email_hash[:hostname]}\n"
msg << "To: #{email_hash[:recipient].join('; ')}\n"
msg << "#{email_hash[:subject]}\n"
msg << "Date: #{Time.Now.rfc2822}\n\n"
msg << "#{email_hash[:message]}\n"
msg << "#{run_status.formatted_exception}\n"
msg << Array(backtrace).join('\n')
sender = 'chef-client-noreply@somewhere.com'
Net::SMTP.start(email_hash[:mailserver],25) do |smtp|
smtp.send_message msg,email_hash[:recipient]
end
end
end
end
end
当您使用该代码执行厨师客户端运行时,它会在参数上出错(收到 1,预期为 0)。 我在网上绝对没有发现 def report 有任何参数的例子,所以我认为这就是问题所在。我们的组织需要这些参数,因为邮件服务器并不总是相同的,收件人也不总是相同的。
那么我怎样才能在电子邮件正文中获取厨师客户端运行失败的信息,并将参数传递给库(或自定义处理程序)? 提前致谢。
解决方法
run_status
仅适用于 documentation 中所述的 report
接口。
run_status
对象在为任何处理程序运行 report
接口之前由 Chef Infra Client 初始化。
不过……
那么我如何才能在电子邮件正文中获取厨师客户端运行失败的信息,并将参数传递给库(或自定义处理程序)?
可以从 run_failed
的 event_handler
块中获取异常详细信息。其中一些方法是:message
、backtrace
、full_message
等。
有一个关于为 :run_failed
块 here 设置变量的参考。
例如,在我的食谱中,我将 message
添加到我的 email_hash
。然后将其传递给用于发送电子邮件的辅助方法。
# Adding this for completeness,the required change is in "Chef.event_handler" block
email_hash = Hash.new
email_hash['node_name'] = Chef.run_context.node.name
email_hash['subject'] = "Chef run failed on #{email_hash['node_name']}"
email_hash['sender'] = 'admin@example.io'
email_hash['recipient'] = 'user@example.io'
# This is where we can access details of "exception"
Chef.event_handler do
on :run_failed do |exception|
email_hash['error_msg'] = exception.message
SendEmail::Helper.new.send_email(email_hash)
end
end
再次添加我的 SendEmail
helper library 以确保完整性:
require 'net/smtp'
module SendEmail
class Helper
def send_email(email_hash)
message = "From: #{email_hash['sender']}\n"
message << "To: #{email_hash['recipient']}\n"
message << "Subject: #{email_hash['subject']}\n"
message << "Date: #{Time.now.rfc2822}\n\n"
message << "Chef run failed on #{email_hash['node_name']}\n"
message << "#{email_hash['error_msg']}\n"
Net::SMTP.start('localhost',25) do |smtp|
smtp.send_message message,email_hash['sender'],email_hash['recipient']
end
end
end
end
,
一种解决方法是将 email_hash 设置为一个属性,报告处理程序可以使用节点方法访问节点对象 o 您可以执行 run_status.node['email_hash'][xxx]
而不是 email_hash[xxx]
。
处理程序中 run_status 对象周围的文档是 here
要进行更详细的交流,请随时加入 Chef 的 slack 以获得社区帮助(那里也有 Chef 的开发人员,这对内部位提供了很多帮助):https://community-slack.chef.io/
,谢谢两位的回复。在发布我的问题后继续在互联网上搜索之后,我终于遇到了一个我可以使用的金块。 https://github.com/chef/chef/issues/7101
我很幸运有这个例子:
on :run_failed do |exception,run_status|
我真的不明白它是如何工作的,或者它在哪里记录,但它与你正在做的事情本质上是一样的,seshadri_c,并且运行良好。我可以访问撰写消息所需的内容,例如
run_status.run_context.cookbook_collection