Much cleaner plugin part querying syntax.

Before we were manually going over every plugin and getting each piece,
all over the place. Now we have a central manager that will give us all
the pieces we want. There is still some cleanup to do here but this is
much better overall.
This commit is contained in:
Mitchell Hashimoto 2012-11-03 21:23:51 -07:00
parent 6ca671e2b8
commit c803b0508a
10 changed files with 179 additions and 103 deletions

View File

@ -84,13 +84,10 @@ module Vagrant
protected
def self.new_root_object
# Get all the registered plugins
# Get all the registered configuration objects and use them.
config_map = {}
Vagrant.plugin("1").registered.each do |plugin|
# Get all the available configuration keys and add them to the map
plugin.config.each do |key, klass|
config_map[key] = klass
end
Vagrant.plugin("1").manager.config.each do |key, klass|
config_map[key] = klass
end
# Create the configuration root object

View File

@ -191,10 +191,7 @@ module Vagrant
# will return nil, and we don't want to trigger a detect load.
host_klass = config.global.vagrant.host
if host_klass.nil? || host_klass == :detect
hosts = {}
Vagrant.plugin("1").registered.each do |plugin|
hosts = hosts.merge(plugin.host.to_hash)
end
hosts = Vagrant.plugin("1").manager.hosts
# Get the flattened list of available hosts
host_klass = Hosts.detect(hosts)
@ -437,11 +434,7 @@ module Vagrant
# Loads the persisted VM (if it exists) for this environment.
def load_vms!
# This is hardcoded for now.
provider = nil
Vagrant.plugin("1").registered.each do |plugin|
provider = plugin.provider.get(:virtualbox)
break if provider
end
provider = Vagrant.plugin("1").manager.providers[:virtualbox]
raise "VirtualBox provider not found." if !provider

View File

@ -116,14 +116,8 @@ module Vagrant
if !@communicator
# For now, we always return SSH. In the future, we'll abstract
# this and allow plugins to define new methods of communication.
Vagrant.plugin("1").registered.each do |plugin|
klass = plugin.communicator[:ssh]
if klass
# This plugin has the SSH communicator, use it.
@communicator = klass.new(self)
break
end
end
klass = Vagrant.plugin("1").manager.communicators[:ssh]
@communicator = klass.new(self)
end
@communicator
@ -276,13 +270,7 @@ module Vagrant
def load_guest(guest)
@logger.info("Loading guest: #{guest}")
klass = nil
Vagrant.plugin("1").registered.each do |plugin|
if plugin.guest.has_key?(guest)
klass = plugin.guest[guest]
break
end
end
klass = Vagrant.plugin("1").manager.guests[guest]
if klass.nil?
raise Errors::VMGuestError,

View File

@ -10,6 +10,7 @@ module Vagrant
autoload :Config, "vagrant/plugin/v1/config"
autoload :Guest, "vagrant/plugin/v1/guest"
autoload :Host, "vagrant/plugin/v1/host"
autoload :Manager, "vagrant/plugin/v1/manager"
autoload :Plugin, "vagrant/plugin/v1/plugin"
autoload :Provider, "vagrant/plugin/v1/provider"
autoload :Provisioner, "vagrant/plugin/v1/provisioner"

View File

@ -0,0 +1,112 @@
require "log4r"
module Vagrant
module Plugin
module V1
# This class maintains a list of all the registered plugins as well
# as provides methods that allow querying all registered components of
# those plugins as a single unit.
class Manager
attr_reader :registered
def initialize
@logger = Log4r::Logger.new("vagrant::plugin::v1::manager")
@registered = []
end
# This returns all the registered communicators.
#
# @return [Hash]
def communicators
result = {}
@registered.each do |plugin|
result.merge!(plugin.communicator.to_hash)
end
result
end
# This returns all the registered configuration classes.
#
# @return [Hash]
def config
result = {}
@registered.each do |plugin|
plugin.config.each do |key, klass|
result[key] = klass
end
end
result
end
# This returns all the registered guests.
#
# @return [Hash]
def guests
result = {}
@registered.each do |plugin|
result.merge!(plugin.guest.to_hash)
end
result
end
# This returns all registered host classes.
#
# @return [Hash]
def hosts
hosts = {}
@registered.each do |plugin|
hosts.merge!(plugin.host.to_hash)
end
hosts
end
# This returns all registered providers.
#
# @return [Hash]
def providers
providers = {}
@registered.each do |plugin|
providers.merge!(plugin.provider.to_hash)
end
providers
end
# This registers a plugin. This should _NEVER_ be called by the public
# and should only be called from within Vagrant. Vagrant will
# automatically register V1 plugins when a name is set on the
# plugin.
def register(plugin)
if !@registered.include?(plugin)
@logger.info("Registered plugin: #{plugin.name}")
@registered << plugin
end
end
# This clears out all the registered plugins. This is only used by
# unit tests and should not be called directly.
def reset!
@registered.clear
end
# This unregisters a plugin so that its components will no longer
# be used. Note that this should only be used for testing purposes.
def unregister(plugin)
if @registered.include?(plugin)
@logger.info("Unregistered: #{plugin.name}")
@registered.delete(plugin)
end
end
end
end
end
end

View File

@ -16,11 +16,11 @@ module Vagrant
# from within methods which are probably in subclasses.
ROOT_CLASS = self
# Returns a list of registered plugins for this version.
# This returns the manager for all V1 plugins.
#
# @return [Array]
def self.registered
@registry || []
# @return [V1::Manager]
def self.manager
@manager ||= Manager.new
end
# Set the name of the plugin. The moment that this is called, the
@ -36,7 +36,7 @@ module Vagrant
result = get_or_set(:name, name)
# The plugin should be registered if we're setting a real name on it
register! if name != UNSET_VALUE
Plugin.manager.register(self) if name != UNSET_VALUE
# Return the result
result
@ -116,7 +116,13 @@ module Vagrant
# without breaking anything in future versions of Vagrant.
#
# @param [String] name Configuration key.
def self.config(name=UNSET_VALUE, &block)
# @param [Boolean] upgrade_safe If this is true, then this configuration
# key is safe to load during an upgrade, meaning that it depends
# on NO Vagrant internal classes. Do _not_ set this to true unless
# you really know what you're doing, since you can cause Vagrant
# to crash (although Vagrant will output a user-friendly error
# message if this were to happen).
def self.config(name=UNSET_VALUE, upgrade_safe=false, &block)
data[:config] ||= Registry.new
# Register a new config class only if a name was given.
@ -212,41 +218,6 @@ module Vagrant
data[:provisioners]
end
# 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
# Register only on the root class
return ROOT_CLASS.register!(plugin) if self != ROOT_CLASS
# Register it into the list
@registry ||= []
if !@registry.include?(plugin)
LOGGER.info("Registered plugin: #{plugin.name}")
@registry << plugin
end
end
# This unregisters the plugin. Note that to re-register the plugin
# you must call `register!` again.
def self.unregister!(plugin=nil)
plugin ||= self
# Unregister only on the root class
return ROOT_CLASS.unregister!(plugin) if self != ROOT_CLASS
# Unregister it from the registry
@registry ||= []
if @registry.include?(plugin)
LOGGER.info("Unregistered: #{plugin.name}")
@registry.delete(plugin)
end
end
protected
# Sentinel value denoting that a value has not been set.

View File

@ -18,7 +18,7 @@ shared_context "unit" do
# Unregister each of the plugins we have may have temporarily
# registered for the duration of this test.
@_plugins.each do |plugin|
plugin.unregister!
Vagrant.plugin("1").manager.unregister(plugin)
end
end

View File

@ -13,9 +13,9 @@ describe Vagrant::Config::V1::Loader do
describe "finalizing" do
it "should call `#finalize` on the configuration object" do
# Register a plugin for our test
plugin_class = Class.new(Vagrant.plugin("1")) do
name "test"
config "foo" do
plugin_class = register_plugin do |plugin|
plugin.name "test"
plugin.config "foo" do
Class.new do
attr_accessor :bar
@ -31,28 +31,22 @@ describe Vagrant::Config::V1::Loader do
config.foo.bar = "value"
end
begin
# Test that it works properly
config = described_class.load(config_proc)
config.foo.bar.should == "value"
# Test that it works properly
config = described_class.load(config_proc)
config.foo.bar.should == "value"
# Finalize it
described_class.finalize(config)
config.foo.bar.should == "finalized"
ensure
# We have to unregister the plugin so that future tests
# aren't mucked up.
plugin_class.unregister!
end
# Finalize it
described_class.finalize(config)
config.foo.bar.should == "finalized"
end
end
describe "loading" do
it "should configure with all plugin config keys loaded" do
# Register a plugin for our test
plugin_class = Class.new(Vagrant.plugin("1")) do
name "test"
config "foo" do
plugin_class = register_plugin do |plugin|
plugin.name "test"
plugin.config "foo" do
Class.new do
attr_accessor :bar
end
@ -64,15 +58,9 @@ describe Vagrant::Config::V1::Loader do
config.foo.bar = "value"
end
begin
# Test that it works properly
config = described_class.load(config_proc)
config.foo.bar.should == "value"
ensure
# We have to unregister the plugin so that future tests
# aren't mucked up.
plugin_class.unregister!
end
# Test that it works properly
config = described_class.load(config_proc)
config.foo.bar.should == "value"
end
end

View File

@ -0,0 +1,24 @@
require File.expand_path("../../../../base", __FILE__)
describe Vagrant::Plugin::V1::Manager do
include_context "unit"
let(:instance) { described_class.new }
def plugin
p = Class.new(Vagrant.plugin("1"))
yield p
p
end
it "should enumerate registered configuration classes" do
pA = plugin do |p|
p.config("foo") { "bar" }
end
instance.register(pA)
instance.config.length.should == 1
instance.config[:foo].should == "bar"
end
end

View File

@ -4,7 +4,7 @@ describe Vagrant::Plugin::V1::Plugin do
after(:each) do
# We want to make sure that the registered plugins remains empty
# after each test.
described_class.registered.clear
described_class.manager.reset!
end
it "should be able to set and get the name" do
@ -252,8 +252,10 @@ describe Vagrant::Plugin::V1::Plugin do
end
describe "plugin registration" do
let(:manager) { described_class.manager }
it "should have no registered plugins" do
described_class.registered.should be_empty
manager.registered.should be_empty
end
it "should register a plugin when a name is set" do
@ -261,7 +263,7 @@ describe Vagrant::Plugin::V1::Plugin do
name "foo"
end
described_class.registered.should == [plugin]
manager.registered.should == [plugin]
end
it "should register a plugin only once" do
@ -270,7 +272,7 @@ describe Vagrant::Plugin::V1::Plugin do
name "bar"
end
described_class.registered.should == [plugin]
manager.registered.should == [plugin]
end
end
end