def rmtree(self): """ Removes a resource and all of its contents. The path should point to a directory. If the specified resource is an object, nothing will happen. """ # Ensure there is a trailing slash (path is a dir) delete_path = utils.with_trailing_slash(self) delete_list = delete_path.list() while len(delete_list) > 0: # boto3 only allows deletion of up to 1000 objects at a time len_range = min(len(delete_list), 1000) objects = { 'Objects': [{ 'Key': delete_list.pop(0).resource } for i in range(len_range)] } response = self._s3_client_call('delete_objects', Bucket=self.bucket, Delete=objects) if 'Errors' in response: raise exceptions.RemoteError( 'an error occurred while using rmtree: %s, Key: %s' % (response['Errors'][0].get('Message'), response['Errors'][0].get('Key')), response['Errors'])
def _parse_s3_error(exc, **kwargs): """ Parses botocore.exception.ClientError exceptions to throw a more informative exception. """ http_status = exc.response.get('ResponseMetadata', {}).get('HTTPStatusCode') msg = exc.response['Error'].get('Message', 'Unknown') code = exc.response['Error'].get('Code') operation_name = exc.operation_name msg += ' Bucket: ' + kwargs.get('Bucket') if 'Bucket' in kwargs else '' msg += ' Key: ' + kwargs.get('Key') if 'Key' in kwargs else '' if http_status == 403: if 'storage class' in msg and code == 'InvalidObjectState': if operation_name == 'GetObject': return exceptions.ObjectInColdStorageError(msg, exc) elif operation_name == 'RestoreObject': return exceptions.AlreadyRestoredError(msg, exc) else: # pragma: no cover return exceptions.UnauthorizedError(msg, exc) else: return exceptions.UnauthorizedError(msg, exc) elif http_status == 404: return exceptions.NotFoundError(msg, exc) elif http_status == 503: return exceptions.UnavailableError(msg, exc) elif http_status == 409: if 'Object restore is already in progress' in msg: return exceptions.RestoreAlreadyInProgressError(msg, exc) else: # pragma: no cover return exceptions.ConflictError(msg, exc) else: return exceptions.RemoteError(msg, exc)
def _parse_s3_error(exc, **kwargs): """ Parses botocore.exception.ClientError exceptions to throw a more informative exception. """ http_status = exc.response.get('ResponseMetadata', {}).get('HTTPStatusCode') msg = exc.response['Error'].get('Message', 'Unknown') # Give some more info about the error's origins if 'Bucket' in kwargs: msg += ' Bucket: ' + kwargs.get('Bucket') if 'Key' in kwargs: msg += ', Key: ' + kwargs.get('Key') if http_status == 403: return exceptions.UnauthorizedError(msg, exc) elif http_status == 404: return exceptions.NotFoundError(msg, exc) elif http_status == 503: return exceptions.UnavailableError(msg, exc) return exceptions.RemoteError(msg, exc)
def test_cli_error(self, mock_list): mock_list.side_effect = exceptions.RemoteError('some error') with self.assertOutputMatches(exit_status='1', stderr='RemoteError: some error'): self.parse_args('stor list s3://bucket')
def test_cli_error(self, mock_list, mock_stderr): mock_list.side_effect = exceptions.RemoteError('some error') with self.assertRaisesRegexp(SystemExit, '1'): self.parse_args('stor list s3://bucket')