Foundation for supporting multiple version types
I created VersionBase which is the abstract base class for any configuration versions. Configuration versions are responsible for knowing how to load configuration given a proc (from a Vagrant.configure block), as well as merging configuration procs. In the future, it will have to upgrade versions as well. This is not done yet. The VERSIONS constant was added to Vagrant::Config which is a registry to keep track of all the available configuration versions. The VERSIONS_ORDER constant is an array of the ordering of these versions. The ordering is important so that in the future Vagrant can attempt to gracefully upgrade the configurations. It is also used to determine the current configuration version (which is assumed to be the last version in the order). The loader was modified to use the current version and the VERSIONS registry instead of hardcoding V1.
This commit is contained in:
parent
a34b84e159
commit
95e554314e
|
@ -1,15 +1,31 @@
|
|||
require "vagrant/registry"
|
||||
|
||||
module Vagrant
|
||||
module Config
|
||||
autoload :Base, 'vagrant/config/base'
|
||||
autoload :Container, 'vagrant/config/container'
|
||||
autoload :ErrorRecorder, 'vagrant/config/error_recorder'
|
||||
autoload :Loader, 'vagrant/config/loader'
|
||||
autoload :Top, 'vagrant/config/top'
|
||||
autoload :VersionBase, 'vagrant/config/version_base'
|
||||
|
||||
autoload :V1, 'vagrant/config/v1'
|
||||
|
||||
# This is a mutex used to guarantee that only one thread can load
|
||||
# procs at any given time.
|
||||
CONFIGURE_MUTEX = Mutex.new
|
||||
|
||||
# This is the registry which keeps track of what configuration
|
||||
# versions are available, mapped by the version string used in
|
||||
# `Vagrant.configure` calls.
|
||||
VERSIONS = Registry.new
|
||||
VERSIONS.register("1") { V1 }
|
||||
|
||||
# This is the order of versions. This is used by the loader to figure out
|
||||
# how to "upgrade" versions up to the desired (current) version. The
|
||||
# current version is always considered to be the last version in this
|
||||
# list.
|
||||
VERSIONS_ORDER = ["1"]
|
||||
|
||||
# This is the method which is called by all Vagrantfiles to configure Vagrant.
|
||||
# This method expects a block which accepts a single argument representing
|
||||
# an instance of the {Config::Top} class.
|
||||
|
|
|
@ -70,8 +70,12 @@ module Vagrant
|
|||
@logger.error("Unknown config sources: #{unknown_sources.inspect}")
|
||||
end
|
||||
|
||||
# Get the current version config class to use
|
||||
current_version = Config::VERSIONS_ORDER.last
|
||||
current_config_klass = Config::VERSIONS.get(current_version)
|
||||
|
||||
# This will hold our result
|
||||
result = V1.init
|
||||
result = current_config_klass.init
|
||||
|
||||
@load_order.each do |key|
|
||||
next if !@sources.has_key?(key)
|
||||
|
@ -79,14 +83,14 @@ module Vagrant
|
|||
@sources[key].each do |proc|
|
||||
if !@config_cache.has_key?(proc)
|
||||
@logger.debug("Loading from: #{key} (evaluating)")
|
||||
current = V1.load(proc)
|
||||
current = current_config_klass.load(proc)
|
||||
@config_cache[proc] = current
|
||||
else
|
||||
@logger.debug("Loading from: #{key} (cache)")
|
||||
end
|
||||
|
||||
# Merge the configurations
|
||||
result = V1.merge(result, @config_cache[proc])
|
||||
result = current_config_klass.merge(result, @config_cache[proc])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
require "vagrant/config/version_base"
|
||||
require "vagrant/config/v1/base"
|
||||
require "vagrant/config/v1/root"
|
||||
|
||||
module Vagrant
|
||||
module Config
|
||||
# This is the "version 1" configuration loader.
|
||||
class V1
|
||||
class V1 < VersionBase
|
||||
# Returns a bare empty configuration object.
|
||||
#
|
||||
# @return [V1::Root]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module Vagrant
|
||||
module Config
|
||||
class V1
|
||||
class V1 < VersionBase
|
||||
# Base class for configuration keys. It is not required to inherit
|
||||
# from this class but this class provides useful helpers that config
|
||||
# classes may wish to use.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module Vagrant
|
||||
module Config
|
||||
class V1
|
||||
class V1 < VersionBase
|
||||
# This is the root configuration class. An instance of this is what
|
||||
# is passed into version 1 Vagrant configuration blocks.
|
||||
class Root
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
module Vagrant
|
||||
module Config
|
||||
# This is the base class for any configuration versions, and includes
|
||||
# the stub methods that configuaration versions must implement. Vagrant
|
||||
# supports configuration versioning so that backwards compatibility can be
|
||||
# maintained for past Vagrantfiles while newer configurations are added.
|
||||
# Vagrant only introduces new configuration versions for major versions
|
||||
# of Vagrant.
|
||||
class VersionBase
|
||||
# Returns an empty configuration object. This can be any kind of object,
|
||||
# since it is treated as an opaque value on the other side, used only
|
||||
# for things like calling into {merge}.
|
||||
#
|
||||
# @return [Object]
|
||||
def self.init
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Loads the configuration for the given proc and returns a configuration
|
||||
# object. The return value is treated as an opaque object, so it can be
|
||||
# anything you'd like. The return value is the object that is passed
|
||||
# into methods like {merge}, so it should be something you expect.
|
||||
#
|
||||
# @param [Proc] proc The proc that is to be configured.
|
||||
# @return [Object]
|
||||
def self.load(proc)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Merges two configuration objects, returning the merged object.
|
||||
# The values of `old` and `new` are the opaque objects returned by
|
||||
# {load} or {init}.
|
||||
#
|
||||
# Once again, the return object is treated as an opaque value by
|
||||
# the Vagrant configuration loader, so it can be anything you'd like.
|
||||
#
|
||||
# @param [Object] old Old configuration object.
|
||||
# @param [Object] new New configuration object.
|
||||
# @return [Object] The merged configuration object.
|
||||
def self.merge(old, new)
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue