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

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+

Examples:

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, '[email protected]', '[email protected]'
      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.


164
165
166
# File 'lib/chef/handler.rb', line 164

def run_status
  @run_status
end

Class Method Details

.exception_handlersObject

The list of currently configured exception handlers


137
138
139
# File 'lib/chef/handler.rb', line 137

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

.handler_for(*args) ⇒ Object


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

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


111
112
113
# File 'lib/chef/handler.rb', line 111

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

.resolve_handler_instance(handler) ⇒ Object


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

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.


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

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


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

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


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

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


74
75
76
# File 'lib/chef/handler.rb', line 74

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

Instance Method Details

#dataObject

Return the Hash representation of the run_status


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

def data
  @run_status.to_h
end

#reportObject

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


237
# File 'lib/chef/handler.rb', line 237

def report; end

#run_report_safely(run_status) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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.


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

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.


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

def run_report_unsafe(run_status)
  @run_status = run_status
  report
end