Esempio n. 1
0
    def Run(self, args):
        """Update the service resource.

       Different from `deploy` in that it can only update the service spec but
       no IAM or Cloud build changes.

    Args:
      args: Args!
    Returns:
      googlecloudsdk.api_lib.run.Service, the updated service
    """
        changes = flags.GetServiceConfigurationChanges(args)
        if not changes or (len(changes) == 1 and isinstance(
                changes[0],
                config_changes.SetClientNameAndVersionAnnotationChange)):
            raise exceptions.NoConfigurationChangeError(
                'No configuration change requested. '
                'Did you mean to include the flags `--update-env-vars`, '
                '`--memory`, `--concurrency`, `--timeout`, `--connectivity`, '
                '`--image`?')
        changes.insert(
            0,
            config_changes.DeleteAnnotationChange(
                k8s_object.BINAUTHZ_BREAKGLASS_ANNOTATION))
        changes.append(
            config_changes.SetLaunchStageAnnotationChange(self.ReleaseTrack()))

        conn_context = connection_context.GetConnectionContext(
            args, flags.Product.RUN, self.ReleaseTrack())
        service_ref = args.CONCEPTS.service.Parse()
        flags.ValidateResource(service_ref)

        with serverless_operations.Connect(conn_context) as client:
            service = client.GetService(service_ref)
            resource_change_validators.ValidateClearVpcConnector(service, args)
            has_latest = (service is None or traffic.LATEST_REVISION_KEY
                          in service.spec_traffic)
            deployment_stages = stages.ServiceStages(
                include_iam_policy_set=False, include_route=has_latest)
            with progress_tracker.StagedProgressTracker(
                    'Deploying...',
                    deployment_stages,
                    failure_message='Deployment failed',
                    suppress_output=args.async_) as tracker:
                service = client.ReleaseService(service_ref,
                                                changes,
                                                tracker,
                                                asyn=args.async_,
                                                prefetch=service)

            if args.async_:
                pretty_print.Success(
                    'Service [{{bold}}{serv}{{reset}}] is deploying '
                    'asynchronously.'.format(serv=service.name))
            else:
                service = client.GetService(service_ref)
                pretty_print.Success(
                    messages_util.GetSuccessMessageForSynchronousDeploy(
                        service))
            return service
Esempio n. 2
0
  def testClearVpcConnectorFalse_VpcEgressSet_DoesNothing(self, vpc_egress):
    args = self.arg_parser.parse_args(['--no-clear-vpc-connector'])
    self.service.template_annotations[
        revision.EGRESS_SETTINGS_ANNOTATION] = vpc_egress

    resource_change_validators.ValidateClearVpcConnector(self.service, args)

    self.prompt_continue.assert_not_called()
Esempio n. 3
0
  def testClearVpcConnectorTrue_ServicePrivateRangesOnly_DoesNothing(self):
    args = self.arg_parser.parse_args(['--clear-vpc-connector'])
    self.service.template_annotations[
        revision.
        EGRESS_SETTINGS_ANNOTATION] = revision.EGRESS_SETTINGS_PRIVATE_RANGES_ONLY

    resource_change_validators.ValidateClearVpcConnector(self.service, args)

    self.prompt_continue.assert_not_called()
Esempio n. 4
0
  def testClearVpcConnectorTrue_ServiceAll_CanPrompt_Prompts_NoConfirmThrows(
      self):
    self.can_prompt.return_value = True
    self.prompt_continue.side_effect = console_io.OperationCancelledError
    args = self.arg_parser.parse_args(['--clear-vpc-connector'])
    self.service.template_annotations[
        revision.EGRESS_SETTINGS_ANNOTATION] = revision.EGRESS_SETTINGS_ALL

    with self.assertRaises(console_io.OperationCancelledError):
      resource_change_validators.ValidateClearVpcConnector(self.service, args)
Esempio n. 5
0
  def testClearVpcConnectorTrue_ServiceAll_NoPrompt_Throws(self):
    self.can_prompt.return_value = False
    args = self.arg_parser.parse_args(['--clear-vpc-connector'])
    self.service.template_annotations[
        revision.EGRESS_SETTINGS_ANNOTATION] = revision.EGRESS_SETTINGS_ALL

    with self.assertRaisesRegex(
        exceptions.ConfigurationError, _CONFIGURATION_ERROR_MESSAGE):
      resource_change_validators.ValidateClearVpcConnector(self.service, args)

    self.prompt_continue.assert_not_called()
