diff --git a/lib/vagrant/action/multistep.rb b/lib/vagrant/action/multistep.rb index 5f7285f40..d30702d4e 100644 --- a/lib/vagrant/action/multistep.rb +++ b/lib/vagrant/action/multistep.rb @@ -67,6 +67,8 @@ module Vagrant maps = {} maps = extra_inputs.pop if extra_inputs.last.kind_of?(Hash) + # Go over each extra input and handle the mapping. This is typically + # syntactic sugar. extra_inputs.each do |direct| if direct.is_a?(Symbol) # Symbols are assumed to be inputs to this group @@ -76,6 +78,21 @@ module Vagrant maps[direct] = direct.variable end + # Turn the pure symbols into mapping from last steps + maps.keys.each do |from| + if from.kind_of?(Symbol) + new_from = output(@step_names.last, from) + maps[new_from] = maps.delete(from) + end + end + + # Verify that all the mappings are correctly satisfied. + maps.each do |from, to| + if !mapping_satisfied?(step_class, from, to) + raise ArgumentError, "Mapping from #{from.variable} to #{to} fails." + end + end + # Append the step @step_names << step_name @steps[step_name] = [step_class, maps] @@ -120,6 +137,24 @@ module Vagrant step_outputs[name].dup end end + + protected + + def mapping_satisfied?(step, from, to) + # If the step inputs don't contain to then we fail + return false if !step.inputs.include?(to) + + if from.kind_of?(GroupInput) + # We assume that inputs from the group are satisfied since + # it has to come in. + return true + elsif from.kind_of?(StepOutput) + # Verify that the outputs of the step exist to map. + return @steps[from.name][0].outputs.include?(from.variable) + end + + true + end end end end diff --git a/test/unit/vagrant/action/multistep_test.rb b/test/unit/vagrant/action/multistep_test.rb index 653e3ef7c..2cc4e7e3a 100644 --- a/test/unit/vagrant/action/multistep_test.rb +++ b/test/unit/vagrant/action/multistep_test.rb @@ -136,4 +136,27 @@ describe Vagrant::Action::MultiStep do g = described_class.new expect { g.step :foo }.to raise_error(ArgumentError) end + + it "should not allow remapping from outputs that don't exist" do + step_A = Class.new(Vagrant::Action::Step) do + output :output_A + end + + step_B = Class.new(Vagrant::Action::Step) do + input :input_B + end + + g = described_class.new + g.step step_A + expect { g.step step_B, :output_B => :input_B }.to raise_error(ArgumentError) + end + + it "should not allow remapping to inputs that don't exist" do + step_A = Class.new(Vagrant::Action::Step) do + input :input_A + end + + g = described_class.new + expect { g.step step_A, g.input(:foo) => :input_B }.to raise_error(ArgumentError) + end end