diff options
author | Luke Kanies <luke@madstop.com> | 2009-11-01 13:28:49 -0600 |
---|---|---|
committer | test branch <puppet-dev@googlegroups.com> | 2010-02-17 06:50:53 -0800 |
commit | f2ed655d5e5a9b7c61b29cda229b63db2d73064e (patch) | |
tree | 228e11d5341cbad85d6a57b28e5553557a90c539 | |
parent | 329527f5173d17c9c2b788734033534009efcf04 (diff) | |
download | puppet-f2ed655d5e5a9b7c61b29cda229b63db2d73064e.tar.gz puppet-f2ed655d5e5a9b7c61b29cda229b63db2d73064e.tar.xz puppet-f2ed655d5e5a9b7c61b29cda229b63db2d73064e.zip |
Extracting event management into a separate class
Thus pulls all event-related code out of Transaction.
The Transaction class currently creates a single instance
of this class, so it's nowhere near a "real" event manager,
but at least it has very clean integration points and will
be easy to upgrade as needed.
Signed-off-by: Luke Kanies <luke@madstop.com>
-rw-r--r-- | lib/puppet/transaction.rb | 100 | ||||
-rw-r--r-- | lib/puppet/transaction/event_manager.rb | 90 | ||||
-rwxr-xr-x | spec/unit/transaction.rb | 267 | ||||
-rwxr-xr-x | spec/unit/transaction/event_manager.rb | 259 |
4 files changed, 384 insertions, 332 deletions
diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb index 0a26e33fe..aee541fb1 100644 --- a/lib/puppet/transaction.rb +++ b/lib/puppet/transaction.rb @@ -7,16 +7,20 @@ require 'puppet/util/tagging' class Puppet::Transaction require 'puppet/transaction/change' require 'puppet/transaction/event' + require 'puppet/transaction/event_manager' attr_accessor :component, :catalog, :ignoreschedules attr_accessor :sorted_resources, :configurator - # The list of events generated in this transaction. - attr_reader :events + # The report, once generated. + attr_reader :report # Mostly only used for tests attr_reader :resourcemetrics, :changes + # Routes and stores any events and subscriptions. + attr_reader :event_manager + include Puppet::Util include Puppet::Util::Tagging @@ -157,7 +161,7 @@ class Puppet::Transaction eval_children_and_apply_resource(resource) # Check to see if there are any events queued for this resource - process_events(resource) + event_manager.process_events(resource) end def eval_children_and_apply_resource(resource) @@ -230,6 +234,10 @@ class Puppet::Transaction Puppet.debug "Finishing transaction #{object_id} with #{@changes.length} changes" end + def events + event_manager.events + end + # Determine whether a given resource has failed. def failed?(obj) if @failures[obj] > 0 @@ -345,14 +353,9 @@ class Puppet::Transaction # Metrics for distributing times across the different types. @timemetrics = Hash.new(0) - @event_queues = {} - # The changes we're performing @changes = [] - # The complete list of events generated. - @events = [] - # The resources that have failed and the number of failures each. This # is used for skipping resources because of failed dependencies. @failures = Hash.new do |h, key| @@ -360,6 +363,8 @@ class Puppet::Transaction end @report = Report.new + + @event_manager = Puppet::Transaction::EventManager.new(self) end # Prefetch any providers that support it. We don't support prefetching @@ -400,56 +405,6 @@ class Puppet::Transaction @sorted_resources = relationship_graph.topsort end - # Respond to any queued events for this resource. - def process_events(resource) - restarted = false - queued_events(resource) do |callback, events| - r = process_callback(resource, callback, events) - restarted ||= r - end - - if restarted - queue_event(resource, resource.event(:name => :restarted, :status => "success")) - - @resourcemetrics[:restarted] += 1 - end - end - - # Queue events for other resources to respond to. All of these events have - # to be from the same resource. - def queue_event(resource, event) - @events << event - - # Collect the targets of any subscriptions to those events. We pass - # the parent resource in so it will override the source in the events, - # since eval_generated children can't have direct relationships. - relationship_graph.matching_edges(events, resource).each do |edge| - next unless method = edge.callback - next unless edge.target.respond_to?(method) - - queue_event_for_resource(resource, edge.target, method, event) - end - - if resource.self_refresh? and ! resource.deleting? - queue_event_for_resource(resource, resource, :refresh, event) - end - end - - def queue_event_for_resource(source, target, callback, event) - source.info "Scheduling #{callback} of #{target}" - - @event_queues[target] ||= {} - @event_queues[target][callback] ||= [] - @event_queues[target][callback] << event - end - - def queued_events(resource) - return unless callbacks = @event_queues[resource] - callbacks.each do |callback, events| - yield callback, events - end - end - def relationship_graph catalog.relationship_graph end @@ -474,10 +429,10 @@ class Puppet::Transaction end # And queue the events - queue_event(change.resource, event) + event_manager.queue_event(change.resource, event) # Now check to see if there are any events for this child. - process_events(change.property.resource) + event_manager.process_events(change.property.resource) end end @@ -540,30 +495,7 @@ class Puppet::Transaction else @failures[resource] += 1 end - queue_event(resource, event) - end - - def process_callback(resource, callback, events) - # XXX Should it be any event, or all events? - process_noop_events(resource, callback, events) and return false unless events.detect { |e| e.status != "noop" } - resource.send(callback) - - resource.notice "Triggered '#{callback}' from #{events.length} events" - return true - rescue => detail - resource.err "Failed to call #{callback}: #{detail}" - - @resourcemetrics[:failed_restarts] += 1 - puts detail.backtrace if Puppet[:trace] - return false - end - - def process_noop_events(resource, callback, events) - resource.notice "Would have triggered '#{callback}' from #{events.length} events" - - # And then add an event for it. - queue_event(resource, resource.event(:status => "noop", :name => :noop_restart)) - true # so the 'and if' works + event_manager.queue_event(resource, event) end end diff --git a/lib/puppet/transaction/event_manager.rb b/lib/puppet/transaction/event_manager.rb new file mode 100644 index 000000000..370938c5e --- /dev/null +++ b/lib/puppet/transaction/event_manager.rb @@ -0,0 +1,90 @@ +require 'puppet/transaction' + +class Puppet::Transaction::EventManager + attr_reader :transaction, :events + + def initialize(transaction) + @transaction = transaction + @event_queues = {} + @events = [] + end + + def relationship_graph + transaction.relationship_graph + end + + # Respond to any queued events for this resource. + def process_events(resource) + restarted = false + queued_events(resource) do |callback, events| + r = process_callback(resource, callback, events) + restarted ||= r + end + + if restarted + queue_event(resource, resource.event(:name => :restarted, :status => "success")) + + transaction.resourcemetrics[:restarted] += 1 + end + end + + # Queue events for other resources to respond to. All of these events have + # to be from the same resource. + def queue_event(resource, event) + @events << event + + # Collect the targets of any subscriptions to those events. We pass + # the parent resource in so it will override the source in the events, + # since eval_generated children can't have direct relationships. + relationship_graph.matching_edges(event, resource).each do |edge| + next unless method = edge.callback + next unless edge.target.respond_to?(method) + + queue_event_for_resource(resource, edge.target, method, event) + end + + if resource.self_refresh? and ! resource.deleting? + queue_event_for_resource(resource, resource, :refresh, event) + end + end + + def queue_event_for_resource(source, target, callback, event) + source.info "Scheduling #{callback} of #{target}" + + @event_queues[target] ||= {} + @event_queues[target][callback] ||= [] + @event_queues[target][callback] << event + end + + def queued_events(resource) + return unless callbacks = @event_queues[resource] + callbacks.each do |callback, events| + yield callback, events + end + end + + private + + def process_callback(resource, callback, events) + # XXX Should it be any event, or all events? + process_noop_events(resource, callback, events) and return false unless events.detect { |e| e.status != "noop" } + resource.send(callback) + + resource.notice "Triggered '#{callback}' from #{events.length} events" + return true + rescue => detail + resource.err "Failed to call #{callback}: #{detail}" + + transaction.resourcemetrics[:failed_restarts] += 1 + puts detail.backtrace if Puppet[:trace] + return false + end + + def process_noop_events(resource, callback, events) + resource.notice "Would have triggered '#{callback}' from #{events.length} events" + + # And then add an event for it. + queue_event(resource, resource.event(:status => "noop", :name => :noop_restart)) + true # so the 'and if' works + end +end diff --git a/spec/unit/transaction.rb b/spec/unit/transaction.rb index d0b3a2dd8..3adecf692 100755 --- a/spec/unit/transaction.rb +++ b/spec/unit/transaction.rb @@ -5,6 +5,20 @@ require File.dirname(__FILE__) + '/../spec_helper' require 'puppet/transaction' describe Puppet::Transaction do + it "should delegate its event list to the event manager" do + @transaction = Puppet::Transaction.new(Puppet::Resource::Catalog.new) + @transaction.event_manager.expects(:events).returns %w{my events} + @transaction.events.should == %w{my events} + end + + describe "when initializing" do + it "should create an event manager" do + @transaction = Puppet::Transaction.new(Puppet::Resource::Catalog.new) + @transaction.event_manager.should be_instance_of(Puppet::Transaction::EventManager) + @transaction.event_manager.transaction.should equal(@transaction) + end + end + describe "when evaluating a resource" do before do @transaction = Puppet::Transaction.new(Puppet::Resource::Catalog.new) @@ -27,7 +41,7 @@ describe Puppet::Transaction do end it "should process events" do - @transaction.expects(:process_events).with(@resource) + @transaction.event_manager.expects(:process_events).with(@resource) @transaction.eval_resource(@resource) end @@ -47,7 +61,7 @@ describe Puppet::Transaction do describe "when applying changes" do before do @transaction = Puppet::Transaction.new(Puppet::Resource::Catalog.new) - @transaction.stubs(:queue_event) + @transaction.event_manager.stubs(:queue_event) @resource = stub 'resource' @property = stub 'property', :is_to_s => "is", :should_to_s => "should" @@ -69,8 +83,8 @@ describe Puppet::Transaction do c1 = stub 'c1', :forward => stub("event1", :status => "success"), :property => @property, :changed= => nil c2 = stub 'c2', :forward => stub("event2", :status => "success"), :property => @property, :changed= => nil - @transaction.expects(:queue_event).with(@resource, c1.forward) - @transaction.expects(:queue_event).with(@resource, c2.forward) + @transaction.event_manager.expects(:queue_event).with(@resource, c1.forward) + @transaction.event_manager.expects(:queue_event).with(@resource, c2.forward) @transaction.apply_changes(@resource, [c1, c2]) end @@ -96,255 +110,12 @@ describe Puppet::Transaction do end it "should queue the event" do - @transaction.expects(:queue_event).with(@resource, @event) + @transaction.event_manager.expects(:queue_event).with(@resource, @event) @transaction.apply_changes(@resource, [@change]) end end end - describe "when queueing events" do - before do - @transaction = Puppet::Transaction.new(Puppet::Resource::Catalog.new) - - @resource = stub("resource", :self_refresh? => false, :deleting => false) - - @graph = stub 'graph', :matching_edges => [], :resource => @resource - @transaction.stubs(:relationship_graph).returns @graph - - @event = Puppet::Transaction::Event.new(:name => :foo, :resource => @resource) - end - - it "should store each event in its event list" do - @transaction.queue_event(@resource, @event) - - @transaction.events.should include(@event) - end - - it "should queue events for the target and callback of any matching edges" do - edge1 = stub("edge1", :callback => :c1, :source => stub("s1"), :target => stub("t1", :c1 => nil)) - edge2 = stub("edge2", :callback => :c2, :source => stub("s2"), :target => stub("t2", :c2 => nil)) - - @graph.expects(:matching_edges).with { |events, resource| events == [@event] }.returns [edge1, edge2] - - @transaction.expects(:queue_event_for_resource).with(@resource, edge1.target, edge1.callback, @event) - @transaction.expects(:queue_event_for_resource).with(@resource, edge2.target, edge2.callback, @event) - - @transaction.queue_event(@resource, @event) - end - - it "should queue events for the changed resource if the resource is self-refreshing and not being deleted" do - @graph.stubs(:matching_edges).returns [] - - @resource.expects(:self_refresh?).returns true - @resource.expects(:deleting?).returns false - @transaction.expects(:queue_event_for_resource).with(@resource, @resource, :refresh, @event) - - @transaction.queue_event(@resource, @event) - end - - it "should not queue events for the changed resource if the resource is not self-refreshing" do - @graph.stubs(:matching_edges).returns [] - - @resource.expects(:self_refresh?).returns false - @resource.stubs(:deleting?).returns false - @transaction.expects(:queue_event_for_resource).never - - @transaction.queue_event(@resource, @event) - end - - it "should not queue events for the changed resource if the resource is being deleted" do - @graph.stubs(:matching_edges).returns [] - - @resource.expects(:self_refresh?).returns true - @resource.expects(:deleting?).returns true - @transaction.expects(:queue_event_for_resource).never - - @transaction.queue_event(@resource, @event) - end - - it "should ignore edges that don't have a callback" do - edge1 = stub("edge1", :callback => :nil, :source => stub("s1"), :target => stub("t1", :c1 => nil)) - - @graph.expects(:matching_edges).returns [edge1] - - @transaction.expects(:queue_event_for_resource).never - - @transaction.queue_event(@resource, @event) - end - - it "should ignore targets that don't respond to the callback" do - edge1 = stub("edge1", :callback => :c1, :source => stub("s1"), :target => stub("t1")) - - @graph.expects(:matching_edges).returns [edge1] - - @transaction.expects(:queue_event_for_resource).never - - @transaction.queue_event(@resource, @event) - end - end - - describe "when queueing events for a resource" do - before do - @transaction = Puppet::Transaction.new(Puppet::Resource::Catalog.new) - end - - it "should do nothing if no events are queued" do - @transaction.queued_events(stub("target")) { |callback, events| raise "should never reach this" } - end - - it "should yield the callback and events for each callback" do - target = stub("target") - - 2.times do |i| - @transaction.queue_event_for_resource(stub("source", :info => nil), target, "callback#{i}", ["event#{i}"]) - end - - @transaction.queued_events(target) { |callback, events| } - end - - it "should use the source to log that it's scheduling a refresh of the target" do - target = stub("target") - source = stub 'source' - source.expects(:info) - - @transaction.queue_event_for_resource(source, target, "callback", ["event"]) - - @transaction.queued_events(target) { |callback, events| } - end - end - - describe "when processing events for a given resource" do - before do - @transaction = Puppet::Transaction.new(Puppet::Resource::Catalog.new) - @transaction.stubs(:queue_event) - - @resource = stub 'resource', :notice => nil, :event => @event - @event = Puppet::Transaction::Event.new(:name => :event, :resource => @resource) - end - - it "should call the required callback once for each set of associated events" do - @transaction.expects(:queued_events).with(@resource).multiple_yields([:callback1, [@event]], [:callback2, [@event]]) - - @resource.expects(:callback1) - @resource.expects(:callback2) - - @transaction.process_events(@resource) - end - - it "should update the 'restarted' metric" do - @transaction.expects(:queued_events).with(@resource).yields(:callback1, [@event]) - - @resource.stubs(:callback1) - - @transaction.process_events(@resource) - - @transaction.resourcemetrics[:restarted].should == 1 - end - - it "should queue a 'restarted' event generated by the resource" do - @transaction.expects(:queued_events).with(@resource).yields(:callback1, [@event]) - - @resource.stubs(:callback1) - - @resource.expects(:event).with(:name => :restarted, :status => "success").returns "myevent" - @transaction.expects(:queue_event).with(@resource, "myevent") - - @transaction.process_events(@resource) - end - - it "should log that it restarted" do - @transaction.expects(:queued_events).with(@resource).yields(:callback1, [@event]) - - @resource.stubs(:callback1) - - @resource.expects(:notice).with { |msg| msg.include?("Triggered 'callback1'") } - - @transaction.process_events(@resource) - end - - describe "and the events include a noop event and at least one non-noop event" do - before do - @event.stubs(:status).returns "noop" - @event2 = Puppet::Transaction::Event.new(:name => :event, :resource => @resource) - @event2.status = "success" - @transaction.expects(:queued_events).with(@resource).yields(:callback1, [@event, @event2]) - end - - it "should call the callback" do - @resource.expects(:callback1) - - @transaction.process_events(@resource) - end - end - - describe "and the events are all noop events" do - before do - @event.stubs(:status).returns "noop" - @resource.stubs(:event).returns(Puppet::Transaction::Event.new) - @transaction.expects(:queued_events).with(@resource).yields(:callback1, [@event]) - end - - it "should log" do - @resource.expects(:notice).with { |msg| msg.include?("Would have triggered 'callback1'") } - - @transaction.process_events(@resource) - end - - it "should not call the callback" do - @resource.expects(:callback1).never - - @transaction.process_events(@resource) - end - - it "should queue a new noop event generated from the resource" do - event = Puppet::Transaction::Event.new - @resource.expects(:event).with(:status => "noop", :name => :noop_restart).returns event - @transaction.expects(:queue_event).with(@resource, event) - - @transaction.process_events(@resource) - end - end - - describe "and the callback fails" do - before do - @resource.expects(:callback1).raises "a failure" - @resource.stubs(:err) - - @transaction.expects(:queued_events).yields(:callback1, [@event]) - end - - it "should log but not fail" do - @resource.expects(:err) - - lambda { @transaction.process_events(@resource) }.should_not raise_error - end - - it "should update the 'failed_restarts' metric" do - @transaction.process_events(@resource) - @transaction.resourcemetrics[:failed_restarts].should == 1 - end - - it "should not queue a 'restarted' event" do - @transaction.expects(:queue_event).never - @transaction.process_events(@resource) - end - - it "should not increase the restarted resource count" do - @transaction.process_events(@resource) - @transaction.resourcemetrics[:restarted].should == 0 - end - end - end - - describe "when initializing" do - it "should accept a catalog and set an instance variable for it" do - catalog = stub 'catalog', :vertices => [] - - trans = Puppet::Transaction.new(catalog) - trans.catalog.should == catalog - end - end - describe "when generating resources" do it "should finish all resources" do generator = stub 'generator', :depthfirst? => true, :tags => [] diff --git a/spec/unit/transaction/event_manager.rb b/spec/unit/transaction/event_manager.rb new file mode 100755 index 000000000..96dd37d0a --- /dev/null +++ b/spec/unit/transaction/event_manager.rb @@ -0,0 +1,259 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../spec_helper' + +require 'puppet/transaction/event_manager' + +describe Puppet::Transaction::EventManager do + describe "at initialization" do + it "should require a transaction" do + Puppet::Transaction::EventManager.new("trans").transaction.should == "trans" + end + end + + it "should delegate its relationship graph to the transaction" do + transaction = stub 'transaction' + manager = Puppet::Transaction::EventManager.new(transaction) + + transaction.expects(:relationship_graph).returns "mygraph" + + manager.relationship_graph.should == "mygraph" + end + + describe "when queueing events" do + before do + @transaction = stub 'transaction' + @manager = Puppet::Transaction::EventManager.new(@transaction) + + @resource = stub("resource", :self_refresh? => false, :deleting => false) + + @graph = stub 'graph', :matching_edges => [], :resource => @resource + @manager.stubs(:relationship_graph).returns @graph + + @event = Puppet::Transaction::Event.new(:name => :foo, :resource => @resource) + end + + it "should store each event in its event list" do + @manager.queue_event(@resource, @event) + + @manager.events.should include(@event) + end + + it "should queue events for the target and callback of any matching edges" do + edge1 = stub("edge1", :callback => :c1, :source => stub("s1"), :target => stub("t1", :c1 => nil)) + edge2 = stub("edge2", :callback => :c2, :source => stub("s2"), :target => stub("t2", :c2 => nil)) + + @graph.expects(:matching_edges).with { |event, resource| event == @event }.returns [edge1, edge2] + + @manager.expects(:queue_event_for_resource).with(@resource, edge1.target, edge1.callback, @event) + @manager.expects(:queue_event_for_resource).with(@resource, edge2.target, edge2.callback, @event) + + @manager.queue_event(@resource, @event) + end + + it "should queue events for the changed resource if the resource is self-refreshing and not being deleted" do + @graph.stubs(:matching_edges).returns [] + + @resource.expects(:self_refresh?).returns true + @resource.expects(:deleting?).returns false + @manager.expects(:queue_event_for_resource).with(@resource, @resource, :refresh, @event) + + @manager.queue_event(@resource, @event) + end + + it "should not queue events for the changed resource if the resource is not self-refreshing" do + @graph.stubs(:matching_edges).returns [] + + @resource.expects(:self_refresh?).returns false + @resource.stubs(:deleting?).returns false + @manager.expects(:queue_event_for_resource).never + + @manager.queue_event(@resource, @event) + end + + it "should not queue events for the changed resource if the resource is being deleted" do + @graph.stubs(:matching_edges).returns [] + + @resource.expects(:self_refresh?).returns true + @resource.expects(:deleting?).returns true + @manager.expects(:queue_event_for_resource).never + + @manager.queue_event(@resource, @event) + end + + it "should ignore edges that don't have a callback" do + edge1 = stub("edge1", :callback => :nil, :source => stub("s1"), :target => stub("t1", :c1 => nil)) + + @graph.expects(:matching_edges).returns [edge1] + + @manager.expects(:queue_event_for_resource).never + + @manager.queue_event(@resource, @event) + end + + it "should ignore targets that don't respond to the callback" do + edge1 = stub("edge1", :callback => :c1, :source => stub("s1"), :target => stub("t1")) + + @graph.expects(:matching_edges).returns [edge1] + + @manager.expects(:queue_event_for_resource).never + + @manager.queue_event(@resource, @event) + end + end + + describe "when queueing events for a resource" do + before do + @transaction = stub 'transaction' + @manager = Puppet::Transaction::EventManager.new(@transaction) + end + + it "should do nothing if no events are queued" do + @manager.queued_events(stub("target")) { |callback, events| raise "should never reach this" } + end + + it "should yield the callback and events for each callback" do + target = stub("target") + + 2.times do |i| + @manager.queue_event_for_resource(stub("source", :info => nil), target, "callback#{i}", ["event#{i}"]) + end + + @manager.queued_events(target) { |callback, events| } + end + + it "should use the source to log that it's scheduling a refresh of the target" do + target = stub("target") + source = stub 'source' + source.expects(:info) + + @manager.queue_event_for_resource(source, target, "callback", ["event"]) + + @manager.queued_events(target) { |callback, events| } + end + end + + describe "when processing events for a given resource" do + before do + @transaction = Puppet::Transaction.new(Puppet::Resource::Catalog.new) + @manager = Puppet::Transaction::EventManager.new(@transaction) + @manager.stubs(:queue_event) + + @resource = stub 'resource', :notice => nil, :event => @event + @event = Puppet::Transaction::Event.new(:name => :event, :resource => @resource) + end + + it "should call the required callback once for each set of associated events" do + @manager.expects(:queued_events).with(@resource).multiple_yields([:callback1, [@event]], [:callback2, [@event]]) + + @resource.expects(:callback1) + @resource.expects(:callback2) + + @manager.process_events(@resource) + end + + it "should update the 'restarted' metric" do + @manager.expects(:queued_events).with(@resource).yields(:callback1, [@event]) + + @resource.stubs(:callback1) + + @manager.process_events(@resource) + + @transaction.resourcemetrics[:restarted].should == 1 + end + + it "should queue a 'restarted' event generated by the resource" do + @manager.expects(:queued_events).with(@resource).yields(:callback1, [@event]) + + @resource.stubs(:callback1) + + @resource.expects(:event).with(:name => :restarted, :status => "success").returns "myevent" + @manager.expects(:queue_event).with(@resource, "myevent") + + @manager.process_events(@resource) + end + + it "should log that it restarted" do + @manager.expects(:queued_events).with(@resource).yields(:callback1, [@event]) + + @resource.stubs(:callback1) + + @resource.expects(:notice).with { |msg| msg.include?("Triggered 'callback1'") } + + @manager.process_events(@resource) + end + + describe "and the events include a noop event and at least one non-noop event" do + before do + @event.stubs(:status).returns "noop" + @event2 = Puppet::Transaction::Event.new(:name => :event, :resource => @resource) + @event2.status = "success" + @manager.expects(:queued_events).with(@resource).yields(:callback1, [@event, @event2]) + end + + it "should call the callback" do + @resource.expects(:callback1) + + @manager.process_events(@resource) + end + end + + describe "and the events are all noop events" do + before do + @event.stubs(:status).returns "noop" + @resource.stubs(:event).returns(Puppet::Transaction::Event.new) + @manager.expects(:queued_events).with(@resource).yields(:callback1, [@event]) + end + + it "should log" do + @resource.expects(:notice).with { |msg| msg.include?("Would have triggered 'callback1'") } + + @manager.process_events(@resource) + end + + it "should not call the callback" do + @resource.expects(:callback1).never + + @manager.process_events(@resource) + end + + it "should queue a new noop event generated from the resource" do + event = Puppet::Transaction::Event.new + @resource.expects(:event).with(:status => "noop", :name => :noop_restart).returns event + @manager.expects(:queue_event).with(@resource, event) + + @manager.process_events(@resource) + end + end + + describe "and the callback fails" do + before do + @resource.expects(:callback1).raises "a failure" + @resource.stubs(:err) + + @manager.expects(:queued_events).yields(:callback1, [@event]) + end + + it "should log but not fail" do + @resource.expects(:err) + + lambda { @manager.process_events(@resource) }.should_not raise_error + end + + it "should update the 'failed_restarts' metric" do + @manager.process_events(@resource) + @transaction.resourcemetrics[:failed_restarts].should == 1 + end + + it "should not queue a 'restarted' event" do + @manager.expects(:queue_event).never + @manager.process_events(@resource) + end + + it "should not increase the restarted resource count" do + @manager.process_events(@resource) + @transaction.resourcemetrics[:restarted].should == 0 + end + end + end +end |