Plugin activation
Vagrant is only guaranteeing that the plugin definition superclass (the Vagrant.plugin("1") part) is backwards compatible. Anything else, such as Vagrant::Command::Base and so on, will likely change in future versions. Beacuse of this, plugins should only immediately expose their definition. In order to support loading the other classes, plugins should defer loading to the "activation" phase of a plugin. This can be done using the `activated` block: class MyPlugin < Vagrant.plugin("1") name "my plugin" activated do require "myplugin/my_command" end command("foo") { MyCommand } end Plugin activation is done at two specific times: * Right when a Vagrant::Environment is created and the global plugins (such as from ~.vagrantrc) are loaded. * Right before loading configuration, but after the Vagrantfiles have been evaluated. This allows plugins to be defined within these files as well.
This commit is contained in:
parent
5a3cf0e01b
commit
de78a3637a
|
@ -100,6 +100,9 @@ module Vagrant
|
|||
|
||||
# Load the plugins
|
||||
load_plugins
|
||||
|
||||
# Activate the plugins
|
||||
activate_plugins
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------
|
||||
|
@ -395,6 +398,10 @@ module Vagrant
|
|||
config_loader.set(:vm, subvm.proc_stack)
|
||||
end
|
||||
|
||||
# We activate plugins here because the files which we're loading
|
||||
# configuration from may have defined new plugins as well.
|
||||
activate_plugins
|
||||
|
||||
# Execute the configuration stack and store the result as the final
|
||||
# value in the config ivar.
|
||||
config_loader.load
|
||||
|
@ -515,6 +522,14 @@ module Vagrant
|
|||
nil
|
||||
end
|
||||
|
||||
# This finds all the current plugins and activates them. This is an
|
||||
# idempotent call so it is safe to call this as much as you need.
|
||||
def activate_plugins
|
||||
Vagrant.plugin("1").registered.each do |plugin|
|
||||
plugin.activate!
|
||||
end
|
||||
end
|
||||
|
||||
# Loads the Vagrant plugins by properly setting up RubyGems so that
|
||||
# our private gem repository is on the path.
|
||||
def load_plugins
|
||||
|
|
|
@ -72,6 +72,19 @@ module Vagrant
|
|||
hooks << block
|
||||
end
|
||||
|
||||
# The given block will be called when this plugin is activated. The
|
||||
# activation block should be used to load any of the classes used by
|
||||
# the plugin other than the plugin definition itself. Vagrant only
|
||||
# guarantees that the plugin definition will remain backwards
|
||||
# compatible, but not any other classes (such as command base classes
|
||||
# or so on). Therefore, to avoid crashing future versions of Vagrant,
|
||||
# these classes should be placed in separate files and loaded in the
|
||||
# activation block.
|
||||
def self.activated(&block)
|
||||
data[:activation_block] = block if block_given?
|
||||
data[:activation_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.
|
||||
|
@ -185,6 +198,18 @@ module Vagrant
|
|||
data[:provisioners]
|
||||
end
|
||||
|
||||
# Activates the current plugin. This shouldn't be called publicly.
|
||||
def self.activate!
|
||||
if !data[:activated_called]
|
||||
LOGGER.info("Activating plugin: #{self.name}")
|
||||
data[:activated_called] = true
|
||||
|
||||
# Call the activation block
|
||||
block = activated
|
||||
block.call if block
|
||||
end
|
||||
end
|
||||
|
||||
# Registers the plugin. This makes the plugin actually work with
|
||||
# Vagrant. Prior to registering, the plugin is merely a skeleton.
|
||||
#
|
||||
|
|
|
@ -35,6 +35,34 @@ describe Vagrant::Plugin::V1 do
|
|||
end
|
||||
end
|
||||
|
||||
describe "activation block" do
|
||||
it "should have no activation block by default" do
|
||||
plugin = Class.new(described_class)
|
||||
plugin.activated.should be_nil
|
||||
end
|
||||
|
||||
it "should be able to set and get the activation block" do
|
||||
plugin = Class.new(described_class) do
|
||||
activated do
|
||||
42
|
||||
end
|
||||
end
|
||||
|
||||
plugin.activated.call.should == 42
|
||||
end
|
||||
|
||||
it "should activate when `activate!` is called" do
|
||||
plugin = Class.new(described_class) do
|
||||
activated do
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
|
||||
expect { plugin.activate! }.to raise_error(NotImplementedError)
|
||||
expect { plugin.activate! }.to_not raise_error
|
||||
end
|
||||
end
|
||||
|
||||
describe "commands" do
|
||||
it "should register command classes" do
|
||||
plugin = Class.new(described_class) do
|
||||
|
|
Loading…
Reference in New Issue