Do proper provider configuration merging

This commit is contained in:
Mitchell Hashimoto 2013-02-05 12:22:00 -08:00
parent 2eeccf085b
commit 79beefdb0a
3 changed files with 52 additions and 74 deletions

View File

@ -314,7 +314,7 @@ module Vagrant
end end
# Get the provider configuration from the final loaded configuration # Get the provider configuration from the final loaded configuration
provider_config = config.vm.providers[provider].config provider_config = config.vm.get_provider_config(provider)
# Determine the machine data directory and pass it to the machine. # Determine the machine data directory and pass it to the machine.
# XXX: Permissions error here. # XXX: Permissions error here.

View File

@ -3,7 +3,6 @@ require "pathname"
require "vagrant" require "vagrant"
require "vagrant/config/v2/util" require "vagrant/config/v2/util"
require File.expand_path("../vm_provider", __FILE__)
require File.expand_path("../vm_provisioner", __FILE__) require File.expand_path("../vm_provisioner", __FILE__)
require File.expand_path("../vm_subvm", __FILE__) require File.expand_path("../vm_subvm", __FILE__)
@ -23,7 +22,6 @@ module VagrantPlugins
attr_reader :forwarded_ports attr_reader :forwarded_ports
attr_reader :synced_folders attr_reader :synced_folders
attr_reader :networks attr_reader :networks
attr_reader :providers
attr_reader :provisioners attr_reader :provisioners
def initialize def initialize
@ -34,20 +32,31 @@ module VagrantPlugins
@networks = [] @networks = []
@provisioners = [] @provisioners = []
# The providers hash defaults any key to a provider object # Internal state
@providers = Hash.new do |hash, key| @__compiled_provider_configs = {}
hash[key] = VagrantConfigProvider.new(key) @__finalized = false
end @__providers = {}
end end
# Custom merge method since some keys here are merged differently. # Custom merge method since some keys here are merged differently.
def merge(other) def merge(other)
result = super super.tap do |result|
result.instance_variable_set(:@forwarded_ports, @forwarded_ports + other.forwarded_ports) result.instance_variable_set(:@forwarded_ports, @forwarded_ports + other.forwarded_ports)
result.instance_variable_set(:@synced_folders, @synced_folders.merge(other.synced_folders)) result.instance_variable_set(:@synced_folders, @synced_folders.merge(other.synced_folders))
result.instance_variable_set(:@networks, @networks + other.networks) result.instance_variable_set(:@networks, @networks + other.networks)
result.instance_variable_set(:@provisioners, @provisioners + other.provisioners) result.instance_variable_set(:@provisioners, @provisioners + other.provisioners)
result
# Merge the providers by prepending any configuration blocks we
# have for providers onto the new configuration.
other_providers = other.instance_variable_get(:@__providers)
new_providers = @__providers.dup
other_providers.each do |key, blocks|
new_providers[key] ||= []
new_providers[key] += blocks
end
result.instance_variable_set(:@__providers, new_providers)
end
end end
# Defines a synced folder pair. This pair of folders will be synced # Defines a synced folder pair. This pair of folders will be synced
@ -94,7 +103,8 @@ module VagrantPlugins
# #
# @param [Symbol] name The name of the provider. # @param [Symbol] name The name of the provider.
def provider(name, &block) def provider(name, &block)
@providers[name].add_config_block(block) if block_given? @__providers[name] ||= []
@__providers[name] << block if block_given?
end end
def provision(name, options=nil, &block) def provision(name, options=nil, &block)
@ -129,15 +139,42 @@ module VagrantPlugins
defined_vms[name].config_procs << [options[:config_version], block] if block defined_vms[name].config_procs << [options[:config_version], block] if block
end end
#-------------------------------------------------------------------
# Internal methods, don't call these.
#-------------------------------------------------------------------
def finalize! def finalize!
# If we haven't defined a single VM, then we need to define a # If we haven't defined a single VM, then we need to define a
# default VM which just inherits the rest of the configuration. # default VM which just inherits the rest of the configuration.
define(DEFAULT_VM_NAME) if defined_vm_keys.empty? define(DEFAULT_VM_NAME) if defined_vm_keys.empty?
# Compile all the provider configurations # Compile all the provider configurations
@providers.each do |name, config| @__providers.each do |name, blocks|
# Find the configuration class for this provider
config_class = Vagrant.plugin("2").manager.provider_configs[name]
next if !config_class
# Load it up
config = config_class.new
blocks.each { |b| b.call(config) }
config.finalize! config.finalize!
# Store it for retrieval later
@__compiled_provider_configs[name] = config
end end
# Flag that we finalized
@__finalized = true
end
# This returns the compiled provider-specific configurationf or the
# given provider.
#
# @param [Symbol] name Name of the provider.
def get_provider_config(name)
raise "Must finalize first." if !@__finalized
@__compiled_provider_configs[name]
end end
def validate(machine) def validate(machine)

View File

@ -1,59 +0,0 @@
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. Validation is deferred until later.
class VagrantConfigProvider
# This is the name of the provider, as a symbol.
#
# @return [Symbol]
attr_reader :name
# The compiled configuration. This is only available after finalizing.
#
# @return [Object]
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
@config = nil
@config_blocks = []
@logger = Log4r::Logger.new("vagrant::config::vm::provider")
# Attempt to find the configuration class for this provider and
# load the configuration.
@config_class = Vagrant.plugin("2").manager.provider_configs[@name]
if !@config_class
@logger.info("Provider config for #{@name} not found, ignoring config.")
end
end
# This adds a configuration block to the list of configuration
# blocks to execute when compiling the configuration.
def add_config_block(block)
@config_blocks << block
end
# This is called to compile the configuration
def finalize!
if @config_class
@logger.info("Configuring provider #{@name} with #{@config_class}")
# Call each block in order with the config object
@config = @config_class.new
@config_blocks.each { |b| b.call(@config) }
# Finalize the configuration
@config.finalize!
end
end
end
end
end