1# Copyright (c) 2012-2013 Mitch Garnaat http://garnaat.org/ 2# Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3# 4# Licensed under the Apache License, Version 2.0 (the "License"). You 5# may not use this file except in compliance with the License. A copy of 6# the License is located at 7# 8# http://aws.amazon.com/apache2.0/ 9# 10# or in the "license" file accompanying this file. This file is 11# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 12# ANY KIND, either express or implied. See the License for the specific 13# language governing permissions and limitations under the License. 14from __future__ import unicode_literals 15from botocore.vendored import requests 16from botocore.vendored.requests.packages import urllib3 17 18 19def _exception_from_packed_args(exception_cls, args=None, kwargs=None): 20 # This is helpful for reducing Exceptions that only accept kwargs as 21 # only positional arguments can be provided for __reduce__ 22 # Ideally, this would also be a class method on the BotoCoreError 23 # but instance methods cannot be pickled. 24 if args is None: 25 args = () 26 if kwargs is None: 27 kwargs = {} 28 return exception_cls(*args, **kwargs) 29 30 31class BotoCoreError(Exception): 32 """ 33 The base exception class for BotoCore exceptions. 34 35 :ivar msg: The descriptive message associated with the error. 36 """ 37 fmt = 'An unspecified error occurred' 38 39 def __init__(self, **kwargs): 40 msg = self.fmt.format(**kwargs) 41 Exception.__init__(self, msg) 42 self.kwargs = kwargs 43 44 def __reduce__(self): 45 return _exception_from_packed_args, (self.__class__, None, self.kwargs) 46 47 48class DataNotFoundError(BotoCoreError): 49 """ 50 The data associated with a particular path could not be loaded. 51 52 :ivar data_path: The data path that the user attempted to load. 53 """ 54 fmt = 'Unable to load data for: {data_path}' 55 56 57class UnknownServiceError(DataNotFoundError): 58 """Raised when trying to load data for an unknown service. 59 60 :ivar service_name: The name of the unknown service. 61 62 """ 63 fmt = ( 64 "Unknown service: '{service_name}'. Valid service names are: " 65 "{known_service_names}") 66 67 68class ApiVersionNotFoundError(BotoCoreError): 69 """ 70 The data associated with either the API version or a compatible one 71 could not be loaded. 72 73 :ivar data_path: The data path that the user attempted to load. 74 :ivar api_version: The API version that the user attempted to load. 75 """ 76 fmt = 'Unable to load data {data_path} for: {api_version}' 77 78 79class HTTPClientError(BotoCoreError): 80 fmt = 'An HTTP Client raised an unhandled exception: {error}' 81 82 def __init__(self, request=None, response=None, **kwargs): 83 self.request = request 84 self.response = response 85 super(HTTPClientError, self).__init__(**kwargs) 86 87 def __reduce__(self): 88 return _exception_from_packed_args, ( 89 self.__class__, (self.request, self.response), self.kwargs) 90 91 92class ConnectionError(BotoCoreError): 93 fmt = 'An HTTP Client failed to establish a connection: {error}' 94 95 96class InvalidIMDSEndpointError(BotoCoreError): 97 fmt = 'Invalid endpoint EC2 Instance Metadata endpoint: {endpoint}' 98 99 100class InvalidIMDSEndpointModeError(BotoCoreError): 101 fmt = ( 102 'Invalid EC2 Instance Metadata endpoint mode: {mode}' 103 ' Valid endpoint modes (case-insensitive): {valid_modes}.' 104 ) 105 106 107class EndpointConnectionError(ConnectionError): 108 fmt = 'Could not connect to the endpoint URL: "{endpoint_url}"' 109 110 111class SSLError(ConnectionError, requests.exceptions.SSLError): 112 fmt = 'SSL validation failed for {endpoint_url} {error}' 113 114 115class ConnectionClosedError(HTTPClientError): 116 fmt = ( 117 'Connection was closed before we received a valid response ' 118 'from endpoint URL: "{endpoint_url}".') 119 120 121class ReadTimeoutError(HTTPClientError, requests.exceptions.ReadTimeout, 122 urllib3.exceptions.ReadTimeoutError): 123 fmt = 'Read timeout on endpoint URL: "{endpoint_url}"' 124 125 126class ConnectTimeoutError(ConnectionError, requests.exceptions.ConnectTimeout): 127 fmt = 'Connect timeout on endpoint URL: "{endpoint_url}"' 128 129 130class ProxyConnectionError(ConnectionError, requests.exceptions.ProxyError): 131 fmt = 'Failed to connect to proxy URL: "{proxy_url}"' 132 133 134class NoCredentialsError(BotoCoreError): 135 """ 136 No credentials could be found. 137 """ 138 fmt = 'Unable to locate credentials' 139 140 141class PartialCredentialsError(BotoCoreError): 142 """ 143 Only partial credentials were found. 144 145 :ivar cred_var: The missing credential variable name. 146 147 """ 148 fmt = 'Partial credentials found in {provider}, missing: {cred_var}' 149 150 151class CredentialRetrievalError(BotoCoreError): 152 """ 153 Error attempting to retrieve credentials from a remote source. 154 155 :ivar provider: The name of the credential provider. 156 :ivar error_msg: The msg explaining why credentials could not be 157 retrieved. 158 159 """ 160 fmt = 'Error when retrieving credentials from {provider}: {error_msg}' 161 162 163class UnknownSignatureVersionError(BotoCoreError): 164 """ 165 Requested Signature Version is not known. 166 167 :ivar signature_version: The name of the requested signature version. 168 """ 169 fmt = 'Unknown Signature Version: {signature_version}.' 170 171 172class ServiceNotInRegionError(BotoCoreError): 173 """ 174 The service is not available in requested region. 175 176 :ivar service_name: The name of the service. 177 :ivar region_name: The name of the region. 178 """ 179 fmt = 'Service {service_name} not available in region {region_name}' 180 181 182class BaseEndpointResolverError(BotoCoreError): 183 """Base error for endpoint resolving errors. 184 185 Should never be raised directly, but clients can catch 186 this exception if they want to generically handle any errors 187 during the endpoint resolution process. 188 189 """ 190 191 192class NoRegionError(BaseEndpointResolverError): 193 """No region was specified.""" 194 fmt = 'You must specify a region.' 195 196 197class UnknownEndpointError(BaseEndpointResolverError, ValueError): 198 """ 199 Could not construct an endpoint. 200 201 :ivar service_name: The name of the service. 202 :ivar region_name: The name of the region. 203 """ 204 fmt = ( 205 'Unable to construct an endpoint for ' 206 '{service_name} in region {region_name}') 207 208 209class UnknownFIPSEndpointError(BaseEndpointResolverError): 210 """ 211 Could not construct a FIPS endpoint. 212 213 :ivar service_name: The name of the service. 214 :ivar region_name: The name of the region. 215 """ 216 fmt = ( 217 'The provided FIPS pseudo-region "{region_name}" is not known for ' 218 'the service "{service_name}". A FIPS compliant endpoint cannot be ' 219 'constructed.' 220 ) 221 222 223class ProfileNotFound(BotoCoreError): 224 """ 225 The specified configuration profile was not found in the 226 configuration file. 227 228 :ivar profile: The name of the profile the user attempted to load. 229 """ 230 fmt = 'The config profile ({profile}) could not be found' 231 232 233class ConfigParseError(BotoCoreError): 234 """ 235 The configuration file could not be parsed. 236 237 :ivar path: The path to the configuration file. 238 """ 239 fmt = 'Unable to parse config file: {path}' 240 241 242class ConfigNotFound(BotoCoreError): 243 """ 244 The specified configuration file could not be found. 245 246 :ivar path: The path to the configuration file. 247 """ 248 fmt = 'The specified config file ({path}) could not be found.' 249 250 251class MissingParametersError(BotoCoreError): 252 """ 253 One or more required parameters were not supplied. 254 255 :ivar object: The object that has missing parameters. 256 This can be an operation or a parameter (in the 257 case of inner params). The str() of this object 258 will be used so it doesn't need to implement anything 259 other than str(). 260 :ivar missing: The names of the missing parameters. 261 """ 262 fmt = ('The following required parameters are missing for ' 263 '{object_name}: {missing}') 264 265 266class ValidationError(BotoCoreError): 267 """ 268 An exception occurred validating parameters. 269 270 Subclasses must accept a ``value`` and ``param`` 271 argument in their ``__init__``. 272 273 :ivar value: The value that was being validated. 274 :ivar param: The parameter that failed validation. 275 :ivar type_name: The name of the underlying type. 276 """ 277 fmt = ("Invalid value ('{value}') for param {param} " 278 "of type {type_name} ") 279 280 281class ParamValidationError(BotoCoreError): 282 fmt = 'Parameter validation failed:\n{report}' 283 284 285# These exceptions subclass from ValidationError so that code 286# can just 'except ValidationError' to catch any possibly validation 287# error. 288class UnknownKeyError(ValidationError): 289 """ 290 Unknown key in a struct parameter. 291 292 :ivar value: The value that was being checked. 293 :ivar param: The name of the parameter. 294 :ivar choices: The valid choices the value can be. 295 """ 296 fmt = ("Unknown key '{value}' for param '{param}'. Must be one " 297 "of: {choices}") 298 299 300class RangeError(ValidationError): 301 """ 302 A parameter value was out of the valid range. 303 304 :ivar value: The value that was being checked. 305 :ivar param: The parameter that failed validation. 306 :ivar min_value: The specified minimum value. 307 :ivar max_value: The specified maximum value. 308 """ 309 fmt = ('Value out of range for param {param}: ' 310 '{min_value} <= {value} <= {max_value}') 311 312 313class UnknownParameterError(ValidationError): 314 """ 315 Unknown top level parameter. 316 317 :ivar name: The name of the unknown parameter. 318 :ivar operation: The name of the operation. 319 :ivar choices: The valid choices the parameter name can be. 320 """ 321 fmt = ( 322 "Unknown parameter '{name}' for operation {operation}. Must be one " 323 "of: {choices}" 324 ) 325 326 327class InvalidRegionError(ValidationError, ValueError): 328 """ 329 Invalid region_name provided to client or resource. 330 331 :ivar region_name: region_name that was being validated. 332 """ 333 fmt = ( 334 "Provided region_name '{region_name}' doesn't match a supported format." 335 ) 336 337 338class AliasConflictParameterError(ValidationError): 339 """ 340 Error when an alias is provided for a parameter as well as the original. 341 342 :ivar original: The name of the original parameter. 343 :ivar alias: The name of the alias 344 :ivar operation: The name of the operation. 345 """ 346 fmt = ( 347 "Parameter '{original}' and its alias '{alias}' were provided " 348 "for operation {operation}. Only one of them may be used." 349 ) 350 351 352class UnknownServiceStyle(BotoCoreError): 353 """ 354 Unknown style of service invocation. 355 356 :ivar service_style: The style requested. 357 """ 358 fmt = 'The service style ({service_style}) is not understood.' 359 360 361class PaginationError(BotoCoreError): 362 fmt = 'Error during pagination: {message}' 363 364 365class OperationNotPageableError(BotoCoreError): 366 fmt = 'Operation cannot be paginated: {operation_name}' 367 368 369class ChecksumError(BotoCoreError): 370 """The expected checksum did not match the calculated checksum. 371 372 """ 373 fmt = ('Checksum {checksum_type} failed, expected checksum ' 374 '{expected_checksum} did not match calculated checksum ' 375 '{actual_checksum}.') 376 377 378class UnseekableStreamError(BotoCoreError): 379 """Need to seek a stream, but stream does not support seeking. 380 381 """ 382 fmt = ('Need to rewind the stream {stream_object}, but stream ' 383 'is not seekable.') 384 385 386class WaiterError(BotoCoreError): 387 """Waiter failed to reach desired state.""" 388 fmt = 'Waiter {name} failed: {reason}' 389 390 def __init__(self, name, reason, last_response): 391 super(WaiterError, self).__init__(name=name, reason=reason) 392 self.last_response = last_response 393 394 395class IncompleteReadError(BotoCoreError): 396 """HTTP response did not return expected number of bytes.""" 397 fmt = ('{actual_bytes} read, but total bytes ' 398 'expected is {expected_bytes}.') 399 400 401class InvalidExpressionError(BotoCoreError): 402 """Expression is either invalid or too complex.""" 403 fmt = 'Invalid expression {expression}: Only dotted lookups are supported.' 404 405 406class UnknownCredentialError(BotoCoreError): 407 """Tried to insert before/after an unregistered credential type.""" 408 fmt = 'Credential named {name} not found.' 409 410 411class WaiterConfigError(BotoCoreError): 412 """Error when processing waiter configuration.""" 413 fmt = 'Error processing waiter config: {error_msg}' 414 415 416class UnknownClientMethodError(BotoCoreError): 417 """Error when trying to access a method on a client that does not exist.""" 418 fmt = 'Client does not have method: {method_name}' 419 420 421class UnsupportedSignatureVersionError(BotoCoreError): 422 """Error when trying to use an unsupported Signature Version.""" 423 fmt = 'Signature version is not supported: {signature_version}' 424 425 426class ClientError(Exception): 427 MSG_TEMPLATE = ( 428 'An error occurred ({error_code}) when calling the {operation_name} ' 429 'operation{retry_info}: {error_message}') 430 431 def __init__(self, error_response, operation_name): 432 retry_info = self._get_retry_info(error_response) 433 error = error_response.get('Error', {}) 434 msg = self.MSG_TEMPLATE.format( 435 error_code=error.get('Code', 'Unknown'), 436 error_message=error.get('Message', 'Unknown'), 437 operation_name=operation_name, 438 retry_info=retry_info, 439 ) 440 super(ClientError, self).__init__(msg) 441 self.response = error_response 442 self.operation_name = operation_name 443 444 def _get_retry_info(self, response): 445 retry_info = '' 446 if 'ResponseMetadata' in response: 447 metadata = response['ResponseMetadata'] 448 if metadata.get('MaxAttemptsReached', False): 449 if 'RetryAttempts' in metadata: 450 retry_info = (' (reached max retries: %s)' % 451 metadata['RetryAttempts']) 452 return retry_info 453 454 def __reduce__(self): 455 # Subclasses of ClientError's are dynamically generated and 456 # cannot be pickled unless they are attributes of a 457 # module. So at the very least return a ClientError back. 458 return ClientError, (self.response, self.operation_name) 459 460 461class EventStreamError(ClientError): 462 pass 463 464 465class UnsupportedTLSVersionWarning(Warning): 466 """Warn when an openssl version that uses TLS 1.2 is required""" 467 pass 468 469 470class ImminentRemovalWarning(Warning): 471 pass 472 473 474class InvalidDNSNameError(BotoCoreError): 475 """Error when virtual host path is forced on a non-DNS compatible bucket""" 476 fmt = ( 477 'Bucket named {bucket_name} is not DNS compatible. Virtual ' 478 'hosted-style addressing cannot be used. The addressing style ' 479 'can be configured by removing the addressing_style value ' 480 'or setting that value to \'path\' or \'auto\' in the AWS Config ' 481 'file or in the botocore.client.Config object.' 482 ) 483 484 485class InvalidS3AddressingStyleError(BotoCoreError): 486 """Error when an invalid path style is specified""" 487 fmt = ( 488 'S3 addressing style {s3_addressing_style} is invalid. Valid options ' 489 'are: \'auto\', \'virtual\', and \'path\'' 490 ) 491 492 493class UnsupportedS3ArnError(BotoCoreError): 494 """Error when S3 ARN provided to Bucket parameter is not supported""" 495 fmt = ( 496 'S3 ARN {arn} provided to "Bucket" parameter is invalid. Only ' 497 'ARNs for S3 access-points are supported.' 498 ) 499 500 501class UnsupportedS3ControlArnError(BotoCoreError): 502 """Error when S3 ARN provided to S3 control parameter is not supported""" 503 fmt = ( 504 'S3 ARN "{arn}" provided is invalid for this operation. {msg}' 505 ) 506 507 508class InvalidHostLabelError(BotoCoreError): 509 """Error when an invalid host label would be bound to an endpoint""" 510 fmt = ( 511 'Invalid host label to be bound to the hostname of the endpoint: ' 512 '"{label}".' 513 ) 514 515 516class UnsupportedOutpostResourceError(BotoCoreError): 517 """Error when S3 Outpost ARN provided to Bucket parameter is incomplete""" 518 fmt = ( 519 'S3 Outpost ARN resource "{resource_name}" provided to "Bucket" ' 520 'parameter is invalid. Only ARNs for S3 Outpost arns with an ' 521 'access-point sub-resource are supported.' 522 ) 523 524 525class UnsupportedS3ConfigurationError(BotoCoreError): 526 """Error when an unsupported configuration is used with access-points""" 527 fmt = ( 528 'Unsupported configuration when using S3: {msg}' 529 ) 530 531 532class UnsupportedS3AccesspointConfigurationError(BotoCoreError): 533 """Error when an unsupported configuration is used with access-points""" 534 fmt = ( 535 'Unsupported configuration when using S3 access-points: {msg}' 536 ) 537 538 539class InvalidEndpointDiscoveryConfigurationError(BotoCoreError): 540 """Error when invalid value supplied for endpoint_discovery_enabled""" 541 fmt = ( 542 'Unsupported configuration value for endpoint_discovery_enabled. ' 543 'Expected one of ("true", "false", "auto") but got {config_value}.' 544 ) 545 546 547class UnsupportedS3ControlConfigurationError(BotoCoreError): 548 """Error when an unsupported configuration is used with S3 Control""" 549 fmt = ( 550 'Unsupported configuration when using S3 Control: {msg}' 551 ) 552 553 554class InvalidRetryConfigurationError(BotoCoreError): 555 """Error when invalid retry configuration is specified""" 556 fmt = ( 557 'Cannot provide retry configuration for "{retry_config_option}". ' 558 'Valid retry configuration options are: \'max_attempts\'' 559 ) 560 561 562class InvalidMaxRetryAttemptsError(InvalidRetryConfigurationError): 563 """Error when invalid retry configuration is specified""" 564 fmt = ( 565 'Value provided to "max_attempts": {provided_max_attempts} must ' 566 'be an integer greater than or equal to {min_value}.' 567 ) 568 569 570class InvalidRetryModeError(InvalidRetryConfigurationError): 571 """Error when invalid retry mode configuration is specified""" 572 fmt = ( 573 'Invalid value provided to "mode": "{provided_retry_mode}" must ' 574 'be one of: "legacy", "standard", "adaptive"' 575 ) 576 577 578class InvalidS3UsEast1RegionalEndpointConfigError(BotoCoreError): 579 """Error for invalid s3 us-east-1 regional endpoints configuration""" 580 fmt = ( 581 'S3 us-east-1 regional endpoint option ' 582 '{s3_us_east_1_regional_endpoint_config} is ' 583 'invalid. Valid options are: "legacy", "regional"' 584 ) 585 586 587class InvalidSTSRegionalEndpointsConfigError(BotoCoreError): 588 """Error when invalid sts regional endpoints configuration is specified""" 589 fmt = ( 590 'STS regional endpoints option {sts_regional_endpoints_config} is ' 591 'invalid. Valid options are: "legacy", "regional"' 592 ) 593 594 595class StubResponseError(BotoCoreError): 596 fmt = 'Error getting response stub for operation {operation_name}: {reason}' 597 598 599class StubAssertionError(StubResponseError, AssertionError): 600 pass 601 602 603class UnStubbedResponseError(StubResponseError): 604 pass 605 606 607class InvalidConfigError(BotoCoreError): 608 fmt = '{error_msg}' 609 610 611class InfiniteLoopConfigError(InvalidConfigError): 612 fmt = ( 613 'Infinite loop in credential configuration detected. Attempting to ' 614 'load from profile {source_profile} which has already been visited. ' 615 'Visited profiles: {visited_profiles}' 616 ) 617 618 619class RefreshWithMFAUnsupportedError(BotoCoreError): 620 fmt = 'Cannot refresh credentials: MFA token required.' 621 622 623class MD5UnavailableError(BotoCoreError): 624 fmt = "This system does not support MD5 generation." 625 626 627class MissingDependencyException(BotoCoreError): 628 fmt = "Missing Dependency: {msg}" 629 630 631class MetadataRetrievalError(BotoCoreError): 632 fmt = "Error retrieving metadata: {error_msg}" 633 634 635class UndefinedModelAttributeError(Exception): 636 pass 637 638 639class MissingServiceIdError(UndefinedModelAttributeError): 640 fmt = ( 641 "The model being used for the service {service_name} is missing the " 642 "serviceId metadata property, which is required." 643 ) 644 645 def __init__(self, **kwargs): 646 msg = self.fmt.format(**kwargs) 647 Exception.__init__(self, msg) 648 self.kwargs = kwargs 649 650 651class SSOError(BotoCoreError): 652 fmt = "An unspecified error happened when resolving SSO credentials" 653 654 655class SSOTokenLoadError(SSOError): 656 fmt = "Error loading SSO Token: {error_msg}" 657 658 659class UnauthorizedSSOTokenError(SSOError): 660 fmt = ( 661 "The SSO session associated with this profile has expired or is " 662 "otherwise invalid. To refresh this SSO session run aws sso login " 663 "with the corresponding profile." 664 ) 665 666 667class CapacityNotAvailableError(BotoCoreError): 668 fmt = ( 669 'Insufficient request capacity available.' 670 ) 671 672 673class InvalidProxiesConfigError(BotoCoreError): 674 fmt = ( 675 'Invalid configuration value(s) provided for proxies_config.' 676 ) 677