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
Exemple #2
0
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
Exemple #3
0
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
Exemple #4
0
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
Exemple #5
0
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)