Ejemplo n.º 1
0
def VerifyGKEFlags(args):
    """Raise ConfigurationError if args includes OnePlatform only arguments."""
    error_msg = ('The `{flag}` flag is not supported with Cloud Run on GKE. '
                 'Specify `--platform {platform}` or run `gcloud config set '
                 'run/platform {platform}` to work with {platform_desc}.')

    if _FlagIsExplicitlySet(args, 'allow_unauthenticated'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(flag='--allow-unauthenticated',
                             platform='managed',
                             platform_desc='the managed version of Cloud Run'))

    if _FlagIsExplicitlySet(args, 'service_account'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(flag='--service-account',
                             platform='managed',
                             platform_desc='the managed version of Cloud Run'))

    if _FlagIsExplicitlySet(args, 'region'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(flag='--region',
                             platform='managed',
                             platform_desc='the managed version of Cloud Run'))

    if _FlagIsExplicitlySet(args, 'kubeconfig'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(flag='--kubeconfig',
                             platform='kubernetes',
                             platform_desc='a Kubernetes cluster'))

    if _FlagIsExplicitlySet(args, 'context'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(flag='--context',
                             platform='kubernetes',
                             platform_desc='a Kubernetes cluster'))
Ejemplo n.º 2
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))
    def _OmittedSecretKeyDefault(self, name):
        """The key/version value to use for a secret flag that has no version.

    Args:
      name: The env var or mount point, for use in an error message.

    Returns:
      str value to use as the secret version.

    Raises:
      ConfigurationError: If the key is required on this platform.
    """
        if self.force_managed or platforms.IsManaged():
            # Service returns an error for this, but we can make a better one.
            raise exceptions.ConfigurationError(
                'No secret version specified for {name}. '
                'Use {name}:latest to reference the latest version.'.format(
                    name=name))
        else:  # for GKE+K8S
            if self._connector is SpecialConnector.PATH_OR_ENV:
                raise TypeError(
                    "Can't determine default key for secret named %r." % name)

            if not self._connector.startswith('/'):
                raise exceptions.ConfigurationError(
                    'Missing required item key for the secret at [{}].'.format(
                        name))
            else:  # for a mount point
                return SpecialVersion.MOUNT_ALL
Ejemplo n.º 4
0
def VerifyOnePlatformFlags(args):
    """Raise ConfigurationError if args includes GKE only arguments."""
    if getattr(args, 'connectivity', None):
        raise serverless_exceptions.ConfigurationError(
            'The `--connectivity=[internal|external]` flag '
            'is not supported on OnePlatform.')

    if getattr(args, 'cpu', None):
        raise serverless_exceptions.ConfigurationError(
            'The `--cpu flag is not supported on OnePlatform.')
Ejemplo n.º 5
0
def VerifyGKEFlags(args):
    """Raise ConfigurationError if args includes OnePlatform only arguments."""
    if getattr(args, 'allow_unauthenticated', None):
        raise serverless_exceptions.ConfigurationError(
            'The `--allow-unauthenticated` flag '
            'is not supported with Cloud Run on GKE.')

    if getattr(args, 'service_account', None):
        raise serverless_exceptions.ConfigurationError(
            'The `--service-account` flag '
            'is not supported with Cloud Run on GKE.')
Ejemplo n.º 6
0
    def Adjust(self, resource):
        """Mutates the given config's volumes to match the desired changes."""
        volumes_of_type = getattr(resource.template.volumes, self._type)
        if self._clear_others:
            # Delete all mounts that are mounting the volumes we're deleting
            for path, name in list(resource.template.volume_mounts.items()):
                if name in volumes_of_type:
                    del resource.template.volume_mounts[path]
        elif self._to_remove:
            for path in self._to_remove:
                if path in resource.template.volume_mounts:
                    volume_name = resource.template.volume_mounts[path]
                    # Ensure the mount is mounting a volume of the right type
                    if self._VolumeNotOfType(volume_name, resource):
                        raise exceptions.ConfigurationError(
                            'Cannot remove mount [{}] with volume [{}] because the volume '
                            'is in use with a different type.'.format(
                                path, volume_name))
                    del resource.template.volume_mounts[path]

        if self._to_update:
            for path, split_name in self._to_update.items():
                volume_name = split_name[-1]
                reference_name = split_name[0]
                existing_volume_name = None
                # Ensure if exists, volume currently mounted is of the right type
                if path in resource.template.volume_mounts:
                    existing_volume_name = resource.template.volume_mounts[
                        path]
                    if self._VolumeNotOfType(existing_volume_name, resource):
                        raise exceptions.ConfigurationError(
                            'Cannot update mount [{}] with volume [{}] because the volume '
                            'is in use with a different type.'.format(
                                path, existing_volume_name))
                # Ensure if exists, volume we want to mount is of the right type
                if self._VolumeNotOfType(volume_name, resource):
                    raise exceptions.ConfigurationError(
                        'Cannot update mount [{}] to volume [{}] because the volume '
                        'is already is in use with a different type.'.format(
                            path, volume_name))
                resource.template.volume_mounts[path] = volume_name
                volumes_of_type[volume_name] = reference_name

        # Delete all volumes no longer being mounted
        for volume in list(volumes_of_type):
            if not any(n == volume
                       for n in resource.template.volume_mounts.values()):
                del volumes_of_type[volume]
