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,67 @@
# -*- coding: utf-8 -*- #
# Copyright 2014 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 cloud container clusters."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container import transforms
from googlecloudsdk.calliope import actions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container import container_command_util
from googlecloudsdk.command_lib.container import flags
from googlecloudsdk.core import log
class Clusters(base.Group):
"""Deploy and teardown Google Kubernetes Engine clusters.
The gcloud container clusters command group lets you deploy and teardown
Google Kubernetes Engine clusters.
See $ gcloud docker --help for information about deploying docker images
to clusters.
"""
category = base.COMPUTE_CATEGORY
@staticmethod
def Args(parser):
"""Add arguments to the parser.
Args:
parser: argparse.ArgumentParser, This is a standard argparser parser with
which you can register arguments. See the public argparse documentation
for its capabilities.
"""
flags.AddLocationFlags(parser)
parser.display_info.AddTransforms(transforms.GetTransforms())
def Filter(self, context, args):
"""Modify the context that will be given to this group's commands when run.
Args:
context: {str:object}, A set of key-value pairs that can be used for
common initialization among commands.
args: argparse.Namespace: The same namespace given to the corresponding
.Run() invocation.
Returns:
The refined command context.
"""
base.RequireProjectID(args)
context['location_get'] = container_command_util.GetZoneOrRegion
return context

View File

@@ -0,0 +1,76 @@
# -*- 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.
"""Check autopilot compatibility command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.core import log
@base.UniverseCompatible
class CheckAutopilotCompatibility(base.ListCommand):
"""Check autopilot compatibility of a running cluster."""
detailed_help = {
'DESCRIPTION': (
'{description}' +
'\n\nFor clusters with GKE version 1.31.6-gke.1027000 or later, you ' +
'must enable the control plane component that performs the check by ' +
'running the `gcloud container clusters update` command with the ' +
'[`--enable-autopilot-compatiblity-auditing`](https://cloud.google.com/sdk/gcloud/reference/container/clusters/update#--%5Bno-%5Denable-autopilot-compatibility-auditing) ' +
' flag.'
),
'EXAMPLES':
"""\
To check autopilot compatibility of an existing cluster, run:
$ {command} sample-cluster
""",
}
@staticmethod
def Args(parser):
parser.add_argument('name', help='The name of this cluster.')
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.
"""
adapter = self.context['api_adapter']
location_get = self.context['location_get']
location = location_get(args)
def sort_key(issue):
return (issue.incompatibilityType, issue.constraintType)
resp = adapter.CheckAutopilotCompatibility(
adapter.ParseCluster(args.name, location))
resp.issues = sorted(resp.issues, key=sort_key)
self._summary = resp.summary
return resp.issues
def Epilog(self, results_were_displayed):
if self._summary:
log.out.Print('\nSummary:\n' + self._summary)

View File

@@ -0,0 +1,72 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Complete control plane upgrade command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.GA)
@base.UniverseCompatible
@base.Hidden
class CompleteControlPlaneUpgrade(base.Command):
"""Complete the control plane upgrade for an existing cluster."""
detailed_help = {
'DESCRIPTION': '{description}',
'EXAMPLES': """\
To complete the control plane upgrade for an existing cluster, run:
$ {command} sample-cluster
""",
}
@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.
"""
parser.add_argument('name', help='The name of your existing cluster.')
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:
The result of the complete control plane upgrade operation.
"""
adapter = self.context['api_adapter']
location_get = self.context['location_get']
location = location_get(args)
return adapter.CompleteControlPlaneUpgrade(
adapter.ParseCluster(args.name, location)
)
@base.ReleaseTracks(base.ReleaseTrack.BETA, base.ReleaseTrack.ALPHA)
@base.UniverseCompatible
@base.Visible
class CompleteControlPlaneUpgradeAlphaBeta(CompleteControlPlaneUpgrade):
"""Complete the control plane upgrade for an existing cluster."""

View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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 group for managing Container cluster configurations."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Config(base.Group):
"""Manage Container cluster configurations."""

View File

@@ -0,0 +1,43 @@
release_tracks: [ALPHA]
command_type: CONFIG_EXPORT
help_text:
brief: Export the configuration for a Container cluster.
description: |
*{command}* exports the configuration for a Container cluster.
Cluster configurations can be exported in
Kubernetes Resource Model (krm) or Terraform HCL formats. The
default format is `krm`.
Specifying `--all` allows you to export the configurations for all
clusters within the project.
Specifying `--path` allows you to export the configuration(s) to
a local directory.
examples: |
To export the configuration for a cluster, run:
$ {command} my-cluster
To export the configuration for a cluster to a file, run:
$ {command} my-cluster --path=/path/to/dir/
To export the configuration for a cluster in Terraform
HCL format, run:
$ {command} my-cluster --resource-format=terraform
To export the configurations for all clusters within a
project, run:
$ {command} --all
arguments:
resource:
help_text: Cluster to export the configuration for.
spec: !REF googlecloudsdk.command_lib.container.clusters.resources:cluster
# Inherited from clusters command.
removed_flags: ['location']
command_level_fallthroughs:
location:
- arg_name: 'location'

View File

