feat: Add new gcloud commands, API clients, and third-party libraries across various services.

This commit is contained in:
2026-01-01 20:26:35 +01:00
parent 5e23cbece0
commit a19e592eb7
25221 changed files with 8324611 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*- #
# Copyright 2022 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.
"""The command group for clusters resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Clusters(base.Group):
"""Manage Kubernetes Edge clusters."""

View File

@@ -0,0 +1,159 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 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.
"""Command to create a GDCE cluster."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.edge_cloud.container import cluster
from googlecloudsdk.api_lib.edge_cloud.container import util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.edge_cloud.container import flags as container_flags
from googlecloudsdk.command_lib.edge_cloud.container import print_warning
from googlecloudsdk.command_lib.edge_cloud.container import resource_args
from googlecloudsdk.command_lib.run import flags
from googlecloudsdk.core import log
from googlecloudsdk.core import resources
_EXAMPLES = """
To create a cluster called `my-cluster` in region us-central1,
run:
$ {command} my-cluster --location=us-central1
"""
_API_REFERENCE_ = """
This command uses the edgecontainer/{API} API. The full documentation for this
API can be found at: https://cloud.google.com/edge-cloud
"""
_RCP_LRO_MAXIMUM_TIMEOUT_ = 1800000 # 30 min
_LCP_LRO_MAXIMUM_TIMEOUT_ = 36000000 # 10 hours
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Create(base.CreateCommand):
"""Create an Edge Container cluster."""
detailed_help = {
'EXAMPLES': _EXAMPLES,
'API REFERENCE': _API_REFERENCE_.format(
API=util.VERSION_MAP.get(base.ReleaseTrack.GA)
),
}
@staticmethod
def Args(parser):
resource_args.AddClusterResourceArg(parser, 'to create')
container_flags.AddAdminUsers(parser)
container_flags.AddClusterIPV4CIDR(parser)
container_flags.AddServicesIPV4CIDR(parser)
container_flags.AddDefaultMaxPodsPerNode(parser)
container_flags.AddFleetProject(parser)
container_flags.AddLabels(parser)
container_flags.AddMaintenanceWindowRecurrence(parser)
container_flags.AddMaintenanceWindowEnd(parser)
container_flags.AddMaintenanceWindowStart(parser)
container_flags.AddControlPlaneKMSKey(parser)
container_flags.AddLROMaximumTimeout(parser)
container_flags.AddSystemAddonsConfig(parser)
container_flags.AddExternalLbIpv4AddressPools(parser)
container_flags.AddControlPlaneNodeLocation(parser)
container_flags.AddControlPlaneNodeCount(parser)
container_flags.AddControlPlaneNodeStorageSchema(parser)
container_flags.AddControlPlaneMachineFilter(parser)
container_flags.AddControlPlaneSharedDeploymentPolicy(parser)
container_flags.AddOfflineRebootTtL(parser)
container_flags.AddReleaseChannel(parser)
container_flags.AddVersion(parser)
container_flags.AddZoneStorageKMSKey(parser)
container_flags.AddContainerDefaultRuntimeClass(parser)
container_flags.AddEnableGoogleGroupAuthentication(parser)
base.ASYNC_FLAG.AddToParser(parser)
def Run(self, args):
cluster_ref = cluster.GetClusterReference(args)
req = cluster.GetClusterCreateRequest(args, self.ReleaseTrack())
error = cluster.ValidateClusterCreateRequest(req, self.ReleaseTrack())
if error is not None:
log.error(error)
return None
cluster_client = util.GetClientInstance(self.ReleaseTrack())
op = cluster_client.projects_locations_clusters.Create(req)
op_ref = resources.REGISTRY.ParseRelativeName(
op.name, collection='edgecontainer.projects.locations.operations'
)
log.status.Print(
'Create request issued for: [{cluster}]'.format(
cluster=cluster_ref.clustersId
)
)
if not flags.FlagIsExplicitlySet(args, 'async_'):
progress_string = (
'Waiting for operation [{operation}] to complete'.format(
operation=op_ref.RelativeName()
)
)
operation_poller = util.OperationPoller(
cluster_client.projects_locations_clusters,
cluster_client.projects_locations_operations,
)
lro_maximum_timeout = _RCP_LRO_MAXIMUM_TIMEOUT_
if cluster.IsLCPCluster(args):
lro_maximum_timeout = _LCP_LRO_MAXIMUM_TIMEOUT_
if flags.FlagIsExplicitlySet(args, 'lro_timeout'):
lro_maximum_timeout = int(args.lro_timeout)
response = waiter.WaitFor(
operation_poller,
op_ref,
progress_string,
max_wait_ms=lro_maximum_timeout,
)
log.status.Print(
'Created cluster [{cluster}].'.format(cluster=cluster_ref.clustersId)
)
return print_warning.PrintWarning(response, None)
log.status.Print(
'Check operation [{operation}] for status.'.format(
operation=op_ref.RelativeName()
)
)
return print_warning.PrintWarning(op, None)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class CreateAlpha(Create):
"""Create an Edge Container cluster."""
@staticmethod
def Args(parser, track=base.ReleaseTrack.ALPHA):
"""Registers alpha track flags for this command."""
Create.detailed_help['API REFERENCE'] = _API_REFERENCE_.format(
API=util.VERSION_MAP.get(track)
)
Create.Args(parser)
container_flags.AddClusterIPV6CIDR(parser)
container_flags.AddServicesIPV6CIDR(parser)
container_flags.AddExternalLbIpv6AddressPools(parser)
container_flags.AddExternalLoadBalancerAddressPools(parser)
container_flags.AddEnableClusterIsolation(parser)
container_flags.AddEnableRemoteBackup(parser)
container_flags.AddEnableRobinCNS(parser)
container_flags.AddControlPlaneNodeSystemPartitionSize(parser)