Ejemplo n.º 7
0
    def _Prompt(self, parsed_args):
        """Fallthrough to reading the cluster location from an interactive prompt.

    Only prompt for cluster location if the user-specified platform is GKE
    and if cluster name is already defined.

    Args:
      parsed_args: Namespace, the args namespace.

    Returns:
      A cluster location string
    """
        cluster_name = (getattr(parsed_args, 'cluster', None)
                        or properties.VALUES.run.cluster.Get())
        if flags.IsGKE(parsed_args) and cluster_name:
            clusters = [
                c for c in global_methods.ListClusters()
                if c.name == cluster_name
            ]
            if not clusters:
                raise exceptions.ConfigurationError(
                    'No cluster locations found for cluster [{}]. '
                    'Ensure your clusters have Cloud Run on GKE enabled.'.
                    format(cluster_name))
            cluster_locations = [c.zone for c in clusters]
            idx = console_io.PromptChoice(
                cluster_locations,
                message='GKE cluster location for [{}]:'.format(cluster_name),
                cancel_option=True)
            location = cluster_locations[idx]
            log.status.Print(
                'To make this the default cluster location, run '
                '`gcloud config set run/cluster_location {}`.\n'.format(
                    location))
            return location
Ejemplo n.º 8
0
    def _Prompt(self, parsed_args):
        """Fallthrough to reading the cluster name from an interactive prompt.

    Only prompt for cluster name if cluster location is already defined.

    Args:
      parsed_args: Namespace, the args namespace.

    Returns:
      A cluster name string
    """
        cluster_location = (getattr(parsed_args, 'cluster_location', None)
                            or properties.VALUES.run.cluster_location.Get())

        if cluster_location:
            clusters = global_methods.ListClusters(cluster_location)
            if not clusters:
                raise exceptions.ConfigurationError(
                    'No clusters found for cluster location [{}]. '
                    'Ensure your clusters have Cloud Run on GKE enabled.'.
                    format(cluster_location))
            cluster_names = [c.name for c in clusters]
            idx = console_io.PromptChoice(cluster_names,
                                          message='GKE cluster name:',
                                          cancel_option=True)
            name = cluster_names[idx]
            log.status.Print(
                'To make this the default cluster, run '
                '`gcloud config set run/cluster {}`.\n'.format(name))
            return name
Ejemplo n.º 9
0
  def __init__(self, env_vars_to_update=None,
               env_vars_to_remove=None, clear_others=False):
    """Initialize a new EnvVarSourceChanges object.

    Args:
      env_vars_to_update: {str, str}, Update env var names and values.
      env_vars_to_remove: [str], List of env vars to remove.
      clear_others: bool, If true, clear all non-updated env vars.

    Raises:
      ConfigurationError if a key hasn't been provided for a source.
    """
    self._to_update = None
    self._to_remove = None
    self._clear_others = clear_others
    if env_vars_to_update:
      self._to_update = {}
      for k, v in env_vars_to_update.items():
        name = k.strip()
        # Split the given values into 2 parts:
        #    [env var source name, source data item key]
        value = v.split(':', 1)
        if len(value) < 2:
          raise exceptions.ConfigurationError(
              'Missing required item key for environment variable [{}].'
              .format(name))
        self._to_update[name] = value
    if env_vars_to_remove:
      self._to_remove = [k.lstrip() for k in env_vars_to_remove]
