Begin moving from error_and_exit to exceptions. Fail hard!
This commit is contained in:
parent
354a82a177
commit
ccc45ebd7a
|
@ -10,5 +10,6 @@ rescue Vagrant::Errors::VagrantError => e
|
||||||
opts = { :_translate => false, :_prefix => false }
|
opts = { :_translate => false, :_prefix => false }
|
||||||
env.ui.error e.message, opts
|
env.ui.error e.message, opts
|
||||||
env.ui.error e.backtrace.join("\n"), opts if ENV["VAGRANT_DEBUG"]
|
env.ui.error e.backtrace.join("\n"), opts if ENV["VAGRANT_DEBUG"]
|
||||||
exit e.status_code
|
exit e.status_code if e.respond_to?(:status_code)
|
||||||
|
exit 999 # An error occurred with no status code defined
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,8 +20,6 @@ module Vagrant
|
||||||
@env = env
|
@env = env
|
||||||
|
|
||||||
download if instantiate_downloader
|
download if instantiate_downloader
|
||||||
return if env.error?
|
|
||||||
|
|
||||||
@app.call(@env)
|
@app.call(@env)
|
||||||
|
|
||||||
recover(env) # called in both cases to cleanup workspace
|
recover(env) # called in both cases to cleanup workspace
|
||||||
|
@ -35,10 +33,7 @@ module Vagrant
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if !@downloader
|
raise Errors::BoxDownloadUnknownType.new if !@downloader
|
||||||
@env.error!(:box_download_unknown_type)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
@downloader.prepare(@env["box"].uri)
|
@downloader.prepare(@env["box"].uri)
|
||||||
true
|
true
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
module Vagrant
|
module Vagrant
|
||||||
class Action
|
class Action
|
||||||
|
# The action warden is a middleware which injects itself between
|
||||||
|
# every other middleware, watching for exceptions which are raised
|
||||||
|
# and performing proper cleanup on every action by calling the {#recover}
|
||||||
|
# method. The warden therefore allows middlewares to not worry about
|
||||||
|
# exceptional events, and by providing a simple callback, can clean up
|
||||||
|
# in any erroneous case.
|
||||||
class Warden
|
class Warden
|
||||||
include Util
|
include Util
|
||||||
attr_accessor :actions, :stack
|
attr_accessor :actions, :stack
|
||||||
|
@ -12,11 +18,16 @@ module Vagrant
|
||||||
def call(env)
|
def call(env)
|
||||||
return if @actions.empty?
|
return if @actions.empty?
|
||||||
|
|
||||||
# If the previous action passes and environment error on
|
begin
|
||||||
@stack.unshift(@actions.shift).first.call(env) unless env.error?
|
# Call the next middleware in the sequence, appending to the stack
|
||||||
|
# of "recoverable" middlewares in case something goes wrong!
|
||||||
# if the call action returned prematurely with an error
|
@stack.unshift(@actions.shift).first.call(env)
|
||||||
begin_rescue(env) if env.error?
|
rescue
|
||||||
|
# Something went horribly wrong. Start the rescue chain then
|
||||||
|
# reraise the exception to properly kick us out of limbo here.
|
||||||
|
begin_rescue(env)
|
||||||
|
raise
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def begin_rescue(env)
|
def begin_rescue(env)
|
||||||
|
@ -25,9 +36,6 @@ module Vagrant
|
||||||
end
|
end
|
||||||
|
|
||||||
exit if env.interrupted?
|
exit if env.interrupted?
|
||||||
|
|
||||||
# Erroneous environment resulted. Properly display error message.
|
|
||||||
error_and_exit(*env.error)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def finalize_action(action, env)
|
def finalize_action(action, env)
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
# This file contains all of the internal errors in Vagrant's core
|
||||||
|
# commands, actions, etc.
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module Errors
|
module Errors
|
||||||
# Main superclass of any errors in Vagrant. This provides some
|
# Main superclass of any errors in Vagrant. This provides some
|
||||||
|
@ -6,12 +9,15 @@ module Vagrant
|
||||||
# error code, and the error key is used as a default message from
|
# error code, and the error key is used as a default message from
|
||||||
# I18n.
|
# I18n.
|
||||||
class VagrantError < StandardError
|
class VagrantError < StandardError
|
||||||
|
DEFAULT_NAMESPACE = "vagrant.errors"
|
||||||
|
|
||||||
def self.status_code(code = nil)
|
def self.status_code(code = nil)
|
||||||
define_method(:status_code) { code }
|
define_method(:status_code) { code }
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.error_key(key=nil)
|
def self.error_key(key=nil, namespace=nil)
|
||||||
define_method(:error_key) { key }
|
define_method(:error_key) { key }
|
||||||
|
define_method(:error_namespace) { namespace } if namespace
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(message=nil, *args)
|
def initialize(message=nil, *args)
|
||||||
|
@ -22,7 +28,8 @@ module Vagrant
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def translate_error(key, opts=nil)
|
def translate_error(key, opts=nil)
|
||||||
I18n.t("vagrant.errors.#{key}", opts)
|
namespace = respond_to?(:error_namespace) ? error_namespace : DEFAULT_NAMESPACE
|
||||||
|
I18n.t("#{namespace}.#{key}", opts)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -31,6 +38,11 @@ module Vagrant
|
||||||
error_key(:base_vm_not_found)
|
error_key(:base_vm_not_found)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class BoxDownloadUnknownType < VagrantError
|
||||||
|
status_code(13)
|
||||||
|
error_key(:unknown_type, "vagrant.actions.box.download")
|
||||||
|
end
|
||||||
|
|
||||||
class BoxNotFound < VagrantError
|
class BoxNotFound < VagrantError
|
||||||
status_code(2)
|
status_code(2)
|
||||||
error_key(:box_not_found)
|
error_key(:box_not_found)
|
||||||
|
|
|
@ -173,15 +173,16 @@ en:
|
||||||
|
|
||||||
box:
|
box:
|
||||||
destroy:
|
destroy:
|
||||||
destroying: Deleting box '%{name}'...
|
destroying: "Deleting box '%{name}'..."
|
||||||
download:
|
download:
|
||||||
with: Downloading with %{class}...
|
with: "Downloading with %{class}..."
|
||||||
cleaning: Cleaning up downloaded box...
|
cleaning: "Cleaning up downloaded box..."
|
||||||
copying: Copying box to temporary location...
|
copying: "Copying box to temporary location..."
|
||||||
|
unknown_type: "Unknown or unsupported URI type given for box download."
|
||||||
unpackage:
|
unpackage:
|
||||||
extracting: Extracting box...
|
extracting: "Extracting box..."
|
||||||
verify:
|
verify:
|
||||||
verifying: Verifying box...
|
verifying: "Verifying box..."
|
||||||
|
|
||||||
general:
|
general:
|
||||||
package:
|
package:
|
||||||
|
|
|
@ -10,8 +10,6 @@
|
||||||
:box_already_exists: |-
|
:box_already_exists: |-
|
||||||
This box appears to already exist! Please call `vagrant box remove <%= box_name %>`
|
This box appears to already exist! Please call `vagrant box remove <%= box_name %>`
|
||||||
and then try to add it again.
|
and then try to add it again.
|
||||||
:box_download_unknown_type: |-
|
|
||||||
Unknown URI type for box download.
|
|
||||||
:box_download_http_socket_error: |-
|
:box_download_http_socket_error: |-
|
||||||
An error occurred while trying to download the specified box. This most
|
An error occurred while trying to download the specified box. This most
|
||||||
often happens if there is no internet connection or the address is
|
often happens if there is no internet connection or the address is
|
||||||
|
|
|
@ -35,15 +35,6 @@ class DownloadBoxActionTest < Test::Unit::TestCase
|
||||||
@instance.expects(:recover).with(@env).in_sequence(seq)
|
@instance.expects(:recover).with(@env).in_sequence(seq)
|
||||||
@instance.call(@env)
|
@instance.call(@env)
|
||||||
end
|
end
|
||||||
|
|
||||||
should "halt the chain if downloader instantiation fails" do
|
|
||||||
seq = sequence("seq")
|
|
||||||
@env.error!(:foo)
|
|
||||||
@instance.expects(:instantiate_downloader).in_sequence(seq).returns(false)
|
|
||||||
@instance.expects(:download).never
|
|
||||||
@app.expects(:call).with(@env).never
|
|
||||||
@instance.call(@env)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context "instantiating downloader" do
|
context "instantiating downloader" do
|
||||||
|
@ -56,9 +47,9 @@ class DownloadBoxActionTest < Test::Unit::TestCase
|
||||||
|
|
||||||
should "error environment if URI is invalid for any downloaders" do
|
should "error environment if URI is invalid for any downloaders" do
|
||||||
@env["box"].uri = "foobar"
|
@env["box"].uri = "foobar"
|
||||||
assert !@instance.instantiate_downloader
|
assert_raises(Vagrant::Errors::BoxDownloadUnknownType) {
|
||||||
assert @env.error?
|
@instance.instantiate_downloader
|
||||||
assert_equal :box_download_unknown_type, @env.error.first
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -55,32 +55,17 @@ class ActionWardenTest < Test::Unit::TestCase
|
||||||
@instance.call(new_env)
|
@instance.call(new_env)
|
||||||
end
|
end
|
||||||
|
|
||||||
should "begin recover on environment error" do
|
should "begin recovery sequence when the called action raises an exception" do
|
||||||
@instance.expects(:begin_rescue)
|
|
||||||
@instance.actions << lambda {}
|
|
||||||
@instance.actions.first.expects(:call).never
|
|
||||||
@instance.call(new_env_with_error)
|
|
||||||
end
|
|
||||||
|
|
||||||
should "not call the next action on env err" do
|
|
||||||
action = mock('action')
|
|
||||||
action.expects(:call).never
|
|
||||||
@instance.actions << action
|
|
||||||
@instance.expects(:begin_rescue)
|
|
||||||
@instance.call(new_env_with_error)
|
|
||||||
end
|
|
||||||
|
|
||||||
should "call begin recover when the called action returns with an env error" do
|
|
||||||
class Foo
|
class Foo
|
||||||
def initialize(*args); end
|
def initialize(*args); end
|
||||||
def call(env)
|
def call(env)
|
||||||
return env.error!(:foo)
|
raise "An exception"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@instance.actions << Foo.new
|
@instance.actions << Foo.new
|
||||||
@instance.expects(:begin_rescue)
|
@instance.expects(:begin_rescue)
|
||||||
@instance.call(new_env)
|
assert_raises(RuntimeError) { @instance.call(new_env) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_env_with_error
|
def new_env_with_error
|
||||||
|
|
Loading…
Reference in New Issue