726 lines
21 KiB
Python
726 lines
21 KiB
Python
# -*- coding: utf-8 -*- #
|
|
# Copyright 2018 Google LLC. All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
"""Shared resource flags for Cloud Run commands."""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import print_function
|
|
from __future__ import unicode_literals
|
|
|
|
import abc
|
|
import copy
|
|
import os
|
|
import re
|
|
|
|
from googlecloudsdk.api_lib.run import global_methods
|
|
from googlecloudsdk.calliope.concepts import concepts
|
|
from googlecloudsdk.calliope.concepts import deps
|
|
from googlecloudsdk.calliope.concepts import util as concepts_util
|
|
from googlecloudsdk.command_lib.run import exceptions
|
|
from googlecloudsdk.command_lib.run import platforms
|
|
from googlecloudsdk.command_lib.util.concepts import presentation_specs
|
|
from googlecloudsdk.core import log
|
|
from googlecloudsdk.core import properties
|
|
from googlecloudsdk.core import resources
|
|
from googlecloudsdk.core.console import console_io
|
|
|
|
|
|
class PromptFallthrough(deps.Fallthrough):
|
|
"""Fall through to reading from an interactive prompt."""
|
|
|
|
def __init__(self, hint):
|
|
super(PromptFallthrough, self).__init__(function=None, hint=hint)
|
|
|
|
@abc.abstractmethod
|
|
def _Prompt(self, parsed_args):
|
|
pass
|
|
|
|
def _Call(self, parsed_args):
|
|
if not console_io.CanPrompt():
|
|
return None
|
|
return self._Prompt(parsed_args)
|
|
|
|
|
|
def _GenerateServiceName(image):
|
|
"""Produce a valid default service name from a container image path.
|
|
|
|
Converts a file path or image path into a reasonable default service name by
|
|
stripping file path delimeters, image tags, and image hashes.
|
|
For example, the image name 'gcr.io/myproject/myimage:latest' would produce
|
|
the service name 'myimage'.
|
|
|
|
Args:
|
|
image: str, The container path.
|
|
|
|
Returns:
|
|
A valid Cloud Run service name.
|
|
"""
|
|
base_name = os.path.basename(image.rstrip(os.sep))
|
|
base_name = base_name.split(':')[0] # Discard image tag if present.
|
|
base_name = base_name.split('@')[0] # Disacard image hash if present.
|
|
# Remove non-supported special characters.
|
|
return re.sub(r'[^a-zA-Z0-9-]', '', base_name).strip('-').lower()
|
|
|
|
|
|
def _GenerateServiceNameFromLocalPath(source):
|
|
"""Produce a valid default service name from a local file or directory path.
|
|
|
|
Converts a file or directory path into a reasonable default service name by
|
|
resolving relative paths to absolute paths, removing any extensions, and then
|
|
removing any invalid characters.
|
|
|
|
For example, the paths /tmp/foo/bar/.. and /tmp/foo.tar.gz would both produce
|
|
the service name 'foo'. A source path of "." will be expanded to the current
|
|
directory name."
|
|
|
|
Args:
|
|
source: str, The file or directory path.
|
|
|
|
Returns:
|
|
A valid Cloud Run service name.
|
|
"""
|
|
path, ext = os.path.splitext(os.path.abspath(source))
|
|
while ext:
|
|
path, ext = os.path.splitext(path)
|
|
return _GenerateServiceName(path)
|
|
|
|
|
|
class ResourcePromptFallthrough(PromptFallthrough):
|
|
"""Fall through to reading the resource name from an interactive prompt."""
|
|
|
|
def __init__(self, resource_type_lower):
|
|
super(ResourcePromptFallthrough, self).__init__(
|
|
'specify the {} name from an interactive prompt'.format(
|
|
resource_type_lower
|
|
)
|
|
)
|
|
self.resource_type_lower = resource_type_lower
|
|
|
|
def _Prompt(self, parsed_args):
|
|
message = self.resource_type_lower.capitalize() + ' name'
|
|
default_name = self._DefaultNameFromArgs(parsed_args)
|
|
return console_io.PromptWithDefault(message=message, default=default_name)
|
|
|
|
def _DefaultNameFromArgs(self, parsed_args):
|
|
if getattr(parsed_args, 'image', None):
|
|
return _GenerateServiceName(parsed_args.image)
|
|
elif getattr(parsed_args, 'source', None):
|
|
return _GenerateServiceNameFromLocalPath(parsed_args.source)
|
|
return ''
|
|
|
|
|
|
class RegionPromptFallthrough(PromptFallthrough):
|
|
"""Fall through to reading the region from an interactive prompt."""
|
|
|
|
def __init__(self):
|
|
super(RegionPromptFallthrough, self).__init__(
|
|
'specify the region from an interactive prompt'
|
|
)
|
|
|
|
def _Prompt(self, parsed_args):
|
|
client = global_methods.GetServerlessClientInstance()
|
|
all_regions = global_methods.ListRegions(client)
|
|
idx = console_io.PromptChoice(
|
|
all_regions,
|
|
message='Please specify a region:\n',
|
|
cancel_option=True,
|
|
allow_freeform=True,
|
|
)
|
|
region = all_regions[idx]
|
|
log.status.Print(
|
|
'To make this the default region, run '
|
|
'`gcloud config set run/region {}`.\n'.format(region)
|
|
)
|
|
if region:
|
|
parsed_args.region = region
|
|
return region
|
|
|
|
|
|
class ServicePromptFallthrough(ResourcePromptFallthrough):
|
|
|
|
def __init__(self):
|
|
super(ServicePromptFallthrough, self).__init__('service')
|
|
|
|
|
|
class WorkerPoolPromptFallthrough(ResourcePromptFallthrough):
|
|
|
|
def __init__(self):
|
|
super(WorkerPoolPromptFallthrough, self).__init__('workerpool')
|
|
|
|
|
|
class JobPromptFallthrough(ResourcePromptFallthrough):
|
|
|
|
def __init__(self):
|
|
super(JobPromptFallthrough, self).__init__('job')
|
|
|
|
|
|
class InstancePromptFallthrough(ResourcePromptFallthrough):
|
|
|
|
def __init__(self):
|
|
super(InstancePromptFallthrough, self).__init__('instance')
|
|
|
|
|
|
class ExecutionPromptFallthrough(ResourcePromptFallthrough):
|
|
|
|
def __init__(self):
|
|
super(ExecutionPromptFallthrough, self).__init__('execution')
|
|
|
|
|
|
class DefaultFallthrough(deps.Fallthrough):
|
|
"""Use the namespace "default".
|
|
|
|
For Knative only.
|
|
|
|
For Cloud Run, raises an ArgumentError if project not set.
|
|
"""
|
|
|
|
def __init__(self):
|
|
super(DefaultFallthrough, self).__init__(
|
|
function=None,
|
|
hint=(
|
|
'For Cloud Run on Kubernetes Engine, defaults to "default". '
|
|
'Otherwise, defaults to project ID.'
|
|
),
|
|
)
|
|
|
|
def _Call(self, parsed_args):
|
|
if (
|
|
platforms.GetPlatform() == platforms.PLATFORM_GKE
|
|
or platforms.GetPlatform() == platforms.PLATFORM_KUBERNETES
|
|
):
|
|
return 'default'
|
|
elif not (
|
|
getattr(parsed_args, 'project', None)
|
|
or properties.VALUES.core.project.Get()
|
|
):
|
|
# HACK: Compensate for how "namespace" is actually "project" in Cloud Run
|
|
# by providing an error message explicitly early here.
|
|
raise exceptions.ArgumentError(
|
|
'The [project] resource is not properly specified. '
|
|
'Please specify the argument [--project] on the command line or '
|
|
'set the property [core/project].'
|
|
)
|
|
return None
|
|
|
|
|
|
def NamespaceAttributeConfig():
|
|
return concepts.ResourceParameterAttributeConfig(
|
|
name='namespace',
|
|
help_text=(
|
|
'Specific to Cloud Run for Anthos: '
|
|
'Kubernetes namespace for the {resource}.'
|
|
),
|
|
fallthroughs=[
|
|
deps.PropertyFallthrough(properties.VALUES.run.namespace),
|
|
DefaultFallthrough(),
|
|
deps.ArgFallthrough('project'),
|
|
deps.PropertyFallthrough(properties.VALUES.core.project),
|
|
],
|
|
)
|
|
|
|
|
|
def ProjectAttributeConfig():
|
|
project_attribute_config = copy.deepcopy(
|
|
concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG
|
|
)
|
|
fallthroughs = [
|
|
DefaultFallthrough()
|
|
] + concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG.fallthroughs
|
|
project_attribute_config.fallthroughs = fallthroughs
|
|
return project_attribute_config
|
|
|
|
|
|
def ServiceAttributeConfig(prompt=False):
|
|
"""Attribute config with fallthrough prompt only if requested."""
|
|
if prompt:
|
|
fallthroughs = [ServicePromptFallthrough()]
|
|
else:
|
|
fallthroughs = []
|
|
return concepts.ResourceParameterAttributeConfig(
|
|
name='service',
|
|
help_text='Service for the {resource}.',
|
|
fallthroughs=fallthroughs,
|
|
)
|
|
|
|
|
|
def WorkerPoolAttributeConfig(prompt=False):
|
|
"""Attribute config with fallthrough prompt only if requested."""
|
|
if prompt:
|
|
fallthroughs = [WorkerPoolPromptFallthrough()]
|
|
else:
|
|
fallthroughs = []
|
|
return concepts.ResourceParameterAttributeConfig(
|
|
name='worker-pool',
|
|
help_text='WorkerPool for the {resource}.',
|
|
fallthroughs=fallthroughs,
|
|
)
|
|
|
|
|
|
def ConfigurationAttributeConfig():
|
|
return concepts.ResourceParameterAttributeConfig(
|
|
name='configuration', help_text='Configuration for the {resource}.'
|
|
)
|
|
|
|
|
|
def RouteAttributeConfig():
|
|
return concepts.ResourceParameterAttributeConfig(
|
|
name='route', help_text='Route for the {resource}.'
|
|
)
|
|
|
|
|
|
def RevisionAttributeConfig():
|
|
return concepts.ResourceParameterAttributeConfig(
|
|
name='revision', help_text='Revision for the {resource}.'
|
|
)
|
|
|
|
|
|
def DomainAttributeConfig():
|
|
return concepts.ResourceParameterAttributeConfig(
|
|
name='domain', help_text='Name of the domain to be mapped to.'
|
|
)
|
|
|
|
|
|
def JobAttributeConfig(prompt=False):
|
|
if prompt:
|
|
fallthroughs = [JobPromptFallthrough()]
|
|
else:
|
|
fallthroughs = []
|
|
return concepts.ResourceParameterAttributeConfig(
|
|
name='jobs',
|
|
help_text='Job for the {resource}.',
|
|
fallthroughs=fallthroughs,
|
|
)
|
|
|
|
|
|
def InstanceAttributeConfig(prompt=False):
|
|
if prompt:
|
|
fallthroughs = [InstancePromptFallthrough()]
|
|
else:
|
|
fallthroughs = []
|
|
return concepts.ResourceParameterAttributeConfig(
|
|
name='instances',
|
|
help_text='Instance for the {resource}.',
|
|
fallthroughs=fallthroughs,
|
|
)
|
|
|
|
|
|
def ExecutionAttributeConfig(prompt=False):
|
|
if prompt:
|
|
fallthroughs = [ExecutionPromptFallthrough()]
|
|
else:
|
|
fallthroughs = []
|
|
return concepts.ResourceParameterAttributeConfig(
|
|
name='executions', help_text='Execution.', fallthroughs=fallthroughs
|
|
)
|
|
|
|
|
|
class TaskExecutionAndIndexFallthrough(deps.ArgFallthrough):
|
|
"""Allow the user to provide --execution and --index to find a task."""
|
|
|
|
def __init__(self, arg_name, plural=False):
|
|
super(TaskExecutionAndIndexFallthrough, self).__init__(
|
|
'provide the arguments `{}` and `index` on the command line'.format(
|
|
arg_name
|
|
),
|
|
active=True,
|
|
plural=plural,
|
|
)
|
|
self.arg_name = arg_name
|
|
|
|
def _Call(self, parsed_args):
|
|
prefix = getattr(
|
|
parsed_args, concepts_util.NamespaceFormat(self.arg_name), None
|
|
)
|
|
index = getattr(parsed_args, 'index', None)
|
|
return '{}-{}'.format(prefix, index)
|
|
|
|
|
|
def TaskAttributeConfig(prompt=False):
|
|
if prompt:
|
|
fallthroughs = [TaskExecutionAndIndexFallthrough('task')]
|
|
else:
|
|
fallthroughs = []
|
|
return concepts.ResourceParameterAttributeConfig(
|
|
name='tasks', help_text='Task.', fallthroughs=fallthroughs
|
|
)
|
|
|
|
|
|
def LocationAttributeConfig():
|
|
return concepts.ResourceParameterAttributeConfig(
|
|
name='region',
|
|
help_text=(
|
|
'The Cloud region for the {resource}. Overrides the default '
|
|
'`run/region` property value for this command invocation.'
|
|
),
|
|
fallthroughs=[
|
|
deps.ArgFallthrough('--region'),
|
|
deps.PropertyFallthrough(properties.VALUES.run.region),
|
|
RegionPromptFallthrough(),
|
|
],
|
|
)
|
|
|
|
|
|
class ClusterPromptFallthrough(PromptFallthrough):
|
|
"""Fall through to reading the cluster name from an interactive prompt."""
|
|
|
|
def __init__(self):
|
|
super(ClusterPromptFallthrough, self).__init__(
|
|
'specify the cluster from a list of available clusters'
|
|
)
|
|
|
|
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()
|
|
|
|
def _GetClusterDescription(self, cluster, cluster_location, project):
|
|
"""Description of cluster for prompt."""
|
|
|
|
response = cluster.Name()
|
|
if not cluster_location:
|
|
response = '{} in {}'.format(response, cluster.zone)
|
|
if project != cluster.projectId:
|
|
response = '{} in {}'.format(response, cluster.projectId)
|
|
|
|
return response
|
|
|
|
|
|
def ClusterAttributeConfig():
|
|
return concepts.ResourceParameterAttributeConfig(
|
|
name='cluster',
|
|
help_text=(
|
|
'Name of the Kubernetes Engine cluster to use. '
|
|
'Alternatively, set the property [run/cluster].'
|
|
),
|
|
fallthroughs=[
|
|
deps.PropertyFallthrough(properties.VALUES.run.cluster),
|
|
ClusterPromptFallthrough(),
|
|
],
|
|
)
|
|
|
|
|
|
class ClusterLocationPromptFallthrough(PromptFallthrough):
|
|
"""Fall through to reading the cluster name from an interactive prompt."""
|
|
|
|
def __init__(self):
|
|
super(ClusterLocationPromptFallthrough, self).__init__(
|
|
'specify the cluster location from a list of available zones'
|
|
)
|
|
|
|
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 platforms.GetPlatform() == platforms.PLATFORM_GKE 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 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
|
|
|
|
|
|
def ClusterLocationAttributeConfig():
|
|
return concepts.ResourceParameterAttributeConfig(
|
|
name='location',
|
|
help_text=(
|
|
'Zone in which the {resource} is located. '
|
|
'Alternatively, set the property [run/cluster_location].'
|
|
),
|
|
fallthroughs=[
|
|
deps.PropertyFallthrough(properties.VALUES.run.cluster_location),
|
|
ClusterLocationPromptFallthrough(),
|
|
],
|
|
)
|
|
|
|
|
|
def GetClusterResourceSpec():
|
|
return concepts.ResourceSpec(
|
|
'container.projects.zones.clusters',
|
|
projectId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
|
|
zone=ClusterLocationAttributeConfig(),
|
|
clusterId=ClusterAttributeConfig(),
|
|
resource_name='cluster',
|
|
)
|
|
|
|
|
|
def GetServiceResourceSpec(prompt=False):
|
|
return concepts.ResourceSpec(
|
|
'run.namespaces.services',
|
|
namespacesId=NamespaceAttributeConfig(),
|
|
servicesId=ServiceAttributeConfig(prompt),
|
|
resource_name='service',
|
|
)
|
|
|
|
|
|
def GetConfigurationResourceSpec():
|
|
return concepts.ResourceSpec(
|
|
'run.namespaces.configurations',
|
|
namespacesId=NamespaceAttributeConfig(),
|
|
configurationsId=ConfigurationAttributeConfig(),
|
|
resource_name='configuration',
|
|
)
|
|
|
|
|
|
def GetRouteResourceSpec():
|
|
return concepts.ResourceSpec(
|
|
'run.namespaces.routes',
|
|
namespacesId=NamespaceAttributeConfig(),
|
|
routesId=RouteAttributeConfig(),
|
|
resource_name='route',
|
|
)
|
|
|
|
|
|
# For Worker Pool revisions, we don't use the namespace attribute.
|
|
def GetRevisionResourceSpec(is_worker_pool_revision=False):
|
|
return concepts.ResourceSpec(
|
|
'run.namespaces.revisions',
|
|
namespacesId=NamespaceAttributeConfig()
|
|
if not is_worker_pool_revision
|
|
else concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
|
|
revisionsId=RevisionAttributeConfig(),
|
|
resource_name='revision',
|
|
)
|
|
|
|
|
|
def GetDomainMappingResourceSpec():
|
|
return concepts.ResourceSpec(
|
|
'run.namespaces.domainmappings',
|
|
namespacesId=NamespaceAttributeConfig(),
|
|
domainmappingsId=DomainAttributeConfig(),
|
|
resource_name='DomainMapping',
|
|
)
|
|
|
|
|
|
def GetJobResourceSpec(prompt=False):
|
|
return concepts.ResourceSpec(
|
|
'run.namespaces.jobs',
|
|
namespacesId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
|
|
jobsId=JobAttributeConfig(prompt=prompt),
|
|
resource_name='Job',
|
|
api_version='v1',
|
|
)
|
|
|
|
|
|
def GetInstanceResourceSpec(prompt=False):
|
|
return concepts.ResourceSpec(
|
|
'run.namespaces.instances',
|
|
namespacesId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
|
|
instancesId=InstanceAttributeConfig(prompt=prompt),
|
|
resource_name='Instance',
|
|
api_version='v1',
|
|
)
|
|
|
|
|
|
def GetExecutionResourceSpec(prompt=False):
|
|
return concepts.ResourceSpec(
|
|
'run.namespaces.executions',
|
|
namespacesId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
|
|
executionsId=ExecutionAttributeConfig(prompt=prompt),
|
|
resource_name='Execution',
|
|
api_version='v1',
|
|
)
|
|
|
|
|
|
def GetTaskResourceSpec(prompt=False):
|
|
return concepts.ResourceSpec(
|
|
'run.namespaces.tasks',
|
|
namespacesId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
|
|
tasksId=TaskAttributeConfig(prompt=prompt),
|
|
resource_name='Task',
|
|
api_version='v1',
|
|
)
|
|
|
|
|
|
def GetV1WorkerPoolResourceSpec(prompt=False):
|
|
return concepts.ResourceSpec(
|
|
'run.namespaces.workerpools',
|
|
namespacesId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
|
|
workerpoolsId=WorkerPoolAttributeConfig(prompt),
|
|
resource_name='WorkerPool',
|
|
api_version='v1',
|
|
)
|
|
|
|
|
|
def GetV2WorkerPoolResourceSpec(prompt=False):
|
|
return concepts.ResourceSpec(
|
|
'run.projects.locations.workerPools',
|
|
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
|
|
locationsId=LocationAttributeConfig(),
|
|
workerPoolsId=WorkerPoolAttributeConfig(prompt),
|
|
resource_name='WorkerPool',
|
|
api_version='v2',
|
|
)
|
|
|
|
|
|
def GetV2WorkerPoolRevisionResourceSpec(prompt=False):
|
|
return concepts.ResourceSpec(
|
|
'run.projects.locations.workerPools.revisions',
|
|
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
|
|
locationsId=LocationAttributeConfig(),
|
|
workerPoolsId=WorkerPoolAttributeConfig(prompt),
|
|
revisionsId=RevisionAttributeConfig(),
|
|
resource_name='WorkerPoolRevision',
|
|
api_version='v2',
|
|
)
|
|
|
|
|
|
def GetProjectResourceSpec():
|
|
return concepts.ResourceSpec(
|
|
'run.projects',
|
|
resource_name='project',
|
|
projectsId=ProjectAttributeConfig(),
|
|
)
|
|
|
|
|
|
def GetRegionResourceSpec():
|
|
return concepts.ResourceSpec(
|
|
'run.projects.locations',
|
|
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
|
|
locationsId=LocationAttributeConfig(),
|
|
resource_name='Region',
|
|
api_version='v2',
|
|
)
|
|
|
|
|
|
def GetNamespaceResourceSpec():
|
|
"""Returns a resource spec for the namespace."""
|
|
# TODO(b/148817410): Remove this when the api has been split.
|
|
# This try/except block is needed because the v1alpha1 and v1 run apis
|
|
# have different collection names for the namespaces.
|
|
try:
|
|
return concepts.ResourceSpec(
|
|
'run.namespaces',
|
|
namespacesId=NamespaceAttributeConfig(),
|
|
resource_name='namespace',
|
|
)
|
|
except resources.InvalidCollectionException:
|
|
return concepts.ResourceSpec(
|
|
'run.api.v1.namespaces',
|
|
namespacesId=NamespaceAttributeConfig(),
|
|
resource_name='namespace',
|
|
)
|
|
|
|
|
|
CLUSTER_PRESENTATION = presentation_specs.ResourcePresentationSpec(
|
|
'--cluster',
|
|
GetClusterResourceSpec(),
|
|
'Kubernetes Engine cluster to connect to.',
|
|
hidden=True,
|
|
required=False,
|
|
prefixes=True,
|
|
)
|
|
|
|
REGION_PRESENTATION = presentation_specs.ResourcePresentationSpec(
|
|
'--region',
|
|
GetRegionResourceSpec(),
|
|
'Cloud region to use.',
|
|
hidden=True,
|
|
required=False,
|
|
prefixes=True,
|
|
)
|