Ejemplo n.º 10
0
    def Adjust(self, resource):
        """Mutates the given config's env vars to match the desired changes.

    Args:
      resource: k8s_object to adjust

    Returns:
      The adjusted resource

    Raises:
      ConfigurationError if there's an attempt to replace the source of an
        existing environment variable whose source is of a different type
        (e.g. env var's secret source can't be replaced with a config map
        source).
    """
        _PruneMapping(resource.template.env_vars.literals, self._removes,
                      self._clear_others)

        try:
            resource.template.env_vars.literals.update(self._updates)
        except KeyError as e:
            raise exceptions.ConfigurationError(
                'Cannot update environment variable [{}] to string literal '
                'because it has already been set with a different type.'.
                format(e.args[0]))
        return resource
Ejemplo n.º 11
0
    def WaitForCondition(self, poller):
        """Wait for a configuration to be ready in latest revision.

    Args:
      poller: A ConditionPoller object.

    Returns:
      A condition.Conditions object.

    Raises:
      RetryException: Max retry limit exceeded.
      ConfigurationError: configuration failed to
    """

        try:
            return waiter.PollUntilDone(poller, None, wait_ceiling_ms=1000)
        except retry.RetryException as err:
            conditions = poller.GetConditions()
            # err.message already indicates timeout. Check ready_cond_type for more
            # information.
            msg = conditions.DescriptiveMessage() if conditions else None
            if msg:
                log.error('Still waiting: {}'.format(msg))
            raise err
        if not conditions.IsReady():
            raise serverless_exceptions.ConfigurationError(
                conditions.DescriptiveMessage())
Ejemplo n.º 12
0
 def WaitForCondition(self, getter):
   """Wait for a configuration to be ready in latest revision."""
   stages = _ServiceStages()
   with progress_tracker.StagedProgressTracker(
       'Deploying...',
       stages.values(),
       failure_message='Deployment failed') as tracker:
     config_poller = ConditionPoller(getter, tracker, stages, dependencies={
         'RoutesReady': {'ConfigurationsReady'},
     })
     try:
       conditions = waiter.PollUntilDone(
           config_poller, None,
           wait_ceiling_ms=1000)
     except retry.RetryException as err:
       conditions = config_poller.GetConditions()
       # err.message already indicates timeout. Check ready_cond_type for more
       # information.
       msg = conditions.DescriptiveMessage() if conditions else None
       if msg:
         log.error('Still waiting: {}'.format(msg))
       raise err
     if not conditions.IsReady():
       raise serverless_exceptions.ConfigurationError(
           conditions.DescriptiveMessage())
Ejemplo n.º 13
0
    def Adjust(self, resource):
        """Mutates the given config's env vars to match the desired changes.

    Args:
      resource: k8s_object to adjust

    Returns:
      The adjusted resource

    Raises:
      ConfigurationError if there's an attempt to replace the source of an
        existing environment variable whose source is of a different type
        (e.g. env var's secret source can't be replaced with a config map
        source).
    """
        env_vars = resource.template.env_vars.config_maps
        _PruneMapping(env_vars, self._removes, self._clear_others)

        for name, (source_name, source_key) in self._updates.items():
            try:
                env_vars[name] = self._MakeEnvVarSource(
                    resource.MessagesModule(), source_name, source_key)
            except KeyError:
                raise exceptions.ConfigurationError(
                    'Cannot update environment variable [{}] to the given type '
                    'because it has already been set with a different type.'.
                    format(name))
        return resource
Ejemplo n.º 14
0
  def _Prompt(self, parsed_args):
    """Fallthrough to reading the cluster name from an interactive prompt.

    Only prompt for cluster name if the user-specified platform is GKE.

    Args:
      parsed_args: Namespace, the args namespace.

    Returns:
      A cluster name string
    """
    if platforms.GetPlatform() != platforms.PLATFORM_GKE:
      return

    project = properties.VALUES.core.project.Get(required=True)
    cluster_location = (
        getattr(parsed_args, 'cluster_location', None) or
        properties.VALUES.run.cluster_location.Get())
    cluster_location_msg = ' in [{}]'.format(
        cluster_location) if cluster_location else ''

    cluster_refs = global_methods.MultiTenantClustersForProject(
        project, cluster_location)
    if not cluster_refs:
      raise exceptions.ConfigurationError(
          'No compatible clusters found{}. '
          'Ensure your cluster has Cloud Run enabled.'.format(
              cluster_location_msg))

    cluster_refs_descs = [
        self._GetClusterDescription(c, cluster_location, project)
        for c in cluster_refs
    ]

    idx = console_io.PromptChoice(
        cluster_refs_descs,
        message='GKE cluster{}:'.format(cluster_location_msg),
        cancel_option=True)

    cluster_ref = cluster_refs[idx]

    if cluster_location:
      location_help_text = ''
    else:
      location_help_text = (
          ' && gcloud config set run/cluster_location {}'.format(
              cluster_ref.zone))

    cluster_name = cluster_ref.Name()

    if cluster_ref.projectId != project:
      cluster_name = cluster_ref.RelativeName()
      location_help_text = ''

    log.status.Print('To make this the default cluster, run '
                     '`gcloud config set run/cluster {cluster}'
                     '{location}`.\n'.format(
                         cluster=cluster_name, location=location_help_text))
    return cluster_ref.SelfLink()
