Machines can call actions on their providers.

This commit is contained in:
Mitchell Hashimoto 2012-07-16 14:12:58 -07:00
parent 8fc5591b8e
commit 8f0375d7f3
4 changed files with 67 additions and 5 deletions

View File

@ -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)

View File

@ -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.
#

View File

@ -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`.

View File

@ -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