View File

@@ -0,0 +1,25 @@
- release_tracks: [ALPHA, GA]
help_text:
brief: Delete an Edge Container cluster.
description: |
Delete an Edge Container cluster.
examples: |
To delete a cluster called 'my-cluster' in region us-central1, run:
$ {command} my-cluster --location=us-central1
request:
collection: edgecontainer.projects.locations.clusters
ALPHA:
api_version: v1alpha
GA:
api_version: v1
arguments:
resource:
help_text: Edge Container cluster to delete.
spec: !REF googlecloudsdk.command_lib.edge_cloud.container.resources:cluster
async:
collection: edgecontainer.projects.locations.operations

View File

@@ -0,0 +1,21 @@
- release_tracks: [ALPHA, GA]
help_text:
brief: Show details about the cluster.
description: Show details about the cluster.
examples: |
To show details about a cluster called 'my-cluster' in region us-central1, run:
$ {command} my-cluster --location=us-central1
request:
collection: edgecontainer.projects.locations.clusters
ALPHA:
api_version: v1alpha
GA:
api_version: v1
arguments:
resource:
help_text: The cluster you want to describe.
spec: !REF googlecloudsdk.command_lib.edge_cloud.container.resources:cluster

View File

@@ -0,0 +1,107 @@
# -*- coding: utf-8 -*- #
# Copyright 2022 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.
"""Command to get credentials of a GEC cluster."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container import util as container_util
from googlecloudsdk.api_lib.edge_cloud.container import cluster
from googlecloudsdk.api_lib.edge_cloud.container import util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.edge_cloud.container import flags
from googlecloudsdk.command_lib.edge_cloud.container import kubeconfig
from googlecloudsdk.command_lib.edge_cloud.container import resource_args
from googlecloudsdk.core import log
from googlecloudsdk.core import resources
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class GetCredentials(base.Command):
"""Get credentials of an edge-container cluster."""
detailed_help = {
'EXAMPLES': kubeconfig.COMMAND_EXAMPLE,
'DESCRIPTION': kubeconfig.COMMAND_DESCRIPTION.format(
kind='Edge Container'
),
}
@classmethod
def Args(cls, parser):
resource_args.AddClusterResourceArg(parser, 'to get credentials')
flags.AddAuthProviderCmdPath(parser)
flags.AddOfflineCredential(parser)
def Run(self, args):
"""Runs the get-credentials command."""
container_util.CheckKubectlInstalled()
cluster_ref = resources.REGISTRY.ParseRelativeName(
args.CONCEPTS.cluster.Parse().RelativeName(),
collection='edgecontainer.projects.locations.clusters',
)
messages = util.GetMessagesModule(self.ReleaseTrack())
cluster_client = util.GetClientInstance(self.ReleaseTrack())
req = messages.EdgecontainerProjectsLocationsClustersGetRequest(
name=cluster_ref.RelativeName()
)
resp = cluster_client.projects_locations_clusters.Get(req)
context = kubeconfig.GenerateContext(
cluster_ref.projectsId, cluster_ref.locationsId, cluster_ref.clustersId
)
if cluster.IsOfflineCredential(args):
if resp.controlPlane is None or resp.controlPlane.local is None:
log.error(
'Offline credential is currently supported only in local '
'control plane cluster'
)
return None
offline_credential_req = (
messages.EdgecontainerProjectsLocationsClustersGenerateOfflineCredentialRequest()
)
offline_credential_req.cluster = cluster_ref.RelativeName()
offline_credential_resp = (
cluster_client.projects_locations_clusters.GenerateOfflineCredential(
offline_credential_req
)
)
context += '_' + offline_credential_resp.userId + '_offline'
kubeconfig.GenerateKubeconfigForOfflineCredential(
resp, context, offline_credential_resp
)
log.warning(
'This offline credential will expire at '
+ offline_credential_resp.expireTime
)
else:
cmd_args = kubeconfig.GenerateAuthProviderCmdArgs(
self.ReleaseTrack(),
cluster_ref.clustersId,
cluster_ref.projectsId,
cluster_ref.locationsId,
)
exec_auth_args = kubeconfig.GenerateExecAuthCmdArgs(
cluster_ref.clustersId,
cluster_ref.projectsId,
cluster_ref.locationsId,
)
kubeconfig.GenerateKubeconfig(
resp, context, args.auth_provider_cmd_path, cmd_args, exec_auth_args
)

View File

@@ -0,0 +1,138 @@
# -*- coding: utf-8 -*- #
# Copyright 2024 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.
"""Command to list GDCE clusters."""
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.edge_cloud.container import util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.edge_cloud.container import resource_args
from googlecloudsdk.core import log
from googlecloudsdk.core import properties
from googlecloudsdk.core import resources
DETAILED_HELP = {
'DESCRIPTION':
"""\
List Edge Container clusters.
""",
'EXAMPLES':
"""\
To list the clusters in region us-central1, run:
$ {command} --location=us-central1
""",
'API REFERENCE':
"""\
This command uses the edgecontainer/v1alpha API. The full documentation for\
this API can be found at: https://cloud.google.com/edge-cloud
""",
}
DISPLAY_TABLE = '''
table(
name.basename():label=NAME,
endpoint:label=ENDPOINT,
labels:label=LABELS,
controlPlaneVersion:label=CONTROL_PLANE_VERSION,
nodeVersion:label=NODE_VERSION,
createTime.date():label=CREATED
)
'''
CLUSTERS_COLLECTION_NAME = 'edgecontainer.projects.locations.clusters'
V1_API_VERSION = 'v1'
V1_ALPHA_API_VERSION = 'v1alpha'
LOC_FLAG = '--location'
LOC_FLAG_HELP = ('Parent Edge Container location to list all contained Edge'
' Container clusters.')
RCP_DEPRECATION_RELEASE_NOTES_LINK = (
'https://cloud.google.com/distributed-cloud/edge/latest/docs/'
'release-notes#March_14_2024')
DEPRECATION_WARNING_TEMPLATE = (
'DEPRECATION: Cluster {} is hosting a control plane in the cloud, which is '
'now deprecated. Please migrate all clusters to host the control plane '
'locally on edge-cloud machines: ' + RCP_DEPRECATION_RELEASE_NOTES_LINK
)
def GetUriFromResourceFunc(api_version):
def UriFunc(cluster, **kwargs):
kwargs['api_version'] = api_version
kwargs['collection'] = 'edgecontainer.projects.locations.clusters'
return resources.REGISTRY.Parse(cluster.name, **kwargs).SelfLink()
return UriFunc
def IsRCPCluster(cluster):
return cluster.controlPlane is None or cluster.controlPlane.local is None
def PrintWarningsAndReturnTrue(cluster):
if IsRCPCluster(cluster) and cluster.status != 'PROVISIONING':
log.warning(DEPRECATION_WARNING_TEMPLATE.format(cluster.name))
return True
# TODO(b/331978625): Unify GA in python after validating Alpha.
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class ListAlpha(base.ListCommand):
"""List Edge Container clusters."""
detailed_help = DETAILED_HELP
@staticmethod
def Args(parser):
"""Register flags for this command.
Args:
parser: An argparse.ArgumentParser-like object. It is mocked out in order
to capture some information, but behaves like an ArgumentParser.
"""
resource_args.AddLocationOptionalResourceArgForListing(parser)
parser.display_info.AddFormat(DISPLAY_TABLE)
parser.display_info.AddUriFunc(GetUriFromResourceFunc(V1_ALPHA_API_VERSION))
def Run(self, args):
"""This is what gets called when the user runs this command.
Args:
args: an argparse namespace. All the arguments that were provided to this
command invocation.
Returns:
Some value that we want to have printed later.
"""
cluster_client = util.GetClientInstance(self.ReleaseTrack())
messages = util.GetMessagesModule(self.ReleaseTrack())
vals = properties.VALUES
project_id = args.project or vals.core.project.Get(required=True)
location = args.location or vals.edge_container.location.Get(required=True)
return list_pager.YieldFromList(
cluster_client.projects_locations_clusters,
messages.EdgecontainerProjectsLocationsClustersListRequest(
parent=f'projects/{project_id}/locations/{location}',
pageSize=args.page_size,
filter=args.filter
),
batch_size=args.page_size,
field='clusters',
limit=args.limit,
batch_size_attribute='pageSize',
predicate=PrintWarningsAndReturnTrue)

View File

@@ -0,0 +1,35 @@
# TODO(b/331978625): Unify GA in python after validating Alpha.
- release_tracks: [GA]
help_text:
brief: List Edge Container clusters.
description: |
List Edge Container clusters.
examples: |
To list the clusters in region us-central1, run:
$ {command} --location=us-central1
request:
collection: edgecontainer.projects.locations.clusters
GA:
api_version: v1
response:
id_field: name
arguments:
resource:
help_text: Parent Edge Container location to list all contained Edge Container clusters.
spec: !REF googlecloudsdk.command_lib.edge_cloud.container.resources:location
output:
format: |
table(
name.basename():label=NAME,
endpoint:label=ENDPOINT,
labels:label=LABELS,
controlPlaneVersion:label=CONTROL_PLANE_VERSION,
nodeVersion:label=NODE_VERSION,
createTime.date():label=CREATED
)

View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*- #
# Copyright 2022 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.
"""The command group for the node pools resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class NodePools(base.Group):
"""Manage Kubernetes Edge node pools."""

