The proper enter/exit sequence is called for multisteps

This commit is contained in:
Mitchell Hashimoto 2011-12-06 18:45:37 -08:00
parent 822226cae4
commit 2c73de0043
2 changed files with 76 additions and 3 deletions

View File

@ -121,8 +121,9 @@ module Vagrant
# For each step, call it with proper inputs, using the output # For each step, call it with proper inputs, using the output
# of that call as inputs to the next. # of that call as inputs to the next.
entered_steps = []
step_outputs = {} step_outputs = {}
steps.inject(params) do |inputs, data| result = steps.inject(params) do |inputs, data|
name, step, mappings = data name, step, mappings = data
# If we have inputs to remap, remap them. # If we have inputs to remap, remap them.
@ -139,11 +140,26 @@ module Vagrant
# Call the actual step, using the results for the next # Call the actual step, using the results for the next
# iteration. # iteration.
step_outputs[name] = step.call(inputs) entered_steps << step
begin
step_outputs[name] = step.call_enter(inputs)
rescue Exception => e
entered_steps.reverse.each do |s|
s.call_exit(e)
end
raise
end
# Return a shallow dup of the results # Return a shallow dup of the results
step_outputs[name].dup step_outputs[name].dup
end end
entered_steps.reverse.each do |s|
s.call_exit(nil)
end
result
end end
protected protected

View File

@ -173,4 +173,61 @@ describe Vagrant::Action::MultiStep do
g = described_class.new g = described_class.new
expect { g.step step_A, g.input(:foo) => :input_B }.to raise_error(ArgumentError) expect { g.step step_A, g.input(:foo) => :input_B }.to raise_error(ArgumentError)
end end
it "should call the enter methods in order, and the exit in reverse order" do
step = Class.new(Vagrant::Action::Step) do
input :key
input :data
output :data
def enter
@data << @key
return :data => @data
end
def exit(error)
@data << @key
end
end
g = described_class.new
g.step step
g.step :two, step, g.input(:key2) => :key
g.step :three, step, g.input(:key3) => :key
result = g.call(:data => [], :key => "1", :key2 => "2", :key3 => "3")
result[:data].should == %W[1 2 3 3 2 1]
end
it "should halt the steps and call exit with the error if an error occurs" do
step = Class.new(Vagrant::Action::Step) do
input :key
input :data
output :data
def enter
@data << @key
raise Exception, "E" if @data.last == "2"
return :data => @data
end
def exit(error)
prefix = error ? error.message : ""
@data << "#{prefix}#{@key}"
end
end
g = described_class.new
g.step step
g.step :two, step, g.input(:key2) => :key
g.step :three, step, g.input(:key3) => :key
# Run the actual steps
data = []
expect do
result = g.call(:data => data, :key => "1", :key2 => "2", :key3 => "3")
end.to raise_error(Exception)
# Verify the result hit the methods in the proper order
data.should == %W[1 2 E2 E1]
end
end end