Pulled out action running from VM into its own Actions::Runner class
This commit is contained in:
parent
cbcb877624
commit
f1fda1f0fa
|
@ -0,0 +1,73 @@
|
||||||
|
module Vagrant
|
||||||
|
module Actions
|
||||||
|
# Base class for any class which will act as a runner
|
||||||
|
# for actions. A runner is simply a class which will execute
|
||||||
|
# actions.
|
||||||
|
class Runner
|
||||||
|
class << self
|
||||||
|
# Executes a specific action.
|
||||||
|
def execute!(action_klass, *args)
|
||||||
|
runner = new
|
||||||
|
runner.add_action(action_klass, *args)
|
||||||
|
runner.execute!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns an array of all the actions in queue. Because this
|
||||||
|
# will persist accross calls (calling {#actions} twice will yield
|
||||||
|
# exactly the same object), to clear or modify it, use the ruby
|
||||||
|
# array methods which act on `self`, such as `Array#clear`.
|
||||||
|
#
|
||||||
|
# @return [Array]
|
||||||
|
def actions
|
||||||
|
@actions ||= []
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add an action to the list of queued actions to execute. This method
|
||||||
|
# appends the given action class to the end of the queue.
|
||||||
|
def add_action(action_klass, *args)
|
||||||
|
actions << action_klass.new(self, *args)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Execute the actions in queue.
|
||||||
|
def execute!(single_action=nil, *args)
|
||||||
|
if single_action
|
||||||
|
actions.clear
|
||||||
|
add_action(single_action, *args)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Call the prepare method on each once its
|
||||||
|
# initialized, then call the execute! method
|
||||||
|
return_value = nil
|
||||||
|
[:prepare, :execute!].each do |method|
|
||||||
|
actions.each do |action|
|
||||||
|
return_value = action.send(method)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return_value
|
||||||
|
end
|
||||||
|
|
||||||
|
# Invokes an "around callback" which invokes before_name and
|
||||||
|
# after_name for the given callback name, yielding a block between
|
||||||
|
# callback invokations.
|
||||||
|
def invoke_around_callback(name, *args)
|
||||||
|
invoke_callback("before_#{name}".to_sym, *args)
|
||||||
|
yield
|
||||||
|
invoke_callback("after_#{name}".to_sym, *args)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Invokes a single callback. This method will go through each action
|
||||||
|
# and call the method given in the parameter `name` if the action
|
||||||
|
# responds to it.
|
||||||
|
def invoke_callback(name, *args)
|
||||||
|
# Attempt to call the method for the callback on each of the
|
||||||
|
# actions
|
||||||
|
results = []
|
||||||
|
actions.each do |action|
|
||||||
|
results << action.send(name, *args) if action.respond_to?(name)
|
||||||
|
end
|
||||||
|
results
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,19 +1,11 @@
|
||||||
module Vagrant
|
module Vagrant
|
||||||
class VM
|
class VM < Actions::Runner
|
||||||
include Vagrant::Util
|
include Vagrant::Util
|
||||||
|
|
||||||
attr_accessor :vm
|
attr_accessor :vm
|
||||||
attr_reader :actions
|
|
||||||
attr_accessor :from
|
attr_accessor :from
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
# Executes a specific action
|
|
||||||
def execute!(action_klass, *args)
|
|
||||||
vm = new
|
|
||||||
vm.add_action(action_klass, *args)
|
|
||||||
vm.execute!
|
|
||||||
end
|
|
||||||
|
|
||||||
# Finds a virtual machine by a given UUID and either returns
|
# Finds a virtual machine by a given UUID and either returns
|
||||||
# a Vagrant::VM object or returns nil.
|
# a Vagrant::VM object or returns nil.
|
||||||
def find(uuid)
|
def find(uuid)
|
||||||
|
@ -25,47 +17,6 @@ module Vagrant
|
||||||
|
|
||||||
def initialize(vm=nil)
|
def initialize(vm=nil)
|
||||||
@vm = vm
|
@vm = vm
|
||||||
@actions = []
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_action(action_klass, *args)
|
|
||||||
@actions << action_klass.new(self, *args)
|
|
||||||
end
|
|
||||||
|
|
||||||
def execute!(single_action=nil, *args)
|
|
||||||
if single_action
|
|
||||||
@actions.clear
|
|
||||||
add_action(single_action, *args)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Call the prepare method on each once its
|
|
||||||
# initialized, then call the execute! method
|
|
||||||
return_value = nil
|
|
||||||
[:prepare, :execute!].each do |method|
|
|
||||||
@actions.each do |action|
|
|
||||||
return_value = action.send(method)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return_value
|
|
||||||
end
|
|
||||||
|
|
||||||
# Invokes an "around callback" which invokes before_name and
|
|
||||||
# after_name for the given callback name, yielding a block between
|
|
||||||
# callback invokations.
|
|
||||||
def invoke_around_callback(name, *args)
|
|
||||||
invoke_callback("before_#{name}".to_sym, *args)
|
|
||||||
yield
|
|
||||||
invoke_callback("after_#{name}".to_sym, *args)
|
|
||||||
end
|
|
||||||
|
|
||||||
def invoke_callback(name, *args)
|
|
||||||
# Attempt to call the method for the callback on each of the
|
|
||||||
# actions
|
|
||||||
results = []
|
|
||||||
@actions.each do |action|
|
|
||||||
results << action.send(name, *args) if action.respond_to?(name)
|
|
||||||
end
|
|
||||||
results
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
|
||||||
|
|
||||||
|
class ActionRunnerTest < Test::Unit::TestCase
|
||||||
|
context "callbacks" do
|
||||||
|
setup do
|
||||||
|
@runner = Vagrant::Actions::Runner.new
|
||||||
|
end
|
||||||
|
|
||||||
|
context "around callbacks" do
|
||||||
|
should "invoke before/after_name for around callbacks" do
|
||||||
|
block_obj = mock("block_obj")
|
||||||
|
around_seq = sequence("around_seq")
|
||||||
|
@runner.expects(:invoke_callback).with(:before_foo).once.in_sequence(around_seq)
|
||||||
|
block_obj.expects(:foo).once.in_sequence(around_seq)
|
||||||
|
@runner.expects(:invoke_callback).with(:after_foo).once.in_sequence(around_seq)
|
||||||
|
|
||||||
|
@runner.invoke_around_callback(:foo) do
|
||||||
|
block_obj.foo
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
should "forward arguments to invoke_callback" do
|
||||||
|
@runner.expects(:invoke_callback).with(:before_foo, "foo").once
|
||||||
|
@runner.expects(:invoke_callback).with(:after_foo, "foo").once
|
||||||
|
@runner.invoke_around_callback(:foo, "foo") do; end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
should "not invoke callback on actions which don't respond to it" do
|
||||||
|
action = mock("action")
|
||||||
|
action.stubs(:respond_to?).with(:foo).returns(false)
|
||||||
|
action.expects(:foo).never
|
||||||
|
|
||||||
|
assert_nothing_raised do
|
||||||
|
@runner.actions << action
|
||||||
|
@runner.invoke_callback(:foo)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
should "invoke callback on actions which do respond to the method" do
|
||||||
|
action = mock("action")
|
||||||
|
action.expects(:foo).once
|
||||||
|
|
||||||
|
@runner.actions << action
|
||||||
|
@runner.invoke_callback(:foo)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "collect all the results and return them as an array" do
|
||||||
|
result = []
|
||||||
|
3.times do |i|
|
||||||
|
action = mock("action#{i}")
|
||||||
|
action.expects(:foo).returns("foo#{i}").once
|
||||||
|
|
||||||
|
@runner.actions << action
|
||||||
|
result << "foo#{i}"
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal result, @runner.invoke_callback(:foo)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "actions" do
|
||||||
|
setup do
|
||||||
|
@runner = Vagrant::Actions::Runner.new
|
||||||
|
end
|
||||||
|
|
||||||
|
should "setup actions to be an array" do
|
||||||
|
assert_nil @runner.instance_variable_get(:@actions)
|
||||||
|
actions = @runner.actions
|
||||||
|
assert actions.is_a?(Array)
|
||||||
|
assert actions.equal?(@runner.actions)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "be empty initially" do
|
||||||
|
assert @runner.actions.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
should "initialize the action when added" do
|
||||||
|
action_klass = mock("action_class")
|
||||||
|
action_inst = mock("action_inst")
|
||||||
|
action_klass.expects(:new).once.returns(action_inst)
|
||||||
|
@runner.add_action(action_klass)
|
||||||
|
assert_equal 1, @runner.actions.length
|
||||||
|
end
|
||||||
|
|
||||||
|
should "initialize the action with given arguments when added" do
|
||||||
|
action_klass = mock("action_class")
|
||||||
|
action_klass.expects(:new).with(@runner, "foo", "bar").once
|
||||||
|
@runner.add_action(action_klass, "foo", "bar")
|
||||||
|
end
|
||||||
|
|
||||||
|
should "clear the actions and run a single action if given to execute!" do
|
||||||
|
action = mock("action")
|
||||||
|
run_action = mock("action_run")
|
||||||
|
run_class = mock("run_class")
|
||||||
|
run_class.expects(:new).once.returns(run_action)
|
||||||
|
@runner.actions << action
|
||||||
|
|
||||||
|
[:prepare, :execute!].each do |method|
|
||||||
|
action.expects(method).never
|
||||||
|
run_action.expects(method).once
|
||||||
|
end
|
||||||
|
|
||||||
|
@runner.execute!(run_class)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "run #prepare on all actions, then #execute!" do
|
||||||
|
action_seq = sequence("action_seq")
|
||||||
|
actions = []
|
||||||
|
5.times do |i|
|
||||||
|
action = mock("action#{i}")
|
||||||
|
|
||||||
|
@runner.actions << action
|
||||||
|
actions << action
|
||||||
|
end
|
||||||
|
|
||||||
|
[:prepare, :execute!].each do |method|
|
||||||
|
actions.each do |action|
|
||||||
|
action.expects(method).once.in_sequence(action_seq)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@runner.execute!
|
||||||
|
end
|
||||||
|
|
||||||
|
should "run actions on class method execute!" do
|
||||||
|
vm = mock("vm")
|
||||||
|
execute_seq = sequence("execute_seq")
|
||||||
|
Vagrant::VM.expects(:new).returns(vm).in_sequence(execute_seq)
|
||||||
|
vm.expects(:add_action).with("foo").in_sequence(execute_seq)
|
||||||
|
vm.expects(:execute!).once.in_sequence(execute_seq)
|
||||||
|
|
||||||
|
Vagrant::VM.execute!("foo")
|
||||||
|
end
|
||||||
|
|
||||||
|
should "forward arguments to add_action on class method execute!" do
|
||||||
|
vm = mock("vm")
|
||||||
|
execute_seq = sequence("execute_seq")
|
||||||
|
Vagrant::VM.expects(:new).returns(vm).in_sequence(execute_seq)
|
||||||
|
vm.expects(:add_action).with("foo", "bar", "baz").in_sequence(execute_seq)
|
||||||
|
vm.expects(:execute!).once.in_sequence(execute_seq)
|
||||||
|
|
||||||
|
Vagrant::VM.execute!("foo", "bar", "baz")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -11,142 +11,6 @@ class VMTest < Test::Unit::TestCase
|
||||||
Net::SSH.stubs(:start)
|
Net::SSH.stubs(:start)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "callbacks" do
|
|
||||||
setup do
|
|
||||||
@vm = Vagrant::VM.new(@mock_vm)
|
|
||||||
end
|
|
||||||
|
|
||||||
context "around callbacks" do
|
|
||||||
should "invoke before/after_name for around callbacks" do
|
|
||||||
block_obj = mock("block_obj")
|
|
||||||
around_seq = sequence("around_seq")
|
|
||||||
@vm.expects(:invoke_callback).with(:before_foo).once.in_sequence(around_seq)
|
|
||||||
block_obj.expects(:foo).once.in_sequence(around_seq)
|
|
||||||
@vm.expects(:invoke_callback).with(:after_foo).once.in_sequence(around_seq)
|
|
||||||
|
|
||||||
@vm.invoke_around_callback(:foo) do
|
|
||||||
block_obj.foo
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
should "forward arguments to invoke_callback" do
|
|
||||||
@vm.expects(:invoke_callback).with(:before_foo, "foo").once
|
|
||||||
@vm.expects(:invoke_callback).with(:after_foo, "foo").once
|
|
||||||
@vm.invoke_around_callback(:foo, "foo") do; end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
should "not invoke callback on actions which don't respond to it" do
|
|
||||||
action = mock("action")
|
|
||||||
action.stubs(:respond_to?).with(:foo).returns(false)
|
|
||||||
action.expects(:foo).never
|
|
||||||
|
|
||||||
assert_nothing_raised do
|
|
||||||
@vm.actions << action
|
|
||||||
@vm.invoke_callback(:foo)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
should "invoke callback on actions which do respond to the method" do
|
|
||||||
action = mock("action")
|
|
||||||
action.expects(:foo).once
|
|
||||||
|
|
||||||
@vm.actions << action
|
|
||||||
@vm.invoke_callback(:foo)
|
|
||||||
end
|
|
||||||
|
|
||||||
should "collect all the results and return them as an array" do
|
|
||||||
result = []
|
|
||||||
3.times do |i|
|
|
||||||
action = mock("action#{i}")
|
|
||||||
action.expects(:foo).returns("foo#{i}").once
|
|
||||||
|
|
||||||
@vm.actions << action
|
|
||||||
result << "foo#{i}"
|
|
||||||
end
|
|
||||||
|
|
||||||
assert_equal result, @vm.invoke_callback(:foo)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "actions" do
|
|
||||||
setup do
|
|
||||||
@vm = Vagrant::VM.new(@mock_vm)
|
|
||||||
end
|
|
||||||
|
|
||||||
should "be empty initially" do
|
|
||||||
assert @vm.actions.empty?
|
|
||||||
end
|
|
||||||
|
|
||||||
should "initialize the action when added" do
|
|
||||||
action_klass = mock("action_class")
|
|
||||||
action_inst = mock("action_inst")
|
|
||||||
action_klass.expects(:new).once.returns(action_inst)
|
|
||||||
@vm.add_action(action_klass)
|
|
||||||
assert_equal 1, @vm.actions.length
|
|
||||||
end
|
|
||||||
|
|
||||||
should "initialize the action with given arguments when added" do
|
|
||||||
action_klass = mock("action_class")
|
|
||||||
action_klass.expects(:new).with(@vm, "foo", "bar").once
|
|
||||||
@vm.add_action(action_klass, "foo", "bar")
|
|
||||||
end
|
|
||||||
|
|
||||||
should "clear the actions and run a single action if given to execute!" do
|
|
||||||
action = mock("action")
|
|
||||||
run_action = mock("action_run")
|
|
||||||
run_class = mock("run_class")
|
|
||||||
run_class.expects(:new).once.returns(run_action)
|
|
||||||
@vm.actions << action
|
|
||||||
|
|
||||||
[:prepare, :execute!].each do |method|
|
|
||||||
action.expects(method).never
|
|
||||||
run_action.expects(method).once
|
|
||||||
end
|
|
||||||
|
|
||||||
@vm.execute!(run_class)
|
|
||||||
end
|
|
||||||
|
|
||||||
should "run #prepare on all actions, then #execute!" do
|
|
||||||
action_seq = sequence("action_seq")
|
|
||||||
actions = []
|
|
||||||
5.times do |i|
|
|
||||||
action = mock("action#{i}")
|
|
||||||
|
|
||||||
@vm.actions << action
|
|
||||||
actions << action
|
|
||||||
end
|
|
||||||
|
|
||||||
[:prepare, :execute!].each do |method|
|
|
||||||
actions.each do |action|
|
|
||||||
action.expects(method).once.in_sequence(action_seq)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@vm.execute!
|
|
||||||
end
|
|
||||||
|
|
||||||
should "run actions on class method execute!" do
|
|
||||||
vm = mock("vm")
|
|
||||||
execute_seq = sequence("execute_seq")
|
|
||||||
Vagrant::VM.expects(:new).returns(vm).in_sequence(execute_seq)
|
|
||||||
vm.expects(:add_action).with("foo").in_sequence(execute_seq)
|
|
||||||
vm.expects(:execute!).once.in_sequence(execute_seq)
|
|
||||||
|
|
||||||
Vagrant::VM.execute!("foo")
|
|
||||||
end
|
|
||||||
|
|
||||||
should "forward arguments to add_action on class method execute!" do
|
|
||||||
vm = mock("vm")
|
|
||||||
execute_seq = sequence("execute_seq")
|
|
||||||
Vagrant::VM.expects(:new).returns(vm).in_sequence(execute_seq)
|
|
||||||
vm.expects(:add_action).with("foo", "bar", "baz").in_sequence(execute_seq)
|
|
||||||
vm.expects(:execute!).once.in_sequence(execute_seq)
|
|
||||||
|
|
||||||
Vagrant::VM.execute!("foo", "bar", "baz")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "finding a VM" do
|
context "finding a VM" do
|
||||||
should "return nil if the VM is not found" do
|
should "return nil if the VM is not found" do
|
||||||
VirtualBox::VM.expects(:find).returns(nil)
|
VirtualBox::VM.expects(:find).returns(nil)
|
||||||
|
|
Loading…
Reference in New Issue