diff --git a/lib/vagrant/action/builtin/mixin_synced_folders.rb b/lib/vagrant/action/builtin/mixin_synced_folders.rb index ab8058fd0..42e3a290f 100644 --- a/lib/vagrant/action/builtin/mixin_synced_folders.rb +++ b/lib/vagrant/action/builtin/mixin_synced_folders.rb @@ -22,7 +22,7 @@ module Vagrant ordered << [priority, key, impl] end - # Order the plugins by priority. Higher is tries before lower. + # Order the plugins by priority. Higher is tried before lower. ordered = ordered.sort { |a, b| b[0] <=> a[0] } # Find the proper implementation diff --git a/lib/vagrant/environment.rb b/lib/vagrant/environment.rb index cf37ffeb4..19975b4ec 100644 --- a/lib/vagrant/environment.rb +++ b/lib/vagrant/environment.rb @@ -254,8 +254,35 @@ module Vagrant # environment. # # @return [Symbol] Name of the default provider. - def default_provider - (ENV['VAGRANT_DEFAULT_PROVIDER'] || :virtualbox).to_sym + def default_provider(**opts) + default = ENV["VAGRANT_DEFAULT_PROVIDER"] + default = nil if default == "" + default = default.to_sym if default + + ordered = [] + Vagrant.plugin("2").manager.providers.each do |key, data| + impl = data[0] + opts = data[1] + + ordered << [opts[:priority], key, impl, opts] + end + + # Order the providers by priority. Higher values are tried first. + ordered = ordered.sort do |a, b| + # If we see the default, then that one always wins + next -1 if a[1] == default + next 1 if b[1] == default + + b[0] <=> a[0] + end + + # Find the matching implementation + ordered.each do |_, key, impl, _| + return key if impl.usable?(false) + end + + # If all else fails, return VirtualBox + return :virtualbox end # Returns the collection of boxes for the environment. diff --git a/test/unit/support/shared/capability_helpers_context.rb b/test/unit/support/shared/capability_helpers_context.rb index 7db62d161..4976aaf8d 100644 --- a/test/unit/support/shared/capability_helpers_context.rb +++ b/test/unit/support/shared/capability_helpers_context.rb @@ -7,6 +7,14 @@ shared_context "capability_helpers" do end end + def provider_usable_class(result) + Class.new do + define_singleton_method(:usable?) do |*args| + result + end + end + end + def cap_instance(name, options=nil) options ||= {} diff --git a/test/unit/vagrant/environment_test.rb b/test/unit/vagrant/environment_test.rb index 070df3ecf..ca16d4187 100644 --- a/test/unit/vagrant/environment_test.rb +++ b/test/unit/vagrant/environment_test.rb @@ -699,15 +699,32 @@ VF end describe "default provider" do - it "is virtualbox without any environmental variable" do + let(:plugin_providers) { {} } + + before do + m = Vagrant.plugin("2").manager + m.stub(providers: plugin_providers) + end + + it "is the highest matching usable provider" do + plugin_providers[:foo] = [provider_usable_class(true), { priority: 5 }] + plugin_providers[:bar] = [provider_usable_class(true), { priority: 7 }] + plugin_providers[:baz] = [provider_usable_class(true), { priority: 2 }] + plugin_providers[:boom] = [provider_usable_class(true), { priority: 3 }] + with_temp_env("VAGRANT_DEFAULT_PROVIDER" => nil) do - expect(subject.default_provider).to eq(:virtualbox) + expect(subject.default_provider).to eq(:bar) end end - it "is whatever the environmental variable is if set" do - with_temp_env("VAGRANT_DEFAULT_PROVIDER" => "foo") do - expect(subject.default_provider).to eq(:foo) + it "is the default provider if it is usable" do + plugin_providers[:foo] = [provider_usable_class(true), { priority: 5 }] + plugin_providers[:bar] = [provider_usable_class(true), { priority: 7 }] + plugin_providers[:baz] = [provider_usable_class(true), { priority: 2 }] + plugin_providers[:boom] = [provider_usable_class(true), { priority: 3 }] + + with_temp_env("VAGRANT_DEFAULT_PROVIDER" => "baz") do + expect(subject.default_provider).to eq(:baz) end end end