diff options
author | Ranjib Dey <ranjib@pagerduty.com> | 2015-06-19 15:32:04 -0700 |
---|---|---|
committer | Ranjib Dey <ranjib@pagerduty.com> | 2015-06-23 23:03:02 -0700 |
commit | 9f0ea8aa0ec05819e242dedaa85fe731dca3146c (patch) | |
tree | 028c8ca206e3503243aeb50cfc7a2aa37995823a | |
parent | 3769bf187130c95d5ef2575a0f4ac9e06b197f5c (diff) | |
download | chef-9f0ea8aa0ec05819e242dedaa85fe731dca3146c.tar.gz |
add name class attribute for user defined handlers. more readable invalid event handler exception name.
-rw-r--r-- | lib/chef/chef_class.rb | 4 | ||||
-rw-r--r-- | lib/chef/event_dispatch/dsl.rb | 37 | ||||
-rw-r--r-- | lib/chef/exceptions.rb | 2 | ||||
-rw-r--r-- | spec/unit/chef_class_spec.rb | 2 | ||||
-rw-r--r-- | spec/unit/event_dispatch/dsl_spec.rb | 43 |
5 files changed, 70 insertions, 18 deletions
diff --git a/lib/chef/chef_class.rb b/lib/chef/chef_class.rb index c490615861..d9c141b85d 100644 --- a/lib/chef/chef_class.rb +++ b/lib/chef/chef_class.rb @@ -51,8 +51,10 @@ class Chef attr_reader :run_context # Register an event handler with user specified block + # + # @return[Chef::EventDispatch::Base] handler object def event_handler(&block) - dsl = Chef::EventDispatch::DSL.new + dsl = Chef::EventDispatch::DSL.new('Chef client DSL') dsl.instance_eval(&block) end diff --git a/lib/chef/event_dispatch/dsl.rb b/lib/chef/event_dispatch/dsl.rb index e700fd1640..98854a4716 100644 --- a/lib/chef/event_dispatch/dsl.rb +++ b/lib/chef/event_dispatch/dsl.rb @@ -22,32 +22,43 @@ require 'chef/config' class Chef module EventDispatch class DSL + attr_reader :handler + + def initialize(name) + klass = Class.new(Chef::EventDispatch::Base) do + def self.name + @@name + end + end + klass.class_variable_set(:@@name, name) + @handler = klass.new + # Use current event.register API to add anonymous handler if + # run_context and associated event dispatcher is set, else fallback to + # Chef::Config[:hanlder]. + if Chef.run_context && Chef.run_context.events + Chef::Log.debug("Registering handler '#{name}' using events api") + Chef.run_context.events.register(handler) + else + Chef::Log.debug("Registering handler '#{name}' using global config") + Chef::Config[:event_handlers] << handler + end + end + # Adds a new event handler derived from base handler # with user defined block against a chef event # # @return [Chef::EventDispatch::Base] a base handler object def on(event_type, &block) validate!(event_type) - handler = Chef::EventDispatch::Base.new handler.define_singleton_method(event_type) do |*args| - block.call(args) - end - # Use current event dispatch system is run_context and associated event - # dispatcher is set else fall back to Chef::Config[:hanlder] - if Chef.run_context && Chef.run_context.events - Chef::Log.debug('Registering handler using run_context') - Chef.run_context.events.register(handler) - else - Chef::Log.debug('Registering handler using config, this will only work inside config file') - Chef::Config[:event_handlers] << handler + instance_exec(*args, &block) end - handler end private def validate!(event_type) all_event_types = (Chef::EventDispatch::Base.instance_methods - Object.instance_methods) - raise Chef::Exceptions::UnknownEventType unless all_event_types.include?(event_type) + raise Chef::Exceptions::InvalidEventType, "Invalid event type: #{event_type}" unless all_event_types.include?(event_type) end end end diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb index f38bc32571..0857a9e75e 100644 --- a/lib/chef/exceptions.rb +++ b/lib/chef/exceptions.rb @@ -98,7 +98,7 @@ class Chef class InvalidResourceReference < RuntimeError; end class ResourceNotFound < RuntimeError; end class VerificationNotFound < RuntimeError; end - class UnknownEventType < ArgumentError; end + class InvalidEventType < ArgumentError; end # Can't find a Resource of this type that is valid on this platform. class NoSuchResourceType < NameError diff --git a/spec/unit/chef_class_spec.rb b/spec/unit/chef_class_spec.rb index 65a637dcbb..d6bf74572e 100644 --- a/spec/unit/chef_class_spec.rb +++ b/spec/unit/chef_class_spec.rb @@ -108,7 +108,7 @@ describe "Chef class" do on :yolo do end end - end.to raise_error(Chef::Exceptions::UnknownEventType) + end.to raise_error(Chef::Exceptions::InvalidEventType) end end end diff --git a/spec/unit/event_dispatch/dsl_spec.rb b/spec/unit/event_dispatch/dsl_spec.rb index ba91dde2e7..e30b1cb40e 100644 --- a/spec/unit/event_dispatch/dsl_spec.rb +++ b/spec/unit/event_dispatch/dsl_spec.rb @@ -20,16 +20,55 @@ require 'spec_helper' require 'chef/event_dispatch/dsl' describe Chef::EventDispatch::DSL do - subject{ described_class.new } + subject{ described_class.new('test') } it 'raise error when invalid event type is supplied' do expect do subject.on(:foo_bar) {} - end.to raise_error(Chef::Exceptions::UnknownEventType) + end.to raise_error(Chef::Exceptions::InvalidEventType) end it 'register user hooks against valid event type' do subject.on(:run_failed) {'testhook'} expect(Chef::Config[:event_handlers].first.run_failed).to eq('testhook') end + + it 'preserve state across event hooks' do + Chef::Config.reset! + node = Chef::Node.new + calls = [] + Chef.event_handler do + on :resource_updated do + calls << :updated + end + on :resource_action_start do + calls << :started + end + end + events = Chef::EventDispatch::Dispatcher.new(*Chef::Config[:event_handlers]) + rc = Chef::RunContext.new(node, nil, events) + resource = Chef::Resource::RubyBlock.new('foo', rc) + resource.block { } + resource.run_action(:run) + expect(calls).to eq([:started, :updated]) + end + + it 'preserve instance variables across handler callbacks' do + Chef::Config.reset! + node = Chef::Node.new + Chef.event_handler do + on :resource_action_start do + @ivar = [1] + end + on :resource_updated do + @ivar << 2 + end + end + events = Chef::EventDispatch::Dispatcher.new(*Chef::Config[:event_handlers]) + rc = Chef::RunContext.new(node, nil, events) + resource = Chef::Resource::RubyBlock.new('foo', rc) + resource.block { } + resource.run_action(:run) + expect(Chef::Config[:event_handlers].first.instance_variable_get(:@ivar)).to eq([1, 2]) + end end |