Box downloading middleware
This commit is contained in:
parent
e9bcd3fc16
commit
d84225de66
|
@ -0,0 +1,79 @@
|
||||||
|
module Vagrant
|
||||||
|
class Action
|
||||||
|
module Box
|
||||||
|
class Download
|
||||||
|
BASENAME = "box"
|
||||||
|
|
||||||
|
include Util
|
||||||
|
|
||||||
|
attr_reader :temp_path
|
||||||
|
|
||||||
|
def initialize(app, env)
|
||||||
|
@app = app
|
||||||
|
@env = env
|
||||||
|
@env["download.classes"] ||= []
|
||||||
|
@env["download.classes"] << [Downloaders::HTTP, Downloaders::File]
|
||||||
|
@env["download.classes"].flatten!
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
@env = env
|
||||||
|
|
||||||
|
return if !instantiate_downloader
|
||||||
|
download
|
||||||
|
|
||||||
|
@app.call(@env)
|
||||||
|
|
||||||
|
cleanup
|
||||||
|
end
|
||||||
|
|
||||||
|
def instantiate_downloader
|
||||||
|
@env["download.classes"].each do |klass|
|
||||||
|
if klass.match?(@env["download.uri"])
|
||||||
|
@env.logger.info "Downloading with #{klass}..."
|
||||||
|
@downloader = klass.new(@env["download.uri"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if !@downloader
|
||||||
|
@env.error!(:box_download_unknown_type)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
@downloader.prepare(@env["download.uri"])
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def download
|
||||||
|
with_tempfile do |tempfile|
|
||||||
|
download_to(tempfile)
|
||||||
|
@temp_path = @env["download.temp_path"] = tempfile.path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def cleanup
|
||||||
|
if temp_path && File.exist?(temp_path)
|
||||||
|
@env.logger.info "Cleaning up downloaded box..."
|
||||||
|
File.unlink(temp_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def with_tempfile
|
||||||
|
@env.logger.info "Creating tempfile for storing box file..."
|
||||||
|
File.open(box_temp_path, Platform.tar_file_options) do |tempfile|
|
||||||
|
yield tempfile
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def box_temp_path
|
||||||
|
File.join(@env.env.tmp_path, BASENAME + Time.now.to_i.to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
def download_to(f)
|
||||||
|
@env.logger.info "Copying box to temporary location..."
|
||||||
|
@downloader.download!(@env["download.uri"], f)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,139 @@
|
||||||
|
require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
|
||||||
|
|
||||||
|
class DownloadBoxActionTest < Test::Unit::TestCase
|
||||||
|
setup do
|
||||||
|
@klass = Vagrant::Action::Box::Download
|
||||||
|
@app, @env = mock_action_data
|
||||||
|
|
||||||
|
@vm = mock("vm")
|
||||||
|
@env["vm"] = @vm
|
||||||
|
|
||||||
|
@internal_vm = mock("internal")
|
||||||
|
@vm.stubs(:vm).returns(@internal_vm)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "initializing" do
|
||||||
|
should "initialize download classes" do
|
||||||
|
@klass.new(@app, @env)
|
||||||
|
assert_equal [Vagrant::Downloaders::HTTP, Vagrant::Downloaders::File], @env["download.classes"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with an instance" do
|
||||||
|
setup do
|
||||||
|
@instance = @klass.new(@app, @env)
|
||||||
|
@env["download.uri"] = "http://google.com"
|
||||||
|
end
|
||||||
|
|
||||||
|
context "calling" do
|
||||||
|
should "call the proper methods in sequence" do
|
||||||
|
seq = sequence("seq")
|
||||||
|
@instance.expects(:instantiate_downloader).in_sequence(seq).returns(true)
|
||||||
|
@instance.expects(:download).in_sequence(seq)
|
||||||
|
@app.expects(:call).with(@env).in_sequence(seq)
|
||||||
|
@instance.expects(:cleanup).in_sequence(seq)
|
||||||
|
@instance.call(@env)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "halt the chain if downloader instantiation fails" do
|
||||||
|
seq = sequence("seq")
|
||||||
|
@instance.expects(:instantiate_downloader).in_sequence(seq).returns(false)
|
||||||
|
@instance.expects(:download).never
|
||||||
|
@app.expects(:call).with(@env).never
|
||||||
|
@instance.expects(:cleanup).never
|
||||||
|
@instance.call(@env)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "instantiating downloader" do
|
||||||
|
should "instantiate the proper class" do
|
||||||
|
instance = mock("instance")
|
||||||
|
Vagrant::Downloaders::HTTP.expects(:new).with(@env["download.uri"]).returns(instance)
|
||||||
|
instance.expects(:prepare).with(@env["download.uri"]).once
|
||||||
|
assert @instance.instantiate_downloader
|
||||||
|
end
|
||||||
|
|
||||||
|
should "error environment if URI is invalid for any downloaders" do
|
||||||
|
@env["download.uri"] = "foobar"
|
||||||
|
assert !@instance.instantiate_downloader
|
||||||
|
assert @env.error?
|
||||||
|
assert_equal :box_download_unknown_type, @env.error.first
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "downloading" do
|
||||||
|
setup do
|
||||||
|
@path = "foo"
|
||||||
|
|
||||||
|
@tempfile = mock("tempfile")
|
||||||
|
@tempfile.stubs(:path).returns(@path)
|
||||||
|
|
||||||
|
@instance.stubs(:with_tempfile).yields(@tempfile)
|
||||||
|
@instance.stubs(:download_to)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "make a tempfile and copy the URI contents to it" do
|
||||||
|
@instance.expects(:with_tempfile).yields(@tempfile)
|
||||||
|
@instance.expects(:download_to).with(@tempfile)
|
||||||
|
@instance.download
|
||||||
|
end
|
||||||
|
|
||||||
|
should "save the tempfile path" do
|
||||||
|
@instance.download
|
||||||
|
assert @env.has_key?("download.temp_path")
|
||||||
|
assert_equal @tempfile.path, @env["download.temp_path"]
|
||||||
|
assert_equal @tempfile.path, @instance.temp_path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "tempfile" do
|
||||||
|
should "create a tempfile in the vagrant tmp directory" do
|
||||||
|
File.expects(:open).with { |name, bitmask|
|
||||||
|
name =~ /#{Vagrant::Action::Box::Download::BASENAME}/ && name =~ /#{@env.env.tmp_path}/
|
||||||
|
}.once
|
||||||
|
@instance.with_tempfile
|
||||||
|
end
|
||||||
|
|
||||||
|
should "yield the tempfile object" do
|
||||||
|
@tempfile = mock("tempfile")
|
||||||
|
File.expects(:open).yields(@tempfile)
|
||||||
|
|
||||||
|
@instance.with_tempfile do |otherfile|
|
||||||
|
assert @tempfile.equal?(otherfile)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "cleaning up" do
|
||||||
|
setup do
|
||||||
|
@temp_path = "foo"
|
||||||
|
@instance.stubs(:temp_path).returns(@temp_path)
|
||||||
|
File.stubs(:exist?).returns(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "delete the temporary file if it exists" do
|
||||||
|
File.expects(:unlink).with(@temp_path).once
|
||||||
|
@instance.cleanup
|
||||||
|
end
|
||||||
|
|
||||||
|
should "not delete anything if it doesn't exist" do
|
||||||
|
File.stubs(:exist?).returns(false)
|
||||||
|
File.expects(:unlink).never
|
||||||
|
@instance.cleanup
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "downloading to" do
|
||||||
|
setup do
|
||||||
|
@downloader = mock("downloader")
|
||||||
|
@instance.instance_variable_set(:@downloader, @downloader)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "call download! on the download with the URI and tempfile" do
|
||||||
|
tempfile = "foo"
|
||||||
|
@downloader.expects(:download!).with(@env["download.uri"], tempfile)
|
||||||
|
@instance.download_to(tempfile)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +1,6 @@
|
||||||
require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
|
require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
|
||||||
|
|
||||||
class DownloadBoxActionTest < Test::Unit::TestCase
|
class DownloadBoxActionsTest < Test::Unit::TestCase
|
||||||
setup do
|
setup do
|
||||||
@uri = "foo.com"
|
@uri = "foo.com"
|
||||||
@runner, @vm, @action = mock_action(Vagrant::Actions::Box::Download)
|
@runner, @vm, @action = mock_action(Vagrant::Actions::Box::Download)
|
||||||
|
|
Loading…
Reference in New Issue