diff options
Diffstat (limited to 'lib/chef/exceptions.rb')
-rw-r--r-- | lib/chef/exceptions.rb | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb new file mode 100644 index 0000000000..87802639d3 --- /dev/null +++ b/lib/chef/exceptions.rb @@ -0,0 +1,260 @@ +# +# Author:: Adam Jacob (<adam@opscode.com>) +# Author:: Seth Falcon (<seth@opscode.com>) +# Copyright:: Copyright 2008-2010 Opscode, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +class Chef + # == Chef::Exceptions + # Chef's custom exceptions are all contained within the Chef::Exceptions + # namespace. + class Exceptions + + # Backcompat with Chef::ShellOut code: + require 'mixlib/shellout/exceptions' + + def self.const_missing(const_name) + if const_name == :ShellCommandFailed + Chef::Log.warn("Chef::Exceptions::ShellCommandFailed is deprecated, use Mixlib::ShellOut::ShellCommandFailed") + called_from = caller[0..3].inject("Called from:\n") {|msg, trace_line| msg << " #{trace_line}\n" } + Chef::Log.warn(called_from) + Mixlib::ShellOut::ShellCommandFailed + else + super + end + end + + class Application < RuntimeError; end + class Cron < RuntimeError; end + class Env < RuntimeError; end + class Exec < RuntimeError; end + class ErlCall < RuntimeError; end + class FileNotFound < RuntimeError; end + class Package < RuntimeError; end + class Service < RuntimeError; end + class Route < RuntimeError; end + class SearchIndex < RuntimeError; end + class Override < RuntimeError; end + class UnsupportedAction < RuntimeError; end + class MissingLibrary < RuntimeError; end + class CannotDetermineNodeName < RuntimeError; end + class User < RuntimeError; end + class Group < RuntimeError; end + class Link < RuntimeError; end + class Mount < RuntimeError; end + class PrivateKeyMissing < RuntimeError; end + class CannotWritePrivateKey < RuntimeError; end + class RoleNotFound < RuntimeError; end + class ValidationFailed < ArgumentError; end + class InvalidPrivateKey < ArgumentError; end + class ConfigurationError < ArgumentError; end + class RedirectLimitExceeded < RuntimeError; end + class AmbiguousRunlistSpecification < ArgumentError; end + class CookbookFrozen < ArgumentError; end + class CookbookNotFound < RuntimeError; end + # Cookbook loader used to raise an argument error when cookbook not found. + # for back compat, need to raise an error that inherits from ArgumentError + class CookbookNotFoundInRepo < ArgumentError; end + class RecipeNotFound < ArgumentError; end + class AttributeNotFound < RuntimeError; end + class InvalidCommandOption < RuntimeError; end + class CommandTimeout < RuntimeError; end + class RequestedUIDUnavailable < RuntimeError; end + class InvalidHomeDirectory < ArgumentError; end + class DsclCommandFailed < RuntimeError; end + class UserIDNotFound < ArgumentError; end + class GroupIDNotFound < ArgumentError; end + class InvalidResourceReference < RuntimeError; end + class ResourceNotFound < RuntimeError; end + class InvalidResourceSpecification < ArgumentError; end + class SolrConnectionError < RuntimeError; end + class IllegalChecksumRevert < RuntimeError; end + class CookbookVersionNameMismatch < ArgumentError; end + class MissingParentDirectory < RuntimeError; end + class UnresolvableGitReference < RuntimeError; end + class InvalidRemoteGitReference < RuntimeError; end + class InvalidEnvironmentRunListSpecification < ArgumentError; end + class InvalidDataBagItemID < ArgumentError; end + class InvalidDataBagName < ArgumentError; end + class EnclosingDirectoryDoesNotExist < ArgumentError; end + # Errors originating from calls to the Win32 API + class Win32APIError < RuntimeError; end + # Thrown when Win32 API layer binds to non-existent Win32 function. Occurs + # when older versions of Windows don't support newer Win32 API functions. + class Win32APIFunctionNotImplemented < NotImplementedError; end + + class ObsoleteDependencySyntax < ArgumentError; end + class InvalidDataBagPath < ArgumentError; end + + # A different version of a cookbook was added to a + # VersionedRecipeList than the one already there. + class CookbookVersionConflict < ArgumentError ; end + + # does not follow X.Y.Z format. ArgumentError? + class InvalidCookbookVersion < ArgumentError; end + + # version constraint should be a string or array, or it doesn't + # match OP VERSION. ArgumentError? + class InvalidVersionConstraint < ArgumentError; end + + # File operation attempted but no permissions to perform it + class InsufficientPermissions < RuntimeError; end + + # Ifconfig failed + class Ifconfig < RuntimeError; end + + # Invalid "source" parameter to a remote_file resource + class InvalidRemoteFileURI < ArgumentError; end + + # Node::Attribute computes the merged version of of attributes + # and makes it read-only. Attempting to modify a read-only + # attribute will cause this error. + class ImmutableAttributeModification < NoMethodError; end + + # Merged node attributes are invalidated when the component + # attributes are updated. Attempting to read from a stale copy + # of merged attributes will trigger this error. + class StaleAttributeRead < StandardError; end + + class MissingRole < RuntimeError + NULL = Object.new + + attr_reader :expansion + + def initialize(message_or_expansion=NULL) + @expansion = nil + case message_or_expansion + when NULL + super() + when String + super + when RunList::RunListExpansion + @expansion = message_or_expansion + missing_roles = @expansion.errors.join(', ') + super("The expanded run list includes nonexistent roles: #{missing_roles}") + end + end + + + end + # Exception class for collecting multiple failures. Used when running + # delayed notifications so that chef can process each delayed + # notification even if chef client or other notifications fail. + class MultipleFailures < StandardError + def initialize(*args) + super + @all_failures = [] + end + + def message + base = "Multiple failures occurred:\n" + @all_failures.inject(base) do |message, (location, error)| + message << "* #{error.class} occurred in #{location}: #{error.message}\n" + end + end + + def client_run_failure(exception) + set_backtrace(exception.backtrace) + @all_failures << [ "chef run", exception ] + end + + def notification_failure(exception) + @all_failures << [ "delayed notification", exception ] + end + + def raise! + unless empty? + raise self.for_raise + end + end + + def empty? + @all_failures.empty? + end + + def for_raise + if @all_failures.size == 1 + @all_failures[0][1] + else + self + end + end + end + + class CookbookVersionSelection + + # Compound exception: In run_list expansion and resolution, + # run_list items referred to cookbooks that don't exist and/or + # have no versions available. + class InvalidRunListItems < StandardError + attr_reader :non_existent_cookbooks + attr_reader :cookbooks_with_no_matching_versions + + def initialize(message, non_existent_cookbooks, cookbooks_with_no_matching_versions) + super(message) + + @non_existent_cookbooks = non_existent_cookbooks + @cookbooks_with_no_matching_versions = cookbooks_with_no_matching_versions + end + + def to_json(*a) + result = { + "message" => message, + "non_existent_cookbooks" => non_existent_cookbooks, + "cookbooks_with_no_versions" => cookbooks_with_no_matching_versions + } + result.to_json(*a) + end + end + + # In run_list expansion and resolution, a constraint was + # unsatisfiable. + # + # This exception may not be the complete error report. If you + # resolve the misconfiguration represented by this exception and + # re-solve, you may get another exception + class UnsatisfiableRunListItem < StandardError + attr_reader :run_list_item + attr_reader :non_existent_cookbooks, :most_constrained_cookbooks + + # most_constrained_cookbooks: if I were to remove constraints + # regarding these cookbooks, I would get a solution or move on + # to the next error (deeper in the graph). An item in this list + # may be unsatisfiable, but when resolved may also reveal + # further unsatisfiable constraints; this condition would not be + # reported. + def initialize(message, run_list_item, non_existent_cookbooks, most_constrained_cookbooks) + super(message) + + @run_list_item = run_list_item + @non_existent_cookbooks = non_existent_cookbooks + @most_constrained_cookbooks = most_constrained_cookbooks + end + + def to_json(*a) + result = { + "message" => message, + "unsatisfiable_run_list_item" => run_list_item, + "non_existent_cookbooks" => non_existent_cookbooks, + "most_constrained_cookbooks" => most_constrained_cookbooks + } + result.to_json(*a) + end + end + + end # CookbookVersionSelection + + end +end |