Ejemplo n.º 15
0
  def _Prompt(self, parsed_args):
    """Fallthrough to reading the cluster name from an interactive prompt.

    Only prompt for cluster name if the user-specified platform is GKE.

    Args:
      parsed_args: Namespace, the args namespace.

    Returns:
      A cluster name string
    """
    if flags.IsGKE(parsed_args):
      cluster_location = (
          getattr(parsed_args, 'cluster_location', None) or
          properties.VALUES.run.cluster_location.Get())
      cluster_location_msg = ' in [{}]'.format(
          cluster_location) if cluster_location else ''

      clusters = global_methods.ListClusters(cluster_location)
      if not clusters:
        raise exceptions.ConfigurationError(
            'No compatible clusters found{}. '
            'Ensure your cluster has Cloud Run on GKE enabled.'.format(
                cluster_location_msg))

      def _GetClusterDescription(cluster):
        """Description of cluster for prompt."""
        if cluster_location:
          return cluster.name
        return '{} in {}'.format(cluster.name, cluster.zone)

      cluster_descs = [_GetClusterDescription(c) for c in clusters]

      idx = console_io.PromptChoice(
          cluster_descs,
          message='GKE cluster{}:'.format(cluster_location_msg),
          cancel_option=True)
      cluster = clusters[idx]

      if cluster_location:
        cluster_result = cluster.name
        location_help_text = ''
      else:
        cluster_ref = flags.GetClusterRef(cluster)
        cluster_result = cluster_ref.SelfLink()
        location_help_text = (
            ' && gcloud config set run/cluster_location {}'.format(
                cluster.zone))
      log.status.Print(
          'To make this the default cluster, run '
          '`gcloud config set run/cluster {cluster}'
          '{location}`.\n'.format(
              cluster=cluster.name,
              location=location_help_text))
      return cluster_result
Ejemplo n.º 16
0
def VerifyKubernetesFlags(args, release_track, product):
  """Raise ConfigurationError if args includes OnePlatform or GKE only arguments."""
  error_msg = ('The `{flag}` flag is not supported with Cloud Run for Anthos '
               'deployed on VMware. Specify `--platform {platform}` or run '
               '`gcloud config set run/platform {platform}` to work with '
               '{platform_desc}.')

  if _FlagIsExplicitlySet(args, 'allow_unauthenticated'):
    raise serverless_exceptions.ConfigurationError(
        error_msg.format(
            flag='--allow-unauthenticated',
            platform=PLATFORM_MANAGED,
            platform_desc=_PLATFORM_SHORT_DESCRIPTIONS[PLATFORM_MANAGED]))

  if (release_track != base.ReleaseTrack.ALPHA and
      _FlagIsExplicitlySet(args, 'service_account') and
      product == Product.RUN):
    raise serverless_exceptions.ConfigurationError(
        error_msg.format(
            flag='--service-account',
            platform=PLATFORM_MANAGED,
            platform_desc=_PLATFORM_SHORT_DESCRIPTIONS[PLATFORM_MANAGED]))

  if _FlagIsExplicitlySet(args, 'region'):
    raise serverless_exceptions.ConfigurationError(
        error_msg.format(
            flag='--region',
            platform=PLATFORM_MANAGED,
            platform_desc=_PLATFORM_SHORT_DESCRIPTIONS[PLATFORM_MANAGED]))

  if _FlagIsExplicitlySet(args, 'vpc_connector'):
    raise serverless_exceptions.ConfigurationError(
        error_msg.format(
            flag='--vpc-connector',
            platform='managed',
            platform_desc=_PLATFORM_SHORT_DESCRIPTIONS['managed']))

  if _FlagIsExplicitlySet(args, 'clear_vpc_connector'):
    raise serverless_exceptions.ConfigurationError(
        error_msg.format(
            flag='--clear-vpc-connector',
            platform=PLATFORM_MANAGED,
            platform_desc=_PLATFORM_SHORT_DESCRIPTIONS[PLATFORM_MANAGED]))

  if _FlagIsExplicitlySet(args, 'cluster'):
    raise serverless_exceptions.ConfigurationError(
        error_msg.format(
            flag='--cluster',
            platform=PLATFORM_GKE,
            platform_desc=_PLATFORM_SHORT_DESCRIPTIONS[PLATFORM_GKE]))

  if _FlagIsExplicitlySet(args, 'cluster_location'):
    raise serverless_exceptions.ConfigurationError(
        error_msg.format(
            flag='--cluster-location',
            platform=PLATFORM_GKE,
            platform_desc=_PLATFORM_SHORT_DESCRIPTIONS[PLATFORM_GKE]))