View File

@@ -0,0 +1,138 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 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.
"""Command to create an Edge Container node pool."""
from googlecloudsdk.api_lib.edge_cloud.container import nodepool
from googlecloudsdk.api_lib.edge_cloud.container import util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.edge_cloud.container import flags as container_flags
from googlecloudsdk.command_lib.edge_cloud.container import print_warning
from googlecloudsdk.command_lib.edge_cloud.container import resource_args
from googlecloudsdk.command_lib.run import flags
from googlecloudsdk.command_lib.util.args import labels_util
from googlecloudsdk.core import log
from googlecloudsdk.core import resources
_EXAMPLES = """
To create a node pool called `my-nodePool`, containing 3 nodes in region `us-central1`, run:
$ {command} my-nodePool --cluster=<my-cluster> --location=us-central1 --node-location=<my-node-location> --node-count=3
To create a node pool called `my-nodePool`, containing 3 nodes in region `us-central1`,
using only machine names matching a specific pattern, run:
$ {command} my-nodePool --cluster=<my-cluster> --location=us-central1 --node-location=<my-node-location> --node-count=3 --machine-filter="name:<name>"
To create a node pool called `my-nodePool`, containing 3 nodes in region `us-central1`,
using only machine names NOT matching a specific pattern, run:
$ {command} my-nodePool --cluster=<my-cluster> --location=us-central1 --node-location=<my-node-location> --node-count=3 --machine-filter="NOT name:<name>"
"""
_API_REFERENCE_ = """
This command uses the edgecontainer/{API} API. The full documentation for this
API can be found at: https://cloud.google.com/edge-cloud
"""
_LRO_MAXIMUM_TIMEOUT_ = 68400000 # 19 hours
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Create(base.CreateCommand):
"""Create an Edge Container node pool."""
detailed_help = {
'EXAMPLES': _EXAMPLES,
'API REFERENCE': _API_REFERENCE_.format(
API=util.VERSION_MAP.get(base.ReleaseTrack.GA)
),
}
@staticmethod
def Args(parser):
# TODO(b/176452774) Generate an argument for the `labels` param.
resource_args.AddNodePoolResourceArg(parser, 'to create')
container_flags.AddNodeCount(parser)
container_flags.AddNodeLocation(parser)
container_flags.AddNodeStorageSchema(parser)
container_flags.AddMachineFilter(parser)
container_flags.AddLocalDiskKMSKey(parser)
container_flags.AddLROMaximumTimeout(parser)
container_flags.AddNodeLabelsForCreateNodePool(parser)
labels_util.AddCreateLabelsFlags(parser)
base.ASYNC_FLAG.AddToParser(parser)
def Run(self, args):
node_pool_ref = nodepool.GetNodePoolReference(args)
req = nodepool.GetNodePoolCreateRequest(args, self.ReleaseTrack())
client = util.GetClientInstance(self.ReleaseTrack())
op = client.projects_locations_clusters_nodePools.Create(req)
op_ref = resources.REGISTRY.ParseRelativeName(
op.name, collection='edgecontainer.projects.locations.operations'
)
log.status.Print(
'Create request issued for: [{nodePool}]'.format(
nodePool=node_pool_ref.nodePoolsId
)
)
if not flags.FlagIsExplicitlySet(args, 'async_'):
progress_string = (
'Waiting for operation [{operation}] to complete'.format(
operation=op_ref.RelativeName()
)
)
operation_poller = util.OperationPoller(
client.projects_locations_clusters_nodePools,
client.projects_locations_operations,
)
lro_maximum_timeout = _LRO_MAXIMUM_TIMEOUT_
if flags.FlagIsExplicitlySet(args, 'lro_timeout'):
lro_maximum_timeout = int(args.lro_timeout)
response = waiter.WaitFor(
operation_poller,
op_ref,
progress_string,
max_wait_ms=lro_maximum_timeout,
)
log.status.Print(
'Created node pool [{nodePool}].'.format(
nodePool=node_pool_ref.nodePoolsId
)
)
return print_warning.PrintWarning(response, None)
log.status.Print(
'Check operation [{operation}] for status.'.format(
operation=op_ref.RelativeName()
)
)
return print_warning.PrintWarning(op, None)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class CreateAlpha(Create):
"""Create an Edge Container node pool."""
@staticmethod
def Args(parser, track=base.ReleaseTrack.ALPHA):
"""Registers alpha track flags for this command."""
Create.detailed_help['API REFERENCE'] = _API_REFERENCE_.format(
API=util.VERSION_MAP.get(track)
)
Create.Args(parser)
container_flags.AddNodeSystemPartitionSize(parser)

