예제 #1
0
    def Run(self, args):
        """Delete a Cloud Run Integration."""
        integration_name = args.name

        conn_context = connection_context.GetConnectionContext(
            args, run_flags.Product.RUN_APPS, self.ReleaseTrack())
        with run_apps_operations.Connect(conn_context) as client:
            with progress_tracker.StagedProgressTracker(
                    'Deleting Integration...',
                    stages.IntegrationDeleteStages(),
                    failure_message='Failed to delete integration.'
            ) as tracker:
                try:
                    integration_type = client.DeleteIntegration(
                        name=integration_name, tracker=tracker)
                except exceptions.IntegrationsOperationError as err:
                    pretty_print.Info(
                        messages_util.GetDeleteErrorMessage(integration_name))
                    raise err
                else:
                    pretty_print.Info('')
                    pretty_print.Success(
                        messages_util.GetSuccessMessage(
                            integration_type=integration_type,
                            integration_name=integration_name,
                            action='deleted'))
예제 #2
0
    def Run(self, args):
        """Deploy an app, function or container to Cloud Run."""
        source_ref = flags.GetSourceRef(args.source, args.image)
        config_changes = flags.GetConfigurationChanges(args)

        conn_context = connection_context.GetConnectionContext(args)
        service_ref = flags.GetService(args)
        function_entrypoint = flags.GetFunction(args.function)
        msg = ('Deploying {dep_type} to service [{{bold}}{{service}}{{reset}}]'
               ' in {ns_label} [{{bold}}{{ns}}{{reset}}]')

        msg += conn_context.location_label

        if function_entrypoint:
            pretty_print.Info(msg.format(
                ns_label=conn_context.ns_label,
                dep_type='function [{bold}{function}{reset}]'),
                              function=function_entrypoint,
                              service=service_ref.servicesId,
                              ns=service_ref.namespacesId)
        elif source_ref.source_type is source_ref.SourceType.IMAGE:
            pretty_print.Info(msg.format(ns_label=conn_context.ns_label,
                                         dep_type='container'),
                              service=service_ref.servicesId,
                              ns=service_ref.namespacesId)
        else:
            pretty_print.Info(msg.format(ns_label=conn_context.ns_label,
                                         dep_type='app'),
                              service=service_ref.servicesId,
                              ns=service_ref.namespacesId)

        with serverless_operations.Connect(conn_context) as operations:
            if not (source_ref.source_type is source_ref.SourceType.IMAGE
                    or operations.IsSourceBranch()):
                raise exceptions.SourceNotSupportedError()
            new_deployable = operations.Detect(service_ref.Parent(),
                                               source_ref, function_entrypoint)
            operations.Upload(new_deployable)
            changes = [new_deployable]
            if config_changes:
                changes.extend(config_changes)
            operations.ReleaseService(service_ref, changes, asyn=args. async)
            url = operations.GetServiceUrl(service_ref)
            conf = operations.GetConfiguration(service_ref)

        msg = ('{{bold}}Service [{serv}] revision [{rev}] has been deployed'
               ' and is serving traffic at{{reset}} {url}')
        msg = msg.format(serv=service_ref.servicesId,
                         rev=conf.status.latestReadyRevisionName,
                         url=url)
        pretty_print.Success(msg)
예제 #3
0
  def Run(self, args):
    """Create or Update service from YAML."""
    conn_context = connection_context.GetConnectionContext(
        args, self.ReleaseTrack())

    with serverless_operations.Connect(conn_context) as client:
      new_service = service.Service(
          messages_util.DictToMessageWithErrorCheck(
              args.FILE, client.messages_module.Service),
          client.messages_module)

      # If managed, namespace must match project (or will default to project if
      # not specified).
      # If not managed, namespace simply must not conflict if specified in
      # multiple places (or will default to "default" if not specified).
      namespace = args.CONCEPTS.namespace.Parse().Name()  # From flag or default
      if new_service.metadata.namespace is not None:
        if (args.IsSpecified('namespace') and
            namespace != new_service.metadata.namespace):
          raise exceptions.ConfigurationError(
              'Namespace specified in file does not match passed flag.')
        namespace = new_service.metadata.namespace
        project = properties.VALUES.core.project.Get()
        if flags.IsManaged(args) and namespace != project:
          raise exceptions.ConfigurationError(
              'Namespace must be [{}] for Cloud Run (fully managed).'.format(
                  project))
      new_service.metadata.namespace = namespace

      changes = [config_changes.ReplaceServiceChange(new_service)]
      service_ref = resources.REGISTRY.Parse(
          new_service.metadata.name,
          params={'namespacesId': namespace},
          collection='run.namespaces.services')
      original_service = client.GetService(service_ref)

      pretty_print.Info(deploy.GetStartDeployMessage(conn_context, service_ref))

      deployment_stages = stages.ServiceStages()
      header = (
          'Deploying...' if original_service else 'Deploying new service...')
      with progress_tracker.StagedProgressTracker(
          header,
          deployment_stages,
          failure_message='Deployment failed',
          suppress_output=args.async_) as tracker:
        client.ReleaseService(
            service_ref,
            changes,
            tracker,
            asyn=args.async_,
            allow_unauthenticated=None,
            for_replace=True)
      if args.async_:
        pretty_print.Success(
            'Service [{{bold}}{serv}{{reset}}] is deploying '
            'asynchronously.'.format(serv=service_ref.servicesId))
      else:
        pretty_print.Success(deploy.GetSuccessMessageForSynchronousDeploy(
            client, service_ref))
예제 #4
0
def GetAllowUnauthenticated(args, client=None, service_ref=None, prompt=False):
  """Return bool for the explicit intent to allow unauth invocations or None.

  If --[no-]allow-unauthenticated is set, return that value. If not set,
  prompt for value if desired. If prompting not necessary or doable,
  return None, indicating that no action needs to be taken.

  Args:
    args: Namespace, The args namespace
    client: from googlecloudsdk.command_lib.run import serverless_operations
      serverless_operations.ServerlessOperations object
    service_ref: service resource reference (e.g. args.CONCEPTS.service.Parse())
    prompt: bool, whether to attempt to prompt.

  Returns:
    bool indicating whether to allow/unallow unauthenticated or None if N/A
  """
  if getattr(args, 'allow_unauthenticated', None) is not None:
    return args.allow_unauthenticated

  if prompt:
    # Need to check if the user has permissions before we prompt
    assert client is not None and service_ref is not None
    if client.CanSetIamPolicyBinding(service_ref):
      return console_io.PromptContinue(
          prompt_string=('Allow unauthenticated invocations '
                         'to [{}]'.format(service_ref.servicesId)),
          default=False)
    else:
      pretty_print.Info(
          'This service will require authentication to be invoked.')
  return None
