Load the configuration per machine, so that provider boxes work
Boxes are provider-specific, and we don't know the provider until Environment#machine is called, so we need to build up the machine configuration during this time.
This commit is contained in:
parent
0180ed849d
commit
f2b91d26fd
|
@ -16,6 +16,12 @@ module Vagrant
|
||||||
DEFAULT_HOME = "~/.vagrant.d"
|
DEFAULT_HOME = "~/.vagrant.d"
|
||||||
DEFAULT_RC = "~/.vagrantrc"
|
DEFAULT_RC = "~/.vagrantrc"
|
||||||
|
|
||||||
|
# This is the global config, comprised of loading configuration from
|
||||||
|
# the default, home, and root Vagrantfiles. This configuration is only
|
||||||
|
# really useful for reading the list of virtual machines, since each
|
||||||
|
# individual VM can override _most_ settings.
|
||||||
|
attr_reader :config_global
|
||||||
|
|
||||||
# The `cwd` that this environment represents
|
# The `cwd` that this environment represents
|
||||||
attr_reader :cwd
|
attr_reader :cwd
|
||||||
|
|
||||||
|
@ -99,6 +105,9 @@ module Vagrant
|
||||||
|
|
||||||
# Load the plugins
|
# Load the plugins
|
||||||
load_plugins
|
load_plugins
|
||||||
|
|
||||||
|
# Initialize the configuration. This will load our global configuration.
|
||||||
|
initialize_config
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return a human-friendly string for pretty printed or inspected
|
# Return a human-friendly string for pretty printed or inspected
|
||||||
|
@ -119,7 +128,7 @@ module Vagrant
|
||||||
# @return [Pathname]
|
# @return [Pathname]
|
||||||
def dotfile_path
|
def dotfile_path
|
||||||
return nil if !root_path
|
return nil if !root_path
|
||||||
root_path.join(config.global.vagrant.dotfile_name)
|
root_path.join(config_global.vagrant.dotfile_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the collection of boxes for the environment.
|
# Returns the collection of boxes for the environment.
|
||||||
|
@ -144,8 +153,8 @@ module Vagrant
|
||||||
@machines ||= {}
|
@machines ||= {}
|
||||||
return @machines[cache_key] if @machines.has_key?(cache_key)
|
return @machines[cache_key] if @machines.has_key?(cache_key)
|
||||||
|
|
||||||
vm_config = config.for_vm(name)
|
sub_vm = config_global.vm.defined_vms[name]
|
||||||
if !vm_config
|
if !sub_vm
|
||||||
raise Errors::MachineNotFound, :name => name, :provider => provider
|
raise Errors::MachineNotFound, :name => name, :provider => provider
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -154,11 +163,36 @@ module Vagrant
|
||||||
raise Errors::ProviderNotFound, :machine => name, :provider => provider
|
raise Errors::ProviderNotFound, :machine => name, :provider => provider
|
||||||
end
|
end
|
||||||
|
|
||||||
box = boxes.find(vm_config.vm.box, provider)
|
# Build the machine configuration. This requires two passes: The first pass
|
||||||
|
# loads in the machine sub-configuration. Since this can potentially
|
||||||
|
# define a new box to base the machine from, we then make a second pass
|
||||||
|
# with the box Vagrantfile (if it has one).
|
||||||
|
vm_config_key = "vm_#{name}".to_sym
|
||||||
|
@config_loader.set(vm_config_key, sub_vm.config_procs)
|
||||||
|
config = @config_loader.load([:default, :home, :root, vm_config_key])
|
||||||
|
|
||||||
|
box = nil
|
||||||
|
begin
|
||||||
|
box = boxes.find(config.vm.box, provider)
|
||||||
|
rescue Errors::BoxUpgradeRequired
|
||||||
|
# Upgrade the box if we must
|
||||||
|
@logger.info("Upgrading box during config load: #{config.vm.box}")
|
||||||
|
boxes.upgrade(config.vm.box)
|
||||||
|
retry
|
||||||
|
end
|
||||||
|
|
||||||
|
box_vagrantfile = find_vagrantfile(box.directory)
|
||||||
|
if box_vagrantfile
|
||||||
|
# The box has a custom Vagrantfile, so we load that into the config
|
||||||
|
# as well.
|
||||||
|
box_config_key = "box_#{box.name}_#{box.provider}".to_sym
|
||||||
|
@config_loader.set(box_config_key, box_vagrantfile)
|
||||||
|
config = @config_loader.load([:default, box_config_key, :home, :root, vm_config_key])
|
||||||
|
end
|
||||||
|
|
||||||
# Create the machine and cache it for future calls. This will also
|
# Create the machine and cache it for future calls. This will also
|
||||||
# return the machine from this method.
|
# return the machine from this method.
|
||||||
@machines[cache_key] = Machine.new(name, provider_cls, vm_config, box, self)
|
@machines[cache_key] = Machine.new(name, provider_cls, config, box, self)
|
||||||
end
|
end
|
||||||
|
|
||||||
# This returns a list of the configured machines for this environment.
|
# This returns a list of the configured machines for this environment.
|
||||||
|
@ -167,7 +201,7 @@ module Vagrant
|
||||||
#
|
#
|
||||||
# @return [Array<Symbol>] Configured machine names.
|
# @return [Array<Symbol>] Configured machine names.
|
||||||
def machine_names
|
def machine_names
|
||||||
config.vms
|
config_global.vm.defined_vm_keys.dup
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the primary VM associated with this environment. This
|
# Returns the primary VM associated with this environment. This
|
||||||
|
@ -180,7 +214,7 @@ module Vagrant
|
||||||
return machine(machine_names[0], :virtualbox)
|
return machine(machine_names[0], :virtualbox)
|
||||||
end
|
end
|
||||||
|
|
||||||
config.global.vm.defined_vms.each do |name, subvm|
|
config_global.vm.defined_vms.each do |name, subvm|
|
||||||
return machine(name, :virtualbox) if subvm.options[:primary]
|
return machine(name, :virtualbox) if subvm.options[:primary]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -206,7 +240,7 @@ module Vagrant
|
||||||
# matters here, so please don't touch. Specifically: The symbol
|
# matters here, so please don't touch. Specifically: The symbol
|
||||||
# check is done after the detect check because the symbol check
|
# check is done after the detect check because the symbol check
|
||||||
# will return nil, and we don't want to trigger a detect load.
|
# will return nil, and we don't want to trigger a detect load.
|
||||||
host_klass = config.global.vagrant.host
|
host_klass = config_global.vagrant.host
|
||||||
if host_klass.nil? || host_klass == :detect
|
if host_klass.nil? || host_klass == :detect
|
||||||
hosts = Vagrant.plugin("2").manager.hosts
|
hosts = Vagrant.plugin("2").manager.hosts
|
||||||
|
|
||||||
|
@ -228,7 +262,7 @@ module Vagrant
|
||||||
{
|
{
|
||||||
:action_runner => action_runner,
|
:action_runner => action_runner,
|
||||||
:box_collection => boxes,
|
:box_collection => boxes,
|
||||||
:global_config => config.global,
|
:global_config => config_global,
|
||||||
:host => host,
|
:host => host,
|
||||||
:root_path => root_path,
|
:root_path => root_path,
|
||||||
:tmp_path => tmp_path,
|
:tmp_path => tmp_path,
|
||||||
|
@ -314,138 +348,33 @@ module Vagrant
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
#---------------------------------------------------------------
|
|
||||||
# Config Methods
|
|
||||||
#---------------------------------------------------------------
|
|
||||||
|
|
||||||
# The configuration object represented by this environment. This
|
|
||||||
# will trigger the environment to load if it hasn't loaded yet (see
|
|
||||||
# {#load!}).
|
|
||||||
#
|
|
||||||
# @return [Config::Container]
|
|
||||||
def config
|
|
||||||
load! if !loaded?
|
|
||||||
@config
|
|
||||||
end
|
|
||||||
|
|
||||||
#---------------------------------------------------------------
|
#---------------------------------------------------------------
|
||||||
# Load Methods
|
# Load Methods
|
||||||
#---------------------------------------------------------------
|
#---------------------------------------------------------------
|
||||||
|
|
||||||
# Returns a boolean representing if the environment has been
|
# This initializes the config loader for this environment. The config
|
||||||
# loaded or not.
|
# loader is cached so that prior Vagrantfiles aren't loaded multiple
|
||||||
#
|
# times.
|
||||||
# @return [Bool]
|
def initialize_config
|
||||||
def loaded?
|
home_vagrantfile = nil
|
||||||
!!@loaded
|
root_vagrantfile = nil
|
||||||
end
|
home_vagrantfile = find_vagrantfile(home_path) if home_path
|
||||||
|
root_vagrantfile = find_vagrantfile(root_path) if root_path
|
||||||
|
|
||||||
# Loads this entire environment, setting up the instance variables
|
# Create the configuration loader and set the sources that are global.
|
||||||
# such as `vm`, `config`, etc. on this environment. The order this
|
# We use this to load the configuration, and the list of machines we are
|
||||||
# method calls its other methods is very particular.
|
# managing. Then, the actual individual configuration is loaded for
|
||||||
def load!
|
# each {#machine} call.
|
||||||
if !loaded?
|
@config_loader = Config::Loader.new(Config::VERSIONS, Config::VERSIONS_ORDER)
|
||||||
@loaded = true
|
@config_loader.set(:default, File.expand_path("config/default.rb", Vagrant.source_root))
|
||||||
@logger.info("Loading configuration...")
|
@config_loader.set(:home, home_vagrantfile) if home_vagrantfile
|
||||||
load_config!
|
@config_loader.set(:root, root_vagrantfile) if root_vagrantfile
|
||||||
end
|
|
||||||
|
|
||||||
self
|
# Make the initial call to get the "global" config. This is mostly
|
||||||
end
|
# only useful to get the list of machines that we are managing.
|
||||||
|
@config_global = @config_loader.load([:default, :home, :root])
|
||||||
|
|
||||||
# Reloads the configuration of this environment.
|
# Old order: default, box, home, root, vm
|
||||||
def reload!
|
|
||||||
# Reload the configuration
|
|
||||||
load_config!
|
|
||||||
|
|
||||||
# Clear the VMs because this can now be diferent due to configuration
|
|
||||||
@vms = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
# Loads this environment's configuration and stores it in the {#config}
|
|
||||||
# variable. The configuration loaded by this method is specified to
|
|
||||||
# this environment, meaning that it will use the given root directory
|
|
||||||
# to load the Vagrantfile into that context.
|
|
||||||
def load_config!
|
|
||||||
# Initialize the config loader
|
|
||||||
config_loader = Config::Loader.new(Config::VERSIONS, Config::VERSIONS_ORDER)
|
|
||||||
config_loader.load_order = [:default, :box, :home, :root, :vm]
|
|
||||||
|
|
||||||
inner_load = lambda do |*args|
|
|
||||||
# This is for Ruby 1.8.7 compatibility. Ruby 1.8.7 doesn't allow
|
|
||||||
# default arguments for lambdas, so we get around by doing a *args
|
|
||||||
# and setting the args here.
|
|
||||||
subvm = args[0]
|
|
||||||
box = args[1]
|
|
||||||
|
|
||||||
# Default Vagrantfile first. This is the Vagrantfile that ships
|
|
||||||
# with Vagrant.
|
|
||||||
config_loader.set(:default, File.expand_path("config/default.rb", Vagrant.source_root))
|
|
||||||
|
|
||||||
if box
|
|
||||||
# We load the box Vagrantfile
|
|
||||||
box_vagrantfile = find_vagrantfile(box.directory)
|
|
||||||
config_loader.set(:box, box_vagrantfile) if box_vagrantfile
|
|
||||||
end
|
|
||||||
|
|
||||||
if home_path
|
|
||||||
# Load the home Vagrantfile
|
|
||||||
home_vagrantfile = find_vagrantfile(home_path)
|
|
||||||
config_loader.set(:home, home_vagrantfile) if home_vagrantfile
|
|
||||||
end
|
|
||||||
|
|
||||||
if root_path
|
|
||||||
# Load the Vagrantfile in this directory
|
|
||||||
root_vagrantfile = find_vagrantfile(root_path)
|
|
||||||
config_loader.set(:root, root_vagrantfile) if root_vagrantfile
|
|
||||||
end
|
|
||||||
|
|
||||||
if subvm
|
|
||||||
# We have subvm configuration, so set that up as well.
|
|
||||||
config_loader.set(:vm, subvm.config_procs)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Execute the configuration stack and store the result as the final
|
|
||||||
# value in the config ivar.
|
|
||||||
config_loader.load
|
|
||||||
end
|
|
||||||
|
|
||||||
# For the global configuration, we only need to load the configuration
|
|
||||||
# in a single pass, since nothing is conditional on the configuration.
|
|
||||||
global = inner_load.call
|
|
||||||
|
|
||||||
# For each virtual machine represented by this environment, we have
|
|
||||||
# to load the configuration in two-passes. We do this because the
|
|
||||||
# first pass is used to determine the box for the VM. The second pass
|
|
||||||
# is used to also load the box Vagrantfile.
|
|
||||||
defined_vm_keys = global.vm.defined_vm_keys.dup
|
|
||||||
defined_vms = global.vm.defined_vms.dup
|
|
||||||
|
|
||||||
vm_configs = defined_vm_keys.map do |vm_name|
|
|
||||||
@logger.debug("Loading configuration for VM: #{vm_name}")
|
|
||||||
|
|
||||||
subvm = defined_vms[vm_name]
|
|
||||||
|
|
||||||
# First pass, first run.
|
|
||||||
config = inner_load[subvm]
|
|
||||||
|
|
||||||
# Second pass, with the box
|
|
||||||
box = nil
|
|
||||||
|
|
||||||
begin
|
|
||||||
box = boxes.find(config.vm.box, :virtualbox) if config.vm.box
|
|
||||||
rescue Errors::BoxUpgradeRequired
|
|
||||||
# Upgrade the box if we must.
|
|
||||||
@logger.info("Upgrading box during config load: #{config.vm.box}")
|
|
||||||
boxes.upgrade(config.vm.box)
|
|
||||||
retry
|
|
||||||
end
|
|
||||||
|
|
||||||
inner_load[subvm, box]
|
|
||||||
end
|
|
||||||
|
|
||||||
# Finally, we have our configuration. Set it and forget it.
|
|
||||||
@config = Config::Container.new(global, vm_configs)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# This sets the `@home_path` variable properly.
|
# This sets the `@home_path` variable properly.
|
||||||
|
|
|
@ -117,6 +117,8 @@ Vagrant.configure("2") do |config|
|
||||||
config.vm.define :bar, :primary => true
|
config.vm.define :bar, :primary => true
|
||||||
end
|
end
|
||||||
VF
|
VF
|
||||||
|
|
||||||
|
env.box2("base", :virtualbox)
|
||||||
end
|
end
|
||||||
|
|
||||||
env = environment.create_vagrant_env
|
env = environment.create_vagrant_env
|
||||||
|
@ -135,7 +137,7 @@ VF
|
||||||
end
|
end
|
||||||
|
|
||||||
env = environment.create_vagrant_env
|
env = environment.create_vagrant_env
|
||||||
env.config.global.vagrant.dotfile_name.should == "foo"
|
env.config_global.vagrant.dotfile_name.should == "foo"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should load from a custom Vagrantfile" do
|
it "should load from a custom Vagrantfile" do
|
||||||
|
@ -148,79 +150,9 @@ VF
|
||||||
end
|
end
|
||||||
|
|
||||||
env = environment.create_vagrant_env(:vagrantfile_name => "non_standard_name")
|
env = environment.create_vagrant_env(:vagrantfile_name => "non_standard_name")
|
||||||
env.config.global.vagrant.dotfile_name.should == "custom"
|
env.config_global.vagrant.dotfile_name.should == "custom"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should load VM configuration" do
|
|
||||||
environment = isolated_environment do |env|
|
|
||||||
env.vagrantfile(<<-VF)
|
|
||||||
Vagrant.configure("2") do |config|
|
|
||||||
config.vagrant.dotfile_name = "foo"
|
|
||||||
end
|
|
||||||
VF
|
|
||||||
end
|
|
||||||
|
|
||||||
env = environment.create_vagrant_env
|
|
||||||
env.config.for_vm(:default).vm.name.should == :default
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should load VM configuration with multiple VMs" do
|
|
||||||
environment = isolated_environment do |env|
|
|
||||||
env.vagrantfile(<<-VF)
|
|
||||||
Vagrant.configure("2") do |config|
|
|
||||||
config.vm.define :foo do |vm|
|
|
||||||
vm.ssh.port = 100
|
|
||||||
end
|
|
||||||
|
|
||||||
config.vm.define :bar do |vm|
|
|
||||||
vm.ssh.port = 200
|
|
||||||
end
|
|
||||||
end
|
|
||||||
VF
|
|
||||||
end
|
|
||||||
|
|
||||||
env = environment.create_vagrant_env
|
|
||||||
env.config.for_vm(:foo).ssh.port.should == 100
|
|
||||||
env.config.for_vm(:bar).ssh.port.should == 200
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should load a V1 vagrant box" do
|
|
||||||
environment = isolated_environment do |env|
|
|
||||||
env.vagrantfile(<<-VF)
|
|
||||||
Vagrant.configure("2") do |config|
|
|
||||||
config.vm.box = "base"
|
|
||||||
end
|
|
||||||
VF
|
|
||||||
|
|
||||||
env.box("base", <<-VF)
|
|
||||||
Vagrant.configure("2") do |config|
|
|
||||||
config.ssh.port = 100
|
|
||||||
end
|
|
||||||
VF
|
|
||||||
end
|
|
||||||
|
|
||||||
env = environment.create_vagrant_env
|
|
||||||
env.config.for_vm(:default).ssh.port.should == 100
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should load box configuration" do
|
|
||||||
environment = isolated_environment do |env|
|
|
||||||
env.vagrantfile(<<-VF)
|
|
||||||
Vagrant.configure("2") do |config|
|
|
||||||
config.vm.box = "base"
|
|
||||||
end
|
|
||||||
VF
|
|
||||||
|
|
||||||
env.box2("base", :virtualbox, :vagrantfile => <<-VF)
|
|
||||||
Vagrant.configure("2") do |config|
|
|
||||||
config.ssh.port = 100
|
|
||||||
end
|
|
||||||
VF
|
|
||||||
end
|
|
||||||
|
|
||||||
env = environment.create_vagrant_env
|
|
||||||
env.config.for_vm(:default).ssh.port.should == 100
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "ui" do
|
describe "ui" do
|
||||||
|
@ -261,6 +193,8 @@ Vagrant.configure("2") do |config|
|
||||||
config.vm.define "foo"
|
config.vm.define "foo"
|
||||||
end
|
end
|
||||||
VF
|
VF
|
||||||
|
|
||||||
|
e.box2("base", :foo)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Verify that we can get the machine
|
# Verify that we can get the machine
|
||||||
|
@ -285,6 +219,9 @@ Vagrant.configure("2") do |config|
|
||||||
config.vm.define "vm2"
|
config.vm.define "vm2"
|
||||||
end
|
end
|
||||||
VF
|
VF
|
||||||
|
|
||||||
|
e.box2("base", :foo)
|
||||||
|
e.box2("base", :bar)
|
||||||
end
|
end
|
||||||
|
|
||||||
env = isolated_env.create_vagrant_env
|
env = isolated_env.create_vagrant_env
|
||||||
|
@ -298,6 +235,75 @@ VF
|
||||||
vm2_foo.should eql(env.machine(:vm2, :foo))
|
vm2_foo.should eql(env.machine(:vm2, :foo))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "should load the machine configuration" do
|
||||||
|
register_provider("foo")
|
||||||
|
|
||||||
|
environment = isolated_environment do |env|
|
||||||
|
env.vagrantfile(<<-VF)
|
||||||
|
Vagrant.configure("2") do |config|
|
||||||
|
config.ssh.port = 1
|
||||||
|
config.vagrant.dotfile_name = "foo"
|
||||||
|
config.vm.box = "base"
|
||||||
|
|
||||||
|
config.vm.define "vm1" do |inner|
|
||||||
|
inner.ssh.port = 100
|
||||||
|
end
|
||||||
|
end
|
||||||
|
VF
|
||||||
|
|
||||||
|
env.box2("base", :foo)
|
||||||
|
end
|
||||||
|
|
||||||
|
env = environment.create_vagrant_env
|
||||||
|
machine = env.machine(:vm1, :foo)
|
||||||
|
machine.config.ssh.port.should == 100
|
||||||
|
machine.config.vagrant.dotfile_name.should == "foo"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should load a machine configured with a V1 box" do
|
||||||
|
register_provider("foo")
|
||||||
|
|
||||||
|
environment = isolated_environment do |env|
|
||||||
|
env.vagrantfile(<<-VF)
|
||||||
|
Vagrant.configure("2") do |config|
|
||||||
|
config.vm.box = "base"
|
||||||
|
end
|
||||||
|
VF
|
||||||
|
|
||||||
|
env.box("base", <<-VF)
|
||||||
|
Vagrant.configure("2") do |config|
|
||||||
|
config.ssh.port = 100
|
||||||
|
end
|
||||||
|
VF
|
||||||
|
end
|
||||||
|
|
||||||
|
env = environment.create_vagrant_env
|
||||||
|
machine = env.machine(:default, :virtualbox)
|
||||||
|
machine.config.ssh.port.should == 100
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should load the box configuration for a V2 box" do
|
||||||
|
register_provider("foo")
|
||||||
|
|
||||||
|
environment = isolated_environment do |env|
|
||||||
|
env.vagrantfile(<<-VF)
|
||||||
|
Vagrant.configure("2") do |config|
|
||||||
|
config.vm.box = "base"
|
||||||
|
end
|
||||||
|
VF
|
||||||
|
|
||||||
|
env.box2("base", :foo, :vagrantfile => <<-VF)
|
||||||
|
Vagrant.configure("2") do |config|
|
||||||
|
config.ssh.port = 100
|
||||||
|
end
|
||||||
|
VF
|
||||||
|
end
|
||||||
|
|
||||||
|
env = environment.create_vagrant_env
|
||||||
|
machine = env.machine(:default, :foo)
|
||||||
|
machine.config.ssh.port.should == 100
|
||||||
|
end
|
||||||
|
|
||||||
it "should raise an error if the VM is not found" do
|
it "should raise an error if the VM is not found" do
|
||||||
expect { instance.machine("i-definitely-dont-exist", :virtualbox) }.
|
expect { instance.machine("i-definitely-dont-exist", :virtualbox) }.
|
||||||
to raise_error(Vagrant::Errors::MachineNotFound)
|
to raise_error(Vagrant::Errors::MachineNotFound)
|
||||||
|
|
Loading…
Reference in New Issue