From 67729304a2ed4fe3d63e452b9cac3654f6a421af Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 4 Jul 2010 08:52:01 +0200 Subject: [PATCH] Import action. Erroneous environments for actions. --- lib/vagrant/action.rb | 14 +++++++++- lib/vagrant/action/environment.rb | 26 +++++++++++++++++ lib/vagrant/action/vm/import.rb | 16 ++++++++++- test/test_helper.rb | 6 ++++ test/vagrant/action/environment_test.rb | 18 ++++++++++++ test/vagrant/action/vm/import_test.rb | 37 +++++++++++++++++++++++++ test/vagrant/action_test.rb | 9 ++++++ 7 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 test/vagrant/action/vm/import_test.rb diff --git a/lib/vagrant/action.rb b/lib/vagrant/action.rb index 091f7d318..412dbafde 100644 --- a/lib/vagrant/action.rb +++ b/lib/vagrant/action.rb @@ -3,6 +3,8 @@ module Vagrant # has an instance of {Action} to allow for running in the context of # the environment. class Action + include Util + class << self # Returns the list of registered actions. def actions @@ -37,7 +39,17 @@ module Vagrant # @param [Object] callable An object which responds to `call`. def run(callable) callable = self.class.actions[callable] if callable.kind_of?(Symbol) - callable.call(Action::Environment.new(env)) + + action_environment = Action::Environment.new(env) + callable.call(action_environment) + + if action_environment.error? + # Erroneous environment resulted. Properly display error + # message. + key, options = action_environment.error + error_and_exit(key, options) + return false + end end end end diff --git a/lib/vagrant/action/environment.rb b/lib/vagrant/action/environment.rb index 9f75ffb38..ac8003ff4 100644 --- a/lib/vagrant/action/environment.rb +++ b/lib/vagrant/action/environment.rb @@ -9,8 +9,34 @@ module Vagrant # action environment. attr_reader :env + # If nonnil, the error associated with this environment. Set + # using {#error!} + attr_reader :error + def initialize(env) @env = env + @error = nil + end + + # Returns a logger associated with the environment. + def logger + env.logger + end + + # Flags the environment as erroneous. Stores the given key + # and options until the end of the action sequence. + # + # @param [Symbol] key Key to translation to display error message. + # @param [Hash] options Variables to pass to the translation + def error!(key, options=nil) + @error = [key, (options || {})] + end + + # Returns boolean denoting if environment is in erroneous state. + # + # @return [Boolean] + def error? + !error.nil? end end end diff --git a/lib/vagrant/action/vm/import.rb b/lib/vagrant/action/vm/import.rb index c70e57c73..cbf6ad740 100644 --- a/lib/vagrant/action/vm/import.rb +++ b/lib/vagrant/action/vm/import.rb @@ -7,8 +7,22 @@ module Vagrant end def call(env) + env.logger.info "Importing base VM (#{env.env.box.ovf_file})" + + begin + # Import the virtual machine + env['vm'] = VirtualBox::VM.import(env.env.box.ovf_file) do |progress| + env.logger.report_progress(progress.percent, 100, false) + end + + # Flag as erroneous and return if import failed + return env.error!(:virtualbox_import_failure) if !env['vm'] + ensure + env.logger.clear_progress + end + + # Import completed successfully. Continue the chain @app.call(env) - p env['vm'] end end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 33fb1f575..971e50f15 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -94,6 +94,12 @@ class Test::Unit::TestCase vm end + def mock_action_data + app = lambda { |env| } + env = Vagrant::Action::Environment.new(mock_environment) + [app, env] + end + # Sets up the mocks and instantiates an action for testing def mock_action(action_klass, *args) vm = mock("vboxvm") diff --git a/test/vagrant/action/environment_test.rb b/test/vagrant/action/environment_test.rb index 1d9ef3d2d..aac751ad3 100644 --- a/test/vagrant/action/environment_test.rb +++ b/test/vagrant/action/environment_test.rb @@ -3,6 +3,24 @@ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper') class ActionEnvironmentTest < Test::Unit::TestCase setup do @klass = Vagrant::Action::Environment + @instance = @klass.new(mock_environment) end + should "setup the logger" do + assert_equal @instance.env.logger, @instance.logger + end + + should "not be erroneous initially" do + assert !@instance.error? + end + + should "mark as erroneous" do + @instance.error!(:key) + assert_equal [:key, {}], @instance.error + end + + should "properly report erroneous" do + @instance.error!(:key) + assert @instance.error? + end end diff --git a/test/vagrant/action/vm/import_test.rb b/test/vagrant/action/vm/import_test.rb new file mode 100644 index 000000000..ed87f9984 --- /dev/null +++ b/test/vagrant/action/vm/import_test.rb @@ -0,0 +1,37 @@ +require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper') + +class ImportVMActionTest < Test::Unit::TestCase + setup do + @klass = Vagrant::Action::VM::Import + @app, @env = mock_action_data + @instance = @klass.new(@app, @env) + + ovf_file = "foo" + @box = mock("box") + @box.stubs(:ovf_file).returns(ovf_file) + @env.env.stubs(:box).returns(@box) + + VirtualBox::VM.stubs(:import) + end + + should "call import on VirtualBox with proper base" do + VirtualBox::VM.expects(:import).once.with(@env.env.box.ovf_file).returns("foo") + @instance.call(@env) + end + + should "call next in chain on success and set VM" do + vm = mock("vm") + VirtualBox::VM.stubs(:import).returns(vm) + @app.expects(:call).with(@env).once + @instance.call(@env) + + assert_equal vm, @env["vm"] + end + + should "mark environment erroneous and not continue chain on failure" do + @app.expects(:call).never + @instance.call(@env) + + assert @env.error? + end +end diff --git a/test/vagrant/action_test.rb b/test/vagrant/action_test.rb index 532597f77..9328ce55d 100644 --- a/test/vagrant/action_test.rb +++ b/test/vagrant/action_test.rb @@ -32,5 +32,14 @@ class ActionTest < Test::Unit::TestCase @klass.register(:call, callable) @instance.run(:call) end + + should "error and exit if erroneous environment results" do + callable = lambda do |env| + env.error!(:key, :foo => :bar) + end + + @instance.expects(:error_and_exit).with(:key, :foo => :bar) + @instance.run(callable) + end end end