@@ -0,0 +1,169 @@
# -*- coding: utf-8 -*- #
# Copyright 2020 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.
"""Create-auto cluster command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container import flags
from surface.container.clusters import create
# Select which flags are auto flags
# Arguments for "clusters create-auto" should also be added to "clusters create"
# Unless there is a good reason to exclude them because features should support
# both GKE Standard and Autopilot.
# LINT.IfChange(auto_flags)
auto_flags = [
'args',
'clusterversion',
'masterauth',
'nodeidentity',
'privatecluster',
'authenticatorsecurity',
'databaseencryption',
'bootdiskkms',
'autoprovisioning_network_tags',
'enableworkloadconfigaudit',
'enableworkloadvulnscanning',
'enableGoogleCloudAccess',
'privateEndpointSubnetwork',
'managedConfig',
'fleetProject',
'enableFleet',
'enableSecurityPosture',
'autoprovisioningEnableKubeletReadonlyPort',
'dataplanev2obs',
'enableK8sBetaApis',
'compliance',
'complianceStandards',
'securityPosture',
'workloadVulnerabilityScanning',
'enableRuntimeVulnerabilityInsight',
'masterglobalaccess',
'enableDnsAccess',
'workloadPolicies',
'containerdConfig',
'labels',
'secretManagerConfig',
'enableCiliumClusterwideNetworkPolicy',
'cpDiskEncryptionKey',
'disableL4LbFirewallReconciliation',
'hpaprofile',
'enableIpAccess',
'enableAuthorizedNetworksOnPrivateEndpoint',
'enableAutoIpam',
'enableK8sTokensViaDns',
'enableDefaultComputeClass',
'enableK8sCertsViaDns',
'membershipType',
'secretSyncConfig',
'controlPlaneEgress',
'tag_bindings',
'managedOTelScope',
'autopilotPrivilegedAdmission',
'enablePodSnapshots',
'disablePodSnapshots',
'enableKernelModuleSignatureEnforcement',
'enableLustreMultiNic',
'autopilotGeneralProfile',
'disableMultiNicLustre',
]
# LINT.ThenChange()
# Change default flag values in create-auto
flag_overrides = {
'num_nodes': 1,
'enable_ip_alias': True,
'enable_master_authorized_networks': False,
'privatecluster': {
'private_cluster': None,
},
}
auto_flag_defaults = dict(
list(create.base_flag_defaults.items()) + list(flag_overrides.items())
)
def AddAutoFlags(parser, release_track):
"""Adds flags that are not same in create."""
flags.AddLoggingFlag(parser, True)
flags.AddMonitoringFlag(parser, True)
flags.AddBinauthzFlags(parser, release_track=release_track, autopilot=True)
flags.AddWorkloadPoliciesFlag(parser)
flags.AddReleaseChannelFlag(parser, autopilot=True)
flags.AddEnableBackupRestoreFlag(parser)
flags.AddAutoprovisioningResourceManagerTagsCreate(parser)
flags.AddAdditiveVPCScopeFlags(parser)
flags.AddIPAliasRelatedFlags(parser, autopilot=True)
flags.AddEnableConfidentialNodesFlag(parser)
flags.AddEnableLustreCSIDriverFlag(parser, hidden=False)
flags.AddEnableRayOperatorFlag(parser, hidden=False)
flags.AddEnableRayClusterMonitoring(parser, hidden=False)
flags.AddEnableRayClusterLogging(parser, hidden=False)
flags.AddInsecureRBACBindingFlags(parser, hidden=False)
flags.AddEnableMultiNetworkingFlag(parser, hidden=False)
flags.AddControlPlaneKeysFlags(parser)
flags.AddAutoMonitoringScopeFlags(parser, hidden=False)
flags.AddClusterTierFlag(parser)
flags.AddKubecontextOverrideFlag(parser)
flags.AddAnonymousAuthenticationConfigFlag(parser)
flags.AddEnableLegacyLustrePortFlag(parser, hidden=False)
if release_track != base.ReleaseTrack.GA:
flags.AddPodSnapshotConfigFlags(parser)
@base.ReleaseTracks(base.ReleaseTrack.GA)
@base.DefaultUniverseOnly
class Create(create.Create):
"""Create an Autopilot cluster for running containers."""
autopilot = True
default_flag_values = auto_flag_defaults
@staticmethod
def Args(parser):
create.AddFlags(create.GA, parser, auto_flag_defaults, auto_flags)
AddAutoFlags(parser, base.ReleaseTrack.GA)
@base.ReleaseTracks(base.ReleaseTrack.BETA)
@base.DefaultUniverseOnly
class CreateBeta(create.CreateBeta):
"""Create an Autopilot cluster for running containers."""
autopilot = True
default_flag_values = auto_flag_defaults
@staticmethod
def Args(parser):
create.AddFlags(create.BETA, parser, auto_flag_defaults, auto_flags)
AddAutoFlags(parser, base.ReleaseTrack.BETA)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
@base.DefaultUniverseOnly
class CreateAlpha(create.CreateAlpha):
"""Create an Autopilot cluster for running containers."""
autopilot = True
default_flag_values = auto_flag_defaults
@staticmethod
def Args(parser):
create.AddFlags(create.ALPHA, parser, auto_flag_defaults, auto_flags)
AddAutoFlags(parser, base.ReleaseTrack.ALPHA)

View File

@@ -0,0 +1,156 @@
# -*- coding: utf-8 -*- #
# Copyright 2014 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.
"""Delete cluster command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import exceptions as apitools_exceptions
from googlecloudsdk.api_lib.container import kubeconfig as kconfig
from googlecloudsdk.api_lib.container import util
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.command_lib.container import flags
from googlecloudsdk.core import log
from googlecloudsdk.core import properties
from googlecloudsdk.core.console import console_io
import six
@base.DefaultUniverseOnly
class Delete(base.DeleteCommand):
"""Delete an existing cluster for running containers.
When you delete a cluster, the following resources are deleted:
- The control plane resources
- All of the node instances in the cluster
- Any Pods that are running on those instances
- Any firewalls and routes created by Kubernetes Engine at the time of cluster
creation
- Data stored in host hostPath and emptyDir volumes
GKE will attempt to delete the following resources. Deletion of these
resources is not always guaranteed:
- External load balancers created by the cluster
- Internal load balancers created by the cluster
- Persistent disk volumes
"""
detailed_help = {
'DESCRIPTION':
'{description}',
'EXAMPLES':
"""\
To delete an existing cluster, run:
$ {command} sample-cluster
""",
}
@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.
"""
parser.add_argument(
'names',
metavar='NAME',
nargs='+',
help='The names of the clusters to delete.')
parser.add_argument(
'--timeout',
type=int,
default=3600,
hidden=True,
help='Timeout (seconds) for waiting on the operation to complete.')
flags.AddAsyncFlag(parser)
flags.AddKubecontextOverrideFlag(parser)
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.
"""
adapter = self.context['api_adapter']
location_get = self.context['location_get']
location = location_get(args)
cluster_refs = []
for name in args.names:
cluster_refs.append(adapter.ParseCluster(name, location))
console_io.PromptContinue(
message=util.ConstructList('The following clusters will be deleted.', [
'[{name}] in [{zone}]'.format(
name=ref.clusterId, zone=adapter.Zone(ref))
for ref in cluster_refs
]),
throw_if_unattended=True,
cancel_on_no=True)
operations = []
errors = []
# Issue all deletes first
for cluster_ref in cluster_refs:
try:
op_ref = adapter.DeleteCluster(cluster_ref)
operations.append((op_ref, cluster_ref))
except apitools_exceptions.HttpError as error:
errors.append(
six.text_type(
exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)))
except util.Error as error:
errors.append(error)
if not args.async_:
# Poll each operation for completion
for operation_ref, cluster_ref in operations:
try:
adapter.WaitForOperation(
operation_ref,
'Deleting cluster {0}'.format(cluster_ref.clusterId),
timeout_s=args.timeout)
# Purge cached config files
try:
util.ClusterConfig.Purge(
cluster_ref.clusterId,
adapter.Zone(cluster_ref),
cluster_ref.projectId,
args.kubecontext_override,
)
except kconfig.MissingEnvVarError as error:
log.warning(error)
if properties.VALUES.container.cluster.Get() == cluster_ref.clusterId:
properties.PersistProperty(properties.VALUES.container.cluster,
None)
log.DeletedResource(cluster_ref)
except apitools_exceptions.HttpError as error:
errors.append(exceptions.HttpException(error, util.HTTP_ERROR_FORMAT))
except util.Error as error:
errors.append(error)
if errors:
raise util.Error(
util.ConstructList('Some requests did not succeed:', errors))