예제 #5
0
def GetAllowUnauthenticated(args, service_ref=None, prompt=False):
  """Return bool for the explicit intent to allow unauth invocations or None.

  If --[no-]allow-unauthenticated is set, return that value. If not set,
  prompt for value if desired. If prompting not necessary or doable,
  return None, indicating that no action needs to be taken.

  Args:
    args: Namespace, The args namespace
    service_ref: service resource reference (e.g. args.CONCEPTS.service.Parse())
    prompt: bool, whether to attempt to prompt.

  Returns:
    bool indicating whether to allow/unallow unauthenticated or None if N/A
  """
  if getattr(args, 'allow_unauthenticated', None) is not None:
    return args.allow_unauthenticated

  if prompt:
    project = properties.VALUES.core.project.Get(required=True)
    if resourcemanager_operations.CanSetProjectIamPolicyBinding(project):
      return console_io.PromptContinue(
          prompt_string=('Allow unauthenticated invocations '
                         'to [{}]'.format(service_ref.servicesId)),
          default=False)
    else:
      pretty_print.Info(
          'This service will require authentication to be invoked.')
  return None
예제 #6
0
    def Run(self, args):
        """Creates a Cloud Run Integration."""

        integration_type = args.type
        service = args.service
        input_name = args.name
        parameters = flags.GetParameters(args)
        flags.ValidateCreateParameters(integration_type, parameters)

        conn_context = connection_context.GetConnectionContext(
            args, run_flags.Product.RUN_APPS, self.ReleaseTrack())
        with run_apps_operations.Connect(conn_context) as client:
            self._validateServiceNameAgainstIntegrations(
                client,
                integration_type=integration_type,
                service=service,
                integration_name=input_name)

            with progress_tracker.StagedProgressTracker(
                    'Creating new Integration...',
                    stages.IntegrationStages(create=True),
                    failure_message='Failed to create new integration.'
            ) as tracker:
                integration_name = client.CreateIntegration(
                    tracker=tracker,
                    integration_type=integration_type,
                    parameters=parameters,
                    service=service,
                    name=input_name)
            resource_config = client.GetIntegration(integration_name)
            resource_status = client.GetIntegrationStatus(integration_name)

            pretty_print.Info('')
            pretty_print.Success(
                messages_util.GetSuccessMessage(
                    integration_type=integration_type,
                    integration_name=integration_name,
                    action='created'))

            call_to_action = messages_util.GetCallToAction(
                integration_type, resource_config, resource_status)
            if call_to_action:
                pretty_print.Info('')
                pretty_print.Info(call_to_action)
                pretty_print.Info(
                    messages_util.CheckStatusMessage(self.ReleaseTrack(),
                                                     integration_name))
예제 #7
0
  def Run(self, args):
    """Deploy a container to Cloud Run."""
    service_ref = flags.GetService(args)
    image = args.image
    # Build an image from source if source specified.
    if flags.FlagIsExplicitlySet(args, 'source'):
      # Create a tag for the image creation
      if image is None and not args.IsSpecified('config'):
        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)
      messages = cloudbuild_util.GetMessagesModule()
      build_config = submit_util.CreateBuildConfig(
          image, args.no_cache, messages, args.substitutions, args.config,
          args.IsSpecified('source'), False, args.source,
          args.gcs_source_staging_dir, args.ignore_file, args.gcs_log_dir,
          args.machine_type, args.disk_size)
      submit_util.Build(messages, args.async_, build_config)

    # Deploy a container with an image
    conn_context = connection_context.GetConnectionContext(
        args, flags.Product.RUN, self.ReleaseTrack())
    config_changes = flags.GetConfigurationChanges(args)

    with serverless_operations.Connect(conn_context) as operations:
      image_change = config_changes_mod.ImageChange(image)
      changes = [image_change]
      if config_changes:
        changes.extend(config_changes)
      service = operations.GetService(service_ref)
      allow_unauth = GetAllowUnauth(args, operations, service_ref, service)

      pretty_print.Info(GetStartDeployMessage(conn_context, service_ref))
      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)
      header = 'Deploying...' if service else 'Deploying new service...'
      with progress_tracker.StagedProgressTracker(
          header,
          deployment_stages,
          failure_message='Deployment failed',
          suppress_output=args.async_) as tracker:
        operations.ReleaseService(
            service_ref,
            changes,
            tracker,
            asyn=args.async_,
            allow_unauthenticated=allow_unauth,
            prefetch=service)
      if args.async_:
        pretty_print.Success(
            'Service [{{bold}}{serv}{{reset}}] is deploying '
            'asynchronously.'.format(serv=service_ref.servicesId))
      else:
        pretty_print.Success(GetSuccessMessageForSynchronousDeploy(
            operations, service_ref))
    def Run(self, args):
        """Update a Cloud Run Integration."""

        add_service = args.add_service
        remove_service = args.remove_service
        integration_name = args.name
        parameters = flags.GetParameters(args)

        conn_context = connection_context.GetConnectionContext(
            args, run_flags.Product.RUN_APPS, self.ReleaseTrack())
        with run_apps_operations.Connect(conn_context) as client:

            with progress_tracker.StagedProgressTracker(
                    'Updating Integration...',
                    stages.IntegrationStages(create=False),
                    failure_message='Failed to update integration.'
            ) as tracker:
                client.UpdateIntegration(tracker=tracker,
                                         name=integration_name,
                                         parameters=parameters,
                                         add_service=add_service,
                                         remove_service=remove_service)

            resource_config = client.GetIntegration(integration_name)
            resource_status = client.GetIntegrationStatus(integration_name)
            resource_type = client.GetResourceTypeFromConfig(resource_config)
            integration_type = types_utils.GetIntegrationType(resource_type)

            pretty_print.Info('')
            pretty_print.Success(
                messages_util.GetSuccessMessage(
                    integration_type=integration_type,
                    integration_name=integration_name,
                    action='updated'))

            call_to_action = messages_util.GetCallToAction(
                integration_type, resource_config, resource_status)
            if call_to_action:
                pretty_print.Info('')
                pretty_print.Info(call_to_action)
                pretty_print.Info(
                    messages_util.CheckStatusMessage(self.ReleaseTrack(),
                                                     integration_name))
