Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add architecture support #13239

Merged
merged 11 commits into from
Sep 27, 2023
2 changes: 2 additions & 0 deletions lib/vagrant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ def << msg
rescue => err
global_logger.warn("unexpected failure loading ssl providers, attempting to continue (#{err})")
end
else
global_logger.warn("vagrant ssl helper was not found, continuing...")
end

# We need these components always so instead of an autoload we
Expand Down
92 changes: 75 additions & 17 deletions lib/vagrant/action/builtin/box_add.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,29 @@ def call(env)
# If we received a shorthand URL ("mitchellh/precise64"),
# then expand it properly.
expanded = false
url.each_index do |i|
next if url[i] !~ /^[^\/]+\/[^\/]+$/
# Mark if only a single url entry was provided
single_entry = url.size == 1

if !File.file?(url[i])
url = url.map do |url_entry|
if url_entry =~ /^[^\/]+\/[^\/]+$/ && !File.file?(url_entry)
server = Vagrant.server_url env[:box_server_url]
raise Errors::BoxServerNotSet if !server

expanded = true
url[i] = "#{server}/#{url[i]}"
# If only a single entry, expand to both the API endpoint and
# the direct shorthand endpoint.
if single_entry
url_entry = [
"#{server}/api/v2/vagrant/#{url_entry}",
"#{server}/#{url_entry}"
]
else
url_entry = "#{server}/#{url_entry}"
end
end
end

url_entry
end.flatten

# Call the hook to transform URLs into authenticated URLs.
# In the case we don't have a plugin that does this, then it
Expand All @@ -99,6 +111,21 @@ def call(env)
end
end

# If only a single entry was provided, and it was expanded,
# inspect the metadata check results and extract the one that
# was successful, with preference to the API endpoint
if single_entry && expanded
idx = is_metadata_results.index { |v| v === true }
# If none of the urls were successful, set the index
# as the last entry
idx = is_metadata_results.size - 1 if idx.nil?

# Now reset collections with single value
is_metadata_results = [is_metadata_results[idx]]
authed_urls = [authed_urls[idx]]
url = [url[idx]]
end

if expanded && url.length == 1
is_error = is_metadata_results.find do |b|
b.is_a?(Errors::DownloaderError)
Expand Down Expand Up @@ -165,6 +192,7 @@ def add_direct(urls, env)
env,
checksum: env[:box_checksum],
checksum_type: env[:box_checksum_type],
architecture: env[:architecture]
)
end

Expand All @@ -179,6 +207,9 @@ def add_direct(urls, env)
# a Atlas server URL.
def add_from_metadata(url, env, expanded)
original_url = env[:box_url]
architecture = env[:box_architecture]
display_architecture = architecture == :auto ?
Util::Platform.architecture : architecture
provider = env[:box_provider]
provider = Array(provider) if provider
version = env[:box_version]
Expand Down Expand Up @@ -228,12 +259,17 @@ def add_from_metadata(url, env, expanded)
end

metadata_version = metadata.version(
version || ">= 0", provider: provider)
version || ">= 0",
provider: provider,
architecture: architecture,
)
if !metadata_version
if provider && !metadata.version(">= 0", provider: provider)
if provider && !metadata.version(">= 0", provider: provider, architecture: architecture)
raise Errors::BoxAddNoMatchingProvider,
name: metadata.name,
requested: provider,
requested: [provider,
display_architecture ? "(#{display_architecture})" : nil
].compact.join(" "),
url: display_url
else
raise Errors::BoxAddNoMatchingVersion,
Expand All @@ -249,16 +285,16 @@ def add_from_metadata(url, env, expanded)
# If a provider was specified, make sure we get that specific
# version.
provider.each do |p|
metadata_provider = metadata_version.provider(p)
metadata_provider = metadata_version.provider(p, architecture)
break if metadata_provider
end
elsif metadata_version.providers.length == 1
elsif metadata_version.providers(architecture).length == 1
# If we have only one provider in the metadata, just use that
# provider.
metadata_provider = metadata_version.provider(
metadata_version.providers.first)
metadata_version.providers.first, architecture)
else
providers = metadata_version.providers.sort
providers = metadata_version.providers(architecture).sort

choice = 0
options = providers.map do |p|
Expand All @@ -279,7 +315,7 @@ def add_from_metadata(url, env, expanded)
end

metadata_provider = metadata_version.provider(
providers[choice-1])
providers[choice-1], architecture)
end

provider_url = metadata_provider.url
Expand All @@ -293,6 +329,17 @@ def add_from_metadata(url, env, expanded)
provider_url = authed_urls[0]
end

# The architecture name used when adding the box should be
# the value extracted from the metadata provider
arch_name = metadata_provider.architecture

# In the special case where the architecture name is "unknown" and
# it is listed as the default architecture, unset the architecture
# name so it is installed without architecture information
if arch_name == "unknown" && metadata_provider.default_architecture
arch_name = nil
end

box_add(
[[provider_url, metadata_provider.url]],
metadata.name,
Expand All @@ -302,6 +349,7 @@ def add_from_metadata(url, env, expanded)
env,
checksum: metadata_provider.checksum,
checksum_type: metadata_provider.checksum_type,
architecture: arch_name,
)
end

Expand All @@ -317,16 +365,21 @@ def add_from_metadata(url, env, expanded)
# @param [Hash] env
# @return [Box]
def box_add(urls, name, version, provider, md_url, env, **opts)
display_architecture = opts[:architecture] == :auto ?
Util::Platform.architecture : opts[:architecture]
env[:ui].output(I18n.t(
"vagrant.box_add_with_version",
name: name,
version: version,
providers: Array(provider).join(", ")))
providers: [
provider,
display_architecture ? "(#{display_architecture})" : nil
].compact.join(" ")))

# Verify the box we're adding doesn't already exist
if provider && !env[:box_force]
box = env[:box_collection].find(
name, provider, version)
name, provider, version, opts[:architecture])
if box
raise Errors::BoxAlreadyExists,
name: name,
Expand Down Expand Up @@ -377,7 +430,9 @@ def box_add(urls, name, version, provider, md_url, env, **opts)
box_url, name, version,
force: env[:box_force],
metadata_url: md_url,
providers: provider)
providers: provider,
architecture: opts[:architecture]
)
ensure
# Make sure we delete the temporary file after we add it,
# unless we were interrupted, in which case we keep it around
Expand All @@ -396,7 +451,10 @@ def box_add(urls, name, version, provider, md_url, env, **opts)
"vagrant.box_added",
name: box.name,
version: box.version,
provider: box.provider))
provider: [
provider,
display_architecture ? "(#{display_architecture})" : nil
].compact.join(" ")))

# Store the added box in the env for future middleware
env[:box_added] = box
Expand Down
Loading