View File

@@ -0,0 +1,89 @@
# -*- coding: utf-8 -*- #
# Copyright 2014 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.
"""Describe cluster command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container import util
from googlecloudsdk.calliope import base
from googlecloudsdk.core import log
from surface.container.clusters.upgrade import UpgradeHelpText
from surface.container.clusters.upgrade import VersionVerifier
@base.DefaultUniverseOnly
class Describe(base.DescribeCommand):
"""Describe an existing cluster for running containers."""
detailed_help = {
'DESCRIPTION':
'{description}',
'EXAMPLES':
"""\
To describe an existing cluster, run:
$ {command} sample-cluster
""",
}
@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.
"""
parser.add_argument('name', help='The name of this cluster.')
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.
"""
adapter = self.context['api_adapter']
location_get = self.context['location_get']
location = location_get(args)
self._upgrade_hint = None
vv = VersionVerifier()
c = adapter.GetCluster(adapter.ParseCluster(args.name, location))
ver_status = vv.Compare(c.currentMasterVersion, c.currentNodeVersion)
if ver_status == VersionVerifier.UPGRADE_AVAILABLE:
self._upgrade_hint = UpgradeHelpText.UPGRADE_AVAILABLE
elif ver_status == VersionVerifier.SUPPORT_ENDING:
self._upgrade_hint = UpgradeHelpText.SUPPORT_ENDING
elif ver_status == VersionVerifier.UNSUPPORTED:
self._upgrade_hint = UpgradeHelpText.UNSUPPORTED
if ver_status != VersionVerifier.UP_TO_DATE:
self._upgrade_hint += UpgradeHelpText.UPGRADE_COMMAND.format(name=c.name)
for node_pool in c.nodePools:
util.CheckForCgroupModeV1(node_pool)
return c
def Epilog(self, results_were_displayed):
if self._upgrade_hint:
log.status.Print(self._upgrade_hint)

View File

@@ -0,0 +1,279 @@
# -*- coding: utf-8 -*- #
# Copyright 2015 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.
"""Fetch cluster credentials."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container import util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container import flags
from googlecloudsdk.core import log
NOT_RUNNING_MSG = """\
cluster {0} is not RUNNING. The kubernetes API may or may not be available. \
Check the cluster status for more information."""
def _BaseRun(args, context):
"""Base operations for `get-credentials` run command."""
util.CheckKubectlInstalled()
adapter = context['api_adapter']
location_get = context['location_get']
location = location_get(args)
cluster_ref = adapter.ParseCluster(args.name, location)
log.status.Print('Fetching cluster endpoint and auth data.')
# Call DescribeCluster to get auth info and cache for next time
cluster = adapter.GetCluster(cluster_ref)
auth = cluster.masterAuth
# TODO(b/70856999) Make this consistent with the checks in
# api_lib/container/kubeconfig.py.
missing_creds = not (auth and auth.clientCertificate and auth.clientKey)
if missing_creds and not util.ClusterConfig.UseGCPAuthProvider():
raise util.Error(
'get-credentials requires `container.clusters.getCredentials`'
' permission on {0}'.format(cluster_ref.projectId)
)
if not adapter.IsRunning(cluster):
log.warning(NOT_RUNNING_MSG.format(cluster_ref.clusterId))
return cluster, cluster_ref
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.GA)
class GetCredentials(base.Command):
"""Fetch credentials for a running cluster.
{command} updates a `kubeconfig` file with appropriate credentials and
endpoint information to point `kubectl` at a specific cluster in Google
Kubernetes Engine.
It takes a project and a zone as parameters, passed through by set
defaults or flags. By default, credentials are written to `HOME/.kube/config`.
You can provide an alternate path by setting the `KUBECONFIG` environment
variable. If `KUBECONFIG` contains multiple paths, the first one is used.
This command enables switching to a specific cluster, when working
with multiple clusters. It can also be used to access a previously created
cluster from a new workstation.
By default, {command} will configure kubectl to automatically refresh its
credentials using the same identity as gcloud. If you are running kubectl as
part of an application, it is recommended to use [application default
credentials](https://cloud.google.com/docs/authentication/production).
To configure a `kubeconfig` file to use application default credentials, set
the container/use_application_default_credentials
[Cloud SDK property](https://cloud.google.com/sdk/docs/properties) to true
before running {command}
See
[](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl)
for kubectl usage with Google Kubernetes Engine and
[](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands)
for available kubectl commands.
"""
detailed_help = {
'EXAMPLES': """\
To switch to working on your cluster 'sample-cluster', run:
$ {command} sample-cluster --location=us-central1-f
""",
}
@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.
"""
flags.AddGetCredentialsArgs(parser)
flags.AddDnsEndpointFlag(parser)
flags.AddKubecontextOverrideFlag(parser)
flags.AddUseIamTokenFlag(parser)
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.
Raises:
util.Error: if the cluster is unreachable or not running.
"""
cluster, cluster_ref = _BaseRun(args, self.context)
util.ClusterConfig.Persist(
cluster,
cluster_ref.projectId,
args.internal_ip,
use_dns_endpoint=args.dns_endpoint,
impersonate_service_account=args.impersonate_service_account,
kubecontext_override=args.kubecontext_override,
use_iam_token=args.use_iam_token,
)
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.BETA)
class GetCredentialsBeta(base.Command):
"""Fetch credentials for a running cluster.
{command} updates a `kubeconfig` file with appropriate credentials and
endpoint information to point `kubectl` at a specific cluster in Google
Kubernetes Engine.
It takes a project and a zone as parameters, passed through by set
defaults or flags. By default, credentials are written to `HOME/.kube/config`.
You can provide an alternate path by setting the `KUBECONFIG` environment
variable. If `KUBECONFIG` contains multiple paths, the first one is used.
This command enables switching to a specific cluster, when working
with multiple clusters. It can also be used to access a previously created
cluster from a new workstation.
By default, {command} will configure kubectl to automatically refresh its
credentials using the same identity as gcloud. If you are running kubectl as
part of an application, it is recommended to use [application default
credentials](https://cloud.google.com/docs/authentication/production).
To configure a `kubeconfig` file to use application default credentials, set
the container/use_application_default_credentials
[Cloud SDK property](https://cloud.google.com/sdk/docs/properties) to true
before running {command}
See [](https://cloud.google.com/kubernetes-engine/docs/kubectl) for
kubectl documentation.
"""
detailed_help = {
'EXAMPLES': """\
To switch to working on your cluster 'sample-cluster', run:
$ {command} sample-cluster --location=us-central1-f
""",
}
@staticmethod
def Args(parser):
"""Register flags for this command."""
flags.AddGetCredentialsArgs(parser)
flags.AddCrossConnectSubnetworkFlag(parser)
flags.AddPrivateEndpointFQDNFlag(parser)
flags.AddDnsEndpointFlag(parser)
flags.AddKubecontextOverrideFlag(parser)
flags.AddUseIamTokenFlag(parser)
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.
Raises:
util.Error: if the cluster is unreachable or not running.
"""
flags.VerifyGetCredentialsFlags(args)
cluster, cluster_ref = _BaseRun(args, self.context)
util.ClusterConfig.Persist(
cluster,
cluster_ref.projectId,
args.internal_ip,
args.cross_connect_subnetwork,
args.private_endpoint_fqdn,
args.dns_endpoint,
kubecontext_override=args.kubecontext_override,
use_iam_token=args.use_iam_token,
)
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class GetCredentialsAlpha(base.Command):
"""Fetch credentials for a running cluster.
{command} updates a `kubeconfig` file with appropriate credentials and
endpoint information to point `kubectl` at a specific cluster in Google
Kubernetes Engine.
It takes a project and a zone as parameters, passed through by set
defaults or flags. By default, credentials are written to `HOME/.kube/config`.
You can provide an alternate path by setting the `KUBECONFIG` environment
variable. If `KUBECONFIG` contains multiple paths, the first one is used.
This command enables switching to a specific cluster, when working
with multiple clusters. It can also be used to access a previously created
cluster from a new workstation.
By default, {command} will configure kubectl to automatically refresh its
credentials using the same identity as gcloud. If you are running kubectl as
part of an application, it is recommended to use [application default
credentials](https://cloud.google.com/docs/authentication/production).
To configure a `kubeconfig` file to use application default credentials, set
the container/use_application_default_credentials
[Cloud SDK property](https://cloud.google.com/sdk/docs/properties) to true
before running {command}
See [](https://cloud.google.com/kubernetes-engine/docs/kubectl) for
kubectl documentation.
"""
detailed_help = {
'EXAMPLES': """\
To switch to working on your cluster 'sample-cluster', run:
$ {command} sample-cluster --location=us-central1-f
""",
}
@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.
"""
flags.AddGetCredentialsArgs(parser)
flags.AddCrossConnectSubnetworkFlag(parser)
flags.AddPrivateEndpointFQDNFlag(parser)
flags.AddDnsEndpointFlag(parser)
flags.AddKubecontextOverrideFlag(parser)
flags.AddUseIamTokenFlag(parser)
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.
Raises:
util.Error: if the cluster is unreachable or not running.
"""
flags.VerifyGetCredentialsFlags(args)
cluster, cluster_ref = _BaseRun(args, self.context)
util.ClusterConfig.Persist(
cluster,
cluster_ref.projectId,
args.internal_ip,
args.cross_connect_subnetwork,
args.private_endpoint_fqdn,
args.dns_endpoint,
kubecontext_override=args.kubecontext_override,
use_iam_token=args.use_iam_token,
)

View File

@@ -0,0 +1,64 @@
# -*- 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.
"""Get cluster upgrade info command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.UniverseCompatible
class GetUpgradeInfo(base.Command):
"""Get information about upgrades for existing clusters including auto upgrade status, upgrade history, upgrade targets, and end of support timelines."""
detailed_help = {
'DESCRIPTION':
'{description}',
'EXAMPLES':
"""\
To get upgrade information for an existing cluster, run:
$ {command} sample-cluster
""",
}
@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.
"""
parser.add_argument('name', help='The name of your existing cluster.')
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.
"""
adapter = self.context['api_adapter']
location_get = self.context['location_get']
location = location_get(args)
return adapter.GetClusterUpgradeInfo(adapter.ParseCluster(args.name,
location))

View File

@@ -0,0 +1,145 @@
# -*- coding: utf-8 -*- #
# Copyright 2014 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.
"""List clusters command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import exceptions as apitools_exceptions
from googlecloudsdk.api_lib.container import transforms
from googlecloudsdk.api_lib.container import util
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.command_lib.container import constants
from googlecloudsdk.core import log
from googlecloudsdk.core import properties
from surface.container.clusters.upgrade import UpgradeHelpText
from surface.container.clusters.upgrade import VersionVerifier
class List(base.ListCommand):
"""List existing clusters for running containers."""
detailed_help = {
'DESCRIPTION': """\
{description}
This command queries cluster across all locations unless either
'--location', '--region', or '--zone' are specified.
""",
'EXAMPLES': """\
To list existing clusters in all locations, run:
$ {command}
""",
}
@staticmethod
def Args(parser):
parser.display_info.AddFormat(util.CLUSTERS_FORMAT)
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.
"""
adapter = self.context['api_adapter']
location_get = self.context['location_get']
location = location_get(args, ignore_property=True, required=False)
project = properties.VALUES.core.project.Get(required=True)
def sort_key(cluster):
return (cluster.zone, cluster.name)
try:
clusters = adapter.ListClusters(project, location)
clusters.clusters = sorted(clusters.clusters, key=sort_key)
if clusters.missingZones:
log.warning(
'The following zones did not respond: {0}. List results may be '
'incomplete.'.format(', '.join(clusters.missingZones)))
upgrade_available = False
support_ending = False
unsupported = False
expiring = False
self._upgrade_hint = ''
self._expire_warning = ''
self._degraded_warning = ''
vv = VersionVerifier()
for c in clusters.clusters:
time_left = transforms.ParseExpireTime(c.expireTime)
if time_left and time_left.days < constants.EXPIRE_WARNING_DAYS:
expiring = True
if adapter.IsDegraded(c):
self._degraded_warning += constants.DEGRADED_WARNING.format(
cluster_name=c.name,
cluster_degraded_warning=adapter.GetDegradedWarning(c))
if c.enableKubernetesAlpha:
# Don't print upgrade hints for alpha clusters, they aren't
# upgradeable.
continue
if c.nodePools:
ver_status = vv.Compare(c.currentMasterVersion, c.currentNodeVersion)
# If autopilot is enabled, then nodes cannot be manually upgraded,
# so we don't show the upgrade_available message
# (which prompts users to run a command to upgrade their nodes).
if ver_status == VersionVerifier.UPGRADE_AVAILABLE and not (
c.autopilot and c.autopilot.enabled
):
c.currentNodeVersion += ' *'
upgrade_available = True
elif ver_status == VersionVerifier.SUPPORT_ENDING:
c.currentNodeVersion += ' **'
support_ending = True
elif ver_status == VersionVerifier.UNSUPPORTED:
c.currentNodeVersion += ' ***'
unsupported = True
else:
# cnv is cluster api version for clusters w/ 0 nodes, so hide
c.currentNodeVersion = ''
if upgrade_available:
self._upgrade_hint += UpgradeHelpText.UPGRADE_AVAILABLE
if support_ending:
self._upgrade_hint += UpgradeHelpText.SUPPORT_ENDING
if unsupported:
self._upgrade_hint += UpgradeHelpText.UNSUPPORTED
if self._upgrade_hint:
self._upgrade_hint += UpgradeHelpText.UPGRADE_COMMAND.format(
name='NAME')
if expiring:
self._expire_warning = constants.EXPIRE_WARNING
return clusters.clusters
except apitools_exceptions.HttpError as error:
raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
def Epilog(self, resources_were_displayed):
if self._upgrade_hint:
log.status.Print(self._upgrade_hint)
if self._expire_warning:
log.warning(self._expire_warning)
if self._degraded_warning:
log.warning(self._degraded_warning)

View File

@@ -0,0 +1,144 @@
# -*- coding: utf-8 -*- #
# Copyright 2014 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.
"""Resize cluster command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import exceptions as apitools_exceptions
from googlecloudsdk.api_lib.container import util
from googlecloudsdk.calliope import actions
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.command_lib.container import flags
from googlecloudsdk.core import log
from googlecloudsdk.core.console import console_attr
from googlecloudsdk.core.console import console_io
class Resize(base.Command):
"""Resizes an existing cluster for running containers."""
@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.
"""
parser.add_argument('name', help='The name of this cluster.')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
'--size',
type=int,
dest='num_nodes',
action=actions.DeprecationAction('--size',
warn='The {flag_name} flag is now '
'deprecated. Please use `--num-nodes` '
'instead.'),
help='Target number of nodes in the cluster.')
group.add_argument(
'--num-nodes',
type=int,
help='Target number of nodes in the cluster.')
parser.add_argument('--node-pool', help='The node pool to resize.')
flags.AddAsyncFlag(parser)
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.
"""
adapter = self.context['api_adapter']
location_get = self.context['location_get']
location = location_get(args)
cluster_ref = adapter.ParseCluster(args.name, location)
cluster = None
cluster_name = args.name
pool_name = args.node_pool if args.node_pool else 'default-pool'
try:
# Attempt to get cluster for better prompts and to validate args.
# Error is a warning but not fatal. Should only exit with a failure on
# ResizeNodePool(...) below.
cluster = adapter.GetCluster(cluster_ref)
cluster_name = cluster.name
except (exceptions.HttpException, apitools_exceptions.HttpForbiddenError,
util.Error) as error:
log.warning(('Problem loading details of cluster to resize:\n\n{}\n\n'
'You can still attempt to resize the cluster.\n').format(
console_attr.SafeText(error)))
if cluster is not None:
pool_name = adapter.FindNodePool(cluster, args.node_pool).name
console_io.PromptContinue(
message=('Pool [{pool}] for [{cluster_name}] will be resized to '
'{new_size} node(s) in each zone it spans.').format(
pool=pool_name,
cluster_name=cluster_name,
new_size=args.num_nodes),
throw_if_unattended=True,
cancel_on_no=True)
op_ref = adapter.ResizeNodePool(cluster_ref, pool_name, args.num_nodes)
if not args.async_:
adapter.WaitForOperation(op_ref,
'Resizing {0}'.format(cluster_ref.clusterId))
log.UpdatedResource(cluster_ref)
Resize.detailed_help = {
'brief':
'Resizes an existing cluster for running containers.',
'DESCRIPTION':
"""
Resize an existing cluster to a provided size.
If you have multiple node pools, you must specify which node pool to resize by
using the --node-pool flag. You are not required to use the flag if you have
a single node pool.
When increasing the size of a container cluster, the new instances are created
with the same configuration as the existing instances.
Existing pods are not moved onto the new instances,
but new pods (such as those created by resizing a replication controller)
will be scheduled onto the new instances.
When decreasing a cluster, the nodes are drained. As a result, the pods running
on these nodes are gracefully terminated. If your pods are being managed by a
workload controller, the controller will attempt to reschedule them onto the
remaining instances. If your pods are not managed by a workload controller,
they will not be restarted.
Note that when resizing down, instances running pods and instances without pods
are not differentiated. Resize will pick instances to remove at random.
When you resize a node pool that spans multiple zones, the new size represents
the number of nodes in the node pool per zone. For example, if you have a node
pool of size 2 spanning two zones, the total node count is 4. If you resize the
node pool with `--num-nodes=4`, the total node count becomes 8.
""",
'EXAMPLES':
"""\
To resize the default node pool of an existing cluster, run:
$ {command} sample-cluster --num-nodes=2
""",
}

View File

@@ -0,0 +1,320 @@
# -*- coding: utf-8 -*- #
# Copyright 2015 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.
"""Upgrade cluster command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import exceptions as apitools_exceptions
from googlecloudsdk.api_lib.container import api_adapter
from googlecloudsdk.api_lib.container import util
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.command_lib.container import container_command_util
from googlecloudsdk.command_lib.container import flags
from googlecloudsdk.core import log
from googlecloudsdk.core import properties
from googlecloudsdk.core.console import console_attr
from googlecloudsdk.core.console import console_io
from googlecloudsdk.core.util import iso_duration
from googlecloudsdk.core.util import times
from googlecloudsdk.core.util.semver import SemVer
class UpgradeHelpText(object):
"""Upgrade available help text messages."""
UPGRADE_AVAILABLE = """
* - There is an upgrade available for your cluster(s).
"""
SUPPORT_ENDING = """
** - The current version of your cluster(s) will soon be out of support, please upgrade.
"""
UNSUPPORTED = """
*** - The current version of your cluster(s) is unsupported, please upgrade.
"""
UPGRADE_COMMAND = """
To upgrade nodes to the latest available version, run
$ gcloud container clusters upgrade {name}"""
class VersionVerifier(object):
"""Compares the cluster and master versions for upgrade availablity."""
UP_TO_DATE = 0
UPGRADE_AVAILABLE = 1
SUPPORT_ENDING = 2
UNSUPPORTED = 3
def Compare(self, current_master_version, current_cluster_version):
"""Compares the cluster and master versions and returns an enum."""
if current_master_version == current_cluster_version:
return self.UP_TO_DATE
master_version = SemVer(current_master_version)
cluster_version = SemVer(current_cluster_version)
major, minor, _ = master_version.Distance(cluster_version)
if major != 0 or minor > 2:
return self.UNSUPPORTED
elif minor > 1:
return self.SUPPORT_ENDING
else:
return self.UPGRADE_AVAILABLE
def ParseUpgradeOptionsBase(args):
"""Parses the flags provided with the cluster upgrade command."""
opts = api_adapter.UpdateClusterOptions(
version=args.cluster_version,
update_master=args.master,
update_nodes=(not args.master),
node_pool=args.node_pool,
image_type=args.image_type,
image=args.image,
image_project=args.image_project,
)
if args.control_plane_soak_duration:
opts.control_plane_soak_duration = times.FormatDurationForJson(
iso_duration.Duration(seconds=args.control_plane_soak_duration)
)
return opts
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.
"""
parser.add_argument(
'name', metavar='NAME', help='The name of the cluster to upgrade.')
flags.AddClusterVersionFlag(
parser,
help="""\
The GKE release version to which to upgrade the cluster's node pools or master.
If desired cluster version is omitted, *node pool* upgrades default to the current
*master* version and *master* upgrades default to the default cluster version,
which can be found in the server config.
You can find the list of allowed versions for upgrades by running:
$ gcloud container get-server-config
""")
parser.add_argument('--node-pool', help='The node pool to upgrade.')
parser.add_argument(
'--master',
help=(
"Upgrade the cluster's master. Node pools cannot be upgraded at the "
' same time as the master.'
),
action='store_true',
)
# Timeout in seconds for the operation, default 3600 seconds (60 minutes)
parser.add_argument(
'--timeout',
type=int,
default=3600,
hidden=True,
help='Timeout (seconds) for waiting on the operation to complete.')
flags.AddAsyncFlag(parser)
flags.AddImageTypeFlag(parser, 'cluster/node pool')
flags.AddImageFlag(parser, hidden=True)
flags.AddImageProjectFlag(parser, hidden=True)
def MaybeLog122UpgradeWarning(cluster):
"""Logs deprecation warning for GKE v1.22 upgrades."""
if cluster is not None:
cmv = SemVer(cluster.currentMasterVersion)
if cmv >= SemVer('1.22.0-gke.0'):
return
log.status.Print(
'Upcoming breaking change: Starting with v1.22, Kubernetes has removed '
'several v1beta1 APIs for more stable v1 APIs. Read more about this '
'change - '
'https://cloud.google.com/kubernetes-engine/docs/deprecations/apis-1-22. '
'Please ensure that your cluster is not using any deprecated v1beta1 '
'APIs prior to upgrading to GKE 1.22.')
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Upgrade(base.Command):
"""Upgrade the Kubernetes version of an existing container cluster."""
@staticmethod
def Args(parser):
_Args(parser)
flags.AddControlPlaneSoakDurationFlag(parser, hidden=True)
def ParseUpgradeOptions(self, args):
return ParseUpgradeOptionsBase(args)
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.
"""
adapter = self.context['api_adapter']
location_get = self.context['location_get']
location = location_get(args)
cluster_ref = adapter.ParseCluster(args.name, location)
project_id = properties.VALUES.core.project.Get(required=True)
try:
cluster = adapter.GetCluster(cluster_ref)
except (exceptions.HttpException, apitools_exceptions.HttpForbiddenError,
util.Error) as error:
log.warning(('Problem loading details of cluster to upgrade:\n\n{}\n\n'
'You can still attempt to upgrade the cluster.\n').format(
console_attr.SafeText(error)))
cluster = None
try:
server_conf = adapter.GetServerConfig(project_id, location)
except (exceptions.HttpException, apitools_exceptions.HttpForbiddenError,
util.Error) as error:
log.warning(('Problem loading server config:\n\n{}\n\n'
'You can still attempt to upgrade the cluster.\n').format(
console_attr.SafeText(error)))
server_conf = None
if args.control_plane_soak_duration and not args.master:
raise exceptions.InvalidArgumentException(
'--control-plane-soak-duration',
'--control-plane-soak-duration can only be specified with --master')
upgrade_message = container_command_util.ClusterUpgradeMessage(
name=args.name,
server_conf=server_conf,
cluster=cluster,
master=args.master,
control_plane_soak_duration=args.control_plane_soak_duration,
node_pool_name=args.node_pool,
new_version=args.cluster_version,
new_image_type=args.image_type)
if args.master:
MaybeLog122UpgradeWarning(cluster)
console_io.PromptContinue(
message=upgrade_message, throw_if_unattended=True, cancel_on_no=True)
options = self.ParseUpgradeOptions(args)
try:
op_ref = adapter.UpdateCluster(cluster_ref, options)
except apitools_exceptions.HttpError as error:
raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
if not args.async_:
adapter.WaitForOperation(
op_ref,
'Upgrading {0}'.format(cluster_ref.clusterId),
timeout_s=args.timeout)
try:
cluster = adapter.GetCluster(cluster_ref)
for node_pool in cluster.nodePools:
util.CheckForCgroupModeV1(node_pool)
except (exceptions.HttpException, apitools_exceptions.HttpForbiddenError,
util.Error) as error:
log.warning(
util.CGROUPV1_CHECKING_FAILURE_MSG.format(
console_attr.SafeText(error)
)
)
log.UpdatedResource(cluster_ref)
Upgrade.detailed_help = {
'DESCRIPTION':
"""\
Upgrades the Kubernetes version of an existing container cluster.
This command upgrades the Kubernetes version of the *node pools* or *master* of
a cluster. Note that the Kubernetes version of the cluster's *master* is
also periodically upgraded automatically as new releases are available.
If desired cluster version is omitted, *node pool* upgrades default to the
current *master* version and *master* upgrades default to the default
cluster version, which can be found in the server config.
*During node pool upgrades, nodes will be deleted and recreated.* While
persistent Kubernetes resources, such as
Pods backed by replication controllers, will be rescheduled onto new
nodes, a small cluster may experience a few minutes where there are
insufficient nodes available to run all of the scheduled Kubernetes
resources.
*Please ensure that any data you wish to keep is stored on a persistent*
*disk before upgrading the cluster.* Ephemeral Kubernetes resources--in
particular, Pods without replication controllers--will be lost, while
persistent Kubernetes resources will get rescheduled.
""",
'EXAMPLES':
"""\
Upgrade the node pool `pool-1` of `sample-cluster` to the Kubernetes
version of the cluster's master.
$ {command} sample-cluster --node-pool=pool-1
Upgrade the node pool `pool-1` of `sample-cluster` to Kubernetes version
1.14.7-gke.14:
$ {command} sample-cluster --node-pool=pool-1 --cluster-version="1.14.7-gke.14"
Upgrade the master of `sample-cluster` to the default cluster version:
$ {command} sample-cluster --master
""",
}
@base.ReleaseTracks(base.ReleaseTrack.BETA)
class UpgradeBeta(Upgrade):
"""Upgrade the Kubernetes version of an existing container cluster."""
@staticmethod
def Args(parser):
_Args(parser)
flags.AddControlPlaneSoakDurationFlag(parser, hidden=False)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class UpgradeAlpha(Upgrade):
"""Upgrade the Kubernetes version of an existing container cluster."""
@staticmethod
def Args(parser):
_Args(parser)
flags.AddControlPlaneSoakDurationFlag(parser, hidden=False)
flags.AddSecurityProfileForUpgradeFlags(parser)
def ParseUpgradeOptions(self, args):
ops = ParseUpgradeOptionsBase(args)
ops.security_profile = args.security_profile
ops.security_profile_runtime_rules = args.security_profile_runtime_rules
return ops