The `Call` built-in middleware allows for conditional MW sequences.
Read the documentation for more information.
This commit is contained in:
parent
5eed3b8417
commit
90517a0f9b
|
@ -2,7 +2,6 @@ require 'vagrant/action/builder'
|
|||
|
||||
module Vagrant
|
||||
module Action
|
||||
autoload :Builtin, 'vagrant/action/builtin'
|
||||
autoload :Environment, 'vagrant/action/environment'
|
||||
autoload :Runner, 'vagrant/action/runner'
|
||||
autoload :Warden, 'vagrant/action/warden'
|
||||
|
@ -13,6 +12,12 @@ module Vagrant
|
|||
autoload :Verify, 'vagrant/action/box/verify'
|
||||
end
|
||||
|
||||
# Builtin contains middleware classes that are shipped with Vagrant-core
|
||||
# and are thus available to all plugins as a "standard library" of sorts.
|
||||
module Builtin
|
||||
autoload :Call, "vagrant/action/builtin/call"
|
||||
end
|
||||
|
||||
module Env
|
||||
autoload :Set, 'vagrant/action/env/set'
|
||||
end
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
module Vagrant
|
||||
module Action
|
||||
module Builtin
|
||||
# This middleware class allows a sort of "conditional" run within
|
||||
# a single middlware sequence. It takes another middleware runnable,
|
||||
# runs it with the same environment, then yields the result to a block,
|
||||
# allowing that block to determine the next course of action in the
|
||||
# middleware sequence.
|
||||
#
|
||||
# The first argument to this middleware sequence is anywhere middleware
|
||||
# runnable, whether it be a class, lambda, or something else that
|
||||
# responds to `call`. This middleware runnable is run with the same
|
||||
# environment as this class. The "result" of the run is expected to be
|
||||
# placed in `env[:result]`.
|
||||
#
|
||||
# After running, {Call} takes `env[:result]` and yields it to a block
|
||||
# given to initialize the class, along with an instance of {Builder}.
|
||||
# The result is used to build up a new sequence on the given builder.
|
||||
# This builder is then run.
|
||||
class Call
|
||||
# For documentation, read the description of the {Call} class.
|
||||
#
|
||||
# @param [Object] callable A valid middleware runnable object. This
|
||||
# can be a class, a lambda, or an object that responds to `call`.
|
||||
# @yield [result, builder] This block is expected to build on `builder`
|
||||
# which is the next middleware sequence that will be run.
|
||||
def initialize(app, env, callable, &block)
|
||||
raise ArgumentError, "A block must be given to Call" if !block
|
||||
|
||||
@app = app
|
||||
@callable = callable
|
||||
@block = block
|
||||
end
|
||||
|
||||
def call(env)
|
||||
runner = Runner.new
|
||||
|
||||
# Run our callable with our environment
|
||||
new_env = runner.run(@callable, env)
|
||||
|
||||
# Build our new builder based on the result
|
||||
builder = Builder.new
|
||||
@block.call(new_env[:result], builder)
|
||||
|
||||
# Run the result with our new environment
|
||||
final_env = runner.run(builder, new_env)
|
||||
|
||||
# Call the next step using our final environment
|
||||
@app.call(final_env)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -45,6 +45,10 @@ module Vagrant
|
|||
# We place a process lock around every action that is called
|
||||
@logger.info("Running action: #{callable_id}")
|
||||
Util::Busy.busy(int_callback) { callable.call(environment) }
|
||||
|
||||
# Return the environment in case there are things in there that
|
||||
# the caller wants to use.
|
||||
environment
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,14 +5,26 @@ module VagrantPlugins
|
|||
module Action
|
||||
autoload :CheckAccessible, File.expand_path("../action/check_accessible", __FILE__)
|
||||
autoload :CheckVirtualbox, File.expand_path("../action/check_virtualbox", __FILE__)
|
||||
autoload :Created, File.expand_path("../action/created", __FILE__)
|
||||
|
||||
# Include the built-in modules so that we can use them as top-level
|
||||
# things.
|
||||
include Vagrant::Action::Builtin
|
||||
|
||||
# This is the action that is primarily responsible for completely
|
||||
# freeing the resources of the underlying virtual machine.
|
||||
def self.action_destroy
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use CheckVirtualbox
|
||||
b.use Vagrant::Action::General::Validate
|
||||
b.use CheckAccessible
|
||||
b.use Call, Created do |result, b2|
|
||||
# `result` is a boolean true/false of whether the VM is created or
|
||||
# not. So if the VM _is_ created, then we continue with the
|
||||
# destruction.
|
||||
if result
|
||||
b2.use Vagrant::Action::General::Validate
|
||||
b2.use CheckAccessible
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
module VagrantPlugins
|
||||
module ProviderVirtualBox
|
||||
module Action
|
||||
class Created
|
||||
def initialize(app, env)
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
# Set the result to be true if the machine is created.
|
||||
env[:result] = env[:machine].state != :not_created
|
||||
|
||||
# Call the next if we have one (but we shouldn't, since this
|
||||
# middleware is built to run with the Call-type middlewares)
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,66 @@
|
|||
require File.expand_path("../../../../base", __FILE__)
|
||||
|
||||
describe Vagrant::Action::Builtin::Call do
|
||||
let(:app) { lambda { |env| } }
|
||||
let(:env) { {} }
|
||||
|
||||
it "should yield the result to the block" do
|
||||
received = nil
|
||||
|
||||
callable = lambda do |env|
|
||||
env[:result] = "value"
|
||||
end
|
||||
|
||||
described_class.new(app, env, callable) do |result, builder|
|
||||
received = result
|
||||
end.call({})
|
||||
|
||||
received.should == "value"
|
||||
end
|
||||
|
||||
it "should give a nil result if no result is given" do
|
||||
received = 42
|
||||
callable = lambda { |env| }
|
||||
|
||||
described_class.new(app, env, callable) do |result, builder|
|
||||
received = result
|
||||
end.call({})
|
||||
|
||||
received.should be_nil
|
||||
end
|
||||
|
||||
it "should call the callable with the original environment" do
|
||||
received = nil
|
||||
callable = lambda { |env| received = env[:foo] }
|
||||
|
||||
described_class.new(app, env, callable) do |result, builder|
|
||||
# Nothing.
|
||||
end.call({ :foo => :bar })
|
||||
|
||||
received.should == :bar
|
||||
end
|
||||
|
||||
it "should call the next builder" do
|
||||
received = nil
|
||||
callable = lambda { |env| }
|
||||
next_step = lambda { |env| received = "value" }
|
||||
|
||||
described_class.new(app, env, callable) do |result, builder|
|
||||
builder.use next_step
|
||||
end.call({})
|
||||
|
||||
received.should == "value"
|
||||
end
|
||||
|
||||
it "should call the next builder with the original environment" do
|
||||
received = nil
|
||||
callable = lambda { |env| }
|
||||
next_step = lambda { |env| received = env[:foo] }
|
||||
|
||||
described_class.new(app, env, callable) do |result, builder|
|
||||
builder.use next_step
|
||||
end.call({ :foo => :bar })
|
||||
|
||||
received.should == :bar
|
||||
end
|
||||
end
|
|
@ -25,6 +25,18 @@ describe Vagrant::Action::Runner do
|
|||
expect { instance.run(callable) }.to raise_error(Exception, "BOOM")
|
||||
end
|
||||
|
||||
it "should return the resulting environment" do
|
||||
callable = lambda do |env|
|
||||
env[:data] = "value"
|
||||
|
||||
# Return nil so we can make sure it isn't using this return value
|
||||
nil
|
||||
end
|
||||
|
||||
result = instance.run(callable)
|
||||
result[:data].should == "value"
|
||||
end
|
||||
|
||||
it "should pass options into hash given to callable" do
|
||||
result = nil
|
||||
callable = lambda do |env|
|
||||
|
|
Loading…
Reference in New Issue