Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
74 views
in Technique[技术] by (71.8m points)

Is it possible to access the run_status object when using Chef.event_handler?

I have a bit of a catch-22 that I can't seem to find a solution for. I can successfully do this:

#
# 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'] = [ '[email protected]' ]

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]}
"
      msg << "To: #{email_hash[:recipient].join('; ')}
"
      msg << "#{email_hash[:subject]}
"
      msg << "Date: #{Time.now.rfc2822}

"
      msg << "#{email_hash[:message]}
"
      sender = '[email protected]'
      Net::SMTP.start(email_hash[:mailserver], 25) do |smtp|
        smtp.send_message msg, sender, email_hash[:recipient]
      end
    end
  end
end

However - I need the message to include the chef-client run_status. If you add

msg << "#{run_status.formatted_exception}
"
msg << Array(backtrace).join('
')

to the above example, The run_status isn't defined.

The only examples I've been able to find are with custom handlers using the report interface, and the chef_handler resource declaration. So I tried this (from an example I found):

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]}
"
        msg << "To: #{email_hash[:recipient].join('; ')}
"
        msg << "#{email_hash[:subject]}
"
        msg << "Date: #{Time.now.rfc2822}

"
        msg << "#{email_hash[:message]}
"
        msg << "#{run_status.formatted_exception}
"
        msg << Array(backtrace).join('
')
        sender = '[email protected]'
        Net::SMTP.start(email_hash[:mailserver], 25) do |smtp|
          smtp.send_message msg, sender, email_hash[:recipient]
        end
      end
    end
  end
end

When you do a chef-client run with that code, it errors out on the arguments (received 1, expected 0). I found absolutely no examples online where def report had any parameters, so I am presuming that is the issue. The parameters are required for our organization because the mail server isn't always the same, and the recipients aren't always the same.

So how can I get the information of what failed in a chef-client run in the body of the E-mail message, AND have parameters passed to the library (or custom handler)? Thanks in advance.

question from:https://stackoverflow.com/questions/65940224/is-it-possible-to-access-the-run-status-object-when-using-chef-event-handler

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The run_status is available only with report interface as described in the documentation.

The run_status object is initialized by Chef Infra Client before the report interface is run for any handler.

However...

So how can I get the information of what failed in a chef-client run in the body of the E-mail message, AND have parameters passed to the library (or custom handler)?

It is possible to get exception details from run_failed block of event_handler. Some of the methods are: message, backtrace, full_message, etc.

There is a reference for having variables for :run_failed block here.

For example, in my recipe I am adding message to my email_hash. This will then be passed to the helper method for sending email.

# 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'] = '[email protected]'
email_hash['recipient'] = '[email protected]'

# 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

Adding my SendEmail helper library for completeness again:

require 'net/smtp'

module SendEmail
  class Helper

    def send_email(email_hash)
      message = "From: #{email_hash['sender']}
"
      message << "To: #{email_hash['recipient']}
"
      message << "Subject: #{email_hash['subject']}
"
      message << "Date: #{Time.now.rfc2822}

"
      message << "Chef run failed on #{email_hash['node_name']}
"
      message << "#{email_hash['error_msg']}
"
      Net::SMTP.start('localhost', 25) do |smtp|
        smtp.send_message message, email_hash['sender'], email_hash['recipient']
      end
    end

  end
end

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...