Ejemplo n.º 17
0
    def Run(self, args):
        conn_context = connection_context.GetConnectionContext(args)
        if conn_context.supports_one_platform:
            raise exceptions.ConfigurationError(
                'Triggers are not yet supported on the fully managed version '
                'of Cloud Run.')

        namespace_ref = args.CONCEPTS.namespace.Parse()
        with eventflow_operations.Connect(conn_context) as client:
            self.SetCompleteApiEndpoint(conn_context.endpoint)
            return client.ListTriggers(namespace_ref)
Ejemplo n.º 18
0
def VerifyOnePlatformFlags(args):
    """Raise ConfigurationError if args includes GKE only arguments."""
    error_msg = (
        'The `{flag}` flag is not supported on the fully managed '
        'version of Cloud Run. Specify `--platform {platform}` or run '
        '`gcloud config set run/platform {platform}` to work with '
        '{platform_desc}.')

    if _FlagIsExplicitlySet(args, 'connectivity'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(
                flag='--connectivity=[internal|external]',
                platform='gke',
                platform_desc=_PLATFORM_SHORT_DESCRIPTIONS['gke']))

    if _FlagIsExplicitlySet(args, 'cpu'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(
                flag='--cpu',
                platform='gke',
                platform_desc=_PLATFORM_SHORT_DESCRIPTIONS['gke']))

    if _FlagIsExplicitlySet(args, 'namespace'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(
                flag='--namespace',
                platform='gke',
                platform_desc=_PLATFORM_SHORT_DESCRIPTIONS['gke']))

    if _FlagIsExplicitlySet(args, 'cluster'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(
                flag='--cluster',
                platform='gke',
                platform_desc=_PLATFORM_SHORT_DESCRIPTIONS['gke']))

    if _FlagIsExplicitlySet(args, 'cluster_location'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(
                flag='--cluster-location',
                platform='gke',
                platform_desc=_PLATFORM_SHORT_DESCRIPTIONS['gke']))

    if _FlagIsExplicitlySet(args, 'kubeconfig'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(
                flag='--kubeconfig',
                platform='kubernetes',
                platform_desc=_PLATFORM_SHORT_DESCRIPTIONS['kubernetes']))

    if _FlagIsExplicitlySet(args, 'context'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(
                flag='--context',
                platform='kubernetes',
                platform_desc=_PLATFORM_SHORT_DESCRIPTIONS['kubernetes']))
Ejemplo n.º 19
0
def VerifyGKEFlags(args, release_track):
  """Raise ConfigurationError if args includes OnePlatform only arguments."""
  del release_track  # not currently checked by any flags
  error_msg = ('The `{flag}` flag is not supported with Cloud Run for Anthos '
               'deployed on Google Cloud. Specify `--platform {platform}` or '
               'run `gcloud config set run/platform {platform}` to work with '
               '{platform_desc}.')

  if _FlagIsExplicitlySet(args, 'allow_unauthenticated'):
    raise serverless_exceptions.ConfigurationError(
        error_msg.format(
            flag='--allow-unauthenticated',
            platform=PLATFORM_MANAGED,
            platform_desc=_PLATFORM_SHORT_DESCRIPTIONS[PLATFORM_MANAGED]))

  if _FlagIsExplicitlySet(args, 'service_account'):
    raise serverless_exceptions.ConfigurationError(
        error_msg.format(
            flag='--service-account',
            platform=PLATFORM_MANAGED,
            platform_desc=_PLATFORM_SHORT_DESCRIPTIONS[PLATFORM_MANAGED]))

  if _FlagIsExplicitlySet(args, 'region'):
    raise serverless_exceptions.ConfigurationError(
        error_msg.format(
            flag='--region',
            platform=PLATFORM_MANAGED,
            platform_desc=_PLATFORM_SHORT_DESCRIPTIONS[PLATFORM_MANAGED]))

  if _FlagIsExplicitlySet(args, 'vpc_connector'):
    raise serverless_exceptions.ConfigurationError(
        error_msg.format(
            flag='--vpc-connector',
            platform=PLATFORM_MANAGED,
            platform_desc=_PLATFORM_SHORT_DESCRIPTIONS[PLATFORM_MANAGED]))

  if _FlagIsExplicitlySet(args, 'clear_vpc_connector'):
    raise serverless_exceptions.ConfigurationError(
        error_msg.format(
            flag='--clear-vpc-connector',
            platform=PLATFORM_MANAGED,
            platform_desc=_PLATFORM_SHORT_DESCRIPTIONS[PLATFORM_MANAGED]))

  if _FlagIsExplicitlySet(args, 'kubeconfig'):
    raise serverless_exceptions.ConfigurationError(
        error_msg.format(
            flag='--kubeconfig',
            platform=PLATFORM_KUBERNETES,
            platform_desc=_PLATFORM_SHORT_DESCRIPTIONS[PLATFORM_KUBERNETES]))

  if _FlagIsExplicitlySet(args, 'context'):
    raise serverless_exceptions.ConfigurationError(
        error_msg.format(
            flag='--context',
            platform=PLATFORM_KUBERNETES,
            platform_desc=_PLATFORM_SHORT_DESCRIPTIONS[PLATFORM_KUBERNETES]))
Ejemplo n.º 20
0
def ValidateClusterArgs(args):
    """Raise an error if a cluster is provided with no region or vice versa.

  Args:
    args: Namespace, The args namespace.

  Raises:
    ConfigurationError if a cluster is specified without a location or a
    location is specified without a cluster.
  """
    cluster_name = args.cluster or properties.VALUES.run.cluster.Get()
    cluster_location = (args.cluster_location
                        or properties.VALUES.run.cluster_location.Get())
    error_msg = ('Connecting to a cluster requires a {} to be specified. '
                 'Either set the {} property or use the `{}` flag.')
    if cluster_name and not cluster_location:
        raise serverless_exceptions.ConfigurationError(
            error_msg.format('cluster location', 'run/cluster_location',
                             '--cluster-location'))
    if cluster_location and not cluster_name:
        raise serverless_exceptions.ConfigurationError(
            error_msg.format('cluster name', 'run/cluster', '--cluster'))
Ejemplo n.º 21
0
    def Adjust(self, resource):
        """Mutates the given config's volumes to match the desired changes.

    Args:
      resource: k8s_object to adjust

    Returns:
      The adjusted resource

    Raises:
      ConfigurationError if there's an attempt to replace the volume a mount
        points to whose existing volume has a source of a different type than
        the new volume (e.g. mount that points to a volume with a secret source
        can't be replaced with a volume that has a config map source).
    """
        volume_mounts = self._GetVolumeMounts(resource)
        volumes = self._GetVolumes(resource)

        if self._clear_others:
            volume_mounts.clear()
        elif self._to_remove:
            for path in self._to_remove:
                if path in volume_mounts:
                    del volume_mounts[path]

        if self._to_update:
            for path, (source_name, source_key) in self._to_update.items():
                # Generate unique volume name so that volume source configurations
                # can be unique (e.g. different items) even if the source name matches
                volume_name = None
                while volume_name is None or volume_name in resource.template.volumes:
                    volume_name = _GenerateVolumeName(source_name)

                # volume_mounts is a special mapping that filters for the current kind
                # of mount and KeyErrors on existing keys with other types.
                try:
                    volume_mounts[path] = volume_name
                except KeyError:
                    raise exceptions.ConfigurationError(
                        'Cannot update mount [{}] because its mounted volume '
                        'is of a different source type.'.format(path))
                volumes[volume_name] = self._MakeVolumeSource(
                    resource.MessagesModule(), source_name, source_key)

        # Delete all volumes no longer being mounted
        for volume in list(volumes):
            if volume not in volume_mounts.values():
                del volumes[volume]

        return resource
