Use config finalize to move some version-specific logic to the version

This moves out the concept of a "default VM" from the Environment class
and makes it the responsibility of the V1 configuration that at least
one VM is defined on it. This lets the configuration ultimately decide
what a "default" implementation is.
This commit is contained in:
Mitchell Hashimoto 2012-06-23 12:48:53 -07:00
parent 70fb804128
commit 9bc1ea5f04
7 changed files with 89 additions and 15 deletions

View File

@ -13,6 +13,17 @@ module Vagrant
new_root_object
end
# Finalizes the configuration by making sure there is at least
# one VM defined in it.
def self.finalize(config)
# Call the `#finalize` method on each of the configuration keys.
# They're expected to modify themselves in our case.
config.finalize!
# Return the object
config
end
# Loads the configuration for the given proc and returns a configuration
# object.
#

View File

@ -5,6 +5,15 @@ module Vagrant
# from this class but this class provides useful helpers that config
# classes may wish to use.
class Base
# This is called as a last-minute hook that allows the configuration
# object to finalize itself before it will be put into use. This is
# a useful place to do some defaults in the case the user didn't
# configure something or so on.
#
# The configuration object is expected to mutate itself.
def finalize!
end
# Merge another configuration object into this one. This assumes that
# the other object is the same class as this one.
#

View File

@ -30,6 +30,15 @@ module Vagrant
end
end
# Called to finalize this object just prior to it being used by
# the Vagrant system. The "!" signifies that this is expected to
# mutate itself.
def finalize!
@keys.each do |_key, instance|
instance.finalize!
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

View File

@ -23,6 +23,10 @@ module Vagrant
# This is an optional method to implement. The default implementation
# will simply return the same object.
#
# This will ONLY be called if this is the version that is being
# used. In the case that an `upgrade` is called, this will never
# be called.
#
# @param [Object] obj Final configuration object.
# @param [Object] Finalized configuration object.
def self.finalize(obj)

View File

@ -13,7 +13,6 @@ module Vagrant
# access to the VMs, CLI, etc. all in the scope of this environment.
class Environment
HOME_SUBDIRS = ["tmp", "boxes", "gems"]
DEFAULT_VM = :default
DEFAULT_HOME = "~/.vagrant.d"
DEFAULT_RC = "~/.vagrantrc"
@ -163,7 +162,7 @@ module Vagrant
#
# @return [Bool]
def multivm?
vms.length > 1 || vms.keys.first != DEFAULT_VM
vms.length > 1
end
# Makes a call to the CLI with the given arguments as if they
@ -418,13 +417,6 @@ module Vagrant
defined_vm_keys = global.vm.defined_vm_keys.dup
defined_vms = global.vm.defined_vms.dup
# If this isn't a multi-VM environment, then setup the default VM
# to simply be our configuration.
if defined_vm_keys.empty?
defined_vm_keys << DEFAULT_VM
defined_vms[DEFAULT_VM] = nil
end
vm_configs = defined_vm_keys.map do |vm_name|
@logger.debug("Loading configuration for VM: #{vm_name}")
@ -434,11 +426,7 @@ module Vagrant
config = inner_load[subvm]
# Second pass, with the box
config = inner_load[subvm, boxes.find(config.vm.box)]
config.vm.name = vm_name
# Return the final configuration for this VM
config
inner_load[subvm, boxes.find(config.vm.box)]
end
# Finally, we have our configuration. Set it and forget it.

View File

@ -8,6 +8,8 @@ require File.expand_path("../vm_subvm", __FILE__)
module VagrantPlugins
module Kernel_V1
class VMConfig < Vagrant::Config::V1::Base
DEFAULT_VM_NAME = :default
attr_accessor :name
attr_accessor :auto_port_range
attr_accessor :box
@ -99,11 +101,25 @@ module VagrantPlugins
defined_vm_keys << name
# Add the SubVM to the hash of defined VMs
if !defined_vms[name]
# If it hasn't been defined before, then create the sub-VM configuration
# and configure it so that it has the proper name.
defined_vms[name] ||= VagrantConfigSubVM.new
defined_vms[name].push_proc do |config|
config.vm.name = name
end
end
defined_vms[name].options.merge!(options)
defined_vms[name].push_proc(&block) if block
end
def finalize!
# If we haven't defined a single VM, then we need to define a
# default VM which just inherits the rest of the configuration.
define(DEFAULT_VM_NAME) if defined_vm_keys.empty?
end
def validate(env, errors)
errors.add(I18n.t("vagrant.config.vm.box_missing")) if !box
errors.add(I18n.t("vagrant.config.vm.box_not_found", :name => box)) if box && !box_url && !env.boxes.find(box)

View File

@ -10,6 +10,43 @@ describe Vagrant::Config::V1 do
end
end
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
Class.new do
attr_accessor :bar
def finalize!
@bar = "finalized"
end
end
end
end
# Create the proc we're testing
config_proc = Proc.new do |config|
config.foo.bar = "value"
end
begin
# 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
end
end
describe "loading" do
it "should configure with all plugin config keys loaded" do
# Register a plugin for our test