File: //snap/google-cloud-cli/396/lib/googlecloudsdk/command_lib/deploy/exceptions.py
# -*- 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'
)