From 8850c086b158b05bcf953a822d046a0c98e3b5f3 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 5 May 2012 18:28:07 -0700 Subject: [PATCH] Plugins can now have action_hooks --- lib/vagrant/action/runner.rb | 21 ++++++++++++++++++++- lib/vagrant/plugin/v1.rb | 21 +++++++++++++++++++++ test/unit/vagrant/plugin/v1_test.rb | 12 ++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/lib/vagrant/action/runner.rb b/lib/vagrant/action/runner.rb index 57deccfc6..69cd4569d 100644 --- a/lib/vagrant/action/runner.rb +++ b/lib/vagrant/action/runner.rb @@ -20,7 +20,7 @@ module Vagrant def run(callable_id, options=nil) callable = callable_id callable = Builder.new.use(callable_id) if callable_id.kind_of?(Class) - callable = @registry.get(callable_id) if callable_id.kind_of?(Symbol) + callable = registry_sequence(callable_id) if callable_id.kind_of?(Symbol) raise ArgumentError, "Argument to run must be a callable object or registered action." if !callable || !callable.respond_to?(:call) # Create the initial environment with the options given @@ -48,6 +48,25 @@ module Vagrant @logger.info("Running action: #{callable_id}") Util::Busy.busy(int_callback) { callable.call(environment) } end + + protected + + def registry_sequence(id) + # Attempt to get the sequence + seq = @registry.get(id) + return nil if !seq + + # Go through all the registered plugins and get all the hooks + # for this sequence. + Vagrant.plugin("1").registered.each do |plugin| + plugin.action_hook(id).each do |hook| + hook.call(seq) + end + end + + # Return the sequence + seq + end end end end diff --git a/lib/vagrant/plugin/v1.rb b/lib/vagrant/plugin/v1.rb index 0b1004569..bcb9a2c68 100644 --- a/lib/vagrant/plugin/v1.rb +++ b/lib/vagrant/plugin/v1.rb @@ -40,6 +40,24 @@ module Vagrant get_or_set(:description, value) end + # Registers a callback to be called when a specific action sequence + # is run. This allows plugin authors to hook into things like VM + # bootup, VM provisioning, etc. + # + # @param [Symbol] name Name of the action. + # @return [Array] List of the hooks for the given action. + def self.action_hook(name, &block) + # Get the list of hooks for the given hook name + data[:action_hooks] ||= {} + hooks = data[:action_hooks][name.to_sym] ||= [] + + # Return the list if we don't have a block + return hooks if !block_given? + + # Otherwise add the block to the list of hooks for this action. + hooks << block + end + # Defines additional command line commands available by key. The key # becomes the subcommand, so if you register a command "foo" then # "vagrant foo" becomes available. @@ -116,6 +134,9 @@ module Vagrant # Registers the plugin. This makes the plugin actually work with # Vagrant. Prior to registering, the plugin is merely a skeleton. + # + # This shouldn't be called by the general public. Plugins are automatically + # registered when they are given a name. def self.register!(plugin=nil) plugin ||= self diff --git a/test/unit/vagrant/plugin/v1_test.rb b/test/unit/vagrant/plugin/v1_test.rb index 91ae94bb2..ce95e7c08 100644 --- a/test/unit/vagrant/plugin/v1_test.rb +++ b/test/unit/vagrant/plugin/v1_test.rb @@ -23,6 +23,18 @@ describe Vagrant::Plugin::V1 do plugin.description.should == "bar" end + describe "action hooks" do + it "should register action hooks" do + plugin = Class.new(described_class) do + action_hook("foo") { "bar" } + end + + hooks = plugin.action_hook("foo") + hooks.length.should == 1 + hooks[0].call.should == "bar" + end + end + describe "commands" do it "should register command classes" do plugin = Class.new(described_class) do