Class: Chef::Handler

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/chef/handler.rb,
lib/chef/handler/json_file.rb,
lib/chef/handler/error_report.rb

Overview

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 <[email protected]>\n"
      message << "To: Destination Address <[email protected]>\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

Direct Known Subclasses

ErrorReport, JsonFile

Defined Under Namespace

Classes: ErrorReport, JsonFile

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#run_statusObject (readonly)

The Chef::RunStatus object containing data about the Chef run.



166
167
168
# File 'lib/chef/handler.rb', line 166

def run_status
  @run_status
end

Class Method Details

.exception_handlersObject

The list of currently configured exception handlers



139
140
141
# File 'lib/chef/handler.rb', line 139

def self.exception_handlers
  Array(Chef::Config[:exception_handlers])
end

.handler_for(*args) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/chef/handler.rb', line 60

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

.report_handlersObject

The list of currently configured report handlers



113
114
115
# File 'lib/chef/handler.rb', line 113

def self.report_handlers
  Array(Chef::Config[:report_handlers])
end

.resolve_handler_instance(handler) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/chef/handler.rb', line 80

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

.run_exception_handlers(run_status) ⇒ Object

Run the exception handlers. Usually will be called by a notification from Chef::Client when the run fails.



145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/chef/handler.rb', line 145

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_report_handlers(run_status) ⇒ Object

Run the report handlers. This will usually be called by a notification from Chef::Client



119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/chef/handler.rb', line 119

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_start_handlers(run_status) ⇒ Object

Run the start handlers. This will usually be called by a notification from Chef::Client



97
98
99
100
101
102
103
104
# File 'lib/chef/handler.rb', line 97

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

.start_handlersObject

The list of currently configured start handlers



76
77
78
# File 'lib/chef/handler.rb', line 76

def self.start_handlers
  Array(Chef::Config[:start_handlers])
end

Instance Method Details

#dataObject

Return the Hash representation of the run_status



263
264
265
# File 'lib/chef/handler.rb', line 263

def data
  @run_status.to_hash
end

#reportObject

The main entry point for report handling. Subclasses should override this method with their own report handling logic.



239
240
# File 'lib/chef/handler.rb', line 239

def report
end

#run_report_safely(run_status) ⇒ Object

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.



246
247
248
249
250
251
252
253
# File 'lib/chef/handler.rb', line 246

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

#run_report_unsafe(run_status) ⇒ Object

Runs the report handler without any error handling. This method should not be used directly except in testing.



257
258
259
260
# File 'lib/chef/handler.rb', line 257

def run_report_unsafe(run_status)
  @run_status = run_status
  report
end