Ejemplo n.º 22
0
  def Adjust(self, resource):
    """Removes LATEST from the services traffic assignments."""
    if resource.configuration:
      raise exceptions.UnsupportedOperationError(
          'This service is using an old version of Cloud Run for Anthos '
          'that does not support traffic features. Please upgrade to 0.8 '
          'or later.')

    if not resource.generation:
      raise exceptions.ConfigurationError(
          '--no-traffic not supported when creating a new service.')

    resource.traffic.ZeroLatestTraffic(resource.status.latestReadyRevisionName)
    return resource
    def Adjust(self, resource):
        """Mutates the given config's volumes to match the desired changes.

    Args:
      resource: k8s_object to adjust

    Returns:
      The adjusted resource

    Raises:
      ConfigurationError if there's an attempt to replace the volume a mount
        points to whose existing volume has a source of a different type than
        the new volume (e.g. mount that points to a volume with a secret source
        can't be replaced with a volume that has a config map source).
    """
        volume_mounts = resource.template.volume_mounts.secrets
        volumes = resource.template.volumes.secrets

        # TODO(b/182412304): This is not going to work on secrets in the same dir
        # (but it could be made to work if they're versions of one secret.)
        if platforms.IsManaged():
            removes = [p.rsplit('/', 1)[0] for p in self._removes]
        else:
            removes = self._removes

        _PruneMapping(volume_mounts, removes, self._clear_others)

        for file_path, reachable_secret in self._updates.items():
            volume_name = _UniqueVolumeName(reachable_secret.secret_name,
                                            resource.template.volumes)

            # volume_mounts is a special mapping that filters for the current kind
            # of mount and KeyErrors on existing keys with other types.
            try:
                mount_point = file_path
                if platforms.IsManaged():
                    # TODO(b/182412304): SubPath handling is not ready.
                    mount_point = file_path.rsplit('/', 1)[0]
                volume_mounts[mount_point] = volume_name
            except KeyError:
                raise exceptions.ConfigurationError(
                    'Cannot update mount [{}] because its mounted volume '
                    'is of a different source type.'.format(file_path))
            volumes[volume_name] = reachable_secret.AsSecretVolumeSource(
                resource)

        _PruneVolumes(volume_mounts, volumes)
        secrets_mapping.PruneAnnotation(resource)
        return resource
Ejemplo n.º 24
0
def VerifyKubernetesFlags(args):
    """Raise ConfigurationError if args includes OnePlatform or GKE only arguments."""
    error_msg = ('The `{flag}` flag is not supported when connecting to a '
                 'Kubenetes cluster. Specify `--platform {platform}` or run '
                 '`gcloud config set run/platform {platform}` to work with '
                 '{platform_desc}.')

    if _FlagIsExplicitlySet(args, 'allow_unauthenticated'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(flag='--allow-unauthenticated',
                             platform='managed',
                             platform_desc='the managed version of Cloud Run'))

    if _FlagIsExplicitlySet(args, 'service_account'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(flag='--service-account',
                             platform='managed',
                             platform_desc='the managed version of Cloud Run'))

    if _FlagIsExplicitlySet(args, 'region'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(flag='--region',
                             platform='managed',
                             platform_desc='the managed version of Cloud Run'))

    if _FlagIsExplicitlySet(args, 'cluster'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(flag='--cluster',
                             platform='gke',
                             platform_desc='Cloud Run on GKE'))

    if _FlagIsExplicitlySet(args, 'cluster_location'):
        raise serverless_exceptions.ConfigurationError(
            error_msg.format(flag='--cluster-location',
                             platform='gke',
                             platform_desc='Cloud Run on GKE'))
    def GetResourceTypeFromConfig(self, resource_config):
        """Gets the resource type.

    The input is converted from proto with "oneof" property. Thus the dictionary
    is expected to have only one key, matching the type of the matching oneof.

    Args:
      resource_config: dict, the resource configuration.

    Returns:
      str, the integration type.
    """
        keys = list(resource_config.keys())
        if len(keys) != 1:
            raise exceptions.ConfigurationError(
                'resource config is invalid: {}.'.format(resource_config))
        return keys[0]
Ejemplo n.º 26
0
def ValidateClearVpcConnector(service, args):
    """Validates that the VPC connector can be safely removed.

  Does nothing if 'clear_vpc_connector' is not present in args with value True.

  Args:
    service: A Cloud Run service object.
    args: Namespace object containing the specified command line arguments.

  Raises:
    exceptions.ConfigurationError: If the command cannot prompt and
      VPC egress is set to 'all' or 'all-traffic'.
    console_io.OperationCancelledError: If the user answers no to the
      confirmation prompt.
  """
    if (service is None
            or not flags.FlagIsExplicitlySet(args, 'clear_vpc_connector')
            or not args.clear_vpc_connector):
        return

    if flags.FlagIsExplicitlySet(args, 'vpc_egress'):
        egress = args.vpc_egress
    elif container_resource.EGRESS_SETTINGS_ANNOTATION in service.template_annotations:
        egress = service.template_annotations[
            container_resource.EGRESS_SETTINGS_ANNOTATION]
    else:
        # --vpc-egress flag not specified and egress settings not set on service.
        return

    if (egress != container_resource.EGRESS_SETTINGS_ALL
            and egress != container_resource.EGRESS_SETTINGS_ALL_TRAFFIC):
        return

    if console_io.CanPrompt():
        console_io.PromptContinue(
            message=
            'Removing the VPC connector from this service will clear the '
            'VPC egress setting and route outbound traffic to the public internet.',
            default=False,
            cancel_on_no=True)
    else:
        raise exceptions.ConfigurationError(
            'Cannot remove VPC connector with VPC egress set to "{}". Set'
            ' `--vpc-egress=private-ranges-only` or run this command '
            'interactively and provide confirmation to continue.'.format(
                egress))
