# -*- coding: utf-8 -*- # # Copyright 2023 Google LLC. All Rights Reserved. # # 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. """Exceptions for cloud deploy libraries.""" from googlecloudsdk.calliope import exceptions as c_exceptions from googlecloudsdk.core import exceptions HTTP_ERROR_FORMAT = 'Status code: {status_code}. {status_message}.' class ParserError(exceptions.Error): """Error parsing JSON into a dictionary.""" def __init__(self, path, msg): """Initialize a exceptions.ParserError. Args: path: str, build artifacts file path. msg: str, error message. """ msg = 'parsing {path}: {msg}'.format( path=path, msg=msg, ) super(ParserError, self).__init__(msg) class ReleaseInactiveError(exceptions.Error): """Error when a release is not deployed to any target.""" def __init__(self): super(ReleaseInactiveError, self).__init__( 'This release is not deployed to a target in the active delivery ' 'pipeline. Include the --to-target parameter to indicate which target ' 'to promote to.' ) class AbandonedReleaseError(exceptions.Error): """Error when an activity happens on an abandoned release.""" def __init__(self, error_msg, release_name): error_template = '{} Release {} is abandoned.'.format( error_msg, release_name ) super(AbandonedReleaseError, self).__init__(error_template) class NoStagesError(exceptions.Error): """Error when a release doesn't contain any pipeline stages.""" def __init__(self, release_name): super(NoStagesError, self).__init__( 'No pipeline stages in the release {}.'.format(release_name) ) class InvalidReleaseNameError(exceptions.Error): """Error when a release has extra $ signs after expanding template terms.""" def __init__(self, release_name, error_indices): error_msg = ( "Invalid character '$'" " for release name '{}' at indices:" ' {}. Did you mean to use $DATE or $TIME?' ) super(InvalidReleaseNameError, self).__init__( error_msg.format(release_name, error_indices) ) class CloudDeployConfigError(exceptions.Error): """Error raised for errors in the cloud deploy yaml config.""" @classmethod def for_unnamed_manifest(cls, num, message): return cls(f'Error parsing manifest #{num}: {message}') @classmethod def for_resource(cls, kind, name, message): return cls(f'Error parsing {kind} "{name}": {message}') @classmethod def for_resource_field(cls, kind, name, field, message): return cls(f'Error parsing {kind} "{name}" field "{field}": {message}') class ManifestTransformException(exceptions.Error): """Error raised when a manifest transform fails due to a bug.""" class ListRolloutsError(exceptions.Error): """Error when it failed to list the rollouts that belongs to a release.""" def __init__(self, release_name): super(ListRolloutsError, self).__init__( 'Failed to list rollouts for {}.'.format(release_name) ) class RedeployRolloutError(exceptions.Error): """Error when a rollout can't be redeployed. Redeploy can only be used for rollouts that are in a SUCCEEDED or FAILED state. """ def __init__(self, target_name, rollout_name, rollout_state): error_msg = ( "Unable to redeploy target {}. Rollout {} is in state {} that can't " 'be redeployed'.format(target_name, rollout_name, rollout_state) ) super(RedeployRolloutError, self).__init__(error_msg) class RolloutIDExhaustedError(exceptions.Error): """Error when there are too many rollouts for a given release.""" def __init__(self, release_name): super(RolloutIDExhaustedError, self).__init__( 'Rollout name space exhausted in release {}. Use --rollout-id to ' 'specify rollout ID.'.format(release_name) ) class RolloutInProgressError(exceptions.Error): """Error when there is a rollout in progress, no to-target value is given and a promote is attempted.""" def __init__(self, release_name, target_name): super(RolloutInProgressError, self).__init__( 'Unable to promote release {} to target {}. ' 'A rollout is already in progress.'.format(release_name, target_name) ) class RolloutNotInProgressError(exceptions.Error): """Error when a rollout is not in_progress, but is expected to be.""" def __init__(self, rollout_name): super(RolloutNotInProgressError, self).__init__( 'Rollout {} is not IN_PROGRESS.'.format(rollout_name) ) class RolloutCannotAdvanceError(exceptions.Error): """Error when a rollout cannot be advanced because of a failed precondition.""" def __init__(self, rollout_name, failed_activity_msg): error_msg = '{} Rollout {} cannot be advanced.'.format( failed_activity_msg, rollout_name ) super(RolloutCannotAdvanceError, self).__init__(error_msg) class PipelineSuspendedError(exceptions.Error): """Error when a user performs an activity on a suspended pipeline.""" def __init__(self, pipeline_name, failed_activity_msg): error_msg = '{} DeliveryPipeline {} is suspended.'.format( failed_activity_msg, pipeline_name ) super(PipelineSuspendedError, self).__init__(error_msg) class AutomationNameFormatError(exceptions.Error): """Error when the name of the automation in the config file is not formatted correctly.""" def __init__(self, automation_name): super(AutomationNameFormatError, self).__init__( 'Automation name {} in the configuration should be in the format' ' of pipeline_id/automation_id.'.format(automation_name) ) class AutomationWaitFormatError(exceptions.Error): """Error when the name of the automation in the config file is not formatted correctly.""" def __init__(self): super(AutomationWaitFormatError, self).__init__( 'Wait must be numbers with the last character m, e.g. 5m.' ) class MissingCoupledArgumentsException(c_exceptions.ToolException): """An exception for when only one of several arguments that need to be passed together is passed.""" def __init__(self, parameter_names): super(MissingCoupledArgumentsException, self).__init__( f'All of these flags {parameter_names} must be supplied together' )