core: box URLs can be authenticated by hooking
This commit is contained in:
parent
45b17571ae
commit
7926f7f051
|
@ -57,8 +57,17 @@ module Vagrant
|
|||
end
|
||||
end
|
||||
|
||||
# Call the hook to transform URLs into authenticated URLs.
|
||||
# In the case we don't have a plugin that does this, then it
|
||||
# will just return the same URLs.
|
||||
hook_env = env[:hook].call(:authenticate_box_url, box_urls: url)
|
||||
authed_urls = hook_env[:box_urls]
|
||||
if !authed_urls || authed_urls.length != url.length
|
||||
raise "Bad box authentication hook, did not generate proper results."
|
||||
end
|
||||
|
||||
# Test if any of our URLs point to metadata
|
||||
is_metadata_results = url.map do |u|
|
||||
is_metadata_results = authed_urls.map do |u|
|
||||
begin
|
||||
metadata_url?(u, env)
|
||||
rescue Errors::DownloaderError => e
|
||||
|
@ -86,7 +95,8 @@ module Vagrant
|
|||
end
|
||||
|
||||
if is_metadata
|
||||
add_from_metadata(url.first, env, expanded)
|
||||
url = [url.first, authed_urls.first]
|
||||
add_from_metadata(url, env, expanded)
|
||||
else
|
||||
add_direct(url, env)
|
||||
end
|
||||
|
@ -118,12 +128,28 @@ module Vagrant
|
|||
end
|
||||
|
||||
# Adds a box given that the URL is a metadata document.
|
||||
#
|
||||
# @param [String | Array<String>] url The URL of the metadata for
|
||||
# the box to add. If this is an array, then it must be a two-element
|
||||
# array where the first element is the original URL and the second
|
||||
# element is an authenticated URL.
|
||||
# @param [Hash] env
|
||||
# @param [Bool] expanded True if the metadata URL was expanded with
|
||||
# a Vagrant Cloud server URL.
|
||||
def add_from_metadata(url, env, expanded)
|
||||
original_url = env[:box_url]
|
||||
provider = env[:box_provider]
|
||||
provider = Array(provider) if provider
|
||||
version = env[:box_version]
|
||||
|
||||
authenticated_url = url
|
||||
if url.is_a?(Array)
|
||||
# We have both a normal URL and "authenticated" URL. Split
|
||||
# them up.
|
||||
authenticated_url = url[1]
|
||||
url = url[0]
|
||||
end
|
||||
|
||||
env[:ui].output(I18n.t(
|
||||
"vagrant.box_loading_metadata",
|
||||
name: Array(original_url).first))
|
||||
|
@ -134,7 +160,8 @@ module Vagrant
|
|||
|
||||
metadata = nil
|
||||
begin
|
||||
metadata_path = download(url, env, json: true, ui: false)
|
||||
metadata_path = download(
|
||||
authenticated_url, env, json: true, ui: false)
|
||||
|
||||
File.open(metadata_path) do |f|
|
||||
metadata = BoxMetadata.new(f)
|
||||
|
|
|
@ -44,6 +44,7 @@ module Vagrant
|
|||
options ||= {}
|
||||
|
||||
@directory = directory
|
||||
@hook = options[:hook]
|
||||
@lock = Monitor.new
|
||||
@temp_root = options[:temp_dir_root]
|
||||
@logger = Log4r::Logger.new("vagrant::box_collection")
|
||||
|
@ -289,6 +290,12 @@ module Vagrant
|
|||
metadata_url_file = box_directory.join("metadata_url")
|
||||
metadata_url = metadata_url_file.read if metadata_url_file.file?
|
||||
|
||||
if metadata_url && @hook
|
||||
hook_env = @hook.call(
|
||||
:authenticate_box_url, box_urls: [metadata_url])
|
||||
metadata_url = hook_env[:box_urls].first
|
||||
end
|
||||
|
||||
return Box.new(
|
||||
name, provider, v.to_s, provider_dir,
|
||||
metadata_url: metadata_url,
|
||||
|
|
|
@ -258,7 +258,10 @@ module Vagrant
|
|||
#
|
||||
# @return [BoxCollection]
|
||||
def boxes
|
||||
@_boxes ||= BoxCollection.new(boxes_path, temp_dir_root: tmp_path)
|
||||
@_boxes ||= BoxCollection.new(
|
||||
boxes_path,
|
||||
hook: method(:hook),
|
||||
temp_dir_root: tmp_path)
|
||||
end
|
||||
|
||||
# Returns the {Config::Loader} that can be used to load Vagrantflies
|
||||
|
|
|
@ -41,9 +41,18 @@ describe VagrantPlugins::CommandBox::Command::Update do
|
|||
end
|
||||
|
||||
it "doesn't update if they're up to date" do
|
||||
action_runner.should_receive(:run).never
|
||||
called = false
|
||||
action_runner.stub(:run) do |callable, opts|
|
||||
if opts[:box_provider]
|
||||
called = true
|
||||
end
|
||||
|
||||
opts
|
||||
end
|
||||
|
||||
subject.execute
|
||||
|
||||
expect(called).to be_false
|
||||
end
|
||||
|
||||
it "does update if there is an update" do
|
||||
|
@ -69,14 +78,21 @@ describe VagrantPlugins::CommandBox::Command::Update do
|
|||
RAW
|
||||
end
|
||||
|
||||
action_runner.should_receive(:run).with do |action, opts|
|
||||
expect(opts[:box_url]).to eq(metadata_url.to_s)
|
||||
expect(opts[:box_provider]).to eq("virtualbox")
|
||||
expect(opts[:box_version]).to eq("1.1")
|
||||
true
|
||||
action_called = false
|
||||
action_runner.stub(:run) do |action, opts|
|
||||
if opts[:box_provider]
|
||||
action_called = true
|
||||
expect(opts[:box_url]).to eq(metadata_url.to_s)
|
||||
expect(opts[:box_provider]).to eq("virtualbox")
|
||||
expect(opts[:box_version]).to eq("1.1")
|
||||
end
|
||||
|
||||
opts
|
||||
end
|
||||
|
||||
subject.execute
|
||||
|
||||
expect(action_called).to be_true
|
||||
end
|
||||
|
||||
it "raises an error if there are multiple providers" do
|
||||
|
@ -116,14 +132,21 @@ describe VagrantPlugins::CommandBox::Command::Update do
|
|||
|
||||
test_iso_env.box3("foo", "1.0", :vmware)
|
||||
|
||||
action_runner.should_receive(:run).with do |action, opts|
|
||||
expect(opts[:box_url]).to eq(metadata_url.to_s)
|
||||
expect(opts[:box_provider]).to eq("vmware")
|
||||
expect(opts[:box_version]).to eq("1.1")
|
||||
true
|
||||
action_called = false
|
||||
action_runner.stub(:run) do |action, opts|
|
||||
if opts[:box_provider]
|
||||
action_called = true
|
||||
expect(opts[:box_url]).to eq(metadata_url.to_s)
|
||||
expect(opts[:box_provider]).to eq("vmware")
|
||||
expect(opts[:box_version]).to eq("1.1")
|
||||
end
|
||||
|
||||
opts
|
||||
end
|
||||
|
||||
subject.execute
|
||||
|
||||
expect(action_called).to be_true
|
||||
end
|
||||
|
||||
it "raises an error if that provider doesn't exist" do
|
||||
|
|
|
@ -14,6 +14,7 @@ describe Vagrant::Action::Builtin::BoxAdd do
|
|||
let(:app) { lambda { |env| } }
|
||||
let(:env) { {
|
||||
box_collection: box_collection,
|
||||
hook: Proc.new { |name, env| env },
|
||||
tmp_path: Pathname.new(Dir.mktmpdir),
|
||||
ui: Vagrant::UI::Silent.new,
|
||||
} }
|
||||
|
@ -262,6 +263,60 @@ describe Vagrant::Action::Builtin::BoxAdd do
|
|||
end
|
||||
end
|
||||
|
||||
it "authenticates HTTP URLs and adds them" do
|
||||
box_path = iso_env.box2_file(:virtualbox)
|
||||
tf = Tempfile.new(["vagrant", ".json"]).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
|
||||
|
||||
md_path = Pathname.new(tf.path)
|
||||
with_web_server(md_path) do |port|
|
||||
real_url = "http://127.0.0.1:#{port}/#{md_path.basename}"
|
||||
|
||||
# Set the box URL to something fake so we can modify it in place
|
||||
env[:box_url] = "foo"
|
||||
|
||||
env[:hook] = double("hook")
|
||||
env[:hook].should_receive(:call) do |name, opts|
|
||||
expect(name).to eq(:authenticate_box_url)
|
||||
expect(opts[:box_urls]).to eq(["foo"])
|
||||
{ box_urls: [real_url] }
|
||||
end
|
||||
|
||||
box_collection.should_receive(:add).with do |path, name, version, **opts|
|
||||
expect(name).to eq("foo/bar")
|
||||
expect(version).to eq("0.7")
|
||||
expect(checksum(path)).to eq(checksum(box_path))
|
||||
expect(opts[:metadata_url]).to eq(env[:box_url])
|
||||
true
|
||||
end.and_return(box)
|
||||
|
||||
app.should_receive(:call).with(env)
|
||||
|
||||
subject.call(env)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
it "raises an error if no Vagrant server is set" do
|
||||
tf = Tempfile.new("foo")
|
||||
tf.close
|
||||
|
|
|
@ -56,6 +56,42 @@ describe Vagrant::BoxCollection do
|
|||
expect(result).to_not be_nil
|
||||
expect(result).to be_kind_of(box_class)
|
||||
expect(result.name).to eq("foo")
|
||||
expect(result.metadata_url).to be_nil
|
||||
end
|
||||
|
||||
it "sets a metadata URL if it has one" do
|
||||
# Create the "box"
|
||||
environment.box3("foo", "0", :virtualbox,
|
||||
metadata_url: "foourl")
|
||||
|
||||
# Actual test
|
||||
result = subject.find("foo", :virtualbox, ">= 0")
|
||||
expect(result).to_not be_nil
|
||||
expect(result).to be_kind_of(box_class)
|
||||
expect(result.name).to eq("foo")
|
||||
expect(result.metadata_url).to eq("foourl")
|
||||
end
|
||||
|
||||
it "sets the metadata URL to an authenticated URL if it has one" do
|
||||
hook = double("hook")
|
||||
subject = described_class.new(environment.boxes_dir, hook: hook)
|
||||
|
||||
# Create the "box"
|
||||
environment.box3("foo", "0", :virtualbox,
|
||||
metadata_url: "foourl")
|
||||
|
||||
hook.should_receive(:call).with do |name, env|
|
||||
expect(name).to eq(:authenticate_box_url)
|
||||
expect(env[:box_urls]).to eq(["foourl"])
|
||||
true
|
||||
end.and_return(box_urls: ["bar"])
|
||||
|
||||
# Actual test
|
||||
result = subject.find("foo", :virtualbox, ">= 0")
|
||||
expect(result).to_not be_nil
|
||||
expect(result).to be_kind_of(box_class)
|
||||
expect(result.name).to eq("foo")
|
||||
expect(result.metadata_url).to eq("bar")
|
||||
end
|
||||
|
||||
it "returns latest version matching constraint" do
|
||||
|
|
|
@ -757,6 +757,11 @@ VF
|
|||
collection = instance.boxes
|
||||
collection.should be_kind_of(Vagrant::BoxCollection)
|
||||
collection.directory.should == instance.boxes_path
|
||||
|
||||
# Reach into some internal state here but not sure how else
|
||||
# to test this at the moment.
|
||||
expect(collection.instance_variable_get(:@hook)).
|
||||
to eq(instance.method(:hook))
|
||||
end
|
||||
|
||||
describe "action runner" do
|
||||
|
|
Loading…
Reference in New Issue