core: BoxAdd supports multiple URLs properly
This commit is contained in:
parent
38248c240c
commit
f0607c6df0
|
@ -22,30 +22,49 @@ module Vagrant
|
|||
def call(env)
|
||||
@download_interrupted = false
|
||||
|
||||
url = env[:box_url]
|
||||
url = Array(env[:box_url])
|
||||
|
||||
# If we received a shorthand URL ("mitchellh/precise64"),
|
||||
# then expand it properly.
|
||||
expanded = false
|
||||
uri = URI.parse(url)
|
||||
if !uri.scheme && !File.file?(url)
|
||||
expanded = true
|
||||
url = "#{Vagrant.server_url}/#{url}"
|
||||
url.each_index do |i|
|
||||
uri = URI.parse(url[i])
|
||||
if !uri.scheme && !File.file?(url[i])
|
||||
expanded = true
|
||||
url[i] = "#{Vagrant.server_url}/#{url[i]}"
|
||||
end
|
||||
end
|
||||
|
||||
is_metadata = false
|
||||
begin
|
||||
is_metadata = metadata_url?(url, env)
|
||||
rescue Errors::DownloaderError => e
|
||||
raise if !expanded
|
||||
raise Errors::BoxAddShortNotFound,
|
||||
error: e.extra_data[:message],
|
||||
name: env[:box_url],
|
||||
url: url
|
||||
# Test if any of our URLs point to metadata
|
||||
is_metadata_results = url.map do |u|
|
||||
begin
|
||||
metadata_url?(u, env)
|
||||
rescue Errors::DownloaderError => e
|
||||
e
|
||||
end
|
||||
end
|
||||
|
||||
if expanded && url.length == 1
|
||||
is_error = is_metadata_results.find do |b|
|
||||
b.is_a?(Errors::DownloaderError)
|
||||
end
|
||||
|
||||
if is_error
|
||||
raise Errors::BoxAddShortNotFound,
|
||||
error: is_error.extra_data[:message],
|
||||
name: env[:box_url],
|
||||
url: url
|
||||
end
|
||||
end
|
||||
|
||||
is_metadata = is_metadata_results.any? { |b| b === true }
|
||||
if is_metadata && url.length > 1
|
||||
raise Errors::BoxAddMetadataMultiURL,
|
||||
urls: url.join(", ")
|
||||
end
|
||||
|
||||
if is_metadata
|
||||
add_from_metadata(url, env)
|
||||
add_from_metadata(url.first, env, expanded)
|
||||
else
|
||||
add_direct(url, env)
|
||||
end
|
||||
|
@ -55,7 +74,10 @@ module Vagrant
|
|||
|
||||
# Adds a box file directly (no metadata component, versioning,
|
||||
# etc.)
|
||||
def add_direct(url, env)
|
||||
#
|
||||
# @param [Array<String>] urls
|
||||
# @param [Hash] env
|
||||
def add_direct(urls, env)
|
||||
name = env[:box_name]
|
||||
if !name || name == ""
|
||||
raise Errors::BoxAddNameRequired
|
||||
|
@ -65,7 +87,7 @@ module Vagrant
|
|||
provider = Array(provider) if provider
|
||||
|
||||
box_add(
|
||||
url,
|
||||
urls,
|
||||
name,
|
||||
"0",
|
||||
provider,
|
||||
|
@ -73,7 +95,7 @@ module Vagrant
|
|||
end
|
||||
|
||||
# Adds a box given that the URL is a metadata document.
|
||||
def add_from_metadata(url, env)
|
||||
def add_from_metadata(url, env, expanded)
|
||||
original_url = env[:box_url]
|
||||
provider = env[:box_provider]
|
||||
provider = Array(provider) if provider
|
||||
|
@ -93,6 +115,12 @@ module Vagrant
|
|||
File.open(metadata_path) do |f|
|
||||
metadata = BoxMetadata.new(f)
|
||||
end
|
||||
rescue Errors::DownloaderError => e
|
||||
raise if !expanded
|
||||
raise Errors::BoxAddShortNotFound,
|
||||
error: e.extra_data[:message],
|
||||
name: original_url,
|
||||
url: url
|
||||
ensure
|
||||
metadata_path.delete if metadata_path && metadata_path.file?
|
||||
end
|
||||
|
@ -160,7 +188,7 @@ module Vagrant
|
|||
end
|
||||
|
||||
box_add(
|
||||
metadata_provider.url,
|
||||
[metadata_provider.url],
|
||||
metadata.name,
|
||||
metadata_version.version,
|
||||
metadata_provider.name, env)
|
||||
|
@ -232,13 +260,13 @@ module Vagrant
|
|||
# Shared helper to add a box once you know various details
|
||||
# about it. Shared between adding via metadata or by direct.
|
||||
#
|
||||
# @param [String] url
|
||||
# @param [Array<String>] urls
|
||||
# @param [String] name
|
||||
# @param [String] version
|
||||
# @param [String] provider
|
||||
# @param [Hash] env
|
||||
# @return [Box]
|
||||
def box_add(url, name, version, provider, env, **opts)
|
||||
def box_add(urls, name, version, provider, env, **opts)
|
||||
env[:ui].output(I18n.t(
|
||||
"vagrant.box_add_with_version",
|
||||
name: name,
|
||||
|
@ -260,7 +288,21 @@ module Vagrant
|
|||
# Now we have a URL, we have to download this URL.
|
||||
box = nil
|
||||
begin
|
||||
box_url = download(url, env)
|
||||
box_url = nil
|
||||
|
||||
urls.each do |url|
|
||||
env[:ui].detail(I18n.t(
|
||||
"vagrant.box_downloading", url: url))
|
||||
|
||||
begin
|
||||
box_url = download(url, env)
|
||||
break
|
||||
rescue Errors::DownloaderError => e
|
||||
env[:ui].error(I18n.t(
|
||||
"vagrant.box_download_error", message: e.message))
|
||||
box_url = nil
|
||||
end
|
||||
end
|
||||
|
||||
# Add the box!
|
||||
box = env[:box_collection].add(
|
||||
|
@ -273,7 +315,7 @@ module Vagrant
|
|||
# so we can resume the download later.
|
||||
if !@download_interrupted
|
||||
@logger.debug("Deleting temporary box: #{box_url}")
|
||||
box_url.delete
|
||||
box_url.delete if box_url
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -120,6 +120,10 @@ module Vagrant
|
|||
error_key(:batch_multi_error)
|
||||
end
|
||||
|
||||
class BoxAddMetadataMultiURL < VagrantError
|
||||
error_key(:box_add_metadata_multi_url)
|
||||
end
|
||||
|
||||
class BoxAddNameMismatch < VagrantError
|
||||
error_key(:box_add_name_mismatch)
|
||||
end
|
||||
|
|
|
@ -20,6 +20,10 @@ en:
|
|||
Adding box '%{name}' (v%{version}) for '%{provider}' provider...
|
||||
box_added: |-
|
||||
Successfully added box '%{name}' for '%{provider}'!
|
||||
box_downloading: |-
|
||||
Downloading: %{url}
|
||||
box_download_error: |-
|
||||
Error downloading: %{message}
|
||||
box_expanding_url: |-
|
||||
URL: %{url}
|
||||
box_loading_metadata: |-
|
||||
|
@ -289,6 +293,13 @@ en:
|
|||
Name: %{name}
|
||||
Provider: %{provider}
|
||||
Version: %{version}
|
||||
box_add_metadata_multi_url: |-
|
||||
Multiple URLs for a box can't be specified when adding
|
||||
versioned boxes. Please specify a single URL to the box
|
||||
metadata (JSON) information. The full list of URLs you
|
||||
specified is shown below:
|
||||
|
||||
%{urls}
|
||||
box_add_name_mismatch: |-
|
||||
The box you're adding has a name different from the name you
|
||||
requested. For boxes with metadata, you cannot override the name.
|
||||
|
|
|
@ -77,6 +77,27 @@ describe Vagrant::Action::Builtin::BoxAdd do
|
|||
subject.call(env)
|
||||
end
|
||||
|
||||
it "adds from multiple URLs" do
|
||||
box_path = iso_env.box2_file(:virtualbox)
|
||||
|
||||
env[:box_name] = "foo"
|
||||
env[:box_url] = [
|
||||
"/foo/bar/baz",
|
||||
box_path.to_s,
|
||||
]
|
||||
|
||||
box_collection.should_receive(:add).with do |path, name, version|
|
||||
expect(checksum(path)).to eq(checksum(box_path))
|
||||
expect(name).to eq("foo")
|
||||
expect(version).to eq("0")
|
||||
true
|
||||
end.and_return(box)
|
||||
|
||||
app.should_receive(:call).with(env)
|
||||
|
||||
subject.call(env)
|
||||
end
|
||||
|
||||
it "adds from HTTP URL" do
|
||||
box_path = iso_env.box2_file(:virtualbox)
|
||||
with_web_server(box_path) do |port|
|
||||
|
@ -252,6 +273,42 @@ describe Vagrant::Action::Builtin::BoxAdd do
|
|||
end
|
||||
end
|
||||
|
||||
it "raises an error if multiple metadata URLs are given" do
|
||||
box_path = iso_env.box2_file(:virtualbox)
|
||||
tf = Tempfile.new("vagrant").tap do |f|
|
||||
f.write(<<-RAW)
|
||||
{
|
||||
"name": "foo/bar",
|
||||
"versions": [
|
||||
{
|
||||
"version": "0.5"
|
||||
},
|
||||
{
|
||||
"version": "0.7",
|
||||
"providers": [
|
||||
{
|
||||
"name": "virtualbox",
|
||||
"url": "#{box_path}"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
RAW
|
||||
f.close
|
||||
end
|
||||
|
||||
env[:box_url] = [
|
||||
"/foo/bar/baz",
|
||||
tf.path,
|
||||
]
|
||||
box_collection.should_receive(:add).never
|
||||
app.should_receive(:call).never
|
||||
|
||||
expect { subject.call(env) }.
|
||||
to raise_error(Vagrant::Errors::BoxAddMetadataMultiURL)
|
||||
end
|
||||
|
||||
it "adds the latest version of a box with only one provider" do
|
||||
box_path = iso_env.box2_file(:virtualbox)
|
||||
tf = Tempfile.new("vagrant").tap do |f|
|
||||
|
|
Loading…
Reference in New Issue