View File

@@ -0,0 +1,25 @@
- release_tracks: [ALPHA, GA]
help_text:
brief: Delete an Edge Container nodePool.
description: |
Delete an Edge Container nodePool.
examples: |
To delete a nodePool called 'my-nodePool' in region us-central1, run:
$ {command} my-nodePool --cluster=<my-cluster> --location=us-central1
request:
collection: edgecontainer.projects.locations.clusters.nodePools
ALPHA:
api_version: v1alpha
GA:
api_version: v1
arguments:
resource:
help_text: Edge Container nodePool to delete.
spec: !REF googlecloudsdk.command_lib.edge_cloud.container.resources:nodePool
async:
collection: edgecontainer.projects.locations.operations

View File

@@ -0,0 +1,21 @@
release_tracks: [ALPHA, GA]
help_text:
brief: Show details about the nodePool.
description: Show details about the nodePool.
examples: |
To show details about a node pool called 'my-nodePool' in region us-central1, run:
$ {command} my-nodePool --location=us-central1 --cluster=<my-cluster>
request:
collection: edgecontainer.projects.locations.clusters.nodePools
ALPHA:
api_version: v1alpha
GA:
api_version: v1
arguments:
resource:
help_text: The nodePool you want to describe.
spec: !REF googlecloudsdk.command_lib.edge_cloud.container.resources:nodePool