Ejemplo n.º 27
0
def ValidateClusterArgs(args):
    """Raise an error if a cluster is provided with no region.

  Args:
    args: Namespace, The args namespace.

  Raises:
    ConfigurationError if a cluster is specified without a location.
  """
    cluster_name = properties.VALUES.run.cluster.Get() or args.cluster
    cluster_location = (properties.VALUES.run.cluster_location.Get()
                        or args.cluster_location)
    if cluster_name and not cluster_location:
        raise serverless_exceptions.ConfigurationError(
            'Connecting to a cluster requires a cluster location to be specified.'
            'Either set the run/cluster_location property '
            'or use the --cluster-location flag.')
Ejemplo n.º 28
0
 def Adjust(self, resource):
   """Mutates the given service's traffic assignments."""
   if self._tags_to_update or self._tags_to_remove or self._clear_other_tags:
     resource.spec_traffic.UpdateTags(self._tags_to_update,
                                      self._tags_to_remove,
                                      self._clear_other_tags)
   if self._new_percentages:
     if self._by_tag:
       tag_to_key = resource.spec_traffic.TagToKey()
       percentages = {}
       for tag in self._new_percentages:
         try:
           percentages[tag_to_key[tag]] = self._new_percentages[tag]
         except KeyError:
           raise exceptions.ConfigurationError(
               'There is no revision tagged with [{}] in the traffic allocation for [{}].'
               .format(tag, resource.name))
     else:
       percentages = self._new_percentages
     resource.spec_traffic.UpdateTraffic(percentages)
   return resource
Ejemplo n.º 29
0
    def Adjust(self, resource):
        """Mutates the given config's volumes to match the desired changes.

    Args:
      resource: k8s_object to adjust

    Returns:
      The adjusted resource

    Raises:
      ConfigurationError if there's an attempt to replace the volume a mount
        points to whose existing volume has a source of a different type than
        the new volume (e.g. mount that points to a volume with a secret source
        can't be replaced with a volume that has a config map source).
    """
        volume_mounts = resource.template.volume_mounts.config_maps
        volumes = resource.template.volumes.config_maps

        _PruneMapping(volume_mounts, self._removes, self._clear_others)

        for path, (source_name, source_key) in self._updates.items():
            volume_name = _UniqueVolumeName(source_name,
                                            resource.template.volumes)

            # volume_mounts is a special mapping that filters for the current kind
            # of mount and KeyErrors on existing keys with other types.
            try:
                volume_mounts[path] = volume_name
            except KeyError:
                raise exceptions.ConfigurationError(
                    'Cannot update mount [{}] because its mounted volume '
                    'is of a different source type.'.format(path))
            volumes[volume_name] = self._MakeVolumeSource(
                resource.MessagesModule(), source_name, source_key)

        _PruneVolumes(volume_mounts, volumes)

        return resource
    def WaitForCondition(self, getter):
        """Wait for a configuration to be ready in latest revision."""
        with progress_tracker.StagedProgressTracker(
                'Deploying...',
                _CONDITION_TO_STAGE.values(),
                failure_message='Deployment failed') as tracker:
            for stage in _CONDITION_TO_STAGE.values():
                tracker.StartStage(stage)

            config_poller = ConditionPoller(getter, tracker)
            try:
                conditions = waiter.PollUntilDone(config_poller, None)
            except retry.RetryException as err:
                conditions = config_poller.GetConditions()
                # err.message already indicates timeout. Check ready_cond_type for more
                # information.
                msg = conditions.DescriptiveMessage() if conditions else None
                if msg:
                    log.error('Still waiting: {}'.format(msg))
                raise err
            if not conditions.IsReady():
                raise serverless_exceptions.ConfigurationError(
                    conditions.DescriptiveMessage())