Call hooks before and after each action if they are available

This commit is contained in:
Chris Roberts 2019-12-16 17:10:12 -08:00
parent 8c137e2bba
commit 80c05460ab
2 changed files with 85 additions and 44 deletions

View File

@ -47,7 +47,16 @@ module Vagrant
raise Errors::VagrantInterrupt if env[:interrupted]
action = @actions.shift
@logger.info("Calling IN action: #{action}")
if !action.is_a?(Proc) && env[:hook]
hook_name = action.class.name.split("::").last.
gsub(/([a-z])([A-Z])/, '\1_\2').gsub('-', '_').downcase
end
env[:hook].call("before_#{hook_name}".to_sym) if hook_name
@stack.unshift(action).first.call(env)
env[:hook].call("after_#{hook_name}".to_sym) if hook_name
raise Errors::VagrantInterrupt if env[:interrupted]
@logger.info("Calling OUT action: #{action}")
rescue SystemExit

View File

@ -1,6 +1,48 @@
require File.expand_path("../../../base", __FILE__)
describe Vagrant::Action::Warden do
class ActionOne
def initialize(app, env)
@app = app
end
def call(env)
@app.call(env)
end
def recover(env)
env[:recover] << 1
end
end
class ActionTwo
def initialize(app, env)
@app = app
end
def call(env)
@app.call(env)
end
def recover(env)
env[:recover] << 2
end
end
class ExitAction
def initialize(app, env)
@app = app
end
def call(env)
@app.call(env)
end
def recover(env)
env[:recover] = true
end
end
let(:data) { { data: [] } }
let(:instance) { described_class.new }
@ -18,38 +60,10 @@ describe Vagrant::Action::Warden do
end
it "starts a recovery sequence when an exception is raised" do
class Action
def initialize(app, env)
@app = app
end
def call(env)
@app.call(env)
end
def recover(env)
env[:recover] << 1
end
end
class ActionTwo
def initialize(app, env)
@app = app
end
def call(env)
@app.call(env)
end
def recover(env)
env[:recover] << 2
end
end
error_proc = Proc.new { raise "ERROR!" }
data = { recover: [] }
instance = described_class.new([Action, ActionTwo, error_proc], data)
instance = described_class.new([ActionOne, ActionTwo, error_proc], data)
# The error should be raised back up
expect { instance.call(data) }.
@ -63,25 +77,11 @@ describe Vagrant::Action::Warden do
end
it "does not do a recovery sequence if SystemExit is raised" do
class Action
def initialize(app, env)
@app = app
end
def call(env)
@app.call(env)
end
def recover(env)
env[:recover] = true
end
end
# Make a proc that just calls "abort" which raises a
# SystemExit exception.
error_proc = Proc.new { abort }
instance = described_class.new([Action, error_proc], data)
instance = described_class.new([ExitAction, error_proc], data)
# The SystemExit should come through
expect { instance.call(data) }.to raise_error(SystemExit)
@ -89,4 +89,36 @@ describe Vagrant::Action::Warden do
# The recover should not have been called
expect(data.key?(:recover)).not_to be
end
context "when hook is defined" do
let(:hook) { double("hook") }
before do
data[:hook] = hook
allow(hook).to receive(:call)
end
it "should receive a before hook call" do
expect(hook).to receive(:call).with(:before_action_one)
described_class.new([ActionOne], data).call(data)
end
it "should receive an after hook call" do
expect(hook).to receive(:call).with(:after_action_one)
described_class.new([ActionOne], data).call(data)
end
it "should not receive any hook calls for proc instances" do
expect(hook).not_to receive(:call)
described_class.new([proc{|*_| :testing }], data).call(data)
end
it "should receive before and after calls for each class" do
expect(hook).to receive(:call).with(:before_action_one)
expect(hook).to receive(:call).with(:after_action_one)
expect(hook).to receive(:call).with(:before_action_two)
expect(hook).to receive(:call).with(:after_action_two)
described_class.new([ActionOne, proc{|*_| :testing }, ActionTwo], data).call(data)
end
end
end