View File

@@ -0,0 +1,37 @@
- release_tracks: [ALPHA, GA]
help_text:
brief: List Edge Container nodePools.
description: |
List Edge Container nodePools.
examples: |
To list the nodePools in region us-central1, run:
$ {command} --location=us-central1 --cluster=<my-cluster>
request:
collection: edgecontainer.projects.locations.clusters.nodePools
ALPHA:
api_version: v1alpha
GA:
api_version: v1
response:
id_field: name
arguments:
resource:
help_text: Parent Edge Container location to list all contained Edge Container nodePools.
spec: !REF googlecloudsdk.command_lib.edge_cloud.container.resources:cluster_with_default
output:
format: |
table(
name.basename():label=NAME,
name.scope(clusters).segment(0):label=CLUSTER,
nodeCount:label=NODE_COUNT,
nodeLocation:label=NODE_LOCATION,
nodeVersion:label=NODE_VERSION,
labels:label=LABELS,
createTime.date():label=CREATED
)

View File

@@ -0,0 +1,139 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 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.
"""Command to update an Edge Container node pool."""
from googlecloudsdk.api_lib.edge_cloud.container import nodepool
from googlecloudsdk.api_lib.edge_cloud.container import util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.edge_cloud.container import flags as container_flags
from googlecloudsdk.command_lib.edge_cloud.container import print_warning
from googlecloudsdk.command_lib.edge_cloud.container import resource_args
from googlecloudsdk.command_lib.run import flags
from googlecloudsdk.command_lib.util.args import labels_util
from googlecloudsdk.core import log
from googlecloudsdk.core import resources
from googlecloudsdk.core.resource import resource_printer
_EXAMPLES = """
To update the number of nodes in a node pool called `my-node-pool` in region `us-central1`,
run:
$ {command} my-node-pool --location=us-central1 --cluster=<my-cluster> \
--node-count=<new-count>
"""
_API_REFERENCE_ = """
This command uses the edgecontainer/{API} API. The full documentation for this
API can be found at: https://cloud.google.com/edge-cloud
"""
_LRO_MAXIMUM_TIMEOUT_ = 68400000 # 19 hours
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Update(base.UpdateCommand):
"""Updates an Edge Container node pool."""
detailed_help = {
'EXAMPLES': _EXAMPLES,
'API REFERENCE': _API_REFERENCE_.format(
API=util.VERSION_MAP.get(base.ReleaseTrack.GA)
),
}
@staticmethod
def Args(parser):
resource_args.AddNodePoolResourceArg(parser, 'to update')
container_flags.AddNodeCount(parser, required=False)
container_flags.AddMachineFilter(parser)
container_flags.AddLROMaximumTimeout(parser)
container_flags.AddNodeLabelsForUpdateNodePool(parser)
labels_util.AddUpdateLabelsFlags(parser)
container_flags.AddLocalDiskKMSKey(parser)
container_flags.AddUseGoogleManagedKey(parser)
base.ASYNC_FLAG.AddToParser(parser)
def Run(self, args):
node_pool_ref = nodepool.GetNodePoolReference(args)
client = util.GetClientInstance(self.ReleaseTrack())
get_req = nodepool.GetNodePoolGetRequest(args, self.ReleaseTrack())
existing_node_pool = client.projects_locations_clusters_nodePools.Get(
get_req
)
update_req = nodepool.GetNodePoolUpdateRequest(
args, self.ReleaseTrack(), existing_node_pool
)
op = client.projects_locations_clusters_nodePools.Patch(update_req)
op_ref = resources.REGISTRY.ParseRelativeName(
op.name, collection='edgecontainer.projects.locations.operations'
)
log.status.Print(
'Update request issued for: [{nodePool}]'.format(
nodePool=node_pool_ref.nodePoolsId
)
)
if not flags.FlagIsExplicitlySet(args, 'async_'):
progress_string = (
'Waiting for operation [{operation}] to complete'.format(
operation=op_ref.RelativeName()
)
)
operation_poller = util.OperationPoller(
client.projects_locations_clusters_nodePools,
client.projects_locations_operations,
)
lro_maximum_timeout = _LRO_MAXIMUM_TIMEOUT_
if flags.FlagIsExplicitlySet(args, 'lro_timeout'):
lro_maximum_timeout = int(args.lro_timeout)
response = waiter.WaitFor(
operation_poller,
op_ref,
progress_string,
max_wait_ms=lro_maximum_timeout,
)
updated_node_pool = client.projects_locations_clusters_nodePools.Get(
get_req
)
log.status.Print(
'Updated node pool [{nodePool}].'.format(
nodePool=node_pool_ref.nodePoolsId
)
)
resource_printer.Print(updated_node_pool, 'json', out=log.status)
return print_warning.PrintWarning(response, None)
log.status.Print(
'Check operation [{operation}] for status.'.format(
operation=op_ref.RelativeName()
)
)
return print_warning.PrintWarning(op, None)
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class UpdateAlpha(Update):
"""Updates an Edge Container node pool."""
@staticmethod
def Args(parser, track=base.ReleaseTrack.ALPHA):
"""Registers alpha track flags for this command."""
Update.detailed_help['API REFERENCE'] = _API_REFERENCE_.format(
API=util.VERSION_MAP.get(track)
)
Update.Args(parser)

View File

@@ -0,0 +1,45 @@
# -*- coding: utf-8 -*- #
# Copyright 2022 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.
"""Command to print access tokens for a GKE cluster on GEC."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.edge_cloud.container import util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.edge_cloud.container import resource_args
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
@base.Hidden
class PrintAccessToken(base.Command):
"""Generate an access token for an Edge Container cluster."""
@staticmethod
def Args(parser):
"""Register flags for this command."""
resource_args.AddClusterResourceArg(parser, "to access")
def Run(self, args):
"""Run the command."""
cluster_ref = args.CONCEPTS.cluster.Parse()
messages = util.GetMessagesModule(self.ReleaseTrack())
cluster_client = util.GetClientInstance(self.ReleaseTrack())
req = messages.EdgecontainerProjectsLocationsClustersGenerateAccessTokenRequest(
cluster=cluster_ref.RelativeName())
resp = cluster_client.projects_locations_clusters.GenerateAccessToken(req)
return resp

View File

@@ -0,0 +1,177 @@
- release_tracks: [ALPHA, GA]
help_text:
brief: Update an Edge Container cluster.
description: |
Update an Edge Container cluster.
examples: |
To update the maintenance window recurrence rule of a cluster called
'my-cluster' in region us-central1, run:
$ {command} my-cluster --location=us-central1 --maintenance-window-recurrence="FREQ=WEEKLY"
request:
collection: edgecontainer.projects.locations.clusters
ALPHA:
api_version: v1alpha
GA:
api_version: v1
modify_request_hooks:
- googlecloudsdk.command_lib.edge_cloud.container.container_runtime:UpdateContainerRuntimeclass
- googlecloudsdk.command_lib.edge_cloud.container.cluster_isolation:UpdateClusterIsolation
- googlecloudsdk.command_lib.edge_cloud.container.maintenance_policy:AddMaintenanceExclusionWindow
- googlecloudsdk.command_lib.edge_cloud.container.maintenance_policy:RemoveMaintenanceExclusionWindow
- googlecloudsdk.command_lib.edge_cloud.container.maintenance_policy:ClearMaintenanceWindow
- googlecloudsdk.command_lib.edge_cloud.container.max_unavailable:ClearMaxUnavailable
- googlecloudsdk.command_lib.edge_cloud.container.kms:UseGoogleManagedKey
- googlecloudsdk.command_lib.edge_cloud.container.kms:UpdateKmsKey
- googlecloudsdk.command_lib.edge_cloud.container.kms:UseGoogleManagedZoneKey
- googlecloudsdk.command_lib.edge_cloud.container.kms:UpdateZoneKmsKey
- googlecloudsdk.command_lib.edge_cloud.container.robin:HandleEnableRobinCNSUpdate
arguments:
resource:
help_text: Edge Container cluster to update.
spec: !REF googlecloudsdk.command_lib.edge_cloud.container.resources:cluster
params:
- group:
mutex: true
params:
- arg_name: clear-maintenance-window
action: store_true
help_text: |
If set, removes the maintenance window setting from the cluster. If any exclusion windows exist, they must be removed beforehand as a maintenance policy cannot exist without a maintenance window.
- group:
help_text: Updates cluster maintenance window setting (more than one flags can be specified from this group)
mutex: false
params:
- arg_name: maintenance-window-start
api_field: cluster.maintenancePolicy.window.recurringWindow.window.startTime
repeated: false
help_text: |
Start time of the recurring cluster maintenance window in the [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.txt)
format. E.g. "2021-01-01T00:00:00Z" or "2021-01-01T00:00:00-05:00"
- arg_name: maintenance-window-end
api_field: cluster.maintenancePolicy.window.recurringWindow.window.endTime
repeated: false
help_text: |
End time of the recurring cluster maintenance window in the [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.txt)
format. E.g. "2021-01-01T00:00:00Z" or "2021-01-01T00:00:00-05:00"
- arg_name: maintenance-window-recurrence
api_field: cluster.maintenancePolicy.window.recurringWindow.recurrence
repeated: false
help_text: |
An [RFC 5545](https://tools.ietf.org/html/rfc5545#section-3.8.5.3)
recurrence rule for how the cluster maintenance window recurs. They go
on for the span of time between the start and the end time. E.g. FREQ=WEEKLY;BYDAY=SU.
- arg_name: remove-maintenance-exclusion-window
help_text: |
Name of the maintenance exclusion to remove.
- group:
help_text: Add a maintenance exclusion window (all flags must be specified to add a valid maintenance exclusion window). There can be a maximum of 3 exclusion windows set at a given time. A maintenance exclusion window cannot be added in the absence of a maintenance window.
mutex: false
params:
- arg_name: add-maintenance-exclusion-name
repeated: false
help_text: |
Unique name (per cluster) of the maintenance exclusion window that can be used to remove it.
- arg_name: add-maintenance-exclusion-start
repeated: false
help_text: |
Start time of the maintenance exclusion window (can occur in the past) in the RFC 3339
(https://www.rfc-editor.org/rfc/rfc3339.txt) format. E.g.
"2021-01-01T00:00:00Z" or "2021-01-01T00:00:00-05:00".
- arg_name: add-maintenance-exclusion-end
repeated: false
help_text: |
End time of the maintenance exclusion window in the RFC 3339
(https://www.rfc-editor.org/rfc/rfc3339.txt) format. E.g.
"2021-01-01T00:00:00Z" or "2021-01-01T00:00:00-05:00".
- arg_name: release-channel
api_field: cluster.releaseChannel
repeated: false
help_text: |
Release channel a cluster is subscribed to. It supports two values, NONE and REGULAR. NONE
is used to opt out of any release channel. Clusters subscribed to the REGULAR channel will
be automatically upgraded to versions that are considered GA quality, and cannot be manually
upgraded.
- arg_name: offline-reboot-ttl
type: googlecloudsdk.core.util.times:ParseDuration
processor: googlecloudsdk.core.util.times:FormatDurationForJson
api_field: cluster.survivabilityConfig.offlineRebootTtl
required: false
help_text: |
Specifies the maximum duration a node can reboot offline (without connection to Google) and
then rejoin its cluster to resume its designated workloads. This duration is relative to the
machine's most recent connection to Google. The maximum allowed duration is 7 days. If left
unspecified, the default 0 means not allowed. The parameter should be an ISO 8601 duration
string, for example, "P1DT1H2M3S".
- group:
release_tracks: [ALPHA]
mutex: true
params:
- arg_name: clear-max-unavailable-worker-nodes
action: store_true
help_text: |
Clear the worker node upgrade parallelism, which will default to the upgrade stage size.
- arg_name: max-unavailable-worker-nodes
api_field: cluster.upgradeSettings.maxUnavailableWorkerNodes
help_text: |
Set the worker node upgrade parallelism. The value must be between 1 and the worker node
upgrade stage size, inclusively. If unset, the worker node upgrade parallelism defaults
to the upgrade stage size. This value does not affect the control plane node upgrade
parallelism.
- group:
mutex: true
params:
- arg_name: use-google-managed-key
action: store_true
help_text: |
If set, use Google managed key for the cluster control plane nodes encryption.
- arg_name: control-plane-kms-key
repeated: false
help_text: |
If set, use the specified KMS key for the cluster control plane nodes encryption.
- group:
mutex: true
params:
- arg_name: use-google-managed-zone-key
action: store_true
help_text: |
If set, use Google managed key for zone storage encryption.
- arg_name: zone-storage-kms-key
repeated: false
help_text: |
If set, use the specified KMS key for zone storage encryption.
- arg_name: container-default-runtime-class
repeated: false
help_text: |
If set, use the specified default container runtime class for the cluster.
- arg_name: enable-robin-cns
release_tracks: [ALPHA]
hidden: true
action: store_true
help_text: |
If set, Robin CNS will be enabled on the cluster.
WARNING:
Enabling Robin CNS is irreversible. Once enabled, it cannot be disabled.
Enabling Robin CNS will take over all unused local Persistent Volumes (PVs)
in the cluster. Any data on these PVs will be permanently lost.
- arg_name: enable-cluster-isolation
release_tracks: [ALPHA]
repeated: false
help_text: |
If set to true, the cluster will be created in a secure cluster isolation mode.
response:
modify_response_hooks:
- googlecloudsdk.command_lib.edge_cloud.container.print_warning:PrintWarning
async:
collection: edgecontainer.projects.locations.operations
extract_resource_result: false
update:
read_modify_update: true

View File

@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 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.
"""Command to upgrade an Edge Container cluster."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.edge_cloud.container import cluster
from googlecloudsdk.api_lib.edge_cloud.container import util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.edge_cloud.container import flags as container_flags
from googlecloudsdk.command_lib.edge_cloud.container import print_warning
from googlecloudsdk.command_lib.edge_cloud.container import resource_args
from googlecloudsdk.core import log
from googlecloudsdk.core import resources
_EXAMPLES = """
To upgrade an Edge Container cluster to 1.5.1 immediately, run:
$ {command} my-cluster --version=1.5.1 --schedule=IMMEDIATELY
"""
_API_REFERENCE_ = """
This command uses the edgecontainer/{API} API. The full documentation for this
API can be found at: https://cloud.google.com/edge-cloud
"""
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Upgrade(base.Command):
"""Upgrade an Edge Container cluster."""
detailed_help = {
'EXAMPLES': _EXAMPLES,
'API REFERENCE': _API_REFERENCE_.format(
API=util.VERSION_MAP.get(base.ReleaseTrack.GA)
),
}
@staticmethod
def Args(parser):
resource_args.AddClusterResourceArg(parser, 'to upgrade')
container_flags.AddUpgradeVersion(parser)
container_flags.AddUpgradeSchedule(parser)
def Run(self, args):
cluster_ref = cluster.GetClusterReference(args)
req = cluster.GetClusterUpgradeRequest(args, self.ReleaseTrack())
cluster_client = util.GetClientInstance(self.ReleaseTrack())
op = cluster_client.projects_locations_clusters.Upgrade(req)
op_ref = resources.REGISTRY.ParseRelativeName(
op.name, collection='edgecontainer.projects.locations.operations'
)
log.status.Print(
'Upgrade request issued for: [{cluster}]\nCheck operation [{operation}]'
' for status.'.format(
cluster=cluster_ref.clustersId, operation=op_ref.RelativeName()
)
)
return print_warning.PrintWarning(op, None)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class UpgradeAlpha(Upgrade):
"""Upgrade an Edge Container cluster."""
@staticmethod
def Args(parser, track=base.ReleaseTrack.ALPHA):
Upgrade.detailed_help['API REFERENCE'] = _API_REFERENCE_.format(
API=util.VERSION_MAP.get(track)
)
Upgrade.Args(parser)