Config class is now responsible for loading configuration. Cleans up environment.

This commit is contained in:
Mitchell Hashimoto 2010-09-03 11:16:38 -07:00
parent 57506c8c00
commit b8a4188fa3
4 changed files with 146 additions and 113 deletions

View File

@ -1,11 +1,15 @@
require 'vagrant/config/base'
module Vagrant
# The config class is responsible for loading Vagrant configurations
# (usually through Vagrantfiles).
class Config
extend Util::StackedProcRunner
@@config = nil
attr_reader :queue
class << self
def reset!(env=nil)
@@config = nil
@ -36,6 +40,29 @@ module Vagrant
end
end
def initialize(env)
@env = env
@queue = []
end
# Loads the queue of files/procs, executes them in the proper
# sequence, and returns the resulting configuration object.
def load!
self.class.reset!(@env)
queue.flatten.each do |item|
if item.is_a?(String) && File.exist?(item)
load item
elsif item.is_a?(Proc)
self.class.run(&item)
end
end
return self.class.execute!
end
end
class Config
class Top < Base
@@configures = []

View File

@ -215,40 +215,21 @@ module Vagrant
# this environment, meaning that it will use the given root directory
# to load the Vagrantfile into that context.
def load_config!
# Prepare load paths for config files and append to config queue
config_queue = [File.expand_path("config/default.rb", Vagrant.source_root)]
config_queue << File.join(box.directory, ROOTFILE_NAME) if box
config_queue << File.join(home_path, ROOTFILE_NAME) if home_path
config_queue << File.join(root_path, ROOTFILE_NAME) if root_path
loader = Config.new(self)
loader.queue << File.expand_path("config/default.rb", Vagrant.source_root)
loader.queue << File.join(box.directory, ROOTFILE_NAME) if box
loader.queue << File.join(home_path, ROOTFILE_NAME) if home_path
loader.queue << File.join(root_path, ROOTFILE_NAME) if root_path
# If this environment represents some VM in a multi-VM environment,
# we push that VM's configuration onto the config_queue.
if vm_name
subvm = parent.config.vm.defined_vms[vm_name]
config_queue << subvm.proc_stack if subvm
end
# Flatten the config queue so any nested procs are flattened
config_queue.flatten!
# Clear out the old data
Config.reset!(self)
# Load each of the config files in order
config_queue.each do |item|
if item.is_a?(String) && File.exist?(item)
load item
next
end
if item.is_a?(Proc)
# Just push the proc straight onto the config runnable stack
Config.run(&item)
end
loader.queue << subvm.proc_stack if subvm
end
# Execute the configuration stack and store the result
@config = Config.execute!
@config = loader.load!
# (re)load the logger
@logger = nil

View File

@ -1,81 +1,139 @@
require "test_helper"
class ConfigTest < Test::Unit::TestCase
setup do
@klass = Vagrant::Config
end
context "with an instance" do
setup do
@env = mock_environment
@instance = @klass.new(@env)
end
should "initially have an empty queue" do
assert @instance.queue.empty?
end
should "reset the config class on load, then execute" do
seq = sequence("sequence")
@klass.expects(:reset!).with(@env).in_sequence(seq)
@klass.expects(:execute!).in_sequence(seq)
@instance.load!
end
should "run the queue in the order given" do
@instance.queue << Proc.new { |config| config.vm.box = "foo" }
@instance.queue << Proc.new { |config| config.vm.box = "bar" }
result = @instance.load!
assert_equal "bar", result.vm.box
end
should "allow nested arrays" do
queue = []
queue << Proc.new { |config| config.vm.box = "foo" }
queue << Proc.new { |config| config.vm.box = "bar" }
@instance.queue << queue
result = @instance.load!
assert_equal "bar", result.vm.box
end
should "load a file if it exists" do
filename = "foo"
File.expects(:exist?).with(filename).returns(true)
@instance.expects(:load).with(filename).once
@instance.queue << filename
@instance.load!
end
should "not load a file if it doesn't exist" do
filename = "foo"
File.expects(:exist?).with(filename).returns(false)
@instance.expects(:load).with(filename).never
@instance.queue << filename
@instance.load!
end
end
context "adding configures" do
should "forward the method to the Top class" do
key = mock("key")
klass = mock("klass")
Vagrant::Config::Top.expects(:configures).with(key, klass)
Vagrant::Config.configures(key, klass)
@klass::Top.expects(:configures).with(key, klass)
@klass.configures(key, klass)
end
end
context "resetting" do
setup do
Vagrant::Config.run { |config| }
Vagrant::Config.execute!
@klass.run { |config| }
@klass.execute!
end
should "return the same config object typically" do
config = Vagrant::Config.config
assert config.equal?(Vagrant::Config.config)
config = @klass.config
assert config.equal?(@klass.config)
end
should "create a new object if cleared" do
config = Vagrant::Config.config
Vagrant::Config.reset!
assert !config.equal?(Vagrant::Config.config)
config = @klass.config
@klass.reset!
assert !config.equal?(@klass.config)
end
should "empty the proc stack" do
assert !Vagrant::Config.proc_stack.empty?
Vagrant::Config.reset!
assert Vagrant::Config.proc_stack.empty?
assert !@klass.proc_stack.empty?
@klass.reset!
assert @klass.proc_stack.empty?
end
should "reload the config object based on the given environment" do
env = mock("env")
Vagrant::Config.expects(:config).with(env).once
Vagrant::Config.reset!(env)
@klass.expects(:config).with(env).once
@klass.reset!(env)
end
end
context "initializing" do
setup do
Vagrant::Config.reset!
@klass.reset!
end
should "add the given block to the proc stack" do
proc = Proc.new {}
Vagrant::Config.run(&proc)
assert_equal [proc], Vagrant::Config.proc_stack
@klass.run(&proc)
assert_equal [proc], @klass.proc_stack
end
should "run the proc stack with the config when execute is called" do
Vagrant::Config.expects(:run_procs!).with(Vagrant::Config.config).once
Vagrant::Config.execute!
@klass.expects(:run_procs!).with(@klass.config).once
@klass.execute!
end
should "not be loaded, initially" do
assert !Vagrant::Config.config.loaded?
assert !@klass.config.loaded?
end
should "be loaded after running" do
Vagrant::Config.run {}
Vagrant::Config.execute!
assert Vagrant::Config.config.loaded?
@klass.run {}
@klass.execute!
assert @klass.config.loaded?
end
should "return the configuration on execute!" do
Vagrant::Config.run {}
result = Vagrant::Config.execute!
assert result.is_a?(Vagrant::Config::Top)
@klass.run {}
result = @klass.execute!
assert result.is_a?(@klass::Top)
end
should "use given configuration object if given" do
fake_env = mock("env")
config = Vagrant::Config::Top.new(fake_env)
result = Vagrant::Config.execute!(config)
config = @klass::Top.new(fake_env)
result = @klass.execute!(config)
assert_equal config.env, result.env
end
end
@ -83,18 +141,18 @@ class ConfigTest < Test::Unit::TestCase
context "top config class" do
setup do
@configures_list = []
Vagrant::Config::Top.stubs(:configures_list).returns(@configures_list)
@klass::Top.stubs(:configures_list).returns(@configures_list)
end
context "adding configure keys" do
setup do
@key = "top_config_foo"
@klass = mock("klass")
@config_klass = mock("klass")
end
should "add key and klass to configures list" do
@configures_list.expects(:<<).with([@key, @klass])
Vagrant::Config::Top.configures(@key, @klass)
@configures_list.expects(:<<).with([@key, @config_klass])
@klass::Top.configures(@key, @config_klass)
end
end
@ -115,7 +173,7 @@ class ConfigTest < Test::Unit::TestCase
@configures_list << [key, klass]
end
Vagrant::Config::Top.new(env)
@klass::Top.new(env)
end
should "allow reading via methods" do
@ -124,16 +182,16 @@ class ConfigTest < Test::Unit::TestCase
instance = mock("instance")
instance.stubs(:env=)
klass.expects(:new).returns(instance)
Vagrant::Config::Top.configures(key, klass)
@klass::Top.configures(key, klass)
config = Vagrant::Config::Top.new
config = @klass::Top.new
assert_equal instance, config.send(key)
end
end
context "loaded status" do
setup do
@top= Vagrant::Config::Top.new
@top= @klass::Top.new
end
should "not be loaded by default" do
@ -152,8 +210,8 @@ class ConfigTest < Test::Unit::TestCase
end
setup do
Vagrant::Config::Top.configures :deep, DeepCloneConfig
@top = Vagrant::Config::Top.new
@klass::Top.configures :deep, DeepCloneConfig
@top = @klass::Top.new
@top.deep.attribute = [1,2,3]
end

View File

@ -393,47 +393,36 @@ class EnvironmentTest < Test::Unit::TestCase
@env.stubs(:root_path).returns(@root_path)
@env.stubs(:home_path).returns(@home_path)
@parent_env = mock_environment
File.stubs(:exist?).returns(false)
end
should "reset the configuration object" do
Vagrant::Config.expects(:reset!).with(@env).once
@env.load_config!
@loader = Vagrant::Config.new(@env)
Vagrant::Config.stubs(:new).returns(@loader)
@loader.stubs(:load!)
end
should "load from the project root" do
File.expects(:exist?).with(File.join(Vagrant.source_root, "config", "default.rb")).once
@env.load_config!
assert @loader.queue.include?(File.expand_path("config/default.rb", Vagrant.source_root))
end
should "load from the root path" do
File.expects(:exist?).with(File.join(@root_path, @klass::ROOTFILE_NAME)).once
@env.load_config!
assert @loader.queue.include?(File.join(@root_path, @klass::ROOTFILE_NAME))
end
should "not load from the root path if nil" do
@env.stubs(:root_path).returns(nil)
File.expects(:exist?).with(File.join(@root_path, @klass::ROOTFILE_NAME)).never
@env.load_config!
assert !@loader.queue.include?(File.join(@root_path, @klass::ROOTFILE_NAME))
end
should "load from the home directory" do
File.expects(:exist?).with(File.join(@env.home_path, @klass::ROOTFILE_NAME)).once
@env.load_config!
assert @loader.queue.include?(File.join(@env.home_path, @klass::ROOTFILE_NAME))
end
should "not load from the home directory if the config is nil" do
@env.stubs(:home_path).returns(nil)
File.expects(:exist?).twice.returns(false)
@env.load_config!
end
should "not load from the box directory if it is nil" do
@env.expects(:box).once.returns(nil)
File.expects(:exist?).twice.returns(false)
@env.load_config!
assert !@loader.queue.include?(File.join(@home_path, @klass::ROOTFILE_NAME))
end
should "load from the box directory if it is not nil" do
@ -441,52 +430,30 @@ class EnvironmentTest < Test::Unit::TestCase
box = mock("box")
box.stubs(:directory).returns(dir)
@env.expects(:box).twice.returns(box)
File.expects(:exist?).with(File.join(dir, @klass::ROOTFILE_NAME)).once
@env.load_config!
assert @loader.queue.include?(File.join(dir, @klass::ROOTFILE_NAME))
end
should "load a sub-VM configuration if specified" do
vm_name = :foo
sub_box = :YO
@parent_env.config.vm.box = :NO
@parent_env.config.vm.define(vm_name) do |config|
config.vm.box = sub_box
end
# Sanity
assert_equal :NO, @parent_env.config.vm.box
vm_name = :foobar
proc = Proc.new {}
parent_env = mock_environment
parent_env.config.vm.define(vm_name, &proc)
@env.stubs(:parent).returns(parent_env)
@env.stubs(:vm_name).returns(vm_name)
@env.stubs(:parent).returns(@parent_env)
@env.load_config!
assert_equal sub_box, @env.config.vm.box
end
should "load the files only if exist? returns true" do
File.expects(:exist?).once.returns(true)
@env.expects(:load).once
@env.load_config!
end
should "not load the files if exist? returns false" do
@env.expects(:load).never
@env.load_config!
assert @loader.queue.flatten.include?(proc)
end
should "execute after loading and set result to environment config" do
result = mock("result")
File.expects(:exist?).once.returns(true)
@env.expects(:load).once
Vagrant::Config.expects(:execute!).once.returns(result)
@loader.expects(:load!).once.returns(result)
@env.load_config!
assert_equal result, @env.config
end
should "reload the logger after executing" do
load_seq = sequence("load_seq")
Vagrant::Config.expects(:execute!).once.returns(nil).in_sequence(load_seq)
@env.load_config!
assert @env.instance_variable_get(:@logger).nil?
end