Rewrite Environment#default_provider to be less confusing

This commit is contained in:
Aron Griffis 2017-05-02 14:52:41 -04:00
parent 1073aa8163
commit f256fc882f
No known key found for this signature in database
GPG Key ID: 9052C6069B7D31A7
1 changed files with 48 additions and 33 deletions

View File

@ -317,6 +317,18 @@ module Vagrant
opts[:force_default] = true if !opts.key?(:force_default) opts[:force_default] = true if !opts.key?(:force_default)
opts[:check_usable] = true if !opts.key?(:check_usable) opts[:check_usable] = true if !opts.key?(:check_usable)
# Implement the algorithm from
# https://www.vagrantup.com/docs/providers/basic_usage.html#default-provider
#
# 1. The --provider flag on a vagrant up is chosen above all else, if it is
# present.
#
# (Step 1 is done by the caller; this method is only called if --provider
# wasn't given.)
#
# 2. If the VAGRANT_DEFAULT_PROVIDER environmental variable is set, it
# takes next priority and will be the provider chosen.
default = ENV["VAGRANT_DEFAULT_PROVIDER"] default = ENV["VAGRANT_DEFAULT_PROVIDER"]
default = nil if default == "" default = nil if default == ""
default = default.to_sym if default default = default.to_sym if default
@ -334,22 +346,12 @@ module Vagrant
root_config = machine_info[:config] root_config = machine_info[:config]
end end
# Get the list of providers within our configuration and assign # Get the list of providers within our configuration, in order.
# a priority to each in the order they exist so that we try these first. config = root_config.vm.__providers
config = {}
root_config.vm.__providers.reverse.each_with_index do |key, idx|
config[key] = idx + 1
end
# Determine the max priority so that we can add the config priority # Get the list of usable providers with their internally-declared
# to that to make sure it is highest. # priorities.
max_priority = 0 usable = []
Vagrant.plugin("2").manager.providers.each do |key, data|
priority = data[1][:priority]
max_priority = priority if priority > max_priority
end
ordered = []
Vagrant.plugin("2").manager.providers.each do |key, data| Vagrant.plugin("2").manager.providers.each do |key, data|
impl = data[0] impl = data[0]
popts = data[1] popts = data[1]
@ -359,33 +361,46 @@ module Vagrant
# Skip providers that can't be defaulted, unless they're in our # Skip providers that can't be defaulted, unless they're in our
# config, in which case someone made our decision for us. # config, in which case someone made our decision for us.
if !config.key?(key) if !config.include?(key)
next if popts.key?(:defaultable) && !popts[:defaultable] next if popts.key?(:defaultable) && !popts[:defaultable]
end end
# The priority is higher if it is in our config. Otherwise, it is # Skip providers that aren't usable.
# the priority it set PLUS the length of the config to make sure it next if opts[:check_usable] && !impl.usable?(false)
# is never higher than the configuration keys.
priority = popts[:priority]
priority = config[key] + max_priority if config.key?(key)
ordered << [priority, key, impl, popts] # Each provider sets its own priority, defaulting to 5 so we can trust
# it's always set.
usable << [popts[:priority], key]
end end
# Order the providers by priority. Higher values are tried first. # Sort the usable providers by priority. Higher numbers are higher
ordered = ordered.sort do |a, b| # priority, otherwise alpha sort.
# If we see the default, then that one always wins usable = usable.sort {|a, b| a[0] == b[0] ? a[1] <=> b[1] : b[0] <=> a[0]}
next -1 if a[1] == default .map {|prio, key| key}
next 1 if b[1] == default
b[0] <=> a[0] # If we're not forcing the default, but it's usable and hasn't been
# otherwise excluded, return it now.
return default if usable.include?(default)
# 3. Vagrant will go through all of the config.vm.provider calls in the
# Vagrantfile and try each in order. It will choose the first provider
# that is usable. For example, if you configure Hyper-V, it will never
# be chosen on Mac this way. It must be both configured and usable.
config.each do |key|
return key if usable.include?(key)
end end
# Find the matching implementation # 4. Vagrant will go through all installed provider plugins (including the
ordered.each do |_, key, impl, _| # ones that come with Vagrant), and find the first plugin that reports
return key if !opts[:check_usable] # it is usable. There is a priority system here: systems that are known
return key if impl.usable?(false) # better have a higher priority than systems that are worse. For
end # example, if you have the VMware provider installed, it will always
# take priority over VirtualBox.
return usable[0] if !usable.empty?
# 5. If Vagrant still has not found any usable providers, it will error.
# No providers available is a critical error for Vagrant. # No providers available is a critical error for Vagrant.
raise Errors::NoDefaultProvider raise Errors::NoDefaultProvider