Loader uses the new configuration classes

This commit is contained in:
Mitchell Hashimoto 2012-04-18 17:03:34 -07:00
parent 98d6bf958e
commit b38fb5e974
6 changed files with 75 additions and 8 deletions

View File

@ -70,8 +70,8 @@ module Vagrant
@logger.error("Unknown config sources: #{unknown_sources.inspect}")
end
# Create the top-level configuration which will hold all the config.
result = Top.new
# This will hold our result
result = V1.init
@load_order.each do |key|
next if !@sources.has_key?(key)
@ -79,15 +79,14 @@ module Vagrant
@sources[key].each do |proc|
if !@config_cache.has_key?(proc)
@logger.debug("Loading from: #{key} (evaluating)")
current = Top.new
proc.call(current)
current = V1.load(proc)
@config_cache[proc] = current
else
@logger.debug("Loading from: #{key} (cache)")
end
# Merge in the results of this proc's configuration
result = result.merge(@config_cache[proc])
# Merge the configurations
result = V1.merge(result, @config_cache[proc])
end
end

View File

@ -5,6 +5,13 @@ module Vagrant
module Config
# This is the "version 1" configuration loader.
class V1
# Returns a bare empty configuration object.
#
# @return [V1::Root]
def self.init
new_root_object
end
# Loads the configuration for the given proc and returns a configuration
# object.
#

View File

@ -9,6 +9,37 @@ module Vagrant
# merge for this class will use this as a marker that a value is
# unset (versus just being explicitly set to `nil`)
UNSET_VALUE = Object.new
# Merge another configuration object into this one. This assumes that
# the other object is the same class as this one.
#
# @param [Object] other The other configuration object to merge from,
# this must be the same type of object as this one.
# @return [Object] The merged object.
def merge(other)
result = self.class.new
# Set all of our instance variables on the new class
[self, other].each do |obj|
obj.instance_variables.each do |key|
# Ignore keys that start with a double underscore. This allows
# configuration classes to still hold around internal state
# that isn't propagated.
if !key.to_s.start_with?("__")
result.instance_variable_set(key, obj.instance_variable_get(key))
end
end
end
result
end
# Called by {Root} after the configuration is loaded to validate
# the configuaration objects. Subclasses should implement this
# method and add any errors to the `errors` object given.
#
# @param [ErrorRecorder] errors
def validate(env, errors); end
end
end
end

View File

@ -30,6 +30,26 @@ module Vagrant
end
end
# Validates the configuration classes of this instance and raises an
# exception if they are invalid. If you are implementing a custom configuration
# class, the method you want to implement is {Base#validate}. This is
# the method that checks all the validation, not one which defines
# validation rules.
def validate!(env)
# Validate each of the configured classes and store the results into
# a hash.
errors = @keys.inject({}) do |container, data|
key, instance = data
recorder = ErrorRecorder.new
instance.validate(env, recorder)
container[key.to_sym] = recorder if !recorder.errors.empty?
container
end
return if errors.empty?
raise Errors::ConfigValidationFailed, :messages => Util::TemplateRenderer.render("config/validation_failed", :errors => errors)
end
# Returns the internal state of the root object. This is used
# by outside classes when merging, and shouldn't be called directly.
# Note the strange method name is to attempt to avoid any name

View File

@ -31,10 +31,13 @@ module VagrantPlugins
def validate(env, errors)
[:username, :host, :max_tries, :timeout].each do |field|
errors.add(I18n.t("vagrant.config.common.error_empty", :field => field)) if !instance_variable_get("@#{field}".to_sym)
value = instance_variable_get("@#{field}".to_sym)
if value == UNSET_VALUE || !value
errors.add(I18n.t("vagrant.config.common.error_empty", :field => field))
end
end
if private_key_path && !File.file?(File.expand_path(private_key_path, env.root_path))
if private_key_path && private_key_path != UNSET_VALUE && !File.file?(File.expand_path(private_key_path, env.root_path))
errors.add(I18n.t("vagrant.config.ssh.private_key_missing", :path => private_key_path))
end
end

View File

@ -3,6 +3,13 @@ require File.expand_path("../../../base", __FILE__)
describe Vagrant::Config::V1 do
include_context "unit"
describe "empty" do
it "returns an empty configuration object" do
result = described_class.init
result.should be_kind_of(Vagrant::Config::V1::Root)
end
end
describe "loading" do
it "should configure with all plugin config keys loaded" do
# Register a plugin for our test