def _UpdateOrCreateService(
      self, service_ref, config_changes, with_code, serv):
    """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.
      serv: service.Service, For update the Service to update and for
        create None.

    Returns:
      The Service object we created or modified.
    """
    messages = self.messages_module
    try:
      if serv:
        # PUT the changed Service
        for config_change in config_changes:
          serv = config_change.Adjust(serv)
        serv_name = service_ref.RelativeName()
        serv_update_req = (
            messages.RunNamespacesServicesReplaceServiceRequest(
                service=serv.Message(),
                name=serv_name))
        with metrics.RecordDuration(metric_names.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
        parent = service_ref.Parent().RelativeName()
        for config_change in config_changes:
          new_serv = config_change.Adjust(new_serv)
        serv_create_req = (
            messages.RunNamespacesServicesCreateRequest(
                service=new_serv.Message(),
                parent=parent))
        with metrics.RecordDuration(metric_names.CREATE_SERVICE):
          raw_service = self._client.namespaces_services.Create(
              serv_create_req)
        return service.Service(raw_service, messages)
    except api_exceptions.HttpBadRequestError as e:
      exceptions.reraise(serverless_exceptions.HttpError(e))
    except api_exceptions.HttpNotFoundError as e:
      platform = properties.VALUES.run.platform.Get()
      error_msg = 'Deployment endpoint was not found.'
      if platform == 'gke':
        all_clusters = global_methods.ListClusters()
        clusters = ['* {} in {}'.format(c.name, c.zone) for c in all_clusters]
        error_msg += (' Perhaps the provided cluster was invalid or '
                      'does not have Cloud Run enabled. Pass the '
                      '`--cluster` and `--cluster-location` flags or set the '
                      '`run/cluster` and `run/cluster_location` properties to '
                      'a valid cluster and zone and retry.'
                      '\nAvailable clusters:\n{}'.format('\n'.join(clusters)))
      elif platform == 'managed':
        all_regions = global_methods.ListRegions(self._op_client)
        if self._region not in all_regions:
          regions = ['* {}'.format(r) for r in all_regions]
          error_msg += (' The provided region was invalid. '
                        'Pass the `--region` flag or set the '
                        '`run/region` property to a valid region and retry.'
                        '\nAvailable regions:\n{}'.format('\n'.join(regions)))
      elif platform == 'kubernetes':
        error_msg += (' Perhaps the provided cluster was invalid or '
                      'does not have Cloud Run enabled. Ensure in your '
                      'kubeconfig file that the cluster referenced in '
                      'the current context or the specified context '
                      'is a valid cluster and retry.')
      raise serverless_exceptions.DeploymentFailedError(error_msg)
    except api_exceptions.HttpError as e:
      platform = properties.VALUES.run.platform.Get()
      if platform == 'managed':
        exceptions.reraise(e)
      k8s_error = serverless_exceptions.KubernetesExceptionParser(e)
      causes = '\n\n'.join([c['message'] for c in k8s_error.causes])
      if not causes:
        causes = k8s_error.error
      raise serverless_exceptions.KubernetesError('Error{}:\n{}\n'.format(
          's' if len(k8s_error.causes) > 1 else '', causes))
    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: bool, 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),
            _SetClientNameAndVersion()
        ] + 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)

                # Revision names must be unique across the namespace.
                # To prevent the revision name being unchanged from the last revision,
                # we reset the value so the default naming scheme will be used instead.
                serv.template.name = None

                # PUT the changed Service
                for config_change in config_changes:
                    config_change.Adjust(serv)
                serv_name = service_ref.RelativeName()
                serv_update_req = (
                    messages.RunNamespacesServicesReplaceServiceRequest(
                        service=serv.Message(), name=serv_name))
                with metrics.RecordDuration(metric_names.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
                parent = service_ref.Parent().RelativeName()
                for config_change in config_changes:
                    config_change.Adjust(new_serv)
                serv_create_req = (messages.RunNamespacesServicesCreateRequest(
                    service=new_serv.Message(), parent=parent))
                with metrics.RecordDuration(metric_names.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))
                elif (serverless_exceptions.MalformedLabelError.
                      LABEL_ERROR_FIELD in error_payload.field_violations):
                    exceptions.reraise(
                        serverless_exceptions.MalformedLabelError(e))
            exceptions.reraise(e)
        except api_exceptions.HttpNotFoundError as e:
            platform = properties.VALUES.run.platform.Get()
            error_msg = 'Deployment endpoint was not found.'
            if platform == 'gke':
                all_clusters = global_methods.ListClusters()
                clusters = [
                    '* {} in {}'.format(c.name, c.zone) for c in all_clusters
                ]
                error_msg += (
                    ' Perhaps the provided cluster was invalid or '
                    'does not have Cloud Run enabled. Pass the '
                    '`--cluster` and `--cluster-location` flags or set the '
                    '`run/cluster` and `run/cluster_location` properties to '
                    'a valid cluster and zone and retry.'
                    '\nAvailable clusters:\n{}'.format('\n'.join(clusters)))
            elif platform == 'managed':
                all_regions = global_methods.ListRegions(self._op_client)
                if self._region not in all_regions:
                    regions = ['* {}'.format(r) for r in all_regions]
                    error_msg += (
                        ' The provided region was invalid. '
                        'Pass the `--region` flag or set the '
                        '`run/region` property to a valid region and retry.'
                        '\nAvailable regions:\n{}'.format('\n'.join(regions)))
            elif platform == 'kubernetes':
                error_msg += (
                    ' Perhaps the provided cluster was invalid or '
                    'does not have Cloud Run enabled. Ensure in your '
                    'kubeconfig file that the cluster referenced in '
                    'the current context or the specified context '
                    'is a valid cluster and retry.')
            raise serverless_exceptions.DeploymentFailedError(error_msg)
        except api_exceptions.HttpError as e:
            k8s_error = serverless_exceptions.KubernetesExceptionParser(e)
            raise serverless_exceptions.KubernetesError(
                'Error{}:\n{}\n'.format(
                    's' if len(k8s_error.causes) > 1 else '',
                    '\n\n'.join([c['message'] for c in k8s_error.causes])))