diff --git a/CHANGELOG.md b/CHANGELOG.md index 78f791e53..b1ed95f07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ FEATURES: - Box downloads are now done via `curl` rather than Ruby's built-in HTTP library. This results in massive speedups, support for SSL verification, FTP downloads, and more. + - `config.vm.provider` now takes an optional second parameter to the block, + allowing you to override any configuration value. These overrides are + applied last, and therefore override any other configuration value. + Note that while this feature is available, the "Vagrant way" is instead + to use box manifests to ensure that the "box" for every provider matches, + so these sorts of overrides are unnecessary. IMPROVEMENTS: diff --git a/lib/vagrant/environment.rb b/lib/vagrant/environment.rb index 15c363933..0d9d37688 100644 --- a/lib/vagrant/environment.rb +++ b/lib/vagrant/environment.rb @@ -355,6 +355,17 @@ module Vagrant end end + # If there are provider overrides for the machine, then we run + # those as well. + provider_overrides = config.vm.get_provider_overrides(provider) + if provider_overrides.length > 0 + @logger.info("Applying #{provider_overrides.length} provider overrides. Reloading config.") + provider_override_key = "vm_#{name}_#{config.vm.box}_#{provider}".to_sym + @config_loader.set(provider_override_key, provider_overrides) + config, config_warnings, config_errors = \ + @config_loader.load([:default, box_config_key, :home, :root, vm_config_key, provider_override_key]) + end + # Get the provider configuration from the final loaded configuration provider_config = config.vm.get_provider_config(provider) diff --git a/plugins/kernel_v2/config/vm.rb b/plugins/kernel_v2/config/vm.rb index 2273331a2..45320f3f4 100644 --- a/plugins/kernel_v2/config/vm.rb +++ b/plugins/kernel_v2/config/vm.rb @@ -33,6 +33,7 @@ module VagrantPlugins # Internal state @__compiled_provider_configs = {} + @__compiled_provider_overrides = {} @__defined_vm_keys = [] @__defined_vms = {} @__finalized = false @@ -196,17 +197,32 @@ module VagrantPlugins # Compile all the provider configurations @__providers.each do |name, blocks| + # If we don't have any configuration blocks, then ignore it + next if blocks.empty? + # Find the configuration class for this provider config_class = Vagrant.plugin("2").manager.provider_configs[name] - next if !config_class + config_class ||= Vagrant::Config::V2::DummyConfig # Load it up - config = config_class.new - blocks.each { |b| b.call(config) } + config = config_class.new + overrides = [] + + blocks.each do |b| + b.call(config, Vagrant::Config::V2::DummyConfig.new) + + # If the block takes two arguments, then we store the second + # one away for overrides later. + if b.arity == 2 + overrides << b.curry[Vagrant::Config::V2::DummyConfig.new] + end + end + config.finalize! # Store it for retrieval later - @__compiled_provider_configs[name] = config + @__compiled_provider_configs[name] = config + @__compiled_provider_overrides[name] = overrides end # Flag that we finalized @@ -235,6 +251,17 @@ module VagrantPlugins return result end + # This returns a list of VM configurations that are overrides + # for this provider. + # + # @param [Symbol] name Name of the provider + # @return [Array] + def get_provider_overrides(name) + (@__compiled_provider_overrides[name] || []).map do |p| + ["2", p] + end + end + # This returns the list of networks configured. def networks @__networks.values diff --git a/test/unit/vagrant/environment_test.rb b/test/unit/vagrant/environment_test.rb index aff33d4ef..02194b96d 100644 --- a/test/unit/vagrant/environment_test.rb +++ b/test/unit/vagrant/environment_test.rb @@ -550,6 +550,29 @@ VF machine.config.ssh.port.should == 100 end + it "should load the provider override if set" do + register_provider("bar") + register_provider("foo") + + isolated_env = isolated_environment do |e| + e.vagrantfile(<<-VF) +Vagrant.configure("2") do |config| + config.vm.box = "foo" + + config.vm.provider :foo do |_, c| + c.vm.box = "bar" + end +end +VF + end + + env = isolated_env.create_vagrant_env + foo_vm = env.machine(:default, :foo) + bar_vm = env.machine(:default, :bar) + foo_vm.config.vm.box.should == "bar" + bar_vm.config.vm.box.should == "foo" + end + it "should reload the cache if refresh is set" do # Create a provider foo_provider = register_provider("foo")