class Chef::Handler
The base class for an Exception or Notification Handler
. Create your own handler by subclassing Chef::Handler
. When a Chef
run fails with an uncaught Exception, Chef
will set the run_status
on your handler and call report
@example
require 'net/smtp' module MyOrg class OhNoes < Chef::Handler def report # Create the email message message = "From: Your Name <your@mail.address>\n" message << "To: Destination Address <someone@example.com>\n" message << "Subject: Chef Run Failure\n" message << "Date: #{Time.now.rfc2822}\n\n" # The Node is available as +node+ message << "Chef run failed on #{node.name}\n" # +run_status+ is a value object with all of the run status data message << "#{run_status.formatted_exception}\n" # Join the backtrace lines. Coerce to an array just in case. message << Array(backtrace).join("\n") # Send the email Net::SMTP.start('your.smtp.server', 25) do |smtp| smtp.send_message message, 'from@address', 'to@address' end end end end
Attributes
The Chef::RunStatus
object containing data about the Chef
run.
Public Class Methods
Source
# File lib/chef/handler.rb, line 143 def self.exception_handlers Array(Chef::Config[:exception_handlers]) end
The list of currently configured exception handlers
Source
# File lib/chef/handler.rb, line 64 def self.handler_for(*args) if args.include?(:start) Chef::Config[:start_handlers] ||= [] Chef::Config[:start_handlers] |= [self] end if args.include?(:report) Chef::Config[:report_handlers] ||= [] Chef::Config[:report_handlers] |= [self] end if args.include?(:exception) Chef::Config[:exception_handlers] ||= [] Chef::Config[:exception_handlers] |= [self] end end
FIXME: Chef::Handler
should probably inherit from EventDispatch::Base
and should wire up to those events rather than the “notifications” system which is hanging off of Chef::Client
. Those “notifications” could then be deprecated in favor of events, and this class could become decoupled from the Chef::Client
object.
Source
# File lib/chef/handler.rb, line 117 def self.report_handlers Array(Chef::Config[:report_handlers]) end
The list of currently configured report handlers
Source
# File lib/chef/handler.rb, line 84 def self.resolve_handler_instance(handler) if handler.is_a?(Class) if handler.respond_to?(:instance) # support retrieving a Singleton reporting object handler.instance else # just a class with no way to insert data handler.new end else # the Chef::Config array contains an instance, not a class handler end end
Source
# File lib/chef/handler.rb, line 149 def self.run_exception_handlers(run_status) events = run_status.events events.handlers_start(exception_handlers.size) Chef::Log.error("Running exception handlers") exception_handlers.each do |handler| handler = resolve_handler_instance(handler) handler.run_report_safely(run_status) events.handler_executed(handler) end events.handlers_completed Chef::Log.error("Exception handlers complete") end
Run the exception handlers. Usually will be called by a notification from Chef::Client
when the run fails.
Source
# File lib/chef/handler.rb, line 123 def self.run_report_handlers(run_status) events = run_status.events events.handlers_start(report_handlers.size) Chef::Log.info("Running report handlers") report_handlers.each do |handler| handler = resolve_handler_instance(handler) handler.run_report_safely(run_status) events.handler_executed(handler) end events.handlers_completed Chef::Log.info("Report handlers complete") end
Run the report handlers. This will usually be called by a notification from Chef::Client
Source
# File lib/chef/handler.rb, line 101 def self.run_start_handlers(run_status) Chef::Log.info("Running start handlers") start_handlers.each do |handler| handler = resolve_handler_instance(handler) handler.run_report_safely(run_status) end Chef::Log.info("Start handlers complete.") end
Run the start handlers. This will usually be called by a notification from Chef::Client
Source
# File lib/chef/handler.rb, line 80 def self.start_handlers Array(Chef::Config[:start_handlers]) end
The list of currently configured start handlers
Public Instance Methods
Source
# File lib/chef/handler.rb, line 269 def action_collection @run_status.run_context.action_collection end
Source
# File lib/chef/handler.rb, line 218 def all_resources @all_resources ||= action_collection&.filtered_collection(unprocessed: false)&.resources || [] end
@return Array<Chef::Resource> all resources other than unprocessed
Source
# File lib/chef/handler.rb, line 208 def_delegator :@run_status, :backtrace
The backtrace captured by the uncaught exception that terminated the chef run, or nil if the run completed successfully
Source
# File lib/chef/handler.rb, line 300 def data @run_status.to_h end
Return the Hash representation of the run_status
Source
# File lib/chef/handler.rb, line 188 def_delegator :@run_status, :elapsed_time
The time elapsed between the start and finish of the chef run
Source
# File lib/chef/handler.rb, line 182 def_delegator :@run_status, :end_time
The time the chef run ended
Source
# File lib/chef/handler.rb, line 201 def_delegator :@run_status, :exception
The uncaught Exception that terminated the chef run, or nil if the run completed successfully
Source
# File lib/chef/handler.rb, line 267 def_delegator :@run_status, :failed?
Did the chef run fail? True if the chef run raised an uncaught exception
Source
# File lib/chef/handler.rb, line 236 def failed_resources @failed_resources ||= action_collection&.filtered_collection(updated: false, up_to_date: false, skipped: false, unprocessed: false)&.resources || [] end
@return Array<Chef::Resource> all failed resources
Source
# File lib/chef/handler.rb, line 214 def_delegator :@run_status, :node
The Chef::Node
for this client run
Source
# File lib/chef/handler.rb, line 275 def report; end
The main entry point for report handling. Subclasses should override this method with their own report handling logic.
Source
# File lib/chef/handler.rb, line 194 def_delegator :@run_status, :run_context
The Chef::RunContext
object used by the chef run
Source
# File lib/chef/handler.rb, line 283 def run_report_safely(run_status) run_report_unsafe(run_status) rescue Exception => e Chef::Log.error("Report handler #{self.class.name} raised #{e.inspect}") Array(e.backtrace).each { |line| Chef::Log.error(line) } ensure @run_status = nil end
Runs the report handler, rescuing and logging any errors it may cause. This ensures that all handlers get a chance to run even if one fails. This method should not be overridden by subclasses unless you know what you’re doing.
@api private
Source
# File lib/chef/handler.rb, line 294 def run_report_unsafe(run_status) @run_status = run_status report end
Runs the report handler without any error handling. This method should not be used directly except in testing.
Source
# File lib/chef/handler.rb, line 242 def skipped_resources @skipped_resources ||= action_collection&.filtered_collection(updated: false, up_to_date: false, failed: false, unprocessed: false)&.resources || [] end
@return Array<Chef::Resource> all skipped resources
Source
# File lib/chef/handler.rb, line 176 def_delegator :@run_status, :start_time
The time the chef run started
Source
# File lib/chef/handler.rb, line 261 def_delegator :@run_status, :success?
Was the chef run successful? True if the chef run did not raise an uncaught exception
Source
# File lib/chef/handler.rb, line 252 def unprocessed_resources @unprocessed_resources ||= action_collection&.filtered_collection(updated: false, up_to_date: false, failed: false, skipped: false)&.resources || [] end
Unprocessed resources are those which are left over in the outer recipe context when a run fails. Sub-resources of unprocessed resourced are impossible to capture because they would require processing the outer resource.
@return Array<Chef::Resource> all unprocessed resources
Source
# File lib/chef/handler.rb, line 230 def up_to_date_resources @up_to_date_resources ||= action_collection&.filtered_collection(updated: false, skipped: false, failed: false, unprocessed: false)&.resources || [] end
@return Array<Chef::Resource> all up_to_date resources
Source
# File lib/chef/handler.rb, line 224 def updated_resources @updated_resources ||= action_collection&.filtered_collection(up_to_date: false, skipped: false, failed: false, unprocessed: false)&.resources || [] end
@return Array<Chef::Resource> all updated resources