diff --git a/lib/vagrant/environment.rb b/lib/vagrant/environment.rb index 878cdb2d2..db09a66bf 100644 --- a/lib/vagrant/environment.rb +++ b/lib/vagrant/environment.rb @@ -8,6 +8,9 @@ module Vagrant include Util + attr_reader :parent # Parent environment (in the case of multi-VMs) + attr_reader :vm_name # The name of the VM (internal name) which this environment represents + attr_accessor :cwd attr_reader :root_path attr_reader :config @@ -24,7 +27,7 @@ module Vagrant # directory. If a working directory is not given, it will default # to the pwd. def load!(cwd=nil) - Environment.new(cwd).load! + Environment.new(:cwd => cwd).load! end # Verifies that VirtualBox is installed and that the version of @@ -42,8 +45,17 @@ module Vagrant end end - def initialize(cwd=nil) - @cwd = cwd + def initialize(opts=nil) + defaults = { + :parent => nil, + :vm_name => nil, + :cwd => nil + } + + opts = defaults.merge(opts || {}) + @cwd = opts[:cwd] + @parent = opts[:parent] + @vm_name = opts[:vm_name] end #--------------------------------------------------------------- @@ -123,20 +135,30 @@ 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 - load_paths = [File.join(PROJECT_ROOT, "config", "default.rb")] - load_paths << File.join(box.directory, ROOTFILE_NAME) if box - load_paths << File.join(home_path, ROOTFILE_NAME) if home_path - load_paths << File.join(root_path, ROOTFILE_NAME) if root_path + # Prepare load paths for config files and append to config queue + config_queue = [File.join(PROJECT_ROOT, "config", "default.rb")] + 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 + + # If this environment represents some VM in a multi-VM environment, + # we push that VM's configuration onto the config_queue. + config_queue << parent.config.vm.defined_vms[vm_name] if vm_name # Clear out the old data Config.reset!(self) # Load each of the config files in order - load_paths.each do |path| - if File.exist?(path) - logger.info "Loading config from #{path}..." - load path + config_queue.each do |item| + if item.is_a?(String) && File.exist?(item) + logger.info "Loading config from #{item}..." + load item + next + end + + if item.is_a?(Proc) + # Just push the proc straight onto the config runnable stack + Config.run(&item) end end @@ -198,7 +220,7 @@ module Vagrant # in {Command.up}. This will very likely be refactored at a later # time. def create_vm - @vm = VM.new(self) + @vm = VM.new(:env => self) end # Persists this environment's VM to the dotfile so it can be diff --git a/lib/vagrant/vm.rb b/lib/vagrant/vm.rb index 66d605214..8abed1888 100644 --- a/lib/vagrant/vm.rb +++ b/lib/vagrant/vm.rb @@ -12,15 +12,25 @@ module Vagrant def find(uuid, env=nil) vm = VirtualBox::VM.find(uuid) return nil if vm.nil? - new(env, vm) + new(:vm => vm, :env => env) end end - def initialize(env, vm=nil) - @env = env - @vm = vm + def initialize(opts=nil) + defaults = { + :vm => nil, + :env => nil, + :vm_name => nil + } - load_system! if !@env.nil? + opts = defaults.merge(opts || {}) + + @vm = opts[:vm] + + if !opts[:env].nil? + @env = Vagrant::Environment.new(:cwd => opts[:env].cwd, :parent => opts[:env], :vm_name => opts[:vm_name]).load! + load_system! + end end # Loads the system associated with the VM. The system class is diff --git a/test/test_helper.rb b/test/test_helper.rb index 16c87585b..6058edc1a 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -76,7 +76,7 @@ class Test::Unit::TestCase # Sets up the mocks for a VM def mock_vm(env=nil) env ||= mock_environment - vm = Vagrant::VM.new(nil, nil) + vm = Vagrant::VM.new vm.stubs(:env).returns(env) vm.stubs(:ssh).returns(Vagrant::SSH.new(vm.env)) vm diff --git a/test/vagrant/environment_test.rb b/test/vagrant/environment_test.rb index 4f75c090c..708459f0a 100644 --- a/test/vagrant/environment_test.rb +++ b/test/vagrant/environment_test.rb @@ -42,13 +42,13 @@ class EnvironmentTest < Test::Unit::TestCase end should "create the environment with given cwd, load it, and return it" do - Vagrant::Environment.expects(:new).with(@cwd).once.returns(@env) + Vagrant::Environment.expects(:new).with(:cwd => @cwd).once.returns(@env) @env.expects(:load!).returns(@env) assert_equal @env, Vagrant::Environment.load!(@cwd) end should "work without a given cwd" do - Vagrant::Environment.expects(:new).with(nil).returns(@env) + Vagrant::Environment.expects(:new).with(:cwd => nil).returns(@env) assert_nothing_raised { env = Vagrant::Environment.load! @@ -60,7 +60,7 @@ class EnvironmentTest < Test::Unit::TestCase context "initialization" do should "set the cwd if given" do cwd = "foobarbaz" - env = Vagrant::Environment.new(cwd) + env = Vagrant::Environment.new(:cwd => cwd) assert_equal cwd, env.cwd end @@ -215,9 +215,9 @@ 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) - Vagrant::Config.stubs(:execute!) - Vagrant::Config.stubs(:reset!) end should "reset the configuration object" do @@ -267,6 +267,25 @@ class EnvironmentTest < Test::Unit::TestCase @env.load_config! 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 + + @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 @@ -517,6 +536,13 @@ class EnvironmentTest < Test::Unit::TestCase end context "creating a new VM" do + should "create a new VM with the given environment" do + result = mock("result") + Vagrant::VM.expects(:new).with(:env => @env).once.returns(result) + @env.create_vm + assert_equal result, @env.vm + end + should "create a new VM" do assert_nil @env.vm @env.create_vm @@ -524,11 +550,6 @@ class EnvironmentTest < Test::Unit::TestCase assert @env.vm.is_a?(Vagrant::VM) end - should "set the new VM's environment to the env" do - @env.create_vm - assert_equal @env, @env.vm.env - end - should "return the new VM" do result = @env.create_vm assert result.is_a?(Vagrant::VM) diff --git a/test/vagrant/vm_test.rb b/test/vagrant/vm_test.rb index 1a4b902b6..a200d9bde 100644 --- a/test/vagrant/vm_test.rb +++ b/test/vagrant/vm_test.rb @@ -14,7 +14,7 @@ class VMTest < Test::Unit::TestCase context "being an action runner" do should "be an action runner" do - vm = Vagrant::VM.new(@env) + vm = Vagrant::VM.new(:env => @env) assert vm.is_a?(Vagrant::Actions::Runner) end end @@ -35,7 +35,7 @@ class VMTest < Test::Unit::TestCase context "vagrant VM instance" do setup do - @vm = Vagrant::VM.new(@env, @mock_vm) + @vm = Vagrant::VM.new(:env => @env, :vm => @mock_vm) @mock_vm.stubs(:uuid).returns("foo") end @@ -49,7 +49,7 @@ class VMTest < Test::Unit::TestCase end should "load it the first time" do - Vagrant::SSH.expects(:new).with(@env).once.returns(@ssh) + Vagrant::SSH.expects(:new).with(@vm.env).once.returns(@ssh) @vm.ssh @vm.ssh @vm.ssh