diff --git a/lib/vagrant/plugin/v2.rb b/lib/vagrant/plugin/v2.rb index 917caf7a6..91803e648 100644 --- a/lib/vagrant/plugin/v2.rb +++ b/lib/vagrant/plugin/v2.rb @@ -1,5 +1,8 @@ require "log4r" +# We don't autoload components because if we're loading anything in the +# V2 namespace anyways, then we're going to need the Components class. +require "vagrant/plugin/v2/components" require "vagrant/plugin/v2/errors" module Vagrant diff --git a/lib/vagrant/plugin/v2/components.rb b/lib/vagrant/plugin/v2/components.rb new file mode 100644 index 000000000..b982b8c0a --- /dev/null +++ b/lib/vagrant/plugin/v2/components.rb @@ -0,0 +1,14 @@ +module Vagrant + module Plugin + module V2 + # This is the container class for the components of a single plugin. + class Components + attr_reader :provider_configs + + def initialize + @provider_configs = Registry.new + end + end + end + end +end diff --git a/lib/vagrant/plugin/v2/manager.rb b/lib/vagrant/plugin/v2/manager.rb index 88f8e2b2a..18ec2e013 100644 --- a/lib/vagrant/plugin/v2/manager.rb +++ b/lib/vagrant/plugin/v2/manager.rb @@ -55,25 +55,6 @@ module Vagrant result end - # This returns all the registered configuration classes that were - # marked as "upgrade safe." - # - # @return [Hash] - def config_upgrade_safe - result = {} - - @registered.each do |plugin| - configs = plugin.data[:config_upgrade_safe] - if configs - configs.each do |key| - result[key] = plugin.config.get(key) - end - end - end - - result - end - # This returns all the registered guests. # # @return [Hash] @@ -113,6 +94,19 @@ module Vagrant providers end + # This returns all the config classes for the various providers. + # + # @return [Hash] + def provider_configs + configs = {} + + @registered.each do |plugin| + configs.merge!(plugin.components.provider_configs.to_hash) + end + + configs + end + # This returns all registered provisioners. # # @return [Hash] diff --git a/lib/vagrant/plugin/v2/plugin.rb b/lib/vagrant/plugin/v2/plugin.rb index 26134572b..28a27a026 100644 --- a/lib/vagrant/plugin/v2/plugin.rb +++ b/lib/vagrant/plugin/v2/plugin.rb @@ -2,6 +2,8 @@ require "set" require "log4r" +require "vagrant/plugin/v2/components" + module Vagrant module Plugin module V2 @@ -25,6 +27,13 @@ module Vagrant @manager ||= Manager.new end + # Returns the {Components} for this plugin. + # + # @return [Components] + def self.components + @components ||= Components.new + end + # Set the name of the plugin. The moment that this is called, the # plugin will be registered and available. Before this is called, a # plugin does not exist. The name must be unique among all installed @@ -118,24 +127,21 @@ module Vagrant # without breaking anything in future versions of Vagrant. # # @param [String] name Configuration key. - # @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) + # XXX: Document options hash + def self.config(name=UNSET_VALUE, options=nil, &block) data[:config] ||= Registry.new # Register a new config class only if a name was given. if name != UNSET_VALUE - data[:config].register(name.to_sym, &block) + options ||= {} - # If we were told this is an upgrade safe configuration class - # then we add it to the set. - if upgrade_safe - data[:config_upgrade_safe] ||= Set.new - data[:config_upgrade_safe].add(name.to_sym) + if options[:provider] + # This config is for a specific provider. Register it as + # a provider config component. + components.provider_configs.register(name.to_sym, &block) + else + # This is a generic configuration plugin, register it as such. + data[:config].register(name.to_sym, &block) end end diff --git a/plugins/kernel_v2/config/vm.rb b/plugins/kernel_v2/config/vm.rb index 818b09350..9e3c1379f 100644 --- a/plugins/kernel_v2/config/vm.rb +++ b/plugins/kernel_v2/config/vm.rb @@ -29,7 +29,7 @@ module VagrantPlugins @forwarded_ports = [] @shared_folders = {} @networks = [] - @providers = [] + @providers = {} @provisioners = [] @customizations = [] end @@ -76,8 +76,9 @@ module VagrantPlugins # Configures a provider for this VM. # # @param [Symbol] name The name of the provider. - def provider(name) - @providers << VagrantConfigProvider.new(name) + def provider(name, &block) + # TODO: Error if a provider is defined multiple times. + @providers[name] = VagrantConfigProvider.new(name, block) end def provision(name, options=nil, &block) diff --git a/plugins/kernel_v2/config/vm_provider.rb b/plugins/kernel_v2/config/vm_provider.rb index ae326b1f3..cb1abac1e 100644 --- a/plugins/kernel_v2/config/vm_provider.rb +++ b/plugins/kernel_v2/config/vm_provider.rb @@ -1,16 +1,48 @@ +require "log4r" + +require "vagrant/util/stacked_proc_runner" + module VagrantPlugins module Kernel_V2 # Represents a single configured provider for a VM. This may or may - # not be a valid provider. + # not be a valid provider. Validation is deferred until later. class VagrantConfigProvider attr_reader :name + attr_reader :config # Initializes a new provider configuration for a VM. This should # only be instantiated internally by calling `config.vm.provider`. # # @param [Symbol] name The name of the provider that is registered. - def initialize(name) - @name = name + def initialize(name, block) + @name = name + @config = nil + @logger = Log4r::Logger.new("vagrant::config::vm::provider") + + # If we were given a block to configure with, then let's try + # to do that. + load_config(block) if block + end + + protected + + # This takes the config block given to define the provider and + # attempts to turn this into a real configuration object. If the + # provider plugin is not found then it is simply ignored. This allows + # people to share Vagrantfiles that have configuration for providers + # which may not be setup on every user's system. + # + # @param [Proc] config_proc + def load_config(config_proc) + config_class = Vagrant.plugin("2").manager.provider_configs[@name] + if !config_class + @logger.info("Provider config for #{@name} not found, ignoring that config.") + return + end + + @logger.info("Configuring provider #{@name} with #{config_class}") + @config = config_class.new + config_proc.call(@config) end end end diff --git a/plugins/kernel_v2/plugin.rb b/plugins/kernel_v2/plugin.rb index 36b6233b6..55cfcc0dc 100644 --- a/plugins/kernel_v2/plugin.rb +++ b/plugins/kernel_v2/plugin.rb @@ -11,31 +11,31 @@ module VagrantPlugins basic functionality of Vagrant version 2. DESC - # Core configuration keys provided by the kernel. Note that all - # the kernel configuration classes are marked as _upgrade safe_ (the - # true 2nd param). This means that these can be loaded in ANY version - # of the core of Vagrant. - config("ssh", true) do + # Core configuration keys provided by the kernel. Note that unlike + # "kernel_v1", none of these configuration classes are upgradable. + # This is by design, since we can't be sure if they're upgradable + # until another version is available. + config("ssh") do require File.expand_path("../config/ssh", __FILE__) SSHConfig end - config("nfs", true) do + config("nfs") do require File.expand_path("../config/nfs", __FILE__) NFSConfig end - config("package", true) do + config("package") do require File.expand_path("../config/package", __FILE__) PackageConfig end - config("vagrant", true) do + config("vagrant") do require File.expand_path("../config/vagrant", __FILE__) VagrantConfig end - config("vm", true) do + config("vm") do require File.expand_path("../config/vm", __FILE__) VMConfig end diff --git a/test/unit/vagrant/plugin/v2/components_test.rb b/test/unit/vagrant/plugin/v2/components_test.rb new file mode 100644 index 000000000..30c2df403 --- /dev/null +++ b/test/unit/vagrant/plugin/v2/components_test.rb @@ -0,0 +1,9 @@ +require File.expand_path("../../../../base", __FILE__) + +describe Vagrant::Plugin::V2::Components do + let(:instance) { described_class.new } + + it "should have provider configs" do + instance.provider_configs.should be_kind_of(Vagrant::Registry) + end +end diff --git a/test/unit/vagrant/plugin/v2/manager_test.rb b/test/unit/vagrant/plugin/v2/manager_test.rb index 0929bc5f0..46d044ece 100644 --- a/test/unit/vagrant/plugin/v2/manager_test.rb +++ b/test/unit/vagrant/plugin/v2/manager_test.rb @@ -45,22 +45,6 @@ describe Vagrant::Plugin::V2::Manager do instance.config[:bar].should == "baz" end - it "should enumerate registered upgrade safe config classes" do - pA = plugin do |p| - p.config("foo", true) { "bar" } - end - - pB = plugin do |p| - p.config("bar") { "baz" } - end - - instance.register(pA) - instance.register(pB) - - instance.config_upgrade_safe.length.should == 1 - instance.config_upgrade_safe[:foo].should == "bar" - end - it "should enumerate registered guest classes" do pA = plugin do |p| p.guest("foo") { "bar" } @@ -111,4 +95,22 @@ describe Vagrant::Plugin::V2::Manager do instance.providers[:foo].should == "bar" instance.providers[:bar].should == "baz" end + + it "provides the collection of registered provider configs" do + pA = plugin do |p| + p.config("foo", :provider => true) { "foo" } + end + + pB = plugin do |p| + p.config("bar", :provider => true) { "bar" } + p.config("baz") { "baz" } + end + + instance.register(pA) + instance.register(pB) + + instance.provider_configs.length.should == 2 + instance.provider_configs[:foo].should == "foo" + instance.provider_configs[:bar].should == "bar" + end end diff --git a/test/unit/vagrant/plugin/v2/plugin_test.rb b/test/unit/vagrant/plugin/v2/plugin_test.rb index c12cc32b0..d6acb0128 100644 --- a/test/unit/vagrant/plugin/v2/plugin_test.rb +++ b/test/unit/vagrant/plugin/v2/plugin_test.rb @@ -126,6 +126,14 @@ describe Vagrant::Plugin::V2::Plugin do plugin.config[:foo] }.to raise_error(StandardError) end + + it "should register configuration classes for providers" do + plugin = Class.new(described_class) do + config("foo", :provider => true) { "bar" } + end + + plugin.components.provider_configs[:foo].should == "bar" + end end describe "easy commands" do