From 8f0375d7f3e94bcfb3ea97c457afb97113f73586 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 16 Jul 2012 14:12:58 -0700 Subject: [PATCH] Machines can call actions on their providers. --- lib/vagrant/errors.rb | 4 +++ lib/vagrant/machine.rb | 20 ++++++++++++++ templates/locales/en.yml | 5 ++++ test/unit/vagrant/machine_test.rb | 43 +++++++++++++++++++++++++++---- 4 files changed, 67 insertions(+), 5 deletions(-) diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index 0b57d7c45..6097de946 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -376,6 +376,10 @@ module Vagrant error_key(:ui_expects_tty) end + class UnimplementedProviderAction < VagrantError + error_key(:unimplemented_provider_action) + end + class VagrantInterrupt < VagrantError status_code(40) error_key(:interrupted) diff --git a/lib/vagrant/machine.rb b/lib/vagrant/machine.rb index 534f5b5a5..e807a65a1 100644 --- a/lib/vagrant/machine.rb +++ b/lib/vagrant/machine.rb @@ -42,6 +42,26 @@ module Vagrant @provider = provider_cls.new(self) end + # This calls an action on the provider. The provider may or may not + # actually implement the action. + # + # @param [Symbol] name Name of the action to run. + def action(name) + # Get the callable from the provider. + callable = @provider.action(name) + + # If this action doesn't exist on the provider, then an exception + # must be raised. + if callable.nil? + raise Errors::UnimplementedProviderAction, + :action => name, + :provider => @provider.to_s + end + + # Run the action with the action runner on the environment + @env.action_runner.run(callable, :machine => self) + end + # Returns the state of this machine. The state is queried from the # backing provider, so it can be any arbitrary symbol. # diff --git a/templates/locales/en.yml b/templates/locales/en.yml index d5325b4cd..de3d55e31 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -182,6 +182,11 @@ en: a TTY. Most actions in Vagrant that require a TTY have configuration switches to disable this requirement. Please do that or run Vagrant with TTY. + unimplemented_provider_action: |- + Vagrant attempted to call the action '%{action}' on the provider + '%{provider}', but this provider doesn't support this action. This + is probably a bug in either the provider or the plugin calling this + action, and should be reported. vagrantfile_exists: |- `Vagrantfile` already exists in this directory. Remove it before running `vagrant init`. diff --git a/test/unit/vagrant/machine_test.rb b/test/unit/vagrant/machine_test.rb index 2895e8ab7..f941c349b 100644 --- a/test/unit/vagrant/machine_test.rb +++ b/test/unit/vagrant/machine_test.rb @@ -12,9 +12,10 @@ describe Vagrant::Machine do end let(:box) { Object.new } let(:config) { Object.new } - let(:environment) { isolated_environment } + let(:env) { test_env.create_vagrant_env } + let(:test_env) { isolated_environment } - let(:instance) { described_class.new(name, provider_cls, config, box, environment) } + let(:instance) { described_class.new(name, provider_cls, config, box, env) } describe "initialization" do it "should initialize the provider with the machine object" do @@ -30,10 +31,10 @@ describe Vagrant::Machine do machine.name.should == name machine.config.should eql(config) machine.box.should eql(box) - machine.env.should eql(environment) + machine.env.should eql(env) end - instance = described_class.new(name, provider_cls, config, box, environment) + instance = described_class.new(name, provider_cls, config, box, env) received_machine.should eql(instance) end end @@ -52,7 +53,39 @@ describe Vagrant::Machine do end it "should provide access to the environment" do - instance.env.should eql(environment) + instance.env.should eql(env) + end + end + + describe "actions" do + it "should be able to run an action that exists" do + action_name = :up + called = false + callable = lambda { |_env| called = true } + + provider.should_receive(:action).with(action_name).and_return(callable) + instance.action(:up) + called.should be + end + + it "should provide the machine in the environment" do + action_name = :up + machine = nil + callable = lambda { |env| machine = env[:machine] } + + provider.stub(:action).with(action_name).and_return(callable) + instance.action(:up) + + machine.should eql(instance) + end + + it "should raise an exception if the action is not implemented" do + action_name = :up + + provider.stub(:action).with(action_name).and_return(nil) + + expect { instance.action(action_name) }. + to raise_error(Vagrant::Errors::UnimplementedProviderAction) end end