Esempio n. 6
0
  def testClearVpcConnectorTrue_ServiceAll_CanPrompt_Prompts_ConfirmSucceeds(
      self):
    self.can_prompt.return_value = True
    self.prompt_continue.return_value = True
    args = self.arg_parser.parse_args(['--clear-vpc-connector'])
    self.service.template_annotations[
        revision.EGRESS_SETTINGS_ANNOTATION] = revision.EGRESS_SETTINGS_ALL

    resource_change_validators.ValidateClearVpcConnector(self.service, args)

    self.prompt_continue.assert_called_once_with(
        message=_PROMPT_MESSAGE, default=False, cancel_on_no=True)
Esempio n. 7
0
    def Run(self, args):
        """Deploy a container to Cloud Run."""
        platform = flags.GetAndValidatePlatform(args, self.ReleaseTrack(),
                                                flags.Product.RUN)

        include_build = flags.FlagIsExplicitlySet(args, 'source')
        if not include_build and not args.IsSpecified('image'):
            if console_io.CanPrompt():
                args.source = flags.PromptForDefaultSource()
                include_build = True
            else:
                raise c_exceptions.RequiredArgumentException(
                    '--image', 'Requires a container image to deploy (e.g. '
                    '`gcr.io/cloudrun/hello:latest`) if no build source is provided.'
                )

        service_ref = args.CONCEPTS.service.Parse()
        flags.ValidateResource(service_ref)

        # Obtaining the connection context prompts the user to select a region if
        # one hasn't been provided. We want to do this prior to preparing a source
        # deploy so that we can use that region for the Artifact Registry repo.
        conn_context = connection_context.GetConnectionContext(
            args, flags.Product.RUN, self.ReleaseTrack())

        build_type = None
        image = None
        pack = None
        source = None
        operation_message = 'Deploying container to'
        repo_to_create = None
        # Build an image from source if source specified
        if include_build:
            source = args.source

            ar_repo = docker_util.DockerRepo(
                project_id=properties.VALUES.core.project.Get(required=True),
                location_id=artifact_registry.RepoRegion(
                    args,
                    cluster_location=(conn_context.cluster_location if platform
                                      == platforms.PLATFORM_GKE else None)),
                repo_id='cloud-run-source-deploy')
            if artifact_registry.ShouldCreateRepository(ar_repo):
                repo_to_create = ar_repo
            # The image is built with latest tag. After build, the image digest
            # from the build result will be added to the image of the service spec.
            args.image = '{repo}/{service}'.format(
                repo=ar_repo.GetDockerString(), service=service_ref.servicesId)
            # Use GCP Buildpacks if Dockerfile doesn't exist
            docker_file = source + '/Dockerfile'
            if os.path.exists(docker_file):
                build_type = BuildType.DOCKERFILE
            else:
                pack = [{'image': args.image}]
                build_type = BuildType.BUILDPACKS
            image = None if pack else args.image
            operation_message = (
                'Building using {build_type} and deploying container'
                ' to').format(build_type=build_type.value)
            pretty_print.Info(
                messages_util.GetBuildEquivalentForSourceRunMessage(
                    service_ref.servicesId, pack, source))

        # Deploy a container with an image
        changes = flags.GetServiceConfigurationChanges(args)
        changes.insert(
            0,
            config_changes.DeleteAnnotationChange(
                k8s_object.BINAUTHZ_BREAKGLASS_ANNOTATION))
        changes.append(
            config_changes.SetLaunchStageAnnotationChange(self.ReleaseTrack()))

        with serverless_operations.Connect(conn_context) as operations:
            service = operations.GetService(service_ref)
            allow_unauth = GetAllowUnauth(args, operations, service_ref,
                                          service)
            resource_change_validators.ValidateClearVpcConnector(service, args)

            pretty_print.Info(
                messages_util.GetStartDeployMessage(conn_context, service_ref,
                                                    operation_message))
            has_latest = (service is None or traffic.LATEST_REVISION_KEY
                          in service.spec_traffic)
            deployment_stages = stages.ServiceStages(
                include_iam_policy_set=allow_unauth is not None,
                include_route=has_latest,
                include_build=include_build,
                include_create_repo=repo_to_create is not None,
            )
            header = None
            if include_build:
                header = 'Building and deploying'
            else:
                header = 'Deploying'
            if service is None:
                header += ' new service'
            header += '...'
            with progress_tracker.StagedProgressTracker(
                    header,
                    deployment_stages,
                    failure_message='Deployment failed',
                    suppress_output=args.async_) as tracker:
                service = operations.ReleaseService(
                    service_ref,
                    changes,
                    tracker,
                    asyn=args.async_,
                    allow_unauthenticated=allow_unauth,
                    prefetch=service,
                    build_image=image,
                    build_pack=pack,
                    build_source=source,
                    repo_to_create=repo_to_create)

            if args.async_:
                pretty_print.Success(
                    'Service [{{bold}}{serv}{{reset}}] is deploying '
                    'asynchronously.'.format(serv=service.name))
            else:
                service = operations.GetService(service_ref)
                pretty_print.Success(
                    messages_util.GetSuccessMessageForSynchronousDeploy(
                        service))
            return service
Esempio n. 8
0
    def Run(self, args):
        """Deploy a container to Cloud Run."""
        flags.GetAndValidatePlatform(args, self.ReleaseTrack(),
                                     flags.Product.RUN)
        service_ref = args.CONCEPTS.service.Parse()
        flags.ValidateResource(service_ref)
        build_type = None
        image = None
        pack = None
        source = None
        include_build = flags.FlagIsExplicitlySet(args, 'source')
        operation_message = 'Deploying container'
        # Build an image from source if source specified
        if include_build:
            # Create a tag for the image creation
            source = args.source
            if not args.IsSpecified('image'):
                args.image = 'gcr.io/{projectID}/cloud-run-source-deploy/{service}:{tag}'.format(
                    projectID=properties.VALUES.core.project.Get(
                        required=True),
                    service=service_ref.servicesId,
                    tag=uuid.uuid4().hex)
            # Use GCP Buildpacks if Dockerfile doesn't exist
            docker_file = args.source + '/Dockerfile'
            if os.path.exists(docker_file):
                build_type = BuildType.DOCKERFILE
            else:
                pack = [{'image': args.image}]
                build_type = BuildType.BUILDPACKS
            image = None if pack else args.image
            operation_message = 'Building using {build_type} and deploying container'.format(
                build_type=build_type.value)
        elif not args.IsSpecified('image'):
            raise c_exceptions.RequiredArgumentException(
                '--image', 'Requires a container image to deploy (e.g. '
                '`gcr.io/cloudrun/hello:latest`) if no build source is provided.'
            )
        # Deploy a container with an image
        conn_context = connection_context.GetConnectionContext(
            args, flags.Product.RUN, self.ReleaseTrack())
        changes = flags.GetConfigurationChanges(args)
        changes.insert(
            0,
            config_changes.DeleteAnnotationChange(
                k8s_object.BINAUTHZ_BREAKGLASS_ANNOTATION))
        changes.append(
            config_changes.SetLaunchStageAnnotationChange(self.ReleaseTrack()))

        with serverless_operations.Connect(conn_context) as operations:
            service = operations.GetService(service_ref)
            allow_unauth = GetAllowUnauth(args, operations, service_ref,
                                          service)
            resource_change_validators.ValidateClearVpcConnector(service, args)

            pretty_print.Info(
                messages_util.GetStartDeployMessage(conn_context, service_ref,
                                                    operation_message))
            has_latest = (service is None or traffic.LATEST_REVISION_KEY
                          in service.spec_traffic)
            deployment_stages = stages.ServiceStages(
                include_iam_policy_set=allow_unauth is not None,
                include_route=has_latest,
                include_build=include_build)
            header = None
            if include_build:
                header = 'Building and deploying'
            else:
                header = 'Deploying'
            if service is None:
                header += ' new service'
            header += '...'
            with progress_tracker.StagedProgressTracker(
                    header,
                    deployment_stages,
                    failure_message='Deployment failed',
                    suppress_output=args.async_) as tracker:
                service = operations.ReleaseService(
                    service_ref,
                    changes,
                    tracker,
                    asyn=args.async_,
                    allow_unauthenticated=allow_unauth,
                    prefetch=service,
                    build_image=image,
                    build_pack=pack,
                    build_source=source)

            if args.async_:
                pretty_print.Success(
                    'Service [{{bold}}{serv}{{reset}}] is deploying '
                    'asynchronously.'.format(serv=service.name))
            else:
                service = operations.GetService(service_ref)
                pretty_print.Success(
                    messages_util.GetSuccessMessageForSynchronousDeploy(
                        service))
            return service
Esempio n. 9
0
  def testClearVpcConnectorTrue_NoVpcEgress_DoesNothing(self):
    args = self.arg_parser.parse_args(['--clear-vpc-connector'])

    resource_change_validators.ValidateClearVpcConnector(self.service, args)

    self.prompt_continue.assert_not_called()