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
|
||||
class VM
|
||||
class VM < Actions::Runner
|
||||
include Vagrant::Util
|
||||
|
||||
attr_accessor :vm
|
||||
attr_reader :actions
|
||||
attr_accessor :from
|
||||
|
||||
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
|
||||
# a Vagrant::VM object or returns nil.
|
||||
def find(uuid)
|
||||
|
@ -25,47 +17,6 @@ module Vagrant
|
|||
|
||||
def initialize(vm=nil)
|
||||
@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
|
||||
|
||||
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)
|
||||
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
|
||||
should "return nil if the VM is not found" do
|
||||
VirtualBox::VM.expects(:find).returns(nil)
|
||||
|
|
Loading…
Reference in New Issue