예제 #9
0
    def Run(self, args):
        """Create or Update service from YAML."""
        conn_context = connection_context.GetConnectionContext(args)
        if conn_context.supports_one_platform:
            flags.VerifyOnePlatformFlags(args)
        else:
            flags.VerifyGKEFlags(args)

        with serverless_operations.Connect(conn_context) as client:
            message_dict = yaml.load_path(args.FILE)
            new_service = service.Service(
                messages_util.DictToMessageWithErrorCheck(
                    message_dict, client.messages_module.Service),
                client.messages_module)

            changes = [config_changes.ReplaceServiceChange(new_service)]
            service_ref = resources.REGISTRY.Parse(
                new_service.metadata.name,
                params={'namespacesId': new_service.metadata.namespace},
                collection='run.namespaces.services')
            original_service = client.GetService(service_ref)

            pretty_print.Info(
                deploy.GetStartDeployMessage(conn_context, service_ref))

            deployment_stages = stages.ServiceStages()
            header = ('Deploying...'
                      if original_service else 'Deploying new service...')
            with progress_tracker.StagedProgressTracker(
                    header,
                    deployment_stages,
                    failure_message='Deployment failed',
                    suppress_output=args. async) as tracker:
                client.ReleaseService(service_ref,
                                      changes,
                                      tracker,
                                      asyn=args. async,
                                      allow_unauthenticated=None,
                                      for_replace=True)
            if args. async:
                pretty_print.Success(
                    'Service [{{bold}}{serv}{{reset}}] is deploying '
                    'asynchronously.'.format(serv=service_ref.servicesId))
            else:
                pretty_print.Success(
                    deploy.GetSuccessMessageForSynchronousDeploy(
                        client, service_ref))
예제 #10
0
파일: deploy.py 프로젝트: OzLustig/MyDay
    def Run(self, args):
        """Deploy a container to Cloud Run."""
        image = args.image

        conn_context = connection_context.GetConnectionContext(
            args, product=connection_context.Product.RUN)
        config_changes = flags.GetConfigurationChanges(args)

        service_ref = flags.GetService(args)

        with serverless_operations.Connect(conn_context) as operations:
            image_change = config_changes_mod.ImageChange(image)
            changes = [image_change]
            if config_changes:
                changes.extend(config_changes)
            service = operations.GetService(service_ref)
            allow_unauth = GetAllowUnauth(args, operations, service_ref,
                                          service)

            pretty_print.Info(GetStartDeployMessage(conn_context, service_ref))
            has_latest = (service is None
                          or traffic.LATEST_REVISION_KEY in service.traffic)
            deployment_stages = stages.ServiceStages(
                include_iam_policy_set=allow_unauth is not None,
                include_route=has_latest)
            header = 'Deploying...' if service else 'Deploying new service...'
            with progress_tracker.StagedProgressTracker(
                    header,
                    deployment_stages,
                    failure_message='Deployment failed',
                    suppress_output=args.async_) as tracker:
                operations.ReleaseService(service_ref,
                                          changes,
                                          tracker,
                                          asyn=args.async_,
                                          allow_unauthenticated=allow_unauth,
                                          prefetch=service)
            if args.async_:
                pretty_print.Success(
                    'Service [{{bold}}{serv}{{reset}}] is deploying '
                    'asynchronously.'.format(serv=service_ref.servicesId))
            else:
                pretty_print.Success(
                    GetSuccessMessageForSynchronousDeploy(
                        operations, service_ref))
예제 #11
0
  def Run(self, args):
    """Deploy a container to Cloud Run."""
    job_ref = args.CONCEPTS.job.Parse()
    flags.ValidateResource(job_ref)

    conn_context = connection_context.GetConnectionContext(
        args,
        flags.Product.RUN,
        self.ReleaseTrack(),
        version_override='v1alpha1')
    changes = flags.GetConfigurationChanges(args)
    changes.append(
        config_changes.SetLaunchStageAnnotationChange(self.ReleaseTrack()))

    with serverless_operations.Connect(conn_context) as operations:
      pretty_print.Info(
          messages_util.GetStartDeployMessage(conn_context, job_ref, 'job'))
      header_msg = 'Creating and {} job...'.format(
          'running' if args.wait_for_completion else 'starting')
      with progress_tracker.StagedProgressTracker(
          header_msg,
          stages.JobStages(include_completion=args.wait_for_completion),
          failure_message='Job failed',
          suppress_output=args.async_) as tracker:
        job = operations.CreateJob(
            job_ref,
            changes,
            args.wait_for_completion,
            tracker,
            asyn=args.async_)

      if args.async_:
        pretty_print.Success('Job [{{bold}}{job}{{reset}}] is being created '
                             'asynchronously.'.format(job=job.name))
      else:
        job = operations.GetJob(job_ref)
        pretty_print.Success(
            'Job [{{bold}}{job}{{reset}}] has successfully '
            '{operation}.'.format(
                job=job.name,
                operation=('completed'
                           if args.wait_for_completion else 'started running')))
      return job
예제 #12
0
    def Run(self, args):
        """Deploy a container to Cloud Run."""
        image = args.image

        conn_context = connection_context.GetConnectionContext(
            args, self.ReleaseTrack())
        config_changes = flags.GetConfigurationChanges(args)

        service_ref = flags.GetService(args)

        with serverless_operations.Connect(conn_context) as operations:
            image_change = config_changes_mod.ImageChange(image)
            changes = [image_change]
            if config_changes:
                changes.extend(config_changes)
            exists = operations.GetService(service_ref)
            allow_unauth = GetAllowUnauth(args, operations, service_ref,
                                          exists)

            pretty_print.Info(GetStartDeployMessage(conn_context, service_ref))

            deployment_stages = stages.ServiceStages(allow_unauth is not None)
            header = 'Deploying...' if exists else 'Deploying new service...'
            with progress_tracker.StagedProgressTracker(
                    header,
                    deployment_stages,
                    failure_message='Deployment failed',
                    suppress_output=args.async_) as tracker:
                operations.ReleaseService(service_ref,
                                          changes,
                                          tracker,
                                          asyn=args.async_,
                                          allow_unauthenticated=allow_unauth)
            if args.async_:
                pretty_print.Success(
                    'Service [{{bold}}{serv}{{reset}}] is deploying '
                    'asynchronously.'.format(serv=service_ref.servicesId))
            else:
                pretty_print.Success(
                    GetSuccessMessageForSynchronousDeploy(
                        operations, service_ref))
    def Run(self, args):
        """Update a Job on Cloud Run."""
        job_ref = args.CONCEPTS.job.Parse()
        flags.ValidateResource(job_ref)

        conn_context = connection_context.GetConnectionContext(
            args, flags.Product.RUN, self.ReleaseTrack())
        changes = flags.GetJobConfigurationChanges(args)
        changes.append(
            config_changes.SetLaunchStageAnnotationChange(self.ReleaseTrack()))

        with serverless_operations.Connect(conn_context) as operations:
            pretty_print.Info(
                messages_util.GetStartDeployMessage(conn_context, job_ref,
                                                    'Updating', 'job'))
            header_msg = 'Updating job...'
            with progress_tracker.StagedProgressTracker(
                    header_msg,
                    stages.JobStages(),
                    failure_message='Job failed to deploy',
                    suppress_output=args.async_) as tracker:
                job = operations.UpdateJob(job_ref,
                                           changes,
                                           tracker,
                                           asyn=args.async_)

            if args.async_:
                pretty_print.Success(
                    'Job [{{bold}}{job}{{reset}}] is being updated '
                    'asynchronously.'.format(job=job.name))
            else:
                job = operations.GetJob(job_ref)
                pretty_print.Success(
                    'Job [{{bold}}{job}{{reset}}] has been successfully updated'
                    .format(job=job.name))

            log.status.Print(
                messages_util.GetRunJobMessage(self.ReleaseTrack(), job.name))
            return job
    def Run(self, args):
        """Create or Update service from YAML."""
        run_messages = apis.GetMessagesModule(
            global_methods.SERVERLESS_API_NAME,
            global_methods.SERVERLESS_API_VERSION)
        service_dict = dict(args.FILE)
        # Clear the status to make migration from k8s deployments easier.
        # Since a Deployment status will have several fields that Cloud Run doesn't
        # support, trying to convert it to a message as-is will fail even though
        # status is ignored by the server.
        if 'status' in service_dict:
            del service_dict['status']

        # For cases where YAML contains the project number as metadata.namespace,
        # preemptively convert them to a string to avoid validation failures.
        namespace = service_dict.get('metadata', {}).get('namespace', None)
        if namespace is not None and not isinstance(namespace, str):
            service_dict['metadata']['namespace'] = str(namespace)

        try:
            raw_service = messages_util.DictToMessageWithErrorCheck(
                service_dict, run_messages.Service)
            new_service = service.Service(raw_service, run_messages)
        except messages_util.ScalarTypeMismatchError as e:
            exceptions.MaybeRaiseCustomFieldMismatch(
                e,
                help_text=
                'Please make sure that the YAML file matches the Knative '
                'service definition spec in https://kubernetes.io/docs/'
                'reference/kubernetes-api/services-resources/service-v1/'
                '#Service.')

        # If managed, namespace must match project (or will default to project if
        # not specified).
        # If not managed, namespace simply must not conflict if specified in
        # multiple places (or will default to "default" if not specified).
        namespace = args.CONCEPTS.namespace.Parse().Name(
        )  # From flag or default
        if new_service.metadata.namespace is not None:
            if (args.IsSpecified('namespace')
                    and namespace != new_service.metadata.namespace):
                raise exceptions.ConfigurationError(
                    'Namespace specified in file does not match passed flag.')
            namespace = new_service.metadata.namespace
            if platforms.GetPlatform() == platforms.PLATFORM_MANAGED:
                project = properties.VALUES.core.project.Get()
                project_number = projects_util.GetProjectNumber(project)
                if namespace != project and namespace != str(project_number):
                    raise exceptions.ConfigurationError(
                        'Namespace must be project ID [{}] or quoted number [{}] for '
                        'Cloud Run (fully managed).'.format(
                            project, project_number))
        new_service.metadata.namespace = namespace

        changes = [
            config_changes.ReplaceServiceChange(new_service),
            config_changes.SetLaunchStageAnnotationChange(self.ReleaseTrack())
        ]
        service_ref = resources.REGISTRY.Parse(
            new_service.metadata.name,
            params={'namespacesId': new_service.metadata.namespace},
            collection='run.namespaces.services')

        region_label = new_service.region if new_service.is_managed else None

        conn_context = connection_context.GetConnectionContext(
            args,
            flags.Product.RUN,
            self.ReleaseTrack(),
            region_label=region_label)

        with serverless_operations.Connect(conn_context) as client:
            service_obj = client.GetService(service_ref)

            pretty_print.Info(
                run_messages_util.GetStartDeployMessage(
                    conn_context,
                    service_ref,
                    operation='Applying new configuration to'))

            deployment_stages = stages.ServiceStages()
            header = ('Deploying...'
                      if service_obj else 'Deploying new service...')
            with progress_tracker.StagedProgressTracker(
                    header,
                    deployment_stages,
                    failure_message='Deployment failed',
                    suppress_output=args.async_) as tracker:
                service_obj = client.ReleaseService(service_ref,
                                                    changes,
                                                    tracker,
                                                    asyn=args.async_,
                                                    allow_unauthenticated=None,
                                                    for_replace=True)
            if args.async_:
                pretty_print.Success(
                    'New configuration for [{{bold}}{serv}{{reset}}] is being applied '
                    'asynchronously.'.format(serv=service_obj.name))
            else:
                service_obj = client.GetService(service_ref)
                pretty_print.Success(
                    'New configuration has been applied to service '
                    '[{{bold}}{serv}{{reset}}].\n'
                    'URL: {{bold}}{url}{{reset}}'.format(
                        serv=service_obj.name, url=service_obj.domain))
            return service_obj
예제 #15
0
  def _UpdateOrCreateService(self, service_ref, config_changes, with_code,
                             private_endpoint=None):
    """Apply config_changes to the service. Create it if necessary.

    Arguments:
      service_ref: Reference to the service to create or update
      config_changes: list of ConfigChanger to modify the service with
      with_code: bool, True if the config_changes contains code to deploy.
        We can't create the service if we're not deploying code.
      private_endpoint: bool, True if creating a new Service for
        Cloud Run on GKE that should only be addressable from within the
        cluster. False if it should be publicly addressable. None if
        its existing visibility should remain unchanged.

    Returns:
      The Service object we created or modified.
    """
    nonce = _Nonce()
    config_changes = [_NewRevisionForcingChange(nonce)] + config_changes
    messages = self._messages_module
    # GET the Service
    serv = self.GetService(service_ref)
    try:
      if serv:
        if not with_code:
          # Avoid changing the running code by making the new revision by digest
          self._EnsureImageDigest(serv, config_changes)

        if private_endpoint is None:
          # Don't change the existing service visibility
          pass
        elif private_endpoint:
          serv.labels[service.ENDPOINT_VISIBILITY] = service.CLUSTER_LOCAL
        else:
          del serv.labels[service.ENDPOINT_VISIBILITY]

        # PUT the changed Service
        for config_change in config_changes:
          config_change.AdjustConfiguration(serv.configuration, serv.metadata)
        serv_name = service_ref.RelativeName()
        serv_update_req = (
            messages.RunNamespacesServicesReplaceServiceRequest(
                service=serv.Message(),
                name=serv_name))
        with metrics.record_duration(metrics.UPDATE_SERVICE):
          updated = self._client.namespaces_services.ReplaceService(
              serv_update_req)
        return service.Service(updated, messages)

      else:
        if not with_code:
          raise serverless_exceptions.ServiceNotFoundError(
              'Service [{}] could not be found.'.format(service_ref.servicesId))
        # POST a new Service
        new_serv = service.Service.New(self._client, service_ref.namespacesId,
                                       private_endpoint)
        new_serv.name = service_ref.servicesId
        pretty_print.Info('Creating new service [{bold}{service}{reset}]',
                          service=new_serv.name)
        parent = service_ref.Parent().RelativeName()
        for config_change in config_changes:
          config_change.AdjustConfiguration(new_serv.configuration,
                                            new_serv.metadata)
        serv_create_req = (
            messages.RunNamespacesServicesCreateRequest(
                service=new_serv.Message(),
                parent=parent))
        with metrics.record_duration(metrics.CREATE_SERVICE):
          raw_service = self._client.namespaces_services.Create(
              serv_create_req)
        return service.Service(raw_service, messages)
    except api_exceptions.HttpBadRequestError as e:
      error_payload = exceptions_util.HttpErrorPayload(e)
      if error_payload.field_violations:
        if (serverless_exceptions.BadImageError.IMAGE_ERROR_FIELD
            in error_payload.field_violations):
          exceptions.reraise(serverless_exceptions.BadImageError(e))
      exceptions.reraise(e)
    except api_exceptions.HttpNotFoundError as e:
      # TODO(b/118339293): List available regions to check whether provided
      # region is invalid or not.
      raise serverless_exceptions.DeploymentFailedError(
          'Deployment endpoint was not found. Perhaps the provided '
          'region was invalid. Set the `run/region` property to a valid '
          'region and retry. Ex: `gcloud config set run/region us-central1`')
예제 #16
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
예제 #17
0
  def Run(self, args):
    """Deploy an app, function or container to Cloud Run."""
    source_ref = flags.GetSourceRef(args.source, args.image)
    config_changes = flags.GetConfigurationChanges(args)

    conn_context = connection_context.GetConnectionContext(args)

    # pylint: disable=protected-access
    if (not isinstance(conn_context, connection_context._GKEConnectionContext)
        and getattr(args, 'endpoint', None)):
      raise exceptions.ConfigurationError(
          'The `--endpoint=[internal|external]` flag '
          'is only supported with Cloud Run on GKE.')
    # pylint: enable=protected-access

    service_ref = flags.GetService(args)
    function_entrypoint = flags.GetFunction(args.function)
    msg = ('Deploying {dep_type} to {operator} '
           'service [{{bold}}{service}{{reset}}]'
           ' in {ns_label} [{{bold}}{ns}{{reset}}]')

    msg += conn_context.location_label

    if function_entrypoint:
      dep_type = 'function [{{bold}}{}{{reset}}]'.format(function_entrypoint)
      pretty_print.Info(msg.format(
          operator=conn_context.operator,
          ns_label=conn_context.ns_label,
          dep_type=dep_type,
          function=function_entrypoint,
          service=service_ref.servicesId,
          ns=service_ref.namespacesId))
    elif source_ref.source_type is source_ref.SourceType.IMAGE:
      pretty_print.Info(msg.format(
          operator=conn_context.operator,
          ns_label=conn_context.ns_label,
          dep_type='container',
          service=service_ref.servicesId,
          ns=service_ref.namespacesId))
    else:
      pretty_print.Info(msg.format(
          operator=conn_context.operator,
          ns_label=conn_context.ns_label,
          dep_type='app',
          service=service_ref.servicesId,
          ns=service_ref.namespacesId))

    with serverless_operations.Connect(conn_context) as operations:
      if not (source_ref.source_type is source_ref.SourceType.IMAGE
              or operations.IsSourceBranch()):
        raise exceptions.SourceNotSupportedError()
      new_deployable = operations.Detect(service_ref.Parent(),
                                         source_ref, function_entrypoint)
      operations.Upload(new_deployable)
      changes = [new_deployable]
      if config_changes:
        changes.extend(config_changes)

      if args.endpoint == 'internal':
        private_endpoint = True
      elif args.endpoint == 'external':
        private_endpoint = False
      else:
        private_endpoint = None

      operations.ReleaseService(service_ref, changes, asyn=args.async,
                                private_endpoint=private_endpoint)
      url = operations.GetServiceUrl(service_ref)
      conf = operations.GetConfiguration(service_ref)

    msg = (
        'Service [{{bold}}{serv}{{reset}}] revision [{{bold}}{rev}{{reset}}] '
        'has been deployed and is serving traffic at {{bold}}{url}{{reset}}')
    msg = msg.format(
        serv=service_ref.servicesId,
        rev=conf.status.latestReadyRevisionName,
        url=url)
    pretty_print.Success(msg)
예제 #18
0
  def Run(self, args):
    """Deploy a container to Cloud Run."""
    image = args.image

    conn_context = connection_context.GetConnectionContext(args)
    config_changes = flags.GetConfigurationChanges(args)

    if conn_context.supports_one_platform:
      flags.VerifyOnePlatformFlags(args)
    else:
      flags.VerifyGKEFlags(args)

    service_ref = flags.GetService(args)

    with serverless_operations.Connect(conn_context) as operations:
      image_change = config_changes_mod.ImageChange(image)
      changes = [image_change]
      if config_changes:
        changes.extend(config_changes)
      if args.connectivity == 'internal':
        private_endpoint = True
      elif args.connectivity == 'external':
        private_endpoint = False
      else:
        private_endpoint = None
      exists = operations.GetService(service_ref)

      if (not exists and not args.allow_unauthenticated and
          conn_context.supports_one_platform):

        if operations.CanAddIamPolicyBinding(service_ref):
          allow_unauth = console_io.PromptContinue(
              prompt_string=(
                  'Allow unauthenticated invocations '
                  'to new service [{}]?'.format(
                      service_ref.servicesId)),
              default=False)
        else:
          allow_unauth = False
          pretty_print.Info(
              'This new service will require authentication to be invoked.')
      else:
        allow_unauth = False

      msg = ('Deploying {dep_type} to {operator} '
             'service [{{bold}}{service}{{reset}}]'
             ' in {ns_label} [{{bold}}{ns}{{reset}}]')
      msg += conn_context.location_label

      pretty_print.Info(msg.format(
          operator=conn_context.operator,
          ns_label=conn_context.ns_label,
          dep_type='container',
          service=service_ref.servicesId,
          ns=service_ref.namespacesId))

      deployment_stages = stages.ServiceStages(
          allow_unauth or args.allow_unauthenticated)
      header = 'Deploying...' if exists else 'Deploying new service...'
      with progress_tracker.StagedProgressTracker(
          header,
          deployment_stages,
          failure_message='Deployment failed',
          suppress_output=args.async) as tracker:
        operations.ReleaseService(
            service_ref,
            changes,
            tracker,
            asyn=args.async,
            private_endpoint=private_endpoint,
            allow_unauthenticated=allow_unauth or args.allow_unauthenticated)
      if args.async:
        pretty_print.Success(
            'Service [{{bold}}{serv}{{reset}}] is deploying '
            'asynchronously.'.format(serv=service_ref.servicesId))
      else:
        url = operations.GetServiceUrl(service_ref)
        conf = operations.GetConfiguration(service_ref)
        msg = (
            'Service [{{bold}}{serv}{{reset}}] '
            'revision [{{bold}}{rev}{{reset}}] '
            'has been deployed and is serving traffic at '
            '{{bold}}{url}{{reset}}')
        msg = msg.format(
            serv=service_ref.servicesId,
            rev=conf.status.latestReadyRevisionName,
            url=url)
        pretty_print.Success(msg)
예제 #19
0
    def Run(self, args):
        """Deploy an app, function or container to Cloud Run."""
        source_ref = flags.GetSourceRef(args.source, args.image)
        config_changes = flags.GetConfigurationChanges(args)

        conn_context = connection_context.GetConnectionContext(args)

        if (conn_context.supports_one_platform
                and getattr(args, 'connectivity', None)):
            raise exceptions.ConfigurationError(
                'The `--endpoint=[internal|external]` flag '
                'is only supported with Cloud Run on GKE.')

        if (not conn_context.supports_one_platform
                and getattr(args, 'allow_unauthenticated', None)):
            raise exceptions.ConfigurationError(
                'The `--allow-unauthenticated` flag '
                'is not supported with Cloud Run on GKE.')

        service_ref = flags.GetService(args)
        function_entrypoint = flags.GetFunction(args.function)
        msg = ('Deploying {dep_type} to {operator} '
               'service [{{bold}}{service}{{reset}}]'
               ' in {ns_label} [{{bold}}{ns}{{reset}}]')

        msg += conn_context.location_label

        if function_entrypoint:
            dep_type = 'function [{{bold}}{}{{reset}}]'.format(
                function_entrypoint)
            pretty_print.Info(
                msg.format(operator=conn_context.operator,
                           ns_label=conn_context.ns_label,
                           dep_type=dep_type,
                           function=function_entrypoint,
                           service=service_ref.servicesId,
                           ns=service_ref.namespacesId))
        elif source_ref.source_type is source_ref.SourceType.IMAGE:
            pretty_print.Info(
                msg.format(operator=conn_context.operator,
                           ns_label=conn_context.ns_label,
                           dep_type='container',
                           service=service_ref.servicesId,
                           ns=service_ref.namespacesId))
        else:
            pretty_print.Info(
                msg.format(operator=conn_context.operator,
                           ns_label=conn_context.ns_label,
                           dep_type='app',
                           service=service_ref.servicesId,
                           ns=service_ref.namespacesId))

        with serverless_operations.Connect(conn_context) as operations:
            if not (source_ref.source_type is source_ref.SourceType.IMAGE
                    or operations.IsSourceBranch()):
                raise exceptions.SourceNotSupportedError()
            new_deployable = operations.Detect(service_ref.Parent(),
                                               source_ref, function_entrypoint)
            operations.Upload(new_deployable)
            changes = [new_deployable]
            if config_changes:
                changes.extend(config_changes)
            if args.connectivity == 'internal':
                private_endpoint = True
            elif args.connectivity == 'external':
                private_endpoint = False
            else:
                private_endpoint = None
            deployment_stages = stages.ServiceStages()
            exists = operations.GetService(service_ref)

            if (not exists and not args.allow_unauthenticated
                    and conn_context.supports_one_platform):

                if operations.CanAddIamPolicyBinding(service_ref):
                    allow_unauth = console_io.PromptContinue(
                        prompt_string=('Allow unauthenticated invocations '
                                       'to new service [{}]?'.format(
                                           service_ref.servicesId)),
                        default=False)
                else:
                    allow_unauth = False
                    pretty_print.Info(
                        'This new service will require authentication to be invoked.'
                    )
            else:
                allow_unauth = False

            header = 'Deploying...' if exists else 'Deploying new service...'
            with progress_tracker.StagedProgressTracker(
                    header,
                    deployment_stages,
                    failure_message='Deployment failed',
                    suppress_output=args. async) as tracker:
                operations.ReleaseService(service_ref,
                                          changes,
                                          tracker,
                                          asyn=args. async,
                                          private_endpoint=private_endpoint,
                                          allow_unauthenticated=allow_unauth
                                          or args.allow_unauthenticated)
            if args. async:
                pretty_print.Success(
                    'Service [{{bold}}{serv}{{reset}}] is deploying '
                    'asynchronously.'.format(serv=service_ref.servicesId))
            else:
                url = operations.GetServiceUrl(service_ref)
                conf = operations.GetConfiguration(service_ref)
                msg = ('Service [{{bold}}{serv}{{reset}}] '
                       'revision [{{bold}}{rev}{{reset}}] '
                       'has been deployed and is serving traffic at '
                       '{{bold}}{url}{{reset}}')
                msg = msg.format(serv=service_ref.servicesId,
                                 rev=conf.status.latestReadyRevisionName,
                                 url=url)
                pretty_print.Success(msg)
예제 #20
0
    def Run(self, args):
        """Deploy a container to Cloud Run."""
        image = args.image

        conn_context = connection_context.GetConnectionContext(args)
        config_changes = flags.GetConfigurationChanges(args)

        if conn_context.supports_one_platform:
            flags.VerifyOnePlatformFlags(args)
        else:
            flags.VerifyGKEFlags(args)

        service_ref = flags.GetService(args)

        with serverless_operations.Connect(conn_context) as operations:
            image_change = config_changes_mod.ImageChange(image)
            changes = [image_change]
            if config_changes:
                changes.extend(config_changes)
            endpoint_visibility = flags.GetEndpointVisibility(args)
            exists = operations.GetService(service_ref)
            allow_unauth = None
            if conn_context.supports_one_platform:
                allow_unauth = flags.GetAllowUnauthenticated(
                    args, operations, service_ref, not exists)
                # Don't try to remove a policy binding from a service that doesn't exist
                if not exists and not allow_unauth:
                    allow_unauth = None

            msg = ('Deploying {dep_type} to {operator} '
                   'service [{{bold}}{service}{{reset}}]'
                   ' in {ns_label} [{{bold}}{ns}{{reset}}]')
            msg += conn_context.location_label

            pretty_print.Info(
                msg.format(operator=conn_context.operator,
                           ns_label=conn_context.ns_label,
                           dep_type='container',
                           service=service_ref.servicesId,
                           ns=service_ref.namespacesId))

            deployment_stages = stages.ServiceStages(allow_unauth is not None)
            header = 'Deploying...' if exists else 'Deploying new service...'
            with progress_tracker.StagedProgressTracker(
                    header,
                    deployment_stages,
                    failure_message='Deployment failed',
                    suppress_output=args. async) as tracker:
                operations.ReleaseService(service_ref,
                                          changes,
                                          tracker,
                                          asyn=args. async,
                                          private_endpoint=endpoint_visibility,
                                          allow_unauthenticated=allow_unauth)
            if args. async:
                pretty_print.Success(
                    'Service [{{bold}}{serv}{{reset}}] is deploying '
                    'asynchronously.'.format(serv=service_ref.servicesId))
            else:
                url = operations.GetServiceUrl(service_ref)
                conf = operations.GetConfiguration(service_ref)
                msg = ('Service [{{bold}}{serv}{{reset}}] '
                       'revision [{{bold}}{rev}{{reset}}] '
                       'has been deployed and is serving traffic at '
                       '{{bold}}{url}{{reset}}')
                msg = msg.format(serv=service_ref.servicesId,
                                 rev=conf.status.latestReadyRevisionName,
                                 url=url)
                pretty_print.Success(msg)
예제 #21
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
    def _UpdateOrCreateService(self, service_ref, config_changes, with_code):
        """Apply config_changes to the service. Create it if necessary.

    Arguments:
      service_ref: Reference to the service to create or update
      config_changes: list of ConfigChanger to modify the service with
      with_code: boolean, True if the config_changes contains code to deploy.
        We can't create the service if we're not deploying code.

    Returns:
      The Service object we created or modified.
    """
        nonce = _Nonce()
        config_changes = [_NewRevisionForcingChange(nonce)] + config_changes
        messages = self._messages_module
        # GET the Service
        serv = self.GetService(service_ref)
        try:
            if serv:
                if not with_code:
                    # Avoid changing the running code by making the new revision by digest
                    self._EnsureImageDigest(serv, config_changes)
                # PUT the changed Service
                for config_change in config_changes:
                    config_change.AdjustConfiguration(serv.configuration,
                                                      serv.metadata)
                serv_name = service_ref.RelativeName()
                serv_update_req = (
                    messages.ServerlessNamespacesServicesReplaceServiceRequest(
                        service=serv.Message(), name=serv_name))
                with metrics.record_duration(metrics.UPDATE_SERVICE):
                    updated = self._client.namespaces_services.ReplaceService(
                        serv_update_req)
                return service.Service(updated, messages)

            else:
                if not with_code:
                    raise serverless_exceptions.ServiceNotFoundError(
                        'Service [{}] could not be found.'.format(
                            service_ref.servicesId))
                # POST a new Service
                new_serv = service.Service.New(self._client,
                                               service_ref.namespacesId)
                new_serv.name = service_ref.servicesId
                pretty_print.Info(
                    'Creating new service [{bold}{service}{reset}]',
                    service=new_serv.name)
                parent = service_ref.Parent().RelativeName()
                for config_change in config_changes:
                    config_change.AdjustConfiguration(new_serv.configuration,
                                                      new_serv.metadata)
                serv_create_req = (
                    messages.ServerlessNamespacesServicesCreateRequest(
                        service=new_serv.Message(), parent=parent))
                with metrics.record_duration(metrics.CREATE_SERVICE):
                    raw_service = self._client.namespaces_services.Create(
                        serv_create_req)
                return service.Service(raw_service, messages)
        except api_exceptions.HttpBadRequestError as e:
            error_payload = exceptions_util.HttpErrorPayload(e)
            if error_payload.field_violations:
                if (serverless_exceptions.BadImageError.IMAGE_ERROR_FIELD
                        in error_payload.field_violations):
                    exceptions.reraise(serverless_exceptions.BadImageError(e))
            exceptions.reraise(e)
    def Run(self, args):
        """Deploy a Job to Cloud Run."""
        job_ref = args.CONCEPTS.job.Parse()
        flags.ValidateResource(job_ref)

        conn_context = connection_context.GetConnectionContext(
            args, flags.Product.RUN, self.ReleaseTrack())
        changes = flags.GetJobConfigurationChanges(args)
        changes.append(
            config_changes.SetLaunchStageAnnotationChange(self.ReleaseTrack()))

        execute_now = args.execute_now or args.wait
        execution = None

        with serverless_operations.Connect(conn_context) as operations:
            pretty_print.Info(
                messages_util.GetStartDeployMessage(conn_context, job_ref,
                                                    'Creating', 'job'))
            if execute_now:
                header_msg = 'Creating and running job...'
            else:
                header_msg = 'Creating job...'
            with progress_tracker.StagedProgressTracker(
                    header_msg,
                    stages.JobStages(execute_now=execute_now,
                                     include_completion=args.wait),
                    failure_message='Job failed to deploy',
                    suppress_output=args.async_) as tracker:
                job = operations.CreateJob(job_ref,
                                           changes,
                                           tracker,
                                           asyn=(args.async_
                                                 and not execute_now))
                if execute_now:
                    execution = operations.RunJob(job_ref, args.wait, tracker,
                                                  args.async_)

            if args.async_ and not execute_now:
                pretty_print.Success(
                    'Job [{{bold}}{job}{{reset}}] is being created '
                    'asynchronously.'.format(job=job.name))
            else:
                job = operations.GetJob(job_ref)
                operation = 'been created'
                if args.wait:
                    operation += ' and completed execution [{}]'.format(
                        execution.name)
                elif execute_now:
                    operation += ' and started running execution [{}]'.format(
                        execution.name)

                pretty_print.Success(
                    'Job [{{bold}}{job}{{reset}}] has successfully '
                    '{operation}.'.format(job=job.name, operation=operation))

            msg = ''
            if execute_now:
                msg += messages_util.GetExecutionCreatedMessage(
                    self.ReleaseTrack(), execution)
                msg += '\n'
            msg += messages_util.GetRunJobMessage(self.ReleaseTrack(),
                                                  job.name,
                                                  repeat=execute_now)
            log.status.Print(msg)
            return job
예제 #24
0
    def Run(self, args):
        """Create or Update service from YAML."""
        conn_context = connection_context.GetConnectionContext(
            args, flags.Product.RUN, self.ReleaseTrack())

        with serverless_operations.Connect(conn_context) as client:
            try:
                new_service = service.Service(
                    messages_util.DictToMessageWithErrorCheck(
                        args.FILE, client.messages_module.Service),
                    client.messages_module)
            except messages_util.ScalarTypeMismatchError as e:
                exceptions.MaybeRaiseCustomFieldMismatch(e)

            # If managed, namespace must match project (or will default to project if
            # not specified).
            # If not managed, namespace simply must not conflict if specified in
            # multiple places (or will default to "default" if not specified).
            namespace = args.CONCEPTS.namespace.Parse().Name(
            )  # From flag or default
            if new_service.metadata.namespace is not None:
                if (args.IsSpecified('namespace')
                        and namespace != new_service.metadata.namespace):
                    raise exceptions.ConfigurationError(
                        'Namespace specified in file does not match passed flag.'
                    )
                namespace = new_service.metadata.namespace
                if flags.GetPlatform() == flags.PLATFORM_MANAGED:
                    project = properties.VALUES.core.project.Get()
                    project_number = projects_util.GetProjectNumber(project)
                    if namespace != project and namespace != str(
                            project_number):
                        raise exceptions.ConfigurationError(
                            'Namespace must be project ID [{}] or quoted number [{}] for '
                            'Cloud Run (fully managed).'.format(
                                project, project_number))
            new_service.metadata.namespace = namespace

            changes = [
                config_changes.ReplaceServiceChange(new_service),
                config_changes.SetLaunchStageAnnotationChange(
                    self.ReleaseTrack())
            ]
            service_ref = resources.REGISTRY.Parse(
                new_service.metadata.name,
                params={'namespacesId': new_service.metadata.namespace},
                collection='run.namespaces.services')
            service_obj = client.GetService(service_ref)

            pretty_print.Info(
                run_messages_util.GetStartDeployMessage(
                    conn_context,
                    service_ref,
                    operation='Applying new configuration'))

            deployment_stages = stages.ServiceStages()
            header = ('Deploying...'
                      if service_obj else 'Deploying new service...')
            with progress_tracker.StagedProgressTracker(
                    header,
                    deployment_stages,
                    failure_message='Deployment failed',
                    suppress_output=args.async_) as tracker:
                service_obj = client.ReleaseService(service_ref,
                                                    changes,
                                                    tracker,
                                                    asyn=args.async_,
                                                    allow_unauthenticated=None,
                                                    for_replace=True)
            if args.async_:
                pretty_print.Success(
                    'New configuration for [{{bold}}{serv}{{reset}}] is being applied '
                    'asynchronously.'.format(serv=service_obj.name))
            else:
                service_obj = client.GetService(service_ref)
                pretty_print.Success(
                    'New configuration has been applied to service '
                    '[{{bold}}{serv}{{reset}}].\n'
                    'URL: {{bold}}{url}{{reset}}'.format(
                        serv=service_obj.name, url=service_obj.domain))
            return service_obj