def Run(self, args): """This is what gets called when the user runs this command.""" pipeline_ref = args.CONCEPTS.delivery_pipeline.Parse() # Check if the pipeline exists. try: pipeline = delivery_pipeline.DeliveryPipelinesClient().Get( pipeline_ref.RelativeName()) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error) output = {'Delivery Pipeline': pipeline} region = pipeline_ref.AsDict()['locationsId'] targets = [] # output the deployment status of the targets in the pipeline. for stage in pipeline.serialPipeline.stages: target_ref = target_util.TargetReference( stage.targetId, pipeline_ref.AsDict()['projectsId'], region) try: target_obj = target_util.GetTarget(target_ref) except apitools_exceptions.HttpError as error: log.debug('Failed to get target {}: {}'.format(stage.targetId, error)) log.status.Print('Unable to get target {}'.format(stage.targetId)) continue detail = {'Target': target_ref.RelativeName()} current_rollout = target_util.GetCurrentRollout(target_ref, pipeline_ref) detail = describe.SetCurrentReleaseAndRollout(current_rollout, detail) if target_obj.requireApproval: detail = describe.ListPendingApprovals(target_ref, pipeline_ref, detail) targets.append(detail) output['Targets'] = targets return output
def _GetCurrentAndRollbackRelease(release_id, pipeline_id, target_ref): """Gets the current deployed release and the release that will be used by promote API to create the rollback rollout.""" ref_dict = target_ref.AsDict() pipeline_ref = resources.REGISTRY.Parse( pipeline_id, collection='clouddeploy.projects.locations.deliveryPipelines', params={ 'projectsId': ref_dict['projectsId'], 'locationsId': ref_dict['locationsId'], 'deliveryPipelinesId': pipeline_id, }) if release_id: current_rollout = target_util.GetCurrentRollout( target_ref, pipeline_ref) current_release_ref = resources.REGISTRY.ParseRelativeName( resources.REGISTRY.Parse( current_rollout.name, collection= 'clouddeploy.projects.locations.deliveryPipelines.releases.rollouts' ).Parent().RelativeName(), collection= 'clouddeploy.projects.locations.deliveryPipelines.releases') rollback_release_ref = resources.REGISTRY.Parse( release_id, collection= 'clouddeploy.projects.locations.deliveryPipelines.releases', params={ 'projectsId': ref_dict['projectsId'], 'locationsId': ref_dict['locationsId'], 'deliveryPipelinesId': pipeline_id, 'releasesId': release_id }) return current_release_ref, rollback_release_ref else: prior_rollouts = list( rollout_util.GetSucceededRollout(target_ref=target_ref, pipeline_ref=pipeline_ref, limit=2)) if len(prior_rollouts) < 2: raise core_exceptions.Error( 'unable to rollback target {}. Target has less than 2 rollouts.' .format(target_ref.Name())) current_release_ref = resources.REGISTRY.ParseRelativeName( resources.REGISTRY.Parse( prior_rollouts[1].name, collection= 'clouddeploy.projects.locations.deliveryPipelines.releases.rollouts' ).Parent().RelativeName(), collection= 'clouddeploy.projects.locations.deliveryPipelines.releases') rollback_release_ref = resources.REGISTRY.ParseRelativeName( resources.REGISTRY.Parse( prior_rollouts[0].name, collection= 'clouddeploy.projects.locations.deliveryPipelines.releases.rollouts' ).Parent().RelativeName(), collection= 'clouddeploy.projects.locations.deliveryPipelines.releases') return current_release_ref, rollback_release_ref
def SetPipelineReleaseRollout(target_ref, pipeline_ref): """Retrieves latest rollout and release information for a single delivery pipeline. Args: target_ref: protorpc.messages.Message, target object. pipeline_ref: protorpc.messages.Message, DeliveryPipeline object Returns: A content directory. """ current_rollout = target_util.GetCurrentRollout(target_ref, pipeline_ref) output = {} output = SetCurrentReleaseAndRollout(current_rollout, output) return output
def GetPipelinesAndRollouts(target_ref, pipeline_refs): """Retrieves the latest rollout for each delivery pipeline. Args: target_ref: protorpc.messages.Message, target object. pipeline_refs: protorpc.messages.Message, pipeline object. Returns: A list with element [pipeline_ref, rollout] where the rollout is the latest successful rollout of the pipeline resource. """ result = [] for pipeline_ref in pipeline_refs: rollout = target_util.GetCurrentRollout(target_ref, pipeline_ref) if rollout is not None: result.append([pipeline_ref, rollout]) return result
def DescribeTargetWithPipeline(target_obj, target_ref, pipeline_id, output): """Describes details specific to the individual target, delivery pipeline qualified. The output contains four sections: target - detail of the target to be described. latest release - the detail of the active release in the target. latest rollout - the detail of the active rollout in the target. deployed - timestamp of the last successful deployment. pending approvals - list rollouts that require approval. Args: target_obj: protorpc.messages.Message, target object. target_ref: protorpc.messages.Message, target reference. pipeline_id: str, delivery pipeline ID. output: A dictionary of <section name:output>. Returns: A dictionary of <section name:output>. """ target_dict = target_ref.AsDict() pipeline_ref = resources.REGISTRY.Parse( None, collection='clouddeploy.projects.locations.deliveryPipelines', params={ 'projectsId': target_dict['projectsId'], 'locationsId': target_dict['locationsId'], 'deliveryPipelinesId': pipeline_id }) current_rollout = target_util.GetCurrentRollout(target_ref, pipeline_ref) output = SetCurrentReleaseAndRollout(current_rollout, output) if target_obj.requireApproval: output = ListPendingApprovals(target_ref, pipeline_ref, output) return output
def GetToTargetID(release_obj, is_create): """Get the to_target parameter for promote API. This checks the promotion sequence to get the next stage to promote the release to. Args: release_obj: apitools.base.protorpclite.messages.Message, release message. is_create: bool, if getting the target for release creation. Returns: the target ID. Raises: NoSnappedTargetsError: if no target snapshots in the release. ReleaseInactiveError: if this is not called during release creation and the specified release has no rollouts. """ if not release_obj.targetSnapshots: raise exceptions.NoSnappedTargetsError(release_obj.name) # Use release short name to avoid the issue by mixed use of # the project number and id. release_ref = resources.REGISTRY.ParseRelativeName( release_obj.name, collection='clouddeploy.projects.locations.deliveryPipelines.releases', ) to_target = release_obj.targetSnapshots[0].name # The order of target snapshots represents the promotion sequence. # E.g. test->stage->prod. Here we start with the last stage. reversed_snapshots = list(reversed(release_obj.targetSnapshots)) release_dict = release_ref.AsDict() for i, snapshot in enumerate(reversed_snapshots): target_ref = target_util.TargetReferenceFromName(snapshot.name) # Starting with the last target in the promotion sequence per above, find # the last successfully deployed rollout to that target. current_rollout = target_util.GetCurrentRollout( target_ref, resources.REGISTRY.Parse( None, collection='clouddeploy.projects.locations.deliveryPipelines', params={ 'projectsId': release_dict['projectsId'], 'locationsId': release_dict['locationsId'], 'deliveryPipelinesId': release_dict['deliveryPipelinesId'] })) if current_rollout: current_rollout_ref = resources.REGISTRY.Parse( current_rollout.name, collection= 'clouddeploy.projects.locations.deliveryPipelines.releases.rollouts' ) # Promotes the release from the target that is farthest along in the # promotion sequence to its next stage in the promotion sequence. if current_rollout_ref.Parent().Name() == release_ref.Name(): if i > 0: to_target = reversed_snapshots[i - 1].name else: log.status.Print( _LAST_TARGET_IN_SEQUENCE.format( release_ref.Name(), target_ref.Name(), release_ref.RelativeName(), target_ref.RelativeName())) to_target = target_ref.RelativeName() # Once a target to promote to is found break out of the loop break # This means the release is not deployed to any target, # to_target flag is required in this case. if to_target == release_obj.targetSnapshots[0].name and not is_create: raise exceptions.ReleaseInactiveError() return target_util.TargetId(to_target)