diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2016-05-13 14:14:04 -0700 |
---|---|---|
committer | Lamont Granquist <lamont@scriptkiddie.org> | 2016-05-13 14:14:04 -0700 |
commit | 96f8d9583c7f7e16efeac0c4fe085a83d83f5041 (patch) | |
tree | 2a0c80a5ad8b799ce790dc50e0cb1eaa5b7d8849 | |
parent | 103c34b057bba9061c010b4a9836977e9a8dbb90 (diff) | |
download | chef-lcg/better-handler-wiring.tar.gz |
wire up chef handlers directly from librarieslcg/better-handler-wiring
smear just a little bit of minimal DSL wiring into the Chef::Report
class so that classes can wire themselves up automatically as
handlers.
this also extends the Chef::Config[*_handler] arrays to take classes
as well as instances.
in the case of passing a class that is not a singleton, a new instance
will be created when the report is run. it will obviously be difficult
to pass any state into this instance.
if the class that is passed supports calling `#instance` we assume it
is a Singleton and get the instance and use that. this is to support
other chef code grabbing/creating the singleton instance and poking
it with data (probably configuring where the reporter goes and what
creds it needs to publish and other stuff).
-rw-r--r-- | lib/chef/handler.rb | 33 | ||||
-rw-r--r-- | spec/unit/handler_spec.rb | 87 |
2 files changed, 120 insertions, 0 deletions
diff --git a/lib/chef/handler.rb b/lib/chef/handler.rb index b720a11a45..100ed23d9e 100644 --- a/lib/chef/handler.rb +++ b/lib/chef/handler.rb @@ -57,16 +57,47 @@ class Chef # class Handler + 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 + # The list of currently configured start handlers def self.start_handlers Array(Chef::Config[:start_handlers]) end + 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 the start handlers. This will usually be called by a notification # from Chef::Client 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.") @@ -90,6 +121,7 @@ class Chef 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 @@ -115,6 +147,7 @@ class Chef 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 diff --git a/spec/unit/handler_spec.rb b/spec/unit/handler_spec.rb index 65c3ddc4cb..a56645fa78 100644 --- a/spec/unit/handler_spec.rb +++ b/spec/unit/handler_spec.rb @@ -212,4 +212,91 @@ describe Chef::Handler do end end + describe "library report handler" do + before do + # we need to lazily declare this after we have reset Chef::Config in the default rspec before handler + class MyTestHandler < Chef::Handler + handler_for :report, :exception, :start + + class << self + attr_accessor :ran_report + end + + def report + self.class.ran_report = true + end + end + end + + it "gets added to Chef::Config[:report_handlers]" do + expect(Chef::Config[:report_handlers].include?(MyTestHandler)).to be true + end + + it "gets added to Chef::Config[:exception_handlers]" do + expect(Chef::Config[:exception_handlers].include?(MyTestHandler)).to be true + end + + it "gets added to Chef::Config[:start_handlers]" do + expect(Chef::Config[:start_handlers].include?(MyTestHandler)).to be true + end + + it "runs the report handler" do + Chef::Handler.run_report_handlers(@run_status) + expect(MyTestHandler.ran_report).to be true + end + + it "runs the exception handler" do + Chef::Handler.run_exception_handlers(@run_status) + expect(MyTestHandler.ran_report).to be true + end + + it "runs the start handler" do + Chef::Handler.run_start_handlers(@run_status) + expect(MyTestHandler.ran_report).to be true + end + end + + describe "library singleton report handler" do + before do + # we need to lazily declare this after we have reset Chef::Config in the default rspec before handler + class MyTestHandler < Chef::Handler + handler_for :report, :exception, :start + + include Singleton + + attr_accessor :ran_report + + def report + self.ran_report = true + end + end + end + + it "gets added to Chef::Config[:report_handlers]" do + expect(Chef::Config[:report_handlers].include?(MyTestHandler)).to be true + end + + it "gets added to Chef::Config[:exception_handlers]" do + expect(Chef::Config[:exception_handlers].include?(MyTestHandler)).to be true + end + + it "gets added to Chef::Config[:start_handlers]" do + expect(Chef::Config[:start_handlers].include?(MyTestHandler)).to be true + end + + it "runs the report handler" do + Chef::Handler.run_report_handlers(@run_status) + expect(MyTestHandler.instance.ran_report).to be true + end + + it "runs the exception handler" do + Chef::Handler.run_exception_handlers(@run_status) + expect(MyTestHandler.instance.ran_report).to be true + end + + it "runs the start handler" do + Chef::Handler.run_start_handlers(@run_status) + expect(MyTestHandler.instance.ran_report).to be true + end + end end |