12087 lines
466 KiB
Python
12087 lines
466 KiB
Python
# -*- 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.
|
|
"""Api client adapter containers commands."""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import unicode_literals
|
|
|
|
import functools
|
|
import operator
|
|
import os
|
|
import re
|
|
import time
|
|
|
|
from apitools.base.py import exceptions as apitools_exceptions
|
|
from apitools.base.py import http_wrapper
|
|
from googlecloudsdk.api_lib.compute import constants
|
|
from googlecloudsdk.api_lib.container import constants as gke_constants
|
|
from googlecloudsdk.api_lib.container import util
|
|
from googlecloudsdk.api_lib.util import apis as core_apis
|
|
from googlecloudsdk.calliope import base
|
|
from googlecloudsdk.calliope import exceptions
|
|
from googlecloudsdk.command_lib.util.apis import arg_utils
|
|
from googlecloudsdk.command_lib.util.args import labels_util
|
|
from googlecloudsdk.core import log
|
|
from googlecloudsdk.core import properties
|
|
from googlecloudsdk.core import resources as cloud_resources
|
|
from googlecloudsdk.core import yaml
|
|
from googlecloudsdk.core.console import console_io
|
|
from googlecloudsdk.core.console import progress_tracker
|
|
from googlecloudsdk.core.util import times
|
|
import six
|
|
from six.moves import range # pylint: disable=redefined-builtin
|
|
import six.moves.http_client
|
|
|
|
WRONG_ZONE_ERROR_MSG = """\
|
|
{error}
|
|
Could not find [{name}] in [{wrong_zone}].
|
|
Did you mean [{name}] in [{zone}]?"""
|
|
|
|
NO_SUCH_CLUSTER_ERROR_MSG = """\
|
|
{error}
|
|
No cluster named '{name}' in {project}."""
|
|
|
|
NO_SUCH_NODE_POOL_ERROR_MSG = """\
|
|
No node pool named '{name}' in {cluster}."""
|
|
|
|
NO_NODE_POOL_SELECTED_ERROR_MSG = """\
|
|
Please specify one of the following node pools:
|
|
"""
|
|
|
|
MISMATCH_AUTHORIZED_NETWORKS_ERROR_MSG = """\
|
|
Cannot use --master-authorized-networks \
|
|
if --enable-master-authorized-networks is not \
|
|
specified."""
|
|
|
|
NO_AUTOPROVISIONING_MSG = """\
|
|
Node autoprovisioning is currently in beta.
|
|
"""
|
|
|
|
NO_AUTOPROVISIONING_LIMITS_ERROR_MSG = """\
|
|
Must specify both --max-cpu and --max-memory to enable autoprovisioning.
|
|
"""
|
|
|
|
LIMITS_WITHOUT_AUTOPROVISIONING_MSG = """\
|
|
Must enable node autoprovisioning to specify resource limits for autoscaling.
|
|
"""
|
|
|
|
DEFAULTS_WITHOUT_AUTOPROVISIONING_MSG = """\
|
|
Must enable node autoprovisioning to specify defaults for node autoprovisioning.
|
|
"""
|
|
|
|
BOTH_AUTOPROVISIONING_UPGRADE_SETTINGS_ERROR_MSG = """\
|
|
Must specify both 'maxSurgeUpgrade' and 'maxUnavailableUpgrade' in \
|
|
'upgradeSettings' in --autoprovisioning-config-file, or both \
|
|
'--autoprovisioning-max-surge-upgrade' and '--autoprovisioning-max-unavailable-upgrade' \
|
|
from cmd argument to set a surge upgrade strategy.
|
|
"""
|
|
|
|
BOTH_AUTOPROVISIONING_MANAGEMENT_SETTINGS_ERROR_MSG = """\
|
|
Must specify both 'autoUpgrade' and 'autoRepair' in 'management' in \
|
|
--autoprovisioning-config-file to set management settings.
|
|
"""
|
|
|
|
BOTH_AUTOPROVISIONING_SHIELDED_INSTANCE_SETTINGS_ERROR_MSG = """\
|
|
Must specify both 'enableSecureBoot' and 'enableIntegrityMonitoring' \
|
|
in 'shieldedInstanceConfig' in --autoprovisioning-config-file to set \
|
|
management settings.
|
|
"""
|
|
|
|
BOTH_SHIELDED_INSTANCE_SETTINGS_ERROR_MSG = """\
|
|
Must specify both or none of --shielded-secure-boot and \
|
|
--shielded-integrity-monitoring.
|
|
"""
|
|
|
|
LIMITS_WITHOUT_AUTOPROVISIONING_FLAG_MSG = """\
|
|
Must specify --enable-autoprovisioning to specify resource limits for autoscaling.
|
|
"""
|
|
|
|
MISMATCH_ACCELERATOR_TYPE_LIMITS_ERROR_MSG = """\
|
|
Maximum and minimum accelerator limits must be set on the same accelerator type.
|
|
"""
|
|
|
|
NO_SUCH_LABEL_ERROR_MSG = """\
|
|
No label named '{name}' found on cluster '{cluster}'."""
|
|
|
|
NO_LABELS_ON_CLUSTER_ERROR_MSG = """\
|
|
Cluster '{cluster}' has no labels to remove."""
|
|
|
|
CREATE_SUBNETWORK_INVALID_KEY_ERROR_MSG = """\
|
|
Invalid key '{key}' for --create-subnetwork (must be one of 'name', 'range').
|
|
"""
|
|
|
|
CREATE_SUBNETWORK_WITH_SUBNETWORK_ERROR_MSG = """\
|
|
Cannot specify both --subnetwork and --create-subnetwork at the same time.
|
|
"""
|
|
|
|
CREATE_POD_RANGE_INVALID_KEY_ERROR_MSG = """
|
|
Invalid key '{key}' for --create-pod-ipv4-range (must be one of 'name', 'range').
|
|
"""
|
|
|
|
NODE_TAINT_INCORRECT_FORMAT_ERROR_MSG = """\
|
|
Invalid value [{key}={value}] for argument --node-taints. Node taint is of format key=value:effect
|
|
"""
|
|
|
|
NODE_TAINT_INCORRECT_EFFECT_ERROR_MSG = """\
|
|
Invalid taint effect [{effect}] for argument --node-taints. Valid effect values are NoSchedule, PreferNoSchedule, NoExecute'
|
|
"""
|
|
|
|
LOCAL_SSD_INCORRECT_FORMAT_ERROR_MSG = """\
|
|
Invalid local SSD format [{err_format}] for argument --local-ssd-volumes. Valid formats are fs, block
|
|
"""
|
|
|
|
UNKNOWN_WORKLOAD_METADATA_ERROR_MSG = """\
|
|
Invalid option '{option}' for '--workload-metadata' (must be one of 'gce_metadata', 'gke_metadata').
|
|
"""
|
|
|
|
ALLOW_ROUTE_OVERLAP_WITHOUT_EXPLICIT_NETWORK_MODE = """\
|
|
Flag --allow-route-overlap must be used with either --enable-ip-alias or --no-enable-ip-alias.
|
|
"""
|
|
|
|
ALLOW_ROUTE_OVERLAP_WITHOUT_CLUSTER_CIDR_ERROR_MSG = """\
|
|
Flag --cluster-ipv4-cidr must be fully specified (e.g. `10.96.0.0/14`, but not `/14`) with --allow-route-overlap.
|
|
"""
|
|
|
|
ALLOW_ROUTE_OVERLAP_WITHOUT_SERVICES_CIDR_ERROR_MSG = """\
|
|
Flag --services-ipv4-cidr must be fully specified (e.g. `10.96.0.0/14`, but not `/14`) with --allow-route-overlap and --enable-ip-alias.
|
|
"""
|
|
|
|
PREREQUISITE_OPTION_ERROR_MSG = """\
|
|
Cannot specify --{opt} without --{prerequisite}.
|
|
"""
|
|
|
|
CLOUD_LOGGING_OR_MONITORING_DISABLED_ERROR_MSG = """\
|
|
Flag --enable-stackdriver-kubernetes requires Cloud Logging and Cloud Monitoring enabled with --enable-cloud-logging and --enable-cloud-monitoring.
|
|
"""
|
|
|
|
CLOUDRUN_STACKDRIVER_KUBERNETES_DISABLED_ERROR_MSG = """\
|
|
The CloudRun-on-GKE addon (--addons=CloudRun) requires System Logging and Monitoring to be enabled via the --monitoring=SYSTEM and --logging=SYSTEM flags.
|
|
"""
|
|
|
|
CLOUDRUN_INGRESS_KUBERNETES_DISABLED_ERROR_MSG = """\
|
|
The CloudRun-on-GKE addon (--addons=CloudRun) requires HTTP Load Balancing to be enabled via the --addons=HttpLoadBalancing flag.
|
|
"""
|
|
|
|
CONFIGCONNECTOR_STACKDRIVER_KUBERNETES_DISABLED_ERROR_MSG = """\
|
|
The ConfigConnector-on-GKE addon (--addons=ConfigConnector) requires System Logging and Monitoring to be enabled via the --monitoring=SYSTEM and --logging=SYSTEM flags.
|
|
"""
|
|
|
|
CONFIGCONNECTOR_WORKLOAD_IDENTITY_DISABLED_ERROR_MSG = """\
|
|
The ConfigConnector-on-GKE addon (--addons=ConfigConnector) requires workload identity to be enabled via the --workload-pool=WORKLOAD_POOL flag.
|
|
"""
|
|
|
|
CLOUDBUILD_STACKDRIVER_KUBERNETES_DISABLED_ERROR_MSG = """\
|
|
Cloud Build for Anthos (--addons=CloudBuild) requires System Logging and Monitoring to be enabled via the --monitoring=SYSTEM and --logging=SYSTEM flags.
|
|
"""
|
|
|
|
DEFAULT_MAX_PODS_PER_NODE_WITHOUT_IP_ALIAS_ERROR_MSG = """\
|
|
Cannot use --default-max-pods-per-node without --enable-ip-alias.
|
|
"""
|
|
|
|
MAX_PODS_PER_NODE_WITHOUT_IP_ALIAS_ERROR_MSG = """\
|
|
Cannot use --max-pods-per-node without --enable-ip-alias.
|
|
"""
|
|
|
|
ALPHA_CLUSTER_FEATURE_GATES_WITHOUT_ENABLE_KUBERNETES_ALPHA_ERROR_MSG = """\
|
|
Cannot use --alpha-cluster-feature-gates without --enable-kubernetes-alpha.
|
|
"""
|
|
|
|
NOTHING_TO_UPDATE_ERROR_MSG = """\
|
|
Nothing to update.
|
|
"""
|
|
|
|
ENABLE_PRIVATE_NODES_WITH_PRIVATE_CLUSTER_ERROR_MSG = """\
|
|
Cannot specify both --[no-]enable-private-nodes and --[no-]private-cluster at the same time.
|
|
"""
|
|
|
|
ENABLE_NETWORK_EGRESS_METERING_ERROR_MSG = """\
|
|
Cannot use --[no-]enable-network-egress-metering without --resource-usage-bigquery-dataset.
|
|
"""
|
|
|
|
ENABLE_RESOURCE_CONSUMPTION_METERING_ERROR_MSG = """\
|
|
Cannot use --[no-]enable-resource-consumption-metering without --resource-usage-bigquery-dataset.
|
|
"""
|
|
|
|
DISABLE_DEFAULT_SNAT_WITHOUT_IP_ALIAS_ERROR_MSG = """\
|
|
Cannot use --disable-default-snat without --enable-ip-alias.
|
|
"""
|
|
|
|
DISABLE_DEFAULT_SNAT_WITHOUT_PRIVATE_NODES_ERROR_MSG = """\
|
|
Cannot use --disable-default-snat without --enable-private-nodes.
|
|
"""
|
|
|
|
RESERVATION_AFFINITY_SPECIFIC_WITHOUT_RESERVATION_NAME_ERROR_MSG = """\
|
|
Must specify --reservation for --reservation-affinity=specific.
|
|
"""
|
|
|
|
RESERVATION_AFFINITY_NON_SPECIFIC_WITH_RESERVATION_NAME_ERROR_MSG = """\
|
|
Cannot specify --reservation for --reservation-affinity={affinity}.
|
|
"""
|
|
|
|
DATAPATH_PROVIDER_ILL_SPECIFIED_ERROR_MSG = """\
|
|
Invalid provider '{provider}' for argument --datapath-provider. Valid providers are legacy, advanced.
|
|
"""
|
|
|
|
DPV2_OBS_ERROR_MSG = """\
|
|
Invalid '{mode}' for argument --dataplane-v2-observability-mode. Valid modes are DISABLED, INTERNAL_VPC_LB, EXTERNAL_LB.
|
|
"""
|
|
|
|
SANDBOX_TYPE_NOT_PROVIDED = """\
|
|
Must specify sandbox type.
|
|
"""
|
|
|
|
SANDBOX_TYPE_NOT_SUPPORTED = """\
|
|
Provided sandbox type '{type}' not supported.
|
|
"""
|
|
|
|
TPU_SERVING_MODE_ERROR = """\
|
|
Cannot specify --tpu-ipv4-cidr with --enable-tpu-service-networking."""
|
|
|
|
GPU_SHARING_STRATEGY_ERROR_MSG = """\
|
|
Invalid gpu sharing strategy [{gpu-sharing-strategy}] for argument --accelerator. Valid values are time-sharing, mps'
|
|
"""
|
|
|
|
GPU_DRIVER_VERSION_ERROR_MSG = """\
|
|
Invalid gpu driver version [{gpu-driver-version}] for argument --accelerator. Valid values are default, latest, or disabled'
|
|
"""
|
|
|
|
MAINTENANCE_INTERVAL_TYPE_NOT_SUPPORTED = """\
|
|
Provided maintenance interval type '{type}' not supported.
|
|
"""
|
|
|
|
MANGED_CONFIG_TYPE_NOT_SUPPORTED = """\
|
|
Invalid managed config type '{type}' for argument --managed-config. Valid values are: autofleet, disabled'
|
|
"""
|
|
|
|
COMPLIANCE_MODE_NOT_SUPPORTED = """\
|
|
Invalid mode '{mode}' for '--compliance' (must be one of 'enabled', 'disabled').
|
|
"""
|
|
|
|
COMPLIANCE_DISABLED_CONFIGURATION = """\
|
|
Cannot specify --compliance-standards with --compliance=disabled
|
|
"""
|
|
|
|
AUTO_MONITORING_NOT_SUPPORTED_WITHOUT_MANAGED_PROMETHEUS = """\
|
|
Cannot enable Auto Monitoring without enabling Managed Prometheus.
|
|
"""
|
|
|
|
COMPLIANCE_INVALID_STANDARDS_CONFIGURATION = """\
|
|
Invalid value '{standards}' for --compliance-standards: must provide a list of standards separated by commas.
|
|
"""
|
|
|
|
SECURITY_POSTURE_MODE_NOT_SUPPORTED = """\
|
|
Invalid mode '{mode}' for '--security-posture' (must be one of 'disabled', 'standard', 'enterprise').
|
|
"""
|
|
|
|
WORKLOAD_VULNERABILITY_SCANNING_MODE_NOT_SUPPORTED = """\
|
|
Invalid mode '{mode}' for '--workload-vulnerability-scanning' (must be one of 'disabled', 'standard', 'enterprise').
|
|
"""
|
|
|
|
HOST_MAINTENANCE_INTERVAL_TYPE_NOT_SUPPORTED = """\
|
|
Provided host maintenance interval type '{type}' is not supported.
|
|
"""
|
|
OPPORTUNISTIC_MAINTENANCE_FIELD_NOT_SUPPORTED = """\
|
|
Provided opportunistic maintenance field '{field}' with value '{value}' is not supported. This field must end with 's' only.
|
|
"""
|
|
|
|
NODECONFIGDEFAULTS_READONLY_PORT_NOT_SUPPORTED = """\
|
|
nodePoolDefaults.nodeKubeletConfig is not supported on GKE Autopilot clusters.
|
|
"""
|
|
|
|
ADDITIONAL_SUBNETWORKS_NOT_FOUND = """\
|
|
Can not remove subnetwork {subnetwork}: not found in additional subnetworks
|
|
"""
|
|
|
|
ADDITIONAL_SUBNETWORKS_POD_RANG_ENOT_FOUND = """\
|
|
Can not remove pod ipv4 range {range}: not found in additional subnetworks
|
|
"""
|
|
|
|
CLUSTER_TIER_NOT_SUPPORTED = """\
|
|
Provided cluster tier '{tier}' is not supported.
|
|
"""
|
|
|
|
NETWORK_TIER_NOT_SUPPORTED = """\
|
|
Provided network tier '{network_tier}' is not supported.
|
|
"""
|
|
|
|
TPU_TOPOLOGY_INCORRECT_FORMAT_ERROR_MSG = """\
|
|
Invalid format '{topology}' for argument --tpu-topology. Must provide 2-3 integers separated by 'x' (e.g. 2x4 or 2x2x4)
|
|
"""
|
|
|
|
MACHINE_TYPE_INCORRECT_FORMAT_ERROR_MSG = """\
|
|
Invalid machine type '{machine_type}' for argument --machine-type. Unable to parse the number of chips.
|
|
"""
|
|
CONFIDENTIAL_NODE_TYPE_NOT_SUPPORTED = """\
|
|
Invalid type '{type}' for '--confidential-node-type' (must be one of {choices}).
|
|
"""
|
|
|
|
ANONYMOUS_AUTHENTICATION_MODE_NOT_SUPPORTED = """\
|
|
Anonymous authentication mode '{mode}' is not supported.
|
|
"""
|
|
|
|
MEMBERSHIP_TYPE_NOT_SUPPORTED = """\
|
|
Fleet membership type '{type}' is not supported.
|
|
"""
|
|
|
|
ROUTE_BASED_CLUSTERS_NOT_SUPPORTED_WITH_STACK_TYPE_IPV6 = """\
|
|
Route-based clusters are not supported with stack type IPV6.
|
|
"""
|
|
|
|
CONTROL_PLANE_EGRESS_NOT_SUPPORTED = """\
|
|
Control plane egress '{mode}' is not supported.
|
|
"""
|
|
|
|
AUTOPILOT_GENERAL_PROFILE_NOT_SUPPORTED = """\
|
|
Invalid value for --autopilot-general-profile: '{profile}' (must be one of {choices}).
|
|
"""
|
|
|
|
NO_SUCH_RESOURCE_POLICY_ERROR_MSG = """\
|
|
Resource policy '{policy_name}' not found in project '{project}' region '{region}'."""
|
|
|
|
WRONG_REGION_RESOURCE_POLICY_ERROR_MSG = """\
|
|
Resource policy '{policy_name}' was not found in region '{wrong_region}', but a policy with the same name exists in region '{region}'. Did you mean to specify that region?'"""
|
|
|
|
DEFAULT_MAX_NODES_PER_POOL = 1000
|
|
|
|
MAX_AUTHORIZED_NETWORKS_CIDRS_PRIVATE = 100
|
|
MAX_AUTHORIZED_NETWORKS_CIDRS_PUBLIC = 50
|
|
|
|
INGRESS = 'HttpLoadBalancing'
|
|
HPA = 'HorizontalPodAutoscaling'
|
|
DASHBOARD = 'KubernetesDashboard'
|
|
CLOUDBUILD = 'CloudBuild'
|
|
BACKUPRESTORE = 'BackupRestore'
|
|
CONFIGCONNECTOR = 'ConfigConnector'
|
|
GCEPDCSIDRIVER = 'GcePersistentDiskCsiDriver'
|
|
GCPFILESTORECSIDRIVER = 'GcpFilestoreCsiDriver'
|
|
GCSFUSECSIDRIVER = 'GcsFuseCsiDriver'
|
|
STATEFULHA = 'StatefulHA'
|
|
PARALLELSTORECSIDRIVER = 'ParallelstoreCsiDriver'
|
|
HIGHSCALECHECKPOINTING = 'HighScaleCheckpointing'
|
|
LUSTRECSIDRIVER = 'LustreCsiDriver'
|
|
RAYOPERATOR = 'RayOperator'
|
|
ISTIO = 'Istio'
|
|
NETWORK_POLICY = 'NetworkPolicy'
|
|
NODELOCALDNS = 'NodeLocalDNS'
|
|
APPLICATIONMANAGER = 'ApplicationManager'
|
|
RESOURCE_LIMITS = 'resourceLimits'
|
|
SERVICE_ACCOUNT = 'serviceAccount'
|
|
MIN_CPU_PLATFORM = 'minCpuPlatform'
|
|
UPGRADE_SETTINGS = 'upgradeSettings'
|
|
MAX_SURGE_UPGRADE = 'maxSurgeUpgrade'
|
|
MAX_UNAVAILABLE_UPGRADE = 'maxUnavailableUpgrade'
|
|
NODE_MANAGEMENT = 'management'
|
|
ENABLE_AUTO_UPGRADE = 'autoUpgrade'
|
|
ENABLE_AUTO_REPAIR = 'autoRepair'
|
|
SCOPES = 'scopes'
|
|
AUTOPROVISIONING_LOCATIONS = 'autoprovisioningLocations'
|
|
BOOT_DISK_KMS_KEY = 'bootDiskKmsKey'
|
|
DISK_SIZE_GB = 'diskSizeGb'
|
|
DISK_TYPE = 'diskType'
|
|
IMAGE_TYPE = 'imageType'
|
|
SHIELDED_INSTANCE_CONFIG = 'shieldedInstanceConfig'
|
|
ENABLE_SECURE_BOOT = 'enableSecureBoot'
|
|
ENABLE_INTEGRITY_MONITORING = 'enableIntegrityMonitoring'
|
|
DEFAULT_ADDONS = [INGRESS, HPA]
|
|
CLOUDRUN_ADDONS = ['CloudRun', 'KubeRun']
|
|
VISIBLE_CLOUDRUN_ADDONS = ['CloudRun']
|
|
ADDONS_OPTIONS = DEFAULT_ADDONS + [
|
|
DASHBOARD,
|
|
NETWORK_POLICY,
|
|
NODELOCALDNS,
|
|
CONFIGCONNECTOR,
|
|
GCEPDCSIDRIVER,
|
|
GCPFILESTORECSIDRIVER,
|
|
BACKUPRESTORE,
|
|
GCSFUSECSIDRIVER,
|
|
STATEFULHA,
|
|
PARALLELSTORECSIDRIVER,
|
|
HIGHSCALECHECKPOINTING,
|
|
LUSTRECSIDRIVER,
|
|
RAYOPERATOR,
|
|
]
|
|
BETA_ADDONS_OPTIONS = ADDONS_OPTIONS + [
|
|
ISTIO,
|
|
APPLICATIONMANAGER,
|
|
]
|
|
ALPHA_ADDONS_OPTIONS = BETA_ADDONS_OPTIONS + [CLOUDBUILD]
|
|
|
|
NONE = 'NONE'
|
|
SYSTEM = 'SYSTEM'
|
|
WORKLOAD = 'WORKLOAD'
|
|
# TODO(b/187793166): Remove APISERVER when deprecating the legacy API.
|
|
APISERVER = 'APISERVER'
|
|
API_SERVER = 'API_SERVER'
|
|
SCHEDULER = 'SCHEDULER'
|
|
CONTROLLER_MANAGER = 'CONTROLLER_MANAGER'
|
|
ADDON_MANAGER = 'ADDON_MANAGER'
|
|
KCP_SSHD = 'KCP_SSHD'
|
|
KCP_CONNECTION = 'KCP_CONNECTION'
|
|
KCP_HPA = 'KCP_HPA'
|
|
STORAGE = 'STORAGE'
|
|
HPA_COMPONENT = 'HPA'
|
|
POD = 'POD'
|
|
DAEMONSET = 'DAEMONSET'
|
|
DEPLOYMENT = 'DEPLOYMENT'
|
|
STATEFULSET = 'STATEFULSET'
|
|
CADVISOR = 'CADVISOR'
|
|
KUBELET = 'KUBELET'
|
|
DCGM = 'DCGM'
|
|
JOBSET = 'JOBSET'
|
|
LOGGING_OPTIONS = [
|
|
NONE,
|
|
SYSTEM,
|
|
WORKLOAD,
|
|
API_SERVER,
|
|
SCHEDULER,
|
|
CONTROLLER_MANAGER,
|
|
ADDON_MANAGER,
|
|
KCP_SSHD,
|
|
KCP_CONNECTION,
|
|
KCP_HPA,
|
|
]
|
|
MONITORING_OPTIONS = [
|
|
NONE,
|
|
SYSTEM,
|
|
WORKLOAD,
|
|
API_SERVER,
|
|
SCHEDULER,
|
|
CONTROLLER_MANAGER,
|
|
STORAGE,
|
|
HPA_COMPONENT,
|
|
POD,
|
|
DAEMONSET,
|
|
DEPLOYMENT,
|
|
STATEFULSET,
|
|
CADVISOR,
|
|
KUBELET,
|
|
DCGM,
|
|
JOBSET,
|
|
]
|
|
PRIMARY_LOGS_OPTIONS = [
|
|
APISERVER,
|
|
SCHEDULER,
|
|
CONTROLLER_MANAGER,
|
|
ADDON_MANAGER,
|
|
]
|
|
PLACEMENT_OPTIONS = ['UNSPECIFIED', 'COMPACT']
|
|
LOCATION_POLICY_OPTIONS = ['BALANCED', 'ANY']
|
|
|
|
# gcloud-disable-gdu-domain
|
|
SUBNETWORK_URL_PATTERN = (
|
|
r'^https://www.googleapis.com/compute/[a-z1-9_]+/(?P<resource>.*)$'
|
|
)
|
|
ZONE_PATTERN = '^[^-]+-[^-]+-[^-]+$'
|
|
|
|
TPU_TOPOLOGY_PATTERN = r'^\d{1,3}x\d{1,3}(x\d{1,3})?$'
|
|
TPU_MACHINE_TYPES = frozenset({
|
|
'ct3-hightpu-4t',
|
|
'ct3p-hightpu-4t',
|
|
'ct4l-hightpu-4t',
|
|
'ct4p-hightpu-4t',
|
|
'ct5l-hightpu-1t',
|
|
'ct5l-hightpu-4t',
|
|
'ct5l-hightpu-8t',
|
|
'ct5lp-hightpu-1t',
|
|
'ct5lp-hightpu-4t',
|
|
'ct5lp-hightpu-8t',
|
|
'ct5p-hightpu-4t',
|
|
'ct6e-standard-1t',
|
|
'ct6e-standard-4t',
|
|
'ct6e-standard-8t',
|
|
'tpu7x-standard-1t',
|
|
'tpu7x-standard-4t',
|
|
})
|
|
|
|
CLUSTER = 'cluster'
|
|
NODEPOOL = 'nodepool'
|
|
|
|
|
|
def CheckResponse(response):
|
|
"""Wrap http_wrapper.CheckResponse to skip retry on 503."""
|
|
if response.status_code == 503:
|
|
raise apitools_exceptions.HttpError.FromResponse(response)
|
|
return http_wrapper.CheckResponse(response)
|
|
|
|
|
|
def APIVersionFromReleaseTrack(release_track):
|
|
if release_track == base.ReleaseTrack.GA:
|
|
return 'v1'
|
|
elif release_track == base.ReleaseTrack.BETA:
|
|
return 'v1beta1'
|
|
elif release_track == base.ReleaseTrack.ALPHA:
|
|
return 'v1alpha1'
|
|
else:
|
|
raise ValueError('Unsupported Release Track: {}'.format(release_track))
|
|
|
|
|
|
def NewAPIAdapter(api_version):
|
|
if api_version == 'v1alpha1':
|
|
return NewV1Alpha1APIAdapter()
|
|
elif api_version == 'v1beta1':
|
|
return NewV1Beta1APIAdapter()
|
|
else:
|
|
return NewV1APIAdapter()
|
|
|
|
|
|
def NewV1APIAdapter():
|
|
return InitAPIAdapter('v1', V1Adapter)
|
|
|
|
|
|
def NewV1Beta1APIAdapter():
|
|
return InitAPIAdapter('v1beta1', V1Beta1Adapter)
|
|
|
|
|
|
def NewV1Alpha1APIAdapter():
|
|
return InitAPIAdapter('v1alpha1', V1Alpha1Adapter)
|
|
|
|
|
|
def InitAPIAdapter(api_version, adapter):
|
|
"""Initialize an api adapter.
|
|
|
|
Args:
|
|
api_version: the api version we want.
|
|
adapter: the api adapter constructor.
|
|
|
|
Returns:
|
|
APIAdapter object.
|
|
"""
|
|
|
|
api_client = core_apis.GetClientInstance('container', api_version)
|
|
api_client.check_response_func = CheckResponse
|
|
messages = core_apis.GetMessagesModule('container', api_version)
|
|
|
|
compute_api_client = core_apis.GetClientInstance('compute', 'v1')
|
|
compute_messages = core_apis.GetMessagesModule('compute', 'v1')
|
|
|
|
registry = cloud_resources.REGISTRY.Clone()
|
|
registry.RegisterApiByName('container', api_version)
|
|
registry.RegisterApiByName('compute', 'v1')
|
|
|
|
return adapter(
|
|
registry, api_client, messages, compute_messages, compute_api_client
|
|
)
|
|
|
|
|
|
_SERVICE_ACCOUNT_SCOPES = (
|
|
'https://www.googleapis.com/auth/cloud-platform',
|
|
'https://www.googleapis.com/auth/userinfo.email',
|
|
)
|
|
|
|
|
|
def NodeIdentityOptionsToNodeConfig(options, node_config):
|
|
"""Convert node identity options into node config.
|
|
|
|
If scopes are specified with the `--scopes` flag, respect them.
|
|
If no scopes are presented, 'gke-default' will be passed here indicating that
|
|
we should use the default set:
|
|
- If no service account is specified, default set is GKE_DEFAULT_SCOPES which
|
|
is handled by ExpandScopeURIs:
|
|
- https://www.googleapis.com/auth/devstorage.read_only,
|
|
- https://www.googleapis.com/auth/logging.write',
|
|
- https://www.googleapis.com/auth/monitoring,
|
|
- https://www.googleapis.com/auth/servicecontrol,
|
|
- https://www.googleapis.com/auth/service.management.readonly,
|
|
- https://www.googleapis.com/auth/trace.append,
|
|
- If a service account is specified, default set is _SERVICE_ACCOUNT_SCOPES:
|
|
- https://www.googleapis.com/auth/cloud-platform
|
|
- https://www.googleapis.com/auth/userinfo.email
|
|
Args:
|
|
options: the CreateCluster or CreateNodePool options.
|
|
node_config: the messages.node_config object to be populated.
|
|
"""
|
|
if options.service_account:
|
|
node_config.serviceAccount = options.service_account
|
|
replaced_scopes = []
|
|
for scope in options.scopes:
|
|
if scope == 'gke-default':
|
|
replaced_scopes.extend(_SERVICE_ACCOUNT_SCOPES)
|
|
else:
|
|
replaced_scopes.append(scope)
|
|
options.scopes = replaced_scopes
|
|
|
|
options.scopes = ExpandScopeURIs(options.scopes)
|
|
node_config.oauthScopes = sorted(set(options.scopes))
|
|
|
|
|
|
def ExpandScopeURIs(scopes):
|
|
"""Expand scope names to the fully qualified uris.
|
|
|
|
Args:
|
|
scopes: [str,] list of scope names. Can be short names ('compute-rw') or
|
|
full urls ('https://www.googleapis.com/auth/compute'). See SCOPES in
|
|
api_lib/container/constants.py & api_lib/compute/constants.py.
|
|
|
|
Returns:
|
|
list of str, full urls for recognized scopes.
|
|
"""
|
|
|
|
scope_uris = []
|
|
for scope in scopes:
|
|
# Expand any scope aliases (like 'storage-rw') that the user provided
|
|
# to their official URL representation.
|
|
expanded = constants.SCOPES.get(scope, [scope])
|
|
scope_uris.extend(expanded)
|
|
return scope_uris
|
|
|
|
|
|
class CreateClusterOptions(object):
|
|
"""Options to pass to CreateCluster."""
|
|
|
|
def __init__(
|
|
self,
|
|
node_machine_type=None,
|
|
node_source_image=None,
|
|
node_disk_size_gb=None,
|
|
scopes=None,
|
|
num_nodes=None,
|
|
additional_zones=None,
|
|
node_locations=None,
|
|
user=None,
|
|
password=None,
|
|
cluster_version=None,
|
|
node_version=None,
|
|
network=None,
|
|
cluster_ipv4_cidr=None,
|
|
enable_cloud_logging=None,
|
|
enable_cloud_monitoring=None,
|
|
enable_stackdriver_kubernetes=None,
|
|
enable_logging_monitoring_system_only=None,
|
|
enable_workload_monitoring_eap=None,
|
|
subnetwork=None,
|
|
addons=None,
|
|
istio_config=None,
|
|
cloud_run_config=None,
|
|
local_ssd_count=None,
|
|
local_ssd_volume_configs=None,
|
|
local_nvme_ssd_block=None,
|
|
ephemeral_storage=None,
|
|
ephemeral_storage_local_ssd=None,
|
|
data_cache_count=None,
|
|
boot_disk_kms_key=None,
|
|
node_pool_name=None,
|
|
tags=None,
|
|
tag_bindings=None,
|
|
autoprovisioning_network_tags=None,
|
|
node_labels=None,
|
|
node_taints=None,
|
|
enable_autoscaling=None,
|
|
min_nodes=None,
|
|
max_nodes=None,
|
|
total_min_nodes=None,
|
|
total_max_nodes=None,
|
|
location_policy=None,
|
|
image_type=None,
|
|
image=None,
|
|
image_project=None,
|
|
image_family=None,
|
|
issue_client_certificate=None,
|
|
max_nodes_per_pool=None,
|
|
enable_kubernetes_alpha=None,
|
|
alpha_cluster_feature_gates=None,
|
|
enable_cloud_run_alpha=None,
|
|
preemptible=None,
|
|
spot=None,
|
|
placement_type=None,
|
|
placement_policy=None,
|
|
enable_queued_provisioning=None,
|
|
max_run_duration=None,
|
|
consolidation_delay=None,
|
|
flex_start=None,
|
|
enable_autorepair=None,
|
|
enable_autoupgrade=None,
|
|
service_account=None,
|
|
enable_master_authorized_networks=None,
|
|
master_authorized_networks=None,
|
|
enable_legacy_authorization=None,
|
|
labels=None,
|
|
disk_type=None,
|
|
enable_network_policy=None,
|
|
enable_l4_ilb_subsetting=None,
|
|
services_ipv4_cidr=None,
|
|
enable_ip_alias=None,
|
|
create_subnetwork=None,
|
|
cluster_secondary_range_name=None,
|
|
services_secondary_range_name=None,
|
|
accelerators=None,
|
|
enable_binauthz=None,
|
|
binauthz_evaluation_mode=None,
|
|
binauthz_policy_bindings=None,
|
|
min_cpu_platform=None,
|
|
workload_metadata=None,
|
|
workload_metadata_from_node=None,
|
|
maintenance_window=None,
|
|
enable_pod_security_policy=None,
|
|
allow_route_overlap=None,
|
|
private_cluster=None,
|
|
enable_private_nodes=None,
|
|
enable_private_endpoint=None,
|
|
master_ipv4_cidr=None,
|
|
tpu_ipv4_cidr=None,
|
|
enable_tpu=None,
|
|
enable_tpu_service_networking=None,
|
|
default_max_pods_per_node=None,
|
|
max_pods_per_node=None,
|
|
resource_usage_bigquery_dataset=None,
|
|
security_group=None,
|
|
enable_private_ipv6_access=None,
|
|
enable_intra_node_visibility=None,
|
|
enable_vertical_pod_autoscaling=None,
|
|
enable_experimental_vertical_pod_autoscaling=None,
|
|
security_profile=None,
|
|
security_profile_runtime_rules=None,
|
|
autoscaling_profile=None,
|
|
hpa_profile=None,
|
|
database_encryption_key=None,
|
|
metadata=None,
|
|
enable_network_egress_metering=None,
|
|
enable_resource_consumption_metering=None,
|
|
workload_pool=None,
|
|
identity_provider=None,
|
|
enable_workload_certificates=None,
|
|
enable_mesh_certificates=None,
|
|
enable_alts=None,
|
|
enable_gke_oidc=None,
|
|
enable_identity_service=None,
|
|
enable_shielded_nodes=None,
|
|
linux_sysctls=None,
|
|
disable_default_snat=None,
|
|
dataplane_v2=None,
|
|
enable_dataplane_v2_metrics=None,
|
|
disable_dataplane_v2_metrics=None,
|
|
enable_dataplane_v2_flow_observability=None,
|
|
disable_dataplane_v2_flow_observability=None,
|
|
dataplane_v2_observability_mode=None,
|
|
shielded_secure_boot=None,
|
|
shielded_integrity_monitoring=None,
|
|
system_config_from_file=None,
|
|
maintenance_window_start=None,
|
|
maintenance_window_end=None,
|
|
maintenance_window_recurrence=None,
|
|
enable_cost_allocation=None,
|
|
gpudirect_strategy=None,
|
|
max_surge_upgrade=None,
|
|
max_unavailable_upgrade=None,
|
|
enable_autoprovisioning=None,
|
|
autoprovisioning_config_file=None,
|
|
autoprovisioning_service_account=None,
|
|
autoprovisioning_scopes=None,
|
|
autoprovisioning_locations=None,
|
|
min_cpu=None,
|
|
max_cpu=None,
|
|
min_memory=None,
|
|
max_memory=None,
|
|
min_accelerator=None,
|
|
max_accelerator=None,
|
|
autoprovisioning_image_type=None,
|
|
autoprovisioning_max_surge_upgrade=None,
|
|
autoprovisioning_max_unavailable_upgrade=None,
|
|
enable_autoprovisioning_autoupgrade=None,
|
|
enable_autoprovisioning_autorepair=None,
|
|
reservation_affinity=None,
|
|
reservation=None,
|
|
autoprovisioning_min_cpu_platform=None,
|
|
enable_master_global_access=None,
|
|
gvnic=None,
|
|
enable_master_metrics=None,
|
|
master_logs=None,
|
|
release_channel=None,
|
|
notification_config=None,
|
|
autopilot=None,
|
|
private_ipv6_google_access_type=None,
|
|
enable_confidential_nodes=None,
|
|
confidential_node_type=None,
|
|
enable_confidential_storage=None,
|
|
cluster_dns=None,
|
|
cluster_dns_scope=None,
|
|
cluster_dns_domain=None,
|
|
additive_vpc_scope_dns_domain=None,
|
|
disable_additive_vpc_scope=None,
|
|
kubernetes_objects_changes_target=None,
|
|
kubernetes_objects_snapshots_target=None,
|
|
enable_gcfs=None,
|
|
enable_image_streaming=None,
|
|
private_endpoint_subnetwork=None,
|
|
cross_connect_subnetworks=None,
|
|
enable_service_externalips=None,
|
|
threads_per_core=None,
|
|
logging=None,
|
|
monitoring=None,
|
|
enable_managed_prometheus=None,
|
|
auto_monitoring_scope=None,
|
|
managed_otel_scope=None,
|
|
maintenance_interval=None,
|
|
disable_pod_cidr_overprovision=None,
|
|
stack_type=None,
|
|
ipv6_access_type=None,
|
|
enable_workload_config_audit=None,
|
|
enable_workload_vulnerability_scanning=None,
|
|
enable_autoprovisioning_surge_upgrade=None,
|
|
enable_autoprovisioning_blue_green_upgrade=None,
|
|
autoprovisioning_standard_rollout_policy=None,
|
|
autoprovisioning_node_pool_soak_duration=None,
|
|
enable_google_cloud_access=None,
|
|
managed_config=None,
|
|
fleet_project=None,
|
|
enable_fleet=None,
|
|
membership_type=None,
|
|
gateway_api=None,
|
|
logging_variant=None,
|
|
enable_multi_networking=None,
|
|
enable_security_posture=None,
|
|
enable_nested_virtualization=None,
|
|
performance_monitoring_unit=None,
|
|
network_performance_config=None,
|
|
enable_insecure_kubelet_readonly_port=None,
|
|
autoprovisioning_enable_insecure_kubelet_readonly_port=None,
|
|
enable_k8s_beta_apis=None,
|
|
compliance=None,
|
|
compliance_standards=None,
|
|
security_posture=None,
|
|
workload_vulnerability_scanning=None,
|
|
enable_runtime_vulnerability_insight=None,
|
|
workload_policies=None,
|
|
enable_fqdn_network_policy=None,
|
|
host_maintenance_interval=None,
|
|
in_transit_encryption=None,
|
|
containerd_config_from_file=None,
|
|
resource_manager_tags=None,
|
|
autoprovisioning_resource_manager_tags=None,
|
|
enable_secret_manager=None,
|
|
enable_secret_manager_rotation=None,
|
|
secret_manager_rotation_interval=None,
|
|
enable_secret_sync=None,
|
|
enable_secret_sync_rotation=None,
|
|
secret_sync_rotation_interval=None,
|
|
enable_cilium_clusterwide_network_policy=None,
|
|
storage_pools=None,
|
|
local_ssd_encryption_mode=None,
|
|
enable_ray_cluster_logging=None,
|
|
enable_ray_cluster_monitoring=None,
|
|
enable_insecure_binding_system_authenticated=None,
|
|
enable_insecure_binding_system_unauthenticated=None,
|
|
enable_dns_access=None,
|
|
cluster_ca=None,
|
|
aggregation_ca=None,
|
|
etcd_api_ca=None,
|
|
etcd_peer_ca=None,
|
|
service_account_signing_keys=None,
|
|
service_account_verification_keys=None,
|
|
control_plane_disk_encryption_key=None,
|
|
gkeops_etcd_backup_encryption_key=None,
|
|
disable_l4_lb_firewall_reconciliation=None,
|
|
tier=None,
|
|
enable_ip_access=None,
|
|
enable_authorized_networks_on_private_endpoint=None,
|
|
patch_update=None,
|
|
anonymous_authentication_config=None,
|
|
enable_auto_ipam=None,
|
|
enable_k8s_tokens_via_dns=None,
|
|
enable_legacy_lustre_port=None,
|
|
disable_multi_nic_lustre=None,
|
|
enable_default_compute_class=None,
|
|
enable_k8s_certs_via_dns=None,
|
|
boot_disk_provisioned_iops=None,
|
|
boot_disk_provisioned_throughput=None,
|
|
network_tier=None,
|
|
control_plane_egress_mode=None,
|
|
enable_pod_snapshots=None,
|
|
autopilot_privileged_admission=None,
|
|
enable_kernel_module_signature_enforcement=None,
|
|
enable_lustre_multi_nic=None,
|
|
enable_slice_controller=None,
|
|
autopilot_general_profile=None,
|
|
):
|
|
self.node_machine_type = node_machine_type
|
|
self.node_source_image = node_source_image
|
|
self.node_disk_size_gb = node_disk_size_gb
|
|
self.scopes = scopes
|
|
self.num_nodes = num_nodes
|
|
self.additional_zones = additional_zones
|
|
self.node_locations = node_locations
|
|
self.user = user
|
|
self.password = password
|
|
self.cluster_version = cluster_version
|
|
self.node_version = node_version
|
|
self.network = network
|
|
self.cluster_ipv4_cidr = cluster_ipv4_cidr
|
|
self.enable_cloud_logging = enable_cloud_logging
|
|
self.enable_cloud_monitoring = enable_cloud_monitoring
|
|
self.enable_stackdriver_kubernetes = enable_stackdriver_kubernetes
|
|
self.enable_logging_monitoring_system_only = (
|
|
enable_logging_monitoring_system_only
|
|
)
|
|
self.enable_workload_monitoring_eap = (enable_workload_monitoring_eap,)
|
|
self.subnetwork = subnetwork
|
|
self.addons = addons
|
|
self.istio_config = istio_config
|
|
self.cloud_run_config = cloud_run_config
|
|
self.local_ssd_count = local_ssd_count
|
|
self.data_cache_count = data_cache_count
|
|
self.local_ssd_volume_configs = local_ssd_volume_configs
|
|
self.ephemeral_storage = ephemeral_storage
|
|
self.ephemeral_storage_local_ssd = ephemeral_storage_local_ssd
|
|
self.local_nvme_ssd_block = local_nvme_ssd_block
|
|
self.boot_disk_kms_key = boot_disk_kms_key
|
|
self.node_pool_name = node_pool_name
|
|
self.tags = tags
|
|
self.tag_bindings = tag_bindings
|
|
self.autoprovisioning_network_tags = autoprovisioning_network_tags
|
|
self.node_labels = node_labels
|
|
self.node_taints = node_taints
|
|
self.enable_autoscaling = enable_autoscaling
|
|
self.min_nodes = min_nodes
|
|
self.max_nodes = max_nodes
|
|
self.total_min_nodes = total_min_nodes
|
|
self.total_max_nodes = total_max_nodes
|
|
self.location_policy = location_policy
|
|
self.image_type = image_type
|
|
self.image = image
|
|
self.image_project = image_project
|
|
self.image_family = image_family
|
|
self.max_nodes_per_pool = max_nodes_per_pool
|
|
self.enable_kubernetes_alpha = enable_kubernetes_alpha
|
|
self.alpha_cluster_feature_gates = alpha_cluster_feature_gates
|
|
self.enable_cloud_run_alpha = enable_cloud_run_alpha
|
|
self.preemptible = preemptible
|
|
self.spot = spot
|
|
self.placement_type = placement_type
|
|
self.placement_policy = placement_policy
|
|
self.enable_queued_provisioning = enable_queued_provisioning
|
|
self.max_run_duration = max_run_duration
|
|
self.consolidation_delay = consolidation_delay
|
|
self.flex_start = flex_start
|
|
self.enable_autorepair = enable_autorepair
|
|
self.enable_autoupgrade = enable_autoupgrade
|
|
self.service_account = service_account
|
|
self.enable_master_authorized_networks = enable_master_authorized_networks
|
|
self.master_authorized_networks = master_authorized_networks
|
|
self.enable_legacy_authorization = enable_legacy_authorization
|
|
self.enable_network_policy = enable_network_policy
|
|
self.enable_l4_ilb_subsetting = enable_l4_ilb_subsetting
|
|
self.labels = labels
|
|
self.disk_type = disk_type
|
|
self.services_ipv4_cidr = services_ipv4_cidr
|
|
self.enable_ip_alias = enable_ip_alias
|
|
self.create_subnetwork = create_subnetwork
|
|
self.cluster_secondary_range_name = cluster_secondary_range_name
|
|
self.services_secondary_range_name = services_secondary_range_name
|
|
self.accelerators = accelerators
|
|
self.enable_binauthz = enable_binauthz
|
|
self.binauthz_evaluation_mode = binauthz_evaluation_mode
|
|
self.binauthz_policy_bindings = binauthz_policy_bindings
|
|
self.min_cpu_platform = min_cpu_platform
|
|
self.workload_metadata = workload_metadata
|
|
self.workload_metadata_from_node = workload_metadata_from_node
|
|
self.maintenance_window = maintenance_window
|
|
self.enable_pod_security_policy = enable_pod_security_policy
|
|
self.allow_route_overlap = allow_route_overlap
|
|
self.private_cluster = private_cluster
|
|
self.enable_private_nodes = enable_private_nodes
|
|
self.enable_private_endpoint = enable_private_endpoint
|
|
self.master_ipv4_cidr = master_ipv4_cidr
|
|
self.tpu_ipv4_cidr = tpu_ipv4_cidr
|
|
self.enable_tpu_service_networking = enable_tpu_service_networking
|
|
self.enable_tpu = enable_tpu
|
|
self.issue_client_certificate = issue_client_certificate
|
|
self.default_max_pods_per_node = default_max_pods_per_node
|
|
self.max_pods_per_node = max_pods_per_node
|
|
self.resource_usage_bigquery_dataset = resource_usage_bigquery_dataset
|
|
self.security_group = security_group
|
|
self.enable_private_ipv6_access = enable_private_ipv6_access
|
|
self.enable_intra_node_visibility = enable_intra_node_visibility
|
|
self.enable_vertical_pod_autoscaling = enable_vertical_pod_autoscaling
|
|
self.enable_experimental_vertical_pod_autoscaling = (
|
|
enable_experimental_vertical_pod_autoscaling
|
|
)
|
|
self.security_profile = security_profile
|
|
self.security_profile_runtime_rules = security_profile_runtime_rules
|
|
self.autoscaling_profile = autoscaling_profile
|
|
self.hpa_profile = hpa_profile
|
|
self.database_encryption_key = database_encryption_key
|
|
self.metadata = metadata
|
|
self.enable_network_egress_metering = enable_network_egress_metering
|
|
self.enable_resource_consumption_metering = (
|
|
enable_resource_consumption_metering
|
|
)
|
|
self.workload_pool = workload_pool
|
|
self.identity_provider = identity_provider
|
|
self.enable_workload_certificates = enable_workload_certificates
|
|
self.enable_mesh_certificates = enable_mesh_certificates
|
|
self.enable_alts = enable_alts
|
|
self.enable_gke_oidc = enable_gke_oidc
|
|
self.enable_identity_service = enable_identity_service
|
|
self.enable_shielded_nodes = enable_shielded_nodes
|
|
self.linux_sysctls = linux_sysctls
|
|
self.enable_kernel_module_signature_enforcement = (
|
|
enable_kernel_module_signature_enforcement
|
|
)
|
|
self.disable_default_snat = disable_default_snat
|
|
self.dataplane_v2 = dataplane_v2
|
|
self.enable_dataplane_v2_metrics = enable_dataplane_v2_metrics
|
|
self.disable_dataplane_v2_metrics = disable_dataplane_v2_metrics
|
|
self.enable_dataplane_v2_flow_observability = (
|
|
enable_dataplane_v2_flow_observability
|
|
)
|
|
self.disable_dataplane_v2_flow_observability = (
|
|
disable_dataplane_v2_flow_observability
|
|
)
|
|
self.dataplane_v2_observability_mode = dataplane_v2_observability_mode
|
|
self.shielded_secure_boot = shielded_secure_boot
|
|
self.shielded_integrity_monitoring = shielded_integrity_monitoring
|
|
self.system_config_from_file = system_config_from_file
|
|
self.maintenance_window_start = maintenance_window_start
|
|
self.maintenance_window_end = maintenance_window_end
|
|
self.maintenance_window_recurrence = maintenance_window_recurrence
|
|
self.enable_cost_allocation = enable_cost_allocation
|
|
self.gpudirect_strategy = gpudirect_strategy
|
|
self.max_surge_upgrade = max_surge_upgrade
|
|
self.max_unavailable_upgrade = max_unavailable_upgrade
|
|
self.enable_autoprovisioning = enable_autoprovisioning
|
|
self.autoprovisioning_config_file = autoprovisioning_config_file
|
|
self.autoprovisioning_service_account = autoprovisioning_service_account
|
|
self.autoprovisioning_scopes = autoprovisioning_scopes
|
|
self.autoprovisioning_locations = autoprovisioning_locations
|
|
self.min_cpu = min_cpu
|
|
self.max_cpu = max_cpu
|
|
self.min_memory = min_memory
|
|
self.max_memory = max_memory
|
|
self.min_accelerator = min_accelerator
|
|
self.max_accelerator = max_accelerator
|
|
self.autoprovisioning_image_type = autoprovisioning_image_type
|
|
self.autoprovisioning_max_surge_upgrade = autoprovisioning_max_surge_upgrade
|
|
self.autoprovisioning_max_unavailable_upgrade = (
|
|
autoprovisioning_max_unavailable_upgrade
|
|
)
|
|
self.enable_autoprovisioning_autoupgrade = (
|
|
enable_autoprovisioning_autoupgrade
|
|
)
|
|
self.enable_autoprovisioning_autorepair = enable_autoprovisioning_autorepair
|
|
self.reservation_affinity = reservation_affinity
|
|
self.reservation = reservation
|
|
self.autoprovisioning_min_cpu_platform = autoprovisioning_min_cpu_platform
|
|
self.enable_master_global_access = enable_master_global_access
|
|
self.gvnic = gvnic
|
|
self.enable_master_metrics = enable_master_metrics
|
|
self.master_logs = master_logs
|
|
self.release_channel = release_channel
|
|
self.notification_config = notification_config
|
|
self.autopilot = autopilot
|
|
self.private_ipv6_google_access_type = private_ipv6_google_access_type
|
|
self.enable_confidential_nodes = enable_confidential_nodes
|
|
self.confidential_node_type = confidential_node_type
|
|
self.enable_confidential_storage = enable_confidential_storage
|
|
self.storage_pools = storage_pools
|
|
self.local_ssd_encryption_mode = local_ssd_encryption_mode
|
|
self.cluster_dns = cluster_dns
|
|
self.cluster_dns_scope = cluster_dns_scope
|
|
self.cluster_dns_domain = cluster_dns_domain
|
|
self.additive_vpc_scope_dns_domain = additive_vpc_scope_dns_domain
|
|
self.disable_additive_vpc_scope = disable_additive_vpc_scope
|
|
self.kubernetes_objects_changes_target = kubernetes_objects_changes_target
|
|
self.kubernetes_objects_snapshots_target = (
|
|
kubernetes_objects_snapshots_target
|
|
)
|
|
self.enable_gcfs = enable_gcfs
|
|
self.enable_image_streaming = enable_image_streaming
|
|
self.private_endpoint_subnetwork = private_endpoint_subnetwork
|
|
self.cross_connect_subnetworks = cross_connect_subnetworks
|
|
self.enable_service_externalips = enable_service_externalips
|
|
self.threads_per_core = threads_per_core
|
|
self.enable_nested_virtualization = enable_nested_virtualization
|
|
self.performance_monitoring_unit = performance_monitoring_unit
|
|
self.logging = logging
|
|
self.monitoring = monitoring
|
|
self.enable_managed_prometheus = enable_managed_prometheus
|
|
self.auto_monitoring_scope = auto_monitoring_scope
|
|
self.managed_otel_scope = managed_otel_scope
|
|
self.maintenance_interval = maintenance_interval
|
|
self.disable_pod_cidr_overprovision = disable_pod_cidr_overprovision
|
|
self.stack_type = stack_type
|
|
self.ipv6_access_type = ipv6_access_type
|
|
self.enable_workload_config_audit = enable_workload_config_audit
|
|
self.enable_workload_vulnerability_scanning = (
|
|
enable_workload_vulnerability_scanning
|
|
)
|
|
self.enable_autoprovisioning_surge_upgrade = (
|
|
enable_autoprovisioning_surge_upgrade
|
|
)
|
|
self.enable_autoprovisioning_blue_green_upgrade = (
|
|
enable_autoprovisioning_blue_green_upgrade
|
|
)
|
|
self.autoprovisioning_standard_rollout_policy = (
|
|
autoprovisioning_standard_rollout_policy
|
|
)
|
|
self.autoprovisioning_node_pool_soak_duration = (
|
|
autoprovisioning_node_pool_soak_duration
|
|
)
|
|
self.enable_google_cloud_access = enable_google_cloud_access
|
|
self.managed_config = managed_config
|
|
self.fleet_project = fleet_project
|
|
self.enable_fleet = enable_fleet
|
|
self.membership_type = membership_type
|
|
self.gateway_api = gateway_api
|
|
self.logging_variant = logging_variant
|
|
self.enable_multi_networking = enable_multi_networking
|
|
self.enable_security_posture = enable_security_posture
|
|
self.network_performance_config = network_performance_config
|
|
self.enable_insecure_kubelet_readonly_port = (
|
|
enable_insecure_kubelet_readonly_port
|
|
)
|
|
self.autoprovisioning_enable_insecure_kubelet_readonly_port = (
|
|
autoprovisioning_enable_insecure_kubelet_readonly_port
|
|
)
|
|
|
|
self.enable_k8s_beta_apis = enable_k8s_beta_apis
|
|
self.compliance = compliance
|
|
self.compliance_standards = compliance_standards
|
|
self.security_posture = security_posture
|
|
self.workload_vulnerability_scanning = workload_vulnerability_scanning
|
|
self.enable_runtime_vulnerability_insight = (
|
|
enable_runtime_vulnerability_insight
|
|
)
|
|
self.workload_policies = workload_policies
|
|
self.enable_fqdn_network_policy = enable_fqdn_network_policy
|
|
self.host_maintenance_interval = host_maintenance_interval
|
|
self.in_transit_encryption = in_transit_encryption
|
|
self.containerd_config_from_file = containerd_config_from_file
|
|
self.resource_manager_tags = resource_manager_tags
|
|
self.autoprovisioning_resource_manager_tags = (
|
|
autoprovisioning_resource_manager_tags
|
|
)
|
|
self.enable_secret_manager = enable_secret_manager
|
|
self.enable_secret_manager_rotation = enable_secret_manager_rotation
|
|
self.secret_manager_rotation_interval = secret_manager_rotation_interval
|
|
self.enable_secret_sync = enable_secret_sync
|
|
self.enable_secret_sync_rotation = enable_secret_sync_rotation
|
|
self.secret_sync_rotation_interval = secret_sync_rotation_interval
|
|
self.enable_cilium_clusterwide_network_policy = (
|
|
enable_cilium_clusterwide_network_policy
|
|
)
|
|
self.enable_ray_cluster_logging = enable_ray_cluster_logging
|
|
self.enable_ray_cluster_monitoring = enable_ray_cluster_monitoring
|
|
self.enable_insecure_binding_system_authenticated = (
|
|
enable_insecure_binding_system_authenticated
|
|
)
|
|
self.enable_insecure_binding_system_unauthenticated = (
|
|
enable_insecure_binding_system_unauthenticated
|
|
)
|
|
self.enable_dns_access = enable_dns_access
|
|
self.cluster_ca = cluster_ca
|
|
self.aggregation_ca = aggregation_ca
|
|
self.etcd_api_ca = etcd_api_ca
|
|
self.etcd_peer_ca = etcd_peer_ca
|
|
self.service_account_signing_keys = service_account_signing_keys
|
|
self.service_account_verification_keys = service_account_verification_keys
|
|
self.control_plane_disk_encryption_key = control_plane_disk_encryption_key
|
|
self.gkeops_etcd_backup_encryption_key = gkeops_etcd_backup_encryption_key
|
|
self.disable_l4_lb_firewall_reconciliation = (
|
|
disable_l4_lb_firewall_reconciliation
|
|
)
|
|
self.tier = tier
|
|
self.enable_ip_access = enable_ip_access
|
|
self.enable_authorized_networks_on_private_endpoint = (
|
|
enable_authorized_networks_on_private_endpoint
|
|
)
|
|
self.anonymous_authentication_config = anonymous_authentication_config
|
|
self.patch_update = patch_update
|
|
self.enable_auto_ipam = enable_auto_ipam
|
|
self.enable_k8s_tokens_via_dns = enable_k8s_tokens_via_dns
|
|
self.enable_legacy_lustre_port = enable_legacy_lustre_port
|
|
self.disable_multi_nic_lustre = disable_multi_nic_lustre
|
|
self.enable_default_compute_class = enable_default_compute_class
|
|
self.enable_k8s_certs_via_dns = enable_k8s_certs_via_dns
|
|
self.boot_disk_provisioned_iops = boot_disk_provisioned_iops
|
|
self.boot_disk_provisioned_throughput = boot_disk_provisioned_throughput
|
|
self.network_tier = network_tier
|
|
self.control_plane_egress_mode = control_plane_egress_mode
|
|
self.enable_pod_snapshots = enable_pod_snapshots
|
|
self.autopilot_privileged_admission = autopilot_privileged_admission
|
|
self.enable_lustre_multi_nic = enable_lustre_multi_nic
|
|
self.enable_slice_controller = enable_slice_controller
|
|
self.autopilot_general_profile = autopilot_general_profile
|
|
|
|
|
|
class UpdateClusterOptions(object):
|
|
"""Options to pass to UpdateCluster."""
|
|
|
|
def __init__(
|
|
self,
|
|
version=None,
|
|
update_master=None,
|
|
update_nodes=None,
|
|
node_pool=None,
|
|
monitoring_service=None,
|
|
logging_service=None,
|
|
enable_stackdriver_kubernetes=None,
|
|
enable_logging_monitoring_system_only=None,
|
|
enable_workload_monitoring_eap=None,
|
|
master_logs=None,
|
|
no_master_logs=None,
|
|
enable_master_metrics=None,
|
|
logging=None,
|
|
monitoring=None,
|
|
disable_addons=None,
|
|
istio_config=None,
|
|
cloud_run_config=None,
|
|
cluster_dns=None,
|
|
cluster_dns_scope=None,
|
|
cluster_dns_domain=None,
|
|
disable_additive_vpc_scope=None,
|
|
additive_vpc_scope_dns_domain=None,
|
|
enable_autoscaling=None,
|
|
min_nodes=None,
|
|
max_nodes=None,
|
|
total_min_nodes=None,
|
|
total_max_nodes=None,
|
|
location_policy=None,
|
|
image_type=None,
|
|
image=None,
|
|
image_project=None,
|
|
locations=None,
|
|
enable_master_authorized_networks=None,
|
|
master_authorized_networks=None,
|
|
enable_pod_security_policy=None,
|
|
enable_vertical_pod_autoscaling=None,
|
|
enable_experimental_vertical_pod_autoscaling=None,
|
|
enable_intra_node_visibility=None,
|
|
enable_l4_ilb_subsetting=None,
|
|
security_profile=None,
|
|
security_profile_runtime_rules=None,
|
|
autoscaling_profile=None,
|
|
hpa_profile=None,
|
|
enable_peering_route_sharing=None,
|
|
workload_pool=None,
|
|
identity_provider=None,
|
|
disable_workload_identity=None,
|
|
enable_workload_certificates=None,
|
|
enable_mesh_certificates=None,
|
|
enable_alts=None,
|
|
enable_gke_oidc=None,
|
|
enable_identity_service=None,
|
|
enable_shielded_nodes=None,
|
|
disable_default_snat=None,
|
|
resource_usage_bigquery_dataset=None,
|
|
enable_network_egress_metering=None,
|
|
enable_resource_consumption_metering=None,
|
|
database_encryption_key=None,
|
|
disable_database_encryption=None,
|
|
enable_cost_allocation=None,
|
|
enable_autoprovisioning=None,
|
|
autoprovisioning_config_file=None,
|
|
autoprovisioning_service_account=None,
|
|
autoprovisioning_scopes=None,
|
|
autoprovisioning_locations=None,
|
|
min_cpu=None,
|
|
max_cpu=None,
|
|
min_memory=None,
|
|
max_memory=None,
|
|
min_accelerator=None,
|
|
max_accelerator=None,
|
|
release_channel=None,
|
|
autoprovisioning_image_type=None,
|
|
autoprovisioning_max_surge_upgrade=None,
|
|
autoprovisioning_max_unavailable_upgrade=None,
|
|
enable_autoprovisioning_autoupgrade=None,
|
|
enable_autoprovisioning_autorepair=None,
|
|
autoprovisioning_min_cpu_platform=None,
|
|
enable_tpu=None,
|
|
tpu_ipv4_cidr=None,
|
|
enable_master_global_access=None,
|
|
enable_tpu_service_networking=None,
|
|
notification_config=None,
|
|
private_ipv6_google_access_type=None,
|
|
kubernetes_objects_changes_target=None,
|
|
kubernetes_objects_snapshots_target=None,
|
|
disable_autopilot=None,
|
|
add_cross_connect_subnetworks=None,
|
|
remove_cross_connect_subnetworks=None,
|
|
clear_cross_connect_subnetworks=None,
|
|
enable_service_externalips=None,
|
|
security_group=None,
|
|
enable_gcfs=None,
|
|
autoprovisioning_network_tags=None,
|
|
enable_image_streaming=None,
|
|
enable_managed_prometheus=None,
|
|
disable_managed_prometheus=None,
|
|
auto_monitoring_scope=None,
|
|
managed_otel_scope=None,
|
|
maintenance_interval=None,
|
|
dataplane_v2=None,
|
|
enable_dataplane_v2_metrics=None,
|
|
disable_dataplane_v2_metrics=None,
|
|
enable_dataplane_v2_flow_observability=None,
|
|
disable_dataplane_v2_flow_observability=None,
|
|
dataplane_v2_observability_mode=None,
|
|
enable_workload_config_audit=None,
|
|
enable_workload_vulnerability_scanning=None,
|
|
enable_autoprovisioning_surge_upgrade=None,
|
|
enable_autoprovisioning_blue_green_upgrade=None,
|
|
autoprovisioning_standard_rollout_policy=None,
|
|
autoprovisioning_node_pool_soak_duration=None,
|
|
enable_private_endpoint=None,
|
|
enable_google_cloud_access=None,
|
|
stack_type=None,
|
|
gateway_api=None,
|
|
logging_variant=None,
|
|
additional_pod_ipv4_ranges=None,
|
|
removed_additional_pod_ipv4_ranges=None,
|
|
fleet_project=None,
|
|
enable_fleet=None,
|
|
membership_type=None,
|
|
unset_membership_type=None,
|
|
clear_fleet_project=None,
|
|
enable_security_posture=None,
|
|
network_performance_config=None,
|
|
enable_k8s_beta_apis=None,
|
|
compliance=None,
|
|
compliance_standards=None,
|
|
security_posture=None,
|
|
workload_vulnerability_scanning=None,
|
|
enable_runtime_vulnerability_insight=None,
|
|
workload_policies=None,
|
|
remove_workload_policies=None,
|
|
enable_fqdn_network_policy=None,
|
|
host_maintenance_interval=None,
|
|
in_transit_encryption=None,
|
|
enable_multi_networking=None,
|
|
containerd_config_from_file=None,
|
|
autoprovisioning_resource_manager_tags=None,
|
|
convert_to_autopilot=None,
|
|
convert_to_standard=None,
|
|
enable_secret_manager=None,
|
|
enable_secret_manager_rotation=None,
|
|
secret_manager_rotation_interval=None,
|
|
enable_secret_sync=None,
|
|
enable_secret_sync_rotation=None,
|
|
secret_sync_rotation_interval=None,
|
|
enable_cilium_clusterwide_network_policy=None,
|
|
enable_insecure_kubelet_readonly_port=None,
|
|
autoprovisioning_enable_insecure_kubelet_readonly_port=None,
|
|
enable_ray_cluster_logging=None,
|
|
enable_ray_cluster_monitoring=None,
|
|
enable_insecure_binding_system_authenticated=None,
|
|
enable_insecure_binding_system_unauthenticated=None,
|
|
additional_ip_ranges=None,
|
|
remove_additional_ip_ranges=None,
|
|
drain_additional_ip_ranges=None,
|
|
undrain_additional_ip_ranges=None,
|
|
enable_private_nodes=None,
|
|
enable_dns_access=None,
|
|
disable_l4_lb_firewall_reconciliation=None,
|
|
enable_l4_lb_firewall_reconciliation=None,
|
|
tier=None,
|
|
autoprovisioning_cgroup_mode=None,
|
|
enable_ip_access=None,
|
|
enable_authorized_networks_on_private_endpoint=None,
|
|
enable_autopilot_compatibility_auditing=None,
|
|
service_account_signing_keys=None,
|
|
service_account_verification_keys=None,
|
|
control_plane_disk_encryption_key=None,
|
|
anonymous_authentication_config=None,
|
|
patch_update=None,
|
|
enable_auto_ipam=None,
|
|
disable_auto_ipam=None,
|
|
enable_k8s_tokens_via_dns=None,
|
|
enable_legacy_lustre_port=None,
|
|
disable_multi_nic_lustre=None,
|
|
enable_default_compute_class=None,
|
|
enable_k8s_certs_via_dns=None,
|
|
boot_disk_provisioned_iops=None,
|
|
boot_disk_provisioned_throughput=None,
|
|
network_tier=None,
|
|
control_plane_egress_mode=None,
|
|
control_plane_soak_duration=None,
|
|
enable_pod_snapshots=None,
|
|
autopilot_privileged_admission=None,
|
|
enable_slice_controller=None,
|
|
autopilot_general_profile=None,
|
|
):
|
|
self.version = version
|
|
self.update_master = bool(update_master)
|
|
self.update_nodes = bool(update_nodes)
|
|
self.node_pool = node_pool
|
|
self.monitoring_service = monitoring_service
|
|
self.logging_service = logging_service
|
|
self.enable_stackdriver_kubernetes = enable_stackdriver_kubernetes
|
|
self.enable_logging_monitoring_system_only = (
|
|
enable_logging_monitoring_system_only
|
|
)
|
|
self.enable_workload_monitoring_eap = enable_workload_monitoring_eap
|
|
self.no_master_logs = no_master_logs
|
|
self.master_logs = master_logs
|
|
self.enable_master_metrics = enable_master_metrics
|
|
self.logging = logging
|
|
self.monitoring = monitoring
|
|
self.disable_addons = disable_addons
|
|
self.istio_config = istio_config
|
|
self.cloud_run_config = cloud_run_config
|
|
self.cluster_dns = cluster_dns
|
|
self.cluster_dns_scope = cluster_dns_scope
|
|
self.cluster_dns_domain = cluster_dns_domain
|
|
self.disable_additive_vpc_scope = disable_additive_vpc_scope
|
|
self.additive_vpc_scope_dns_domain = additive_vpc_scope_dns_domain
|
|
self.enable_autoscaling = enable_autoscaling
|
|
self.min_nodes = min_nodes
|
|
self.max_nodes = max_nodes
|
|
self.total_min_nodes = total_min_nodes
|
|
self.total_max_nodes = total_max_nodes
|
|
self.location_policy = location_policy
|
|
self.image_type = image_type
|
|
self.image = image
|
|
self.image_project = image_project
|
|
self.locations = locations
|
|
self.enable_master_authorized_networks = enable_master_authorized_networks
|
|
self.master_authorized_networks = master_authorized_networks
|
|
self.enable_pod_security_policy = enable_pod_security_policy
|
|
self.enable_vertical_pod_autoscaling = enable_vertical_pod_autoscaling
|
|
self.enable_experimental_vertical_pod_autoscaling = (
|
|
enable_experimental_vertical_pod_autoscaling
|
|
)
|
|
self.security_profile = security_profile
|
|
self.security_profile_runtime_rules = security_profile_runtime_rules
|
|
self.autoscaling_profile = autoscaling_profile
|
|
self.hpa_profile = hpa_profile
|
|
self.enable_intra_node_visibility = enable_intra_node_visibility
|
|
self.enable_l4_ilb_subsetting = enable_l4_ilb_subsetting
|
|
self.enable_peering_route_sharing = enable_peering_route_sharing
|
|
self.workload_pool = workload_pool
|
|
self.identity_provider = identity_provider
|
|
self.disable_workload_identity = disable_workload_identity
|
|
self.enable_workload_certificates = enable_workload_certificates
|
|
self.enable_mesh_certificates = enable_mesh_certificates
|
|
self.enable_alts = enable_alts
|
|
self.enable_gke_oidc = enable_gke_oidc
|
|
self.enable_identity_service = enable_identity_service
|
|
self.enable_shielded_nodes = enable_shielded_nodes
|
|
self.disable_default_snat = disable_default_snat
|
|
self.resource_usage_bigquery_dataset = resource_usage_bigquery_dataset
|
|
self.enable_network_egress_metering = enable_network_egress_metering
|
|
self.enable_resource_consumption_metering = (
|
|
enable_resource_consumption_metering
|
|
)
|
|
self.database_encryption_key = database_encryption_key
|
|
self.disable_database_encryption = disable_database_encryption
|
|
self.enable_cost_allocation = enable_cost_allocation
|
|
self.enable_autoprovisioning = enable_autoprovisioning
|
|
self.autoprovisioning_config_file = autoprovisioning_config_file
|
|
self.autoprovisioning_service_account = autoprovisioning_service_account
|
|
self.autoprovisioning_scopes = autoprovisioning_scopes
|
|
self.autoprovisioning_locations = autoprovisioning_locations
|
|
self.min_cpu = min_cpu
|
|
self.max_cpu = max_cpu
|
|
self.min_memory = min_memory
|
|
self.max_memory = max_memory
|
|
self.min_accelerator = min_accelerator
|
|
self.max_accelerator = max_accelerator
|
|
self.release_channel = release_channel
|
|
self.autoprovisioning_image_type = autoprovisioning_image_type
|
|
self.autoprovisioning_max_surge_upgrade = autoprovisioning_max_surge_upgrade
|
|
self.autoprovisioning_max_unavailable_upgrade = (
|
|
autoprovisioning_max_unavailable_upgrade
|
|
)
|
|
self.enable_autoprovisioning_autoupgrade = (
|
|
enable_autoprovisioning_autoupgrade
|
|
)
|
|
self.enable_autoprovisioning_autorepair = enable_autoprovisioning_autorepair
|
|
self.autoprovisioning_min_cpu_platform = autoprovisioning_min_cpu_platform
|
|
self.enable_tpu = enable_tpu
|
|
self.tpu_ipv4_cidr = tpu_ipv4_cidr
|
|
self.enable_tpu_service_networking = enable_tpu_service_networking
|
|
self.enable_master_global_access = enable_master_global_access
|
|
self.notification_config = notification_config
|
|
self.private_ipv6_google_access_type = private_ipv6_google_access_type
|
|
self.kubernetes_objects_changes_target = kubernetes_objects_changes_target
|
|
self.kubernetes_objects_snapshots_target = (
|
|
kubernetes_objects_snapshots_target
|
|
)
|
|
self.disable_autopilot = disable_autopilot
|
|
self.add_cross_connect_subnetworks = add_cross_connect_subnetworks
|
|
self.remove_cross_connect_subnetworks = remove_cross_connect_subnetworks
|
|
self.clear_cross_connect_subnetworks = clear_cross_connect_subnetworks
|
|
self.enable_service_externalips = enable_service_externalips
|
|
self.security_group = security_group
|
|
self.enable_gcfs = enable_gcfs
|
|
self.autoprovisioning_network_tags = autoprovisioning_network_tags
|
|
self.enable_image_streaming = enable_image_streaming
|
|
self.enable_managed_prometheus = enable_managed_prometheus
|
|
self.disable_managed_prometheus = disable_managed_prometheus
|
|
self.auto_monitoring_scope = auto_monitoring_scope
|
|
self.managed_otel_scope = managed_otel_scope
|
|
self.maintenance_interval = maintenance_interval
|
|
self.dataplane_v2 = dataplane_v2
|
|
self.enable_dataplane_v2_metrics = enable_dataplane_v2_metrics
|
|
self.disable_dataplane_v2_metrics = disable_dataplane_v2_metrics
|
|
self.enable_dataplane_v2_flow_observability = (
|
|
enable_dataplane_v2_flow_observability
|
|
)
|
|
self.disable_dataplane_v2_flow_observability = (
|
|
disable_dataplane_v2_flow_observability
|
|
)
|
|
self.dataplane_v2_observability_mode = dataplane_v2_observability_mode
|
|
self.enable_workload_config_audit = enable_workload_config_audit
|
|
self.enable_workload_vulnerability_scanning = (
|
|
enable_workload_vulnerability_scanning
|
|
)
|
|
self.enable_autoprovisioning_surge_upgrade = (
|
|
enable_autoprovisioning_surge_upgrade
|
|
)
|
|
self.enable_autoprovisioning_blue_green_upgrade = (
|
|
enable_autoprovisioning_blue_green_upgrade
|
|
)
|
|
self.autoprovisioning_standard_rollout_policy = (
|
|
autoprovisioning_standard_rollout_policy
|
|
)
|
|
self.autoprovisioning_node_pool_soak_duration = (
|
|
autoprovisioning_node_pool_soak_duration
|
|
)
|
|
self.enable_private_endpoint = enable_private_endpoint
|
|
self.enable_google_cloud_access = enable_google_cloud_access
|
|
self.stack_type = stack_type
|
|
self.gateway_api = gateway_api
|
|
self.logging_variant = logging_variant
|
|
self.additional_pod_ipv4_ranges = additional_pod_ipv4_ranges
|
|
self.removed_additional_pod_ipv4_ranges = removed_additional_pod_ipv4_ranges
|
|
self.fleet_project = fleet_project
|
|
self.enable_fleet = enable_fleet
|
|
self.membership_type = membership_type
|
|
self.unset_membership_type = unset_membership_type
|
|
self.clear_fleet_project = clear_fleet_project
|
|
self.enable_security_posture = enable_security_posture
|
|
self.network_performance_config = network_performance_config
|
|
self.enable_k8s_beta_apis = enable_k8s_beta_apis
|
|
self.compliance = compliance
|
|
self.compliance_standards = compliance_standards
|
|
self.security_posture = security_posture
|
|
self.workload_vulnerability_scanning = workload_vulnerability_scanning
|
|
self.enable_runtime_vulnerability_insight = (
|
|
enable_runtime_vulnerability_insight
|
|
)
|
|
self.workload_policies = workload_policies
|
|
self.remove_workload_policies = remove_workload_policies
|
|
self.enable_fqdn_network_policy = enable_fqdn_network_policy
|
|
self.host_maintenance_interval = host_maintenance_interval
|
|
self.in_transit_encryption = in_transit_encryption
|
|
self.enable_multi_networking = enable_multi_networking
|
|
self.containerd_config_from_file = containerd_config_from_file
|
|
self.autoprovisioning_resource_manager_tags = (
|
|
autoprovisioning_resource_manager_tags
|
|
)
|
|
self.convert_to_autopilot = convert_to_autopilot
|
|
self.convert_to_standard = convert_to_standard
|
|
self.enable_secret_manager = enable_secret_manager
|
|
self.enable_secret_manager_rotation = enable_secret_manager_rotation
|
|
self.secret_manager_rotation_interval = secret_manager_rotation_interval
|
|
self.enable_secret_sync = enable_secret_sync
|
|
self.enable_secret_sync_rotation = enable_secret_sync_rotation
|
|
self.secret_sync_rotation_interval = secret_sync_rotation_interval
|
|
self.enable_cilium_clusterwide_network_policy = (
|
|
enable_cilium_clusterwide_network_policy
|
|
)
|
|
self.enable_insecure_kubelet_readonly_port = (
|
|
enable_insecure_kubelet_readonly_port
|
|
)
|
|
self.autoprovisioning_enable_insecure_kubelet_readonly_port = (
|
|
autoprovisioning_enable_insecure_kubelet_readonly_port
|
|
)
|
|
self.enable_ray_cluster_logging = enable_ray_cluster_logging
|
|
self.enable_ray_cluster_monitoring = enable_ray_cluster_monitoring
|
|
self.enable_insecure_binding_system_authenticated = (
|
|
enable_insecure_binding_system_authenticated
|
|
)
|
|
self.enable_insecure_binding_system_unauthenticated = (
|
|
enable_insecure_binding_system_unauthenticated
|
|
)
|
|
self.additional_ip_ranges = additional_ip_ranges
|
|
self.remove_additional_ip_ranges = remove_additional_ip_ranges
|
|
self.drain_additional_ip_ranges = drain_additional_ip_ranges
|
|
self.undrain_additional_ip_ranges = undrain_additional_ip_ranges
|
|
self.enable_private_nodes = enable_private_nodes
|
|
self.enable_dns_access = enable_dns_access
|
|
self.disable_l4_lb_firewall_reconciliation = (
|
|
disable_l4_lb_firewall_reconciliation
|
|
)
|
|
self.enable_l4_lb_firewall_reconciliation = (
|
|
enable_l4_lb_firewall_reconciliation
|
|
)
|
|
self.tier = tier
|
|
self.autoprovisioning_cgroup_mode = autoprovisioning_cgroup_mode
|
|
self.enable_ip_access = enable_ip_access
|
|
self.enable_authorized_networks_on_private_endpoint = (
|
|
enable_authorized_networks_on_private_endpoint
|
|
)
|
|
self.autopilot_privileged_admission = autopilot_privileged_admission
|
|
self.enable_autopilot_compatibility_auditing = (
|
|
enable_autopilot_compatibility_auditing
|
|
)
|
|
self.service_account_verification_keys = service_account_verification_keys
|
|
self.service_account_signing_keys = service_account_signing_keys
|
|
self.control_plane_disk_encryption_key = control_plane_disk_encryption_key
|
|
self.anonymous_authentication_config = anonymous_authentication_config
|
|
self.patch_update = patch_update
|
|
self.enable_auto_ipam = enable_auto_ipam
|
|
self.disable_auto_ipam = disable_auto_ipam
|
|
self.enable_k8s_tokens_via_dns = enable_k8s_tokens_via_dns
|
|
self.enable_legacy_lustre_port = enable_legacy_lustre_port
|
|
self.disable_multi_nic_lustre = disable_multi_nic_lustre
|
|
self.enable_default_compute_class = enable_default_compute_class
|
|
self.enable_k8s_certs_via_dns = enable_k8s_certs_via_dns
|
|
self.boot_disk_provisioned_iops = boot_disk_provisioned_iops
|
|
self.boot_disk_provisioned_throughput = boot_disk_provisioned_throughput
|
|
self.network_tier = network_tier
|
|
self.control_plane_egress_mode = control_plane_egress_mode
|
|
self.control_plane_soak_duration = control_plane_soak_duration
|
|
self.enable_pod_snapshots = enable_pod_snapshots
|
|
self.autopilot_privileged_admission = autopilot_privileged_admission
|
|
self.enable_slice_controller = enable_slice_controller
|
|
self.autopilot_general_profile = autopilot_general_profile
|
|
|
|
|
|
class SetMasterAuthOptions(object):
|
|
"""Options to pass to SetMasterAuth."""
|
|
|
|
SET_PASSWORD = 'SetPassword'
|
|
GENERATE_PASSWORD = 'GeneratePassword'
|
|
SET_USERNAME = 'SetUsername'
|
|
|
|
def __init__(self, action=None, username=None, password=None):
|
|
self.action = action
|
|
self.username = username
|
|
self.password = password
|
|
|
|
|
|
class SetNetworkPolicyOptions(object):
|
|
|
|
def __init__(self, enabled):
|
|
self.enabled = enabled
|
|
|
|
|
|
class CreateNodePoolOptions(object):
|
|
"""Options to pass to CreateNodePool."""
|
|
|
|
def __init__(
|
|
self,
|
|
machine_type=None,
|
|
disk_size_gb=None,
|
|
scopes=None,
|
|
node_version=None,
|
|
num_nodes=None,
|
|
local_ssd_count=None,
|
|
local_ssd_volume_configs=None,
|
|
ephemeral_storage=None,
|
|
local_nvme_ssd_block=None,
|
|
ephemeral_storage_local_ssd=None,
|
|
boot_disk_kms_key=None,
|
|
tags=None,
|
|
tag_bindings=None,
|
|
node_labels=None,
|
|
labels=None,
|
|
node_taints=None,
|
|
enable_autoscaling=None,
|
|
max_nodes=None,
|
|
min_nodes=None,
|
|
total_max_nodes=None,
|
|
total_min_nodes=None,
|
|
location_policy=None,
|
|
enable_autoprovisioning=None,
|
|
image_type=None,
|
|
image=None,
|
|
image_project=None,
|
|
image_family=None,
|
|
preemptible=None,
|
|
spot=None,
|
|
placement_type=None,
|
|
placement_policy=None,
|
|
tpu_topology=None,
|
|
enable_queued_provisioning=None,
|
|
max_run_duration=None,
|
|
consolidation_delay=None,
|
|
flex_start=None,
|
|
enable_autorepair=None,
|
|
enable_autoupgrade=None,
|
|
service_account=None,
|
|
disk_type=None,
|
|
accelerators=None,
|
|
min_cpu_platform=None,
|
|
workload_metadata=None,
|
|
workload_metadata_from_node=None,
|
|
max_pods_per_node=None,
|
|
sandbox=None,
|
|
metadata=None,
|
|
linux_sysctls=None,
|
|
gpudirect_strategy=None,
|
|
max_surge_upgrade=None,
|
|
max_unavailable_upgrade=None,
|
|
node_locations=None,
|
|
shielded_secure_boot=None,
|
|
shielded_integrity_monitoring=None,
|
|
system_config_from_file=None,
|
|
reservation_affinity=None,
|
|
reservation=None,
|
|
node_group=None,
|
|
enable_gcfs=None,
|
|
enable_image_streaming=None,
|
|
gvnic=None,
|
|
pod_ipv4_range=None,
|
|
create_pod_ipv4_range=None,
|
|
enable_private_nodes=None,
|
|
threads_per_core=None,
|
|
enable_blue_green_upgrade=None,
|
|
enable_surge_upgrade=None,
|
|
node_pool_soak_duration=None,
|
|
standard_rollout_policy=None,
|
|
autoscaled_rollout_policy=None,
|
|
maintenance_interval=None,
|
|
network_performance_config=None,
|
|
enable_confidential_nodes=None,
|
|
confidential_node_type=None,
|
|
enable_confidential_storage=None,
|
|
disable_pod_cidr_overprovision=None,
|
|
enable_fast_socket=None,
|
|
logging_variant=None,
|
|
windows_os_version=None,
|
|
enable_best_effort_provision=None,
|
|
min_provision_nodes=None,
|
|
additional_node_network=None,
|
|
additional_pod_network=None,
|
|
enable_nested_virtualization=None,
|
|
performance_monitoring_unit=None,
|
|
sole_tenant_node_affinity_file=None,
|
|
sole_tenant_min_node_cpus=None,
|
|
host_maintenance_interval=None,
|
|
opportunistic_maintenance=None,
|
|
enable_insecure_kubelet_readonly_port=None,
|
|
resource_manager_tags=None,
|
|
containerd_config_from_file=None,
|
|
secondary_boot_disks=None,
|
|
storage_pools=None,
|
|
local_ssd_encryption_mode=None,
|
|
boot_disk_provisioned_iops=None,
|
|
boot_disk_provisioned_throughput=None,
|
|
data_cache_count=None,
|
|
accelerator_network_profile=None,
|
|
enable_kernel_module_signature_enforcement=None,
|
|
runner_pool_control_mode=None,
|
|
control_node_pool=None,
|
|
enable_attestation=None,
|
|
tee_policy=None,
|
|
enable_lustre_multi_nic=None,
|
|
):
|
|
self.machine_type = machine_type
|
|
self.disk_size_gb = disk_size_gb
|
|
self.scopes = scopes
|
|
self.node_version = node_version
|
|
self.num_nodes = num_nodes
|
|
self.local_ssd_count = local_ssd_count
|
|
self.data_cache_count = data_cache_count
|
|
self.local_ssd_volume_configs = local_ssd_volume_configs
|
|
self.ephemeral_storage = ephemeral_storage
|
|
self.ephemeral_storage_local_ssd = ephemeral_storage_local_ssd
|
|
self.local_nvme_ssd_block = local_nvme_ssd_block
|
|
self.boot_disk_kms_key = boot_disk_kms_key
|
|
self.tags = tags
|
|
self.tag_bindings = tag_bindings
|
|
self.labels = labels
|
|
self.node_labels = node_labels
|
|
self.node_taints = node_taints
|
|
self.enable_autoscaling = enable_autoscaling
|
|
self.max_nodes = max_nodes
|
|
self.min_nodes = min_nodes
|
|
self.total_max_nodes = total_max_nodes
|
|
self.total_min_nodes = total_min_nodes
|
|
self.enable_autoprovisioning = enable_autoprovisioning
|
|
self.image_type = image_type
|
|
self.location_policy = location_policy
|
|
self.image = image
|
|
self.image_project = image_project
|
|
self.image_family = image_family
|
|
self.preemptible = preemptible
|
|
self.spot = spot
|
|
self.placement_type = placement_type
|
|
self.placement_policy = placement_policy
|
|
self.tpu_topology = tpu_topology
|
|
self.enable_queued_provisioning = enable_queued_provisioning
|
|
self.max_run_duration = max_run_duration
|
|
self.consolidation_delay = consolidation_delay
|
|
self.flex_start = flex_start
|
|
self.enable_autorepair = enable_autorepair
|
|
self.enable_autoupgrade = enable_autoupgrade
|
|
self.service_account = service_account
|
|
self.disk_type = disk_type
|
|
self.accelerators = accelerators
|
|
self.min_cpu_platform = min_cpu_platform
|
|
self.workload_metadata = workload_metadata
|
|
self.workload_metadata_from_node = workload_metadata_from_node
|
|
self.max_pods_per_node = max_pods_per_node
|
|
self.sandbox = sandbox
|
|
self.metadata = metadata
|
|
self.linux_sysctls = linux_sysctls
|
|
self.gpudirect_strategy = gpudirect_strategy
|
|
self.max_surge_upgrade = max_surge_upgrade
|
|
self.max_unavailable_upgrade = max_unavailable_upgrade
|
|
self.node_locations = node_locations
|
|
self.shielded_secure_boot = shielded_secure_boot
|
|
self.shielded_integrity_monitoring = shielded_integrity_monitoring
|
|
self.system_config_from_file = system_config_from_file
|
|
self.reservation_affinity = reservation_affinity
|
|
self.reservation = reservation
|
|
self.node_group = node_group
|
|
self.enable_gcfs = enable_gcfs
|
|
self.enable_image_streaming = enable_image_streaming
|
|
self.gvnic = gvnic
|
|
self.pod_ipv4_range = pod_ipv4_range
|
|
self.create_pod_ipv4_range = create_pod_ipv4_range
|
|
self.enable_private_nodes = enable_private_nodes
|
|
self.threads_per_core = threads_per_core
|
|
self.enable_nested_virtualization = enable_nested_virtualization
|
|
self.performance_monitoring_unit = performance_monitoring_unit
|
|
self.enable_blue_green_upgrade = enable_blue_green_upgrade
|
|
self.enable_surge_upgrade = enable_surge_upgrade
|
|
self.node_pool_soak_duration = node_pool_soak_duration
|
|
self.standard_rollout_policy = standard_rollout_policy
|
|
self.autoscaled_rollout_policy = autoscaled_rollout_policy
|
|
self.maintenance_interval = maintenance_interval
|
|
self.network_performance_config = network_performance_config
|
|
self.enable_confidential_nodes = enable_confidential_nodes
|
|
self.confidential_node_type = confidential_node_type
|
|
self.enable_confidential_storage = enable_confidential_storage
|
|
self.disable_pod_cidr_overprovision = disable_pod_cidr_overprovision
|
|
self.enable_fast_socket = enable_fast_socket
|
|
self.logging_variant = logging_variant
|
|
self.windows_os_version = windows_os_version
|
|
self.enable_best_effort_provision = enable_best_effort_provision
|
|
self.min_provision_nodes = min_provision_nodes
|
|
self.additional_node_network = additional_node_network
|
|
self.additional_pod_network = additional_pod_network
|
|
self.sole_tenant_node_affinity_file = sole_tenant_node_affinity_file
|
|
self.sole_tenant_min_node_cpus = sole_tenant_min_node_cpus
|
|
self.host_maintenance_interval = host_maintenance_interval
|
|
self.opportunistic_maintenance = opportunistic_maintenance
|
|
self.enable_insecure_kubelet_readonly_port = (
|
|
enable_insecure_kubelet_readonly_port
|
|
)
|
|
self.resource_manager_tags = resource_manager_tags
|
|
self.containerd_config_from_file = containerd_config_from_file
|
|
self.secondary_boot_disks = secondary_boot_disks
|
|
self.storage_pools = storage_pools
|
|
self.local_ssd_encryption_mode = local_ssd_encryption_mode
|
|
self.boot_disk_provisioned_iops = boot_disk_provisioned_iops
|
|
self.boot_disk_provisioned_throughput = boot_disk_provisioned_throughput
|
|
self.accelerator_network_profile = accelerator_network_profile
|
|
self.enable_kernel_module_signature_enforcement = (
|
|
enable_kernel_module_signature_enforcement
|
|
)
|
|
self.runner_pool_control_mode = runner_pool_control_mode
|
|
self.control_node_pool = control_node_pool
|
|
self.enable_attestation = enable_attestation
|
|
self.tee_policy = tee_policy
|
|
self.enable_lustre_multi_nic = enable_lustre_multi_nic
|
|
|
|
|
|
class UpdateNodePoolOptions(object):
|
|
"""Options to pass to UpdateNodePool."""
|
|
|
|
def __init__(
|
|
self,
|
|
enable_autorepair=None,
|
|
enable_autoupgrade=None,
|
|
enable_autoscaling=None,
|
|
max_nodes=None,
|
|
min_nodes=None,
|
|
total_max_nodes=None,
|
|
total_min_nodes=None,
|
|
location_policy=None,
|
|
enable_autoprovisioning=None,
|
|
workload_metadata=None,
|
|
workload_metadata_from_node=None,
|
|
node_locations=None,
|
|
max_surge_upgrade=None,
|
|
max_unavailable_upgrade=None,
|
|
system_config_from_file=None,
|
|
node_labels=None,
|
|
labels=None,
|
|
node_taints=None,
|
|
tags=None,
|
|
enable_private_nodes=None,
|
|
enable_gcfs=None,
|
|
gvnic=None,
|
|
enable_image_streaming=None,
|
|
enable_blue_green_upgrade=None,
|
|
enable_surge_upgrade=None,
|
|
node_pool_soak_duration=None,
|
|
standard_rollout_policy=None,
|
|
autoscaled_rollout_policy=None,
|
|
network_performance_config=None,
|
|
enable_confidential_nodes=None,
|
|
confidential_node_type=None,
|
|
enable_fast_socket=None,
|
|
logging_variant=None,
|
|
accelerators=None,
|
|
windows_os_version=None,
|
|
enable_insecure_kubelet_readonly_port=None,
|
|
resource_manager_tags=None,
|
|
containerd_config_from_file=None,
|
|
secondary_boot_disks=None,
|
|
machine_type=None,
|
|
disk_type=None,
|
|
disk_size_gb=None,
|
|
enable_queued_provisioning=None,
|
|
max_run_duration=None,
|
|
consolidation_delay=None,
|
|
flex_start=None,
|
|
storage_pools=None,
|
|
boot_disk_provisioned_iops=None,
|
|
boot_disk_provisioned_throughput=None,
|
|
enable_kernel_module_signature_enforcement=None,
|
|
enable_lustre_multi_nic=None,
|
|
):
|
|
self.enable_autorepair = enable_autorepair
|
|
self.enable_autoupgrade = enable_autoupgrade
|
|
self.enable_autoscaling = enable_autoscaling
|
|
self.max_nodes = max_nodes
|
|
self.min_nodes = min_nodes
|
|
self.accelerators = accelerators
|
|
self.total_max_nodes = total_max_nodes
|
|
self.total_min_nodes = total_min_nodes
|
|
self.location_policy = location_policy
|
|
self.enable_autoprovisioning = enable_autoprovisioning
|
|
self.workload_metadata = workload_metadata
|
|
self.workload_metadata_from_node = workload_metadata_from_node
|
|
self.node_locations = node_locations
|
|
self.max_surge_upgrade = max_surge_upgrade
|
|
self.max_unavailable_upgrade = max_unavailable_upgrade
|
|
self.system_config_from_file = system_config_from_file
|
|
self.labels = labels
|
|
self.node_labels = node_labels
|
|
self.node_taints = node_taints
|
|
self.tags = tags
|
|
self.enable_private_nodes = enable_private_nodes
|
|
self.enable_gcfs = enable_gcfs
|
|
self.gvnic = gvnic
|
|
self.enable_image_streaming = enable_image_streaming
|
|
self.enable_blue_green_upgrade = enable_blue_green_upgrade
|
|
self.enable_surge_upgrade = enable_surge_upgrade
|
|
self.node_pool_soak_duration = node_pool_soak_duration
|
|
self.standard_rollout_policy = standard_rollout_policy
|
|
self.autoscaled_rollout_policy = autoscaled_rollout_policy
|
|
self.network_performance_config = network_performance_config
|
|
self.enable_confidential_nodes = enable_confidential_nodes
|
|
self.confidential_node_type = confidential_node_type
|
|
self.enable_fast_socket = enable_fast_socket
|
|
self.logging_variant = logging_variant
|
|
self.windows_os_version = windows_os_version
|
|
self.enable_insecure_kubelet_readonly_port = (
|
|
enable_insecure_kubelet_readonly_port
|
|
)
|
|
self.resource_manager_tags = resource_manager_tags
|
|
self.containerd_config_from_file = containerd_config_from_file
|
|
self.secondary_boot_disks = secondary_boot_disks
|
|
self.machine_type = machine_type
|
|
self.disk_type = disk_type
|
|
self.disk_size_gb = disk_size_gb
|
|
self.enable_queued_provisioning = enable_queued_provisioning
|
|
self.max_run_duration = max_run_duration
|
|
self.consolidation_delay = consolidation_delay
|
|
self.flex_start = flex_start
|
|
self.storage_pools = storage_pools
|
|
self.enable_insecure_kubelet_readonly_port = (
|
|
enable_insecure_kubelet_readonly_port
|
|
)
|
|
self.provisioned_iops = boot_disk_provisioned_iops
|
|
self.provisioned_throughput = boot_disk_provisioned_throughput
|
|
self.enable_kernel_module_signature_enforcement = (
|
|
enable_kernel_module_signature_enforcement
|
|
)
|
|
self.enable_lustre_multi_nic = enable_lustre_multi_nic
|
|
|
|
def IsAutoscalingUpdate(self):
|
|
return (
|
|
self.enable_autoscaling is not None
|
|
or self.max_nodes is not None
|
|
or self.min_nodes is not None
|
|
or self.total_max_nodes is not None
|
|
or self.total_min_nodes is not None
|
|
or self.enable_autoprovisioning is not None
|
|
or self.location_policy is not None
|
|
)
|
|
|
|
def IsNodePoolManagementUpdate(self):
|
|
return (
|
|
self.enable_autorepair is not None
|
|
or self.enable_autoupgrade is not None
|
|
)
|
|
|
|
def IsUpdateNodePoolRequest(self):
|
|
return (
|
|
self.workload_metadata is not None
|
|
or self.workload_metadata_from_node is not None
|
|
or self.node_locations is not None
|
|
or self.max_surge_upgrade is not None
|
|
or self.max_unavailable_upgrade is not None
|
|
or self.system_config_from_file is not None
|
|
or self.labels is not None
|
|
or self.node_labels is not None
|
|
or self.node_taints is not None
|
|
or self.tags is not None
|
|
or self.enable_private_nodes is not None
|
|
or self.enable_gcfs is not None
|
|
or self.gvnic is not None
|
|
or self.enable_image_streaming is not None
|
|
or self.enable_surge_upgrade is not None
|
|
or self.enable_blue_green_upgrade is not None
|
|
or self.node_pool_soak_duration is not None
|
|
or self.standard_rollout_policy is not None
|
|
or self.autoscaled_rollout_policy is not None
|
|
or self.network_performance_config is not None
|
|
or self.enable_confidential_nodes is not None
|
|
or self.confidential_node_type is not None
|
|
or self.enable_fast_socket is not None
|
|
or self.logging_variant is not None
|
|
or self.windows_os_version is not None
|
|
or self.accelerators is not None
|
|
or self.resource_manager_tags is not None
|
|
or self.containerd_config_from_file is not None
|
|
or self.machine_type is not None
|
|
or self.disk_type is not None
|
|
or self.disk_size_gb is not None
|
|
or self.enable_queued_provisioning is not None
|
|
or self.max_run_duration is not None
|
|
or self.consolidation_delay is not None
|
|
or self.flex_start is not None
|
|
or self.storage_pools is not None
|
|
or self.provisioned_iops is not None
|
|
or self.provisioned_throughput is not None
|
|
or self.enable_kernel_module_signature_enforcement is not None
|
|
or self.enable_lustre_multi_nic is not None
|
|
)
|
|
|
|
|
|
class APIAdapter(object):
|
|
"""Handles making api requests in a version-agnostic way."""
|
|
|
|
def __init__(
|
|
self, registry, client, messages, compute_messages, compute_client
|
|
):
|
|
self.registry = registry
|
|
self.client = client
|
|
self.messages = messages
|
|
self.compute_messages = compute_messages
|
|
self.compute_client = compute_client
|
|
|
|
def ParseCluster(self, name, location, project=None):
|
|
project = project or properties.VALUES.core.project.GetOrFail()
|
|
# Note: we don't directly use container.projects.locations.clusters, etc,
|
|
# because it has different fields and thus would change the rest of our
|
|
# code heavily.
|
|
return self.registry.Parse(
|
|
util.LocationalResourceToZonal(name),
|
|
params={
|
|
'projectId': project,
|
|
'zone': location,
|
|
},
|
|
collection='container.projects.zones.clusters',
|
|
)
|
|
|
|
def ParseOperation(self, operation_id, location, project=None):
|
|
project = project or properties.VALUES.core.project.GetOrFail()
|
|
return self.registry.Parse(
|
|
util.LocationalResourceToZonal(operation_id),
|
|
params={
|
|
'projectId': project,
|
|
'zone': location,
|
|
},
|
|
collection='container.projects.zones.operations',
|
|
)
|
|
|
|
def ParseNodePool(self, node_pool_id, location, project=None):
|
|
project = project or properties.VALUES.core.project.GetOrFail()
|
|
return self.registry.Parse(
|
|
util.LocationalResourceToZonal(node_pool_id),
|
|
params={
|
|
'projectId': project,
|
|
'clusterId': properties.VALUES.container.cluster.GetOrFail,
|
|
'zone': location,
|
|
},
|
|
collection='container.projects.zones.clusters.nodePools',
|
|
)
|
|
|
|
def GetCluster(self, cluster_ref):
|
|
"""Get a running cluster.
|
|
|
|
Args:
|
|
cluster_ref: cluster Resource to describe.
|
|
|
|
Returns:
|
|
Cluster message.
|
|
Raises:
|
|
Error: if cluster cannot be found or caller is missing permissions. Will
|
|
attempt to find similar clusters in other zones for a more useful error
|
|
if the user has list permissions.
|
|
"""
|
|
try:
|
|
return self.client.projects_locations_clusters.Get(
|
|
self.messages.ContainerProjectsLocationsClustersGetRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
)
|
|
)
|
|
)
|
|
except apitools_exceptions.HttpNotFoundError as error:
|
|
api_error = exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
# Cluster couldn't be found, maybe user got the location wrong?
|
|
self.CheckClusterOtherZones(cluster_ref, api_error)
|
|
except apitools_exceptions.HttpError as error:
|
|
raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
|
|
def GetClusterUpgradeInfo(self, cluster_ref):
|
|
"""Get cluster upgrade info.
|
|
|
|
Args:
|
|
cluster_ref: cluster Resource to get upgrade info for.
|
|
|
|
Returns:
|
|
Cluster Upgrade Info message.
|
|
Raises:
|
|
Error: if cluster cannot be found or caller is missing permissions. Will
|
|
attempt to find similar clusters in other zones for a more useful error
|
|
if the user has list permissions.
|
|
"""
|
|
try:
|
|
return self.client.projects_locations_clusters.FetchClusterUpgradeInfo(
|
|
self.messages.ContainerProjectsLocationsClustersFetchClusterUpgradeInfoRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
)
|
|
)
|
|
)
|
|
except apitools_exceptions.HttpNotFoundError as error:
|
|
api_error = exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
# Cluster couldn't be found, maybe user got the location wrong?
|
|
self.CheckClusterOtherZones(cluster_ref, api_error)
|
|
except apitools_exceptions.HttpError as error:
|
|
raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
|
|
def GetResourcePolicy(self, policy_name, project, location):
|
|
"""Fetches a GCE Resource Policy from the Compute API.
|
|
|
|
Args:
|
|
policy_name (str): The name of the resource policy to retrieve.
|
|
project (str): The Google Cloud project that contains the resource policy.
|
|
location (str): The location of the policy. This can be a region (e.g.,
|
|
'us-central1') or a zone (e.g., 'us-central1-a').
|
|
|
|
Returns:
|
|
The complete ResourcePolicy message object, populated with its
|
|
configuration data and status.
|
|
|
|
Raises:
|
|
exceptions.Error: If the resource policy is not found in the specified
|
|
project and region.
|
|
exceptions.HttpException: For other underlying API errors, such as
|
|
permission denied.
|
|
"""
|
|
if re.match(r'^[^-]+-[^-]+-[^-]+$', location):
|
|
region = location[: location.rfind('-')]
|
|
else:
|
|
region = location
|
|
|
|
try:
|
|
get_request = self.compute_messages.ComputeResourcePoliciesGetRequest(
|
|
project=project,
|
|
region=region,
|
|
resourcePolicy=policy_name,
|
|
)
|
|
|
|
return self.compute_client.resourcePolicies.Get(get_request)
|
|
|
|
except apitools_exceptions.HttpNotFoundError as error:
|
|
api_error = exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
self.CheckPolicyOtherRegions(project, policy_name, region, api_error)
|
|
except apitools_exceptions.HttpError as error:
|
|
raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
|
|
def CompleteControlPlaneUpgrade(self, cluster_ref):
|
|
"""Complete control plane upgrade for a cluster.
|
|
|
|
Args:
|
|
cluster_ref: cluster Resource to complete control plane upgrade for.
|
|
|
|
Returns:
|
|
The operation to be executed.
|
|
Raises:
|
|
exceptions.HttpException: if cluster cannot be found or caller is missing
|
|
permissions. Will attempt to find similar clusters in other zones for a
|
|
more useful error if the user has list permissions.
|
|
"""
|
|
try:
|
|
op = self.client.projects_locations_clusters.CompleteControlPlaneUpgrade(
|
|
self.messages.ContainerProjectsLocationsClustersCompleteControlPlaneUpgradeRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
)
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
except apitools_exceptions.HttpNotFoundError as error:
|
|
api_error = exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
# Cluster couldn't be found, maybe user got the location wrong?
|
|
self.CheckClusterOtherZones(cluster_ref, api_error)
|
|
except apitools_exceptions.HttpError as error:
|
|
raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
|
|
def CheckAutopilotCompatibility(self, cluster_ref):
|
|
"""Check autopilot compatibility of a cluster.
|
|
|
|
Args:
|
|
cluster_ref: cluster resource to check.
|
|
|
|
Returns:
|
|
A list of autopilot compatibility issues.
|
|
Raises:
|
|
Error: if cluster cannot be found or caller is missing permissions. Will
|
|
attempt to find similar clusters in other zones for a more useful error
|
|
if the user has list permissions.
|
|
"""
|
|
try:
|
|
return self.client.projects_locations_clusters.CheckAutopilotCompatibility(
|
|
self.messages.ContainerProjectsLocationsClustersCheckAutopilotCompatibilityRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
)
|
|
)
|
|
)
|
|
except apitools_exceptions.HttpNotFoundError as error:
|
|
api_error = exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
# Cluster couldn't be found, maybe user got the location wrong?
|
|
self.CheckClusterOtherZones(cluster_ref, api_error)
|
|
except apitools_exceptions.HttpError as error:
|
|
raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
|
|
def CheckClusterOtherZones(self, cluster_ref, api_error):
|
|
"""Searches for similar clusters in other locations and reports via error.
|
|
|
|
Args:
|
|
cluster_ref: cluster Resource to look for others with the same ID in
|
|
different locations.
|
|
api_error: current error from original request.
|
|
|
|
Raises:
|
|
Error: wrong zone error if another similar cluster found, otherwise not
|
|
found error.
|
|
"""
|
|
not_found_error = util.Error(
|
|
NO_SUCH_CLUSTER_ERROR_MSG.format(
|
|
error=api_error,
|
|
name=cluster_ref.clusterId,
|
|
project=cluster_ref.projectId,
|
|
)
|
|
)
|
|
try:
|
|
clusters = self.ListClusters(cluster_ref.projectId).clusters
|
|
except apitools_exceptions.HttpForbiddenError:
|
|
# Raise the default 404 Not Found error.
|
|
# 403 Forbidden error shouldn't be raised for this unrequested list.
|
|
raise not_found_error
|
|
except apitools_exceptions.HttpError as error:
|
|
raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
for cluster in clusters:
|
|
if cluster.name == cluster_ref.clusterId:
|
|
# Fall back to generic not found error if we *did* have the zone right.
|
|
# Don't allow the case of a same-name cluster in a different zone to
|
|
# be hinted (confusing!).
|
|
if cluster.zone == cluster_ref.zone:
|
|
raise api_error
|
|
|
|
# User likely got zone wrong.
|
|
raise util.Error(
|
|
WRONG_ZONE_ERROR_MSG.format(
|
|
error=api_error,
|
|
name=cluster_ref.clusterId,
|
|
wrong_zone=self.Zone(cluster_ref),
|
|
zone=cluster.zone,
|
|
)
|
|
)
|
|
# Couldn't find a cluster with that name.
|
|
raise not_found_error
|
|
|
|
def CheckPolicyOtherRegions(self, project, policy_name, region, api_error):
|
|
"""Searches for a resource policy in other regions to provide a better error.
|
|
|
|
Args:
|
|
project (str): The project to search in.
|
|
policy_name (str): The name of the resource policy to find.
|
|
region (str): The region that was searched in previously.
|
|
api_error: current error from original request.
|
|
|
|
Raises:
|
|
util.Error: A more helpful error if a match is found elsewhere.
|
|
exceptions.HttpException: The original error if no helpful suggestion can
|
|
be made.
|
|
"""
|
|
not_found_error = util.Error(
|
|
NO_SUCH_RESOURCE_POLICY_ERROR_MSG.format(
|
|
policy_name=policy_name,
|
|
region=region,
|
|
project=project,
|
|
)
|
|
)
|
|
try:
|
|
aggregated_list_request = (
|
|
self.compute_messages.ComputeResourcePoliciesAggregatedListRequest(
|
|
project=project
|
|
)
|
|
)
|
|
all_policies = self.compute_client.resourcePolicies.AggregatedList(
|
|
aggregated_list_request
|
|
)
|
|
except apitools_exceptions.HttpForbiddenError:
|
|
raise not_found_error
|
|
except apitools_exceptions.HttpError as error:
|
|
raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
|
|
for prop in all_policies.items.additionalProperties:
|
|
scoped_list = prop.value
|
|
if scoped_list.resourcePolicies:
|
|
for policy in scoped_list.resourcePolicies:
|
|
if policy.name == policy_name:
|
|
policy_region = policy.region.split('/')[-1]
|
|
|
|
if policy_region == region:
|
|
raise api_error
|
|
|
|
raise util.Error(
|
|
WRONG_REGION_RESOURCE_POLICY_ERROR_MSG.format(
|
|
wrong_region=region,
|
|
region=policy_region,
|
|
policy_name=policy_name,
|
|
)
|
|
)
|
|
|
|
raise not_found_error
|
|
|
|
def FindNodePool(self, cluster, pool_name=None):
|
|
"""Find the node pool with the given name in the cluster."""
|
|
msg = ''
|
|
if pool_name:
|
|
for np in cluster.nodePools:
|
|
if np.name == pool_name:
|
|
return np
|
|
msg = (
|
|
NO_SUCH_NODE_POOL_ERROR_MSG.format(
|
|
cluster=cluster.name, name=pool_name
|
|
)
|
|
+ os.linesep
|
|
)
|
|
elif len(cluster.nodePools) == 1:
|
|
return cluster.nodePools[0]
|
|
# Couldn't find a node pool with that name or a node pool was not specified.
|
|
msg += NO_NODE_POOL_SELECTED_ERROR_MSG + os.linesep.join(
|
|
[np.name for np in cluster.nodePools]
|
|
)
|
|
raise util.Error(msg)
|
|
|
|
def GetOperation(self, operation_ref):
|
|
return self.client.projects_locations_operations.Get(
|
|
self.messages.ContainerProjectsLocationsOperationsGetRequest(
|
|
name=ProjectLocationOperation(
|
|
operation_ref.projectId,
|
|
operation_ref.zone,
|
|
operation_ref.operationId,
|
|
)
|
|
)
|
|
)
|
|
|
|
def WaitForOperation(
|
|
self, operation_ref, message, timeout_s=1200, poll_period_s=5
|
|
):
|
|
"""Poll container Operation until its status is done or timeout reached.
|
|
|
|
Args:
|
|
operation_ref: operation resource.
|
|
message: str, message to display to user while polling.
|
|
timeout_s: number, seconds to poll with retries before timing out.
|
|
poll_period_s: number, delay in seconds between requests.
|
|
|
|
Returns:
|
|
Operation: the return value of the last successful operations.get
|
|
request.
|
|
|
|
Raises:
|
|
Error: if the operation times out or finishes with an error.
|
|
"""
|
|
|
|
def _MustGetOperation():
|
|
"""Gets the operation or throws an exception, with limited retries."""
|
|
# It's unusual for operation polling to fail, so retry a few times. It's
|
|
# a bit overly broad to retry all errors, but since it's so unusual to
|
|
# get an error at all, this is the simplest approach. The type of error
|
|
# that is most likely to be a true positive is a not found error, but
|
|
# that's also the most likely to be resolveable via retry.
|
|
for attempt in range(3):
|
|
try:
|
|
return self.GetOperation(operation_ref)
|
|
except apitools_exceptions.HttpError as error:
|
|
log.debug('GetOperation failed (attempt %d): %s', attempt + 1, error)
|
|
time.sleep(poll_period_s)
|
|
if attempt == 2:
|
|
raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
|
|
def _WaitForOperation():
|
|
"""Retries getting the operation until it finishes, times out or fails."""
|
|
detail_message = None
|
|
with progress_tracker.ProgressTracker(
|
|
message, autotick=True, detail_message_callback=lambda: detail_message
|
|
):
|
|
start_time = time.time()
|
|
op = _MustGetOperation()
|
|
while timeout_s > (time.time() - start_time):
|
|
if self.IsOperationFinished(op):
|
|
duration = time.time() - start_time
|
|
log.info(f'Operation {op} finished after {duration:.3} seconds')
|
|
return op
|
|
|
|
detail_message = op.detail
|
|
time.sleep(poll_period_s)
|
|
op = _MustGetOperation()
|
|
|
|
log.err.Print(f'Timed out waiting for operation {op}')
|
|
raise util.Error(
|
|
f'Operation [{op}] is still running, check its status via '
|
|
+ f"'gcloud container operations describe {op.name}'"
|
|
)
|
|
|
|
operation = _WaitForOperation()
|
|
if operation.statusMessage:
|
|
raise util.Error(
|
|
f'Operation [{operation}] finished with error: '
|
|
+ f'{operation.statusMessage}'
|
|
)
|
|
|
|
return operation
|
|
|
|
def Zone(self, cluster_ref):
|
|
# TODO(b/72146704): Remove this method.
|
|
return cluster_ref.zone
|
|
|
|
def CreateClusterCommon(self, cluster_ref, options):
|
|
"""Returns a CreateCluster operation.
|
|
|
|
This function is for code that is common across all channels, and the
|
|
return value is intended to be modified by each.
|
|
|
|
Args:
|
|
cluster_ref: A Cluster message from the calling channel.
|
|
options: User selected options passed to the cluster creation.
|
|
|
|
Returns:
|
|
A CreateCluster operation.
|
|
|
|
Raises:
|
|
A util.Error if options selected are invalid.
|
|
"""
|
|
node_config = self.ParseNodeConfig(options)
|
|
pools = self.ParseNodePools(options, node_config)
|
|
cluster = self.messages.Cluster(name=cluster_ref.clusterId, nodePools=pools)
|
|
if options.tag_bindings:
|
|
# Assign the dictionary to the cluster.tags field
|
|
cluster.tags = self.messages.Cluster.TagsValue(
|
|
additionalProperties=[
|
|
self.messages.Cluster.TagsValue.AdditionalProperty(key=k, value=v)
|
|
for k, v in sorted(options.tag_bindings.items())
|
|
]
|
|
)
|
|
if options.additional_zones:
|
|
cluster.locations = sorted([cluster_ref.zone] + options.additional_zones)
|
|
if options.node_locations:
|
|
cluster.locations = sorted(options.node_locations)
|
|
if options.cluster_version:
|
|
cluster.initialClusterVersion = options.cluster_version
|
|
if options.network:
|
|
cluster.network = options.network
|
|
if options.cluster_ipv4_cidr:
|
|
cluster.clusterIpv4Cidr = options.cluster_ipv4_cidr
|
|
if options.enable_stackdriver_kubernetes is not None:
|
|
# When "enable-stackdriver-kubernetes" is specified, either true or false.
|
|
if options.enable_stackdriver_kubernetes:
|
|
cluster.loggingService = 'logging.googleapis.com/kubernetes'
|
|
cluster.monitoringService = 'monitoring.googleapis.com/kubernetes'
|
|
# When "enable-stackdriver-kubernetes" is true, the
|
|
# "enable-cloud-logging" and "enable-cloud-monitoring" flags can be
|
|
# used to explicitly disable logging or monitoring
|
|
if (
|
|
options.enable_cloud_logging is not None
|
|
and not options.enable_cloud_logging
|
|
):
|
|
cluster.loggingService = 'none'
|
|
if (
|
|
options.enable_cloud_monitoring is not None
|
|
and not options.enable_cloud_monitoring
|
|
):
|
|
cluster.monitoringService = 'none'
|
|
else:
|
|
cluster.loggingService = 'none'
|
|
cluster.monitoringService = 'none'
|
|
# When "enable-stackdriver-kubernetes" is unspecified, checks whether
|
|
# "enable-cloud-logging" or "enable-cloud-monitoring" options are specified.
|
|
else:
|
|
if options.enable_cloud_logging is not None:
|
|
if options.enable_cloud_logging:
|
|
cluster.loggingService = 'logging.googleapis.com'
|
|
else:
|
|
cluster.loggingService = 'none'
|
|
if options.enable_cloud_monitoring is not None:
|
|
if options.enable_cloud_monitoring:
|
|
cluster.monitoringService = 'monitoring.googleapis.com'
|
|
else:
|
|
cluster.monitoringService = 'none'
|
|
if options.subnetwork:
|
|
cluster.subnetwork = options.subnetwork
|
|
if options.addons:
|
|
addons = self._AddonsConfig(
|
|
disable_ingress=not options.addons.get(INGRESS, False)
|
|
and not options.autopilot,
|
|
disable_hpa=not options.addons.get(HPA, False)
|
|
and not options.autopilot,
|
|
disable_dashboard=not options.addons.get(DASHBOARD, False),
|
|
disable_network_policy=not options.addons.get(NETWORK_POLICY, False),
|
|
enable_node_local_dns=options.addons.get(NODELOCALDNS),
|
|
enable_gcepd_csi_driver=options.addons.get(GCEPDCSIDRIVER, False),
|
|
enable_filestore_csi_driver=options.addons.get(
|
|
GCPFILESTORECSIDRIVER, False
|
|
),
|
|
enable_application_manager=options.addons.get(
|
|
APPLICATIONMANAGER, False
|
|
),
|
|
enable_cloud_build=options.addons.get(CLOUDBUILD, False),
|
|
enable_backup_restore=options.addons.get(BACKUPRESTORE, False),
|
|
enable_gcsfuse_csi_driver=options.addons.get(GCSFUSECSIDRIVER, False),
|
|
enable_stateful_ha=options.addons.get(STATEFULHA, False),
|
|
enable_parallelstore_csi_driver=options.addons.get(
|
|
PARALLELSTORECSIDRIVER, False
|
|
),
|
|
enable_high_scale_checkpointing=options.addons.get(
|
|
HIGHSCALECHECKPOINTING, False
|
|
),
|
|
enable_lustre_csi_driver=options.addons.get(LUSTRECSIDRIVER, False),
|
|
enable_ray_operator=options.addons.get(RAYOPERATOR, False),
|
|
)
|
|
# CONFIGCONNECTOR is disabled by default.
|
|
if CONFIGCONNECTOR in options.addons:
|
|
if not options.enable_stackdriver_kubernetes and (
|
|
(
|
|
options.monitoring is not None
|
|
and SYSTEM not in options.monitoring
|
|
)
|
|
or (options.logging is not None and SYSTEM not in options.logging)
|
|
):
|
|
raise util.Error(
|
|
CONFIGCONNECTOR_STACKDRIVER_KUBERNETES_DISABLED_ERROR_MSG
|
|
)
|
|
if options.workload_pool is None:
|
|
raise util.Error(CONFIGCONNECTOR_WORKLOAD_IDENTITY_DISABLED_ERROR_MSG)
|
|
addons.configConnectorConfig = self.messages.ConfigConnectorConfig(
|
|
enabled=True
|
|
)
|
|
if options.enable_ray_cluster_logging is not None:
|
|
addons.rayOperatorConfig.rayClusterLoggingConfig = (
|
|
self.messages.RayClusterLoggingConfig(
|
|
enabled=options.enable_ray_cluster_logging
|
|
)
|
|
)
|
|
if options.enable_ray_cluster_monitoring is not None:
|
|
addons.rayOperatorConfig.rayClusterMonitoringConfig = (
|
|
self.messages.RayClusterMonitoringConfig(
|
|
enabled=options.enable_ray_cluster_monitoring
|
|
)
|
|
)
|
|
if options.enable_legacy_lustre_port is not None:
|
|
addons.lustreCsiDriverConfig.enableLegacyLustrePort = (
|
|
options.enable_legacy_lustre_port
|
|
)
|
|
|
|
if options.disable_multi_nic_lustre is not None:
|
|
addons.lustreCsiDriverConfig.disableMultiNic = (
|
|
options.disable_multi_nic_lustre
|
|
)
|
|
|
|
cluster.addonsConfig = addons
|
|
|
|
if options.enable_pod_snapshots is not None:
|
|
if cluster.addonsConfig is None:
|
|
cluster.addonsConfig = self._AddonsConfig()
|
|
cluster.addonsConfig.podSnapshotConfig = self.messages.PodSnapshotConfig(
|
|
enabled=options.enable_pod_snapshots
|
|
)
|
|
|
|
if options.enable_slice_controller is not None:
|
|
if cluster.addonsConfig is None:
|
|
cluster.addonsConfig = self._AddonsConfig()
|
|
cluster.addonsConfig.sliceControllerConfig = (
|
|
self.messages.SliceControllerConfig(
|
|
enabled=options.enable_slice_controller
|
|
)
|
|
)
|
|
|
|
if options.enable_kubernetes_alpha:
|
|
cluster.enableKubernetesAlpha = options.enable_kubernetes_alpha
|
|
|
|
if options.alpha_cluster_feature_gates:
|
|
if not options.enable_kubernetes_alpha:
|
|
raise util.Error(
|
|
ALPHA_CLUSTER_FEATURE_GATES_WITHOUT_ENABLE_KUBERNETES_ALPHA_ERROR_MSG
|
|
)
|
|
cluster.alphaClusterFeatureGates = options.alpha_cluster_feature_gates
|
|
else:
|
|
cluster.alphaClusterFeatureGates = []
|
|
|
|
if options.default_max_pods_per_node is not None:
|
|
if not options.enable_ip_alias:
|
|
raise util.Error(DEFAULT_MAX_PODS_PER_NODE_WITHOUT_IP_ALIAS_ERROR_MSG)
|
|
cluster.defaultMaxPodsConstraint = self.messages.MaxPodsConstraint(
|
|
maxPodsPerNode=options.default_max_pods_per_node
|
|
)
|
|
|
|
if options.disable_default_snat:
|
|
if not options.enable_ip_alias:
|
|
raise util.Error(DISABLE_DEFAULT_SNAT_WITHOUT_IP_ALIAS_ERROR_MSG)
|
|
if not options.enable_private_nodes:
|
|
raise util.Error(DISABLE_DEFAULT_SNAT_WITHOUT_PRIVATE_NODES_ERROR_MSG)
|
|
default_snat_status = self.messages.DefaultSnatStatus(
|
|
disabled=options.disable_default_snat
|
|
)
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig(
|
|
defaultSnatStatus=default_snat_status
|
|
)
|
|
else:
|
|
cluster.networkConfig.defaultSnatStatus = default_snat_status
|
|
|
|
if options.dataplane_v2 is not None and options.dataplane_v2:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig()
|
|
cluster.networkConfig.datapathProvider = (
|
|
self.messages.NetworkConfig.DatapathProviderValueValuesEnum.ADVANCED_DATAPATH
|
|
)
|
|
|
|
if options.enable_l4_ilb_subsetting:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig(
|
|
enableL4ilbSubsetting=options.enable_l4_ilb_subsetting
|
|
)
|
|
else:
|
|
cluster.networkConfig.enableL4ilbSubsetting = (
|
|
options.enable_l4_ilb_subsetting
|
|
)
|
|
|
|
dns_config = self.ParseClusterDNSOptions(options)
|
|
if dns_config is not None:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig(
|
|
dnsConfig=dns_config
|
|
)
|
|
else:
|
|
cluster.networkConfig.dnsConfig = dns_config
|
|
|
|
gateway_config = self.ParseGatewayOptions(options)
|
|
if gateway_config is not None:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig(
|
|
gatewayApiConfig=gateway_config
|
|
)
|
|
else:
|
|
cluster.networkConfig.gatewayApiConfig = gateway_config
|
|
|
|
if options.enable_legacy_authorization is not None:
|
|
cluster.legacyAbac = self.messages.LegacyAbac(
|
|
enabled=bool(options.enable_legacy_authorization)
|
|
)
|
|
|
|
# Only Calico is currently supported as a network policy provider.
|
|
if options.enable_network_policy:
|
|
cluster.networkPolicy = self.messages.NetworkPolicy(
|
|
enabled=options.enable_network_policy,
|
|
provider=self.messages.NetworkPolicy.ProviderValueValuesEnum.CALICO,
|
|
)
|
|
|
|
if options.enable_binauthz is not None:
|
|
cluster.binaryAuthorization = self.messages.BinaryAuthorization(
|
|
enabled=options.enable_binauthz
|
|
)
|
|
|
|
if options.binauthz_evaluation_mode is not None:
|
|
if options.binauthz_policy_bindings is not None:
|
|
cluster.binaryAuthorization = self.messages.BinaryAuthorization(
|
|
evaluationMode=util.GetBinauthzEvaluationModeMapper(
|
|
self.messages, hidden=False
|
|
).GetEnumForChoice(options.binauthz_evaluation_mode),
|
|
)
|
|
for binding in options.binauthz_policy_bindings:
|
|
cluster.binaryAuthorization.policyBindings.append(
|
|
self.messages.PolicyBinding(
|
|
name=binding['name'],
|
|
enforcementMode=self.messages.PolicyBinding.EnforcementModeValueValuesEnum( # pylint:disable=g-long-ternary
|
|
binding['enforcement-mode']
|
|
)
|
|
if 'enforcement-mode' in binding
|
|
else None,
|
|
)
|
|
)
|
|
else:
|
|
cluster.binaryAuthorization = self.messages.BinaryAuthorization(
|
|
evaluationMode=util.GetBinauthzEvaluationModeMapper(
|
|
self.messages, hidden=False
|
|
).GetEnumForChoice(options.binauthz_evaluation_mode),
|
|
)
|
|
|
|
# Policy bindings only makes sense in the context of an evaluation mode.
|
|
if (
|
|
options.binauthz_policy_bindings
|
|
and not options.binauthz_evaluation_mode
|
|
):
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='binauthz-evaluation-mode',
|
|
opt='binauthz-policy-bindings',
|
|
)
|
|
)
|
|
|
|
if options.maintenance_window is not None:
|
|
cluster.maintenancePolicy = self.messages.MaintenancePolicy(
|
|
window=self.messages.MaintenanceWindow(
|
|
dailyMaintenanceWindow=self.messages.DailyMaintenanceWindow(
|
|
startTime=options.maintenance_window
|
|
)
|
|
)
|
|
)
|
|
elif options.maintenance_window_start is not None:
|
|
window_start = options.maintenance_window_start.isoformat()
|
|
window_end = options.maintenance_window_end.isoformat()
|
|
cluster.maintenancePolicy = self.messages.MaintenancePolicy(
|
|
window=self.messages.MaintenanceWindow(
|
|
recurringWindow=self.messages.RecurringTimeWindow(
|
|
window=self.messages.TimeWindow(
|
|
startTime=window_start, endTime=window_end
|
|
),
|
|
recurrence=options.maintenance_window_recurrence,
|
|
)
|
|
)
|
|
)
|
|
|
|
self.ParseResourceLabels(options, cluster)
|
|
|
|
if options.enable_pod_security_policy is not None:
|
|
cluster.podSecurityPolicyConfig = self.messages.PodSecurityPolicyConfig(
|
|
enabled=options.enable_pod_security_policy
|
|
)
|
|
if options.patch_update is not None:
|
|
cluster.gkeAutoUpgradeConfig = _GetGkeAutoUpgradeConfig(
|
|
options, self.messages
|
|
)
|
|
|
|
if options.security_group is not None:
|
|
# The presence of the --security_group="foo" flag implies enabled=True.
|
|
cluster.authenticatorGroupsConfig = (
|
|
self.messages.AuthenticatorGroupsConfig(
|
|
enabled=True, securityGroup=options.security_group
|
|
)
|
|
)
|
|
if options.enable_shielded_nodes is not None:
|
|
cluster.shieldedNodes = self.messages.ShieldedNodes(
|
|
enabled=options.enable_shielded_nodes
|
|
)
|
|
|
|
if options.workload_pool:
|
|
cluster.workloadIdentityConfig = self.messages.WorkloadIdentityConfig(
|
|
workloadPool=options.workload_pool
|
|
)
|
|
|
|
is_cluster_ipv6 = (
|
|
options.stack_type
|
|
and options.stack_type.lower() == gke_constants.IPV6_STACK_TYPE
|
|
)
|
|
if not is_cluster_ipv6:
|
|
# IP Alias is a no-op for IPv6-only clusters.
|
|
self.ParseIPAliasOptions(options, cluster)
|
|
|
|
self.ParseAllowRouteOverlapOptions(options, cluster)
|
|
self.ParsePrivateClusterOptions(options, cluster)
|
|
self.ParseTpuOptions(options, cluster)
|
|
if options.enable_vertical_pod_autoscaling is not None:
|
|
cluster.verticalPodAutoscaling = self.messages.VerticalPodAutoscaling(
|
|
enabled=options.enable_vertical_pod_autoscaling
|
|
)
|
|
|
|
if options.resource_usage_bigquery_dataset:
|
|
bigquery_destination = self.messages.BigQueryDestination(
|
|
datasetId=options.resource_usage_bigquery_dataset
|
|
)
|
|
cluster.resourceUsageExportConfig = (
|
|
self.messages.ResourceUsageExportConfig(
|
|
bigqueryDestination=bigquery_destination
|
|
)
|
|
)
|
|
if options.enable_network_egress_metering:
|
|
cluster.resourceUsageExportConfig.enableNetworkEgressMetering = True
|
|
if options.enable_resource_consumption_metering is not None:
|
|
cluster.resourceUsageExportConfig.consumptionMeteringConfig = (
|
|
self.messages.ConsumptionMeteringConfig(
|
|
enabled=options.enable_resource_consumption_metering
|
|
)
|
|
)
|
|
elif options.enable_network_egress_metering is not None:
|
|
raise util.Error(ENABLE_NETWORK_EGRESS_METERING_ERROR_MSG)
|
|
elif options.enable_resource_consumption_metering is not None:
|
|
raise util.Error(ENABLE_RESOURCE_CONSUMPTION_METERING_ERROR_MSG)
|
|
|
|
# Only instantiate the masterAuth struct if one or both of `user` or
|
|
# `issue_client_certificate` is configured. Server-side Basic auth default
|
|
# behavior is dependent on the absence of the MasterAuth struct. For this
|
|
# reason, if only `issue_client_certificate` is configured, Basic auth will
|
|
# be disabled.
|
|
if options.user is not None or options.issue_client_certificate is not None:
|
|
cluster.masterAuth = self.messages.MasterAuth(
|
|
username=options.user, password=options.password
|
|
)
|
|
if options.issue_client_certificate is not None:
|
|
cluster.masterAuth.clientCertificateConfig = (
|
|
self.messages.ClientCertificateConfig(
|
|
issueClientCertificate=options.issue_client_certificate
|
|
)
|
|
)
|
|
|
|
if options.enable_intra_node_visibility is not None:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig(
|
|
enableIntraNodeVisibility=options.enable_intra_node_visibility
|
|
)
|
|
else:
|
|
cluster.networkConfig.enableIntraNodeVisibility = (
|
|
options.enable_intra_node_visibility
|
|
)
|
|
|
|
if options.database_encryption_key:
|
|
cluster.databaseEncryption = self.messages.DatabaseEncryption(
|
|
keyName=options.database_encryption_key,
|
|
state=self.messages.DatabaseEncryption.StateValueValuesEnum.ENCRYPTED,
|
|
)
|
|
|
|
if options.boot_disk_kms_key:
|
|
for pool in cluster.nodePools:
|
|
pool.config.bootDiskKmsKey = options.boot_disk_kms_key
|
|
|
|
cluster.releaseChannel = _GetReleaseChannel(options, self.messages)
|
|
|
|
if options.patch_update is not None:
|
|
cluster.gkeAutoUpgradeConfig = _GetGkeAutoUpgradeConfig(
|
|
options, self.messages
|
|
)
|
|
|
|
if options.autopilot_general_profile:
|
|
autopilot_general_profile_enum = _GetAutopilotGeneralProfileEnum(
|
|
options, self.messages
|
|
)
|
|
if autopilot_general_profile_enum:
|
|
if cluster.autoscaling is None:
|
|
cluster.autoscaling = self.messages.ClusterAutoscaling()
|
|
cluster.autoscaling.autopilotGeneralProfile = (
|
|
autopilot_general_profile_enum
|
|
)
|
|
|
|
if options.autopilot:
|
|
cluster.autopilot = self.messages.Autopilot()
|
|
cluster.autopilot.enabled = options.autopilot
|
|
|
|
if options.enable_secret_manager:
|
|
if cluster.secretManagerConfig is None:
|
|
cluster.secretManagerConfig = self.messages.SecretManagerConfig(
|
|
enabled=False
|
|
)
|
|
|
|
if options.enable_secret_sync:
|
|
if cluster.secretSyncConfig is None:
|
|
cluster.secretSyncConfig = self.messages.SecretSyncConfig(
|
|
enabled=False
|
|
)
|
|
|
|
if options.boot_disk_kms_key:
|
|
if cluster.autoscaling is None:
|
|
cluster.autoscaling = self.messages.ClusterAutoscaling()
|
|
if cluster.autoscaling.autoprovisioningNodePoolDefaults is None:
|
|
cluster.autoscaling.autoprovisioningNodePoolDefaults = (
|
|
self.messages.AutoprovisioningNodePoolDefaults()
|
|
)
|
|
cluster.autoscaling.autoprovisioningNodePoolDefaults.bootDiskKmsKey = (
|
|
options.boot_disk_kms_key
|
|
)
|
|
|
|
if options.workload_policies:
|
|
if cluster.autopilot is None:
|
|
cluster.autopilot = self.messages.Autopilot()
|
|
cluster.autopilot.enabled = False
|
|
if cluster.autopilot.workloadPolicyConfig is None:
|
|
cluster.autopilot.workloadPolicyConfig = (
|
|
self.messages.WorkloadPolicyConfig()
|
|
)
|
|
if options.workload_policies == 'allow-net-admin':
|
|
cluster.autopilot.workloadPolicyConfig.allowNetAdmin = True
|
|
|
|
if options.enable_confidential_nodes:
|
|
cluster.confidentialNodes = self.messages.ConfidentialNodes(
|
|
enabled=options.enable_confidential_nodes
|
|
)
|
|
|
|
if options.confidential_node_type is not None:
|
|
cluster.confidentialNodes = self.messages.ConfidentialNodes(
|
|
enabled=options.enable_confidential_nodes,
|
|
confidentialInstanceType=_ConfidentialNodeTypeEnumFromString(
|
|
options, self.messages
|
|
),
|
|
)
|
|
|
|
if options.private_ipv6_google_access_type is not None:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig()
|
|
cluster.networkConfig.privateIpv6GoogleAccess = (
|
|
util.GetPrivateIpv6GoogleAccessTypeMapper(
|
|
self.messages, hidden=False
|
|
).GetEnumForChoice(options.private_ipv6_google_access_type)
|
|
)
|
|
|
|
# Apply node kubelet config on non-autopilot clusters.
|
|
if options.enable_insecure_kubelet_readonly_port is not None:
|
|
if options.autopilot:
|
|
raise util.Error(NODECONFIGDEFAULTS_READONLY_PORT_NOT_SUPPORTED)
|
|
|
|
if cluster.nodePoolDefaults is None:
|
|
cluster.nodePoolDefaults = self.messages.NodePoolDefaults()
|
|
|
|
if cluster.nodePoolDefaults.nodeConfigDefaults is None:
|
|
cluster.nodePoolDefaults.nodeConfigDefaults = (
|
|
self.messages.NodeConfigDefaults()
|
|
)
|
|
|
|
if cluster.nodePoolDefaults.nodeConfigDefaults.nodeKubeletConfig is None:
|
|
cluster.nodePoolDefaults.nodeConfigDefaults.nodeKubeletConfig = (
|
|
self.messages.NodeKubeletConfig()
|
|
)
|
|
|
|
cluster.nodePoolDefaults.nodeConfigDefaults.nodeKubeletConfig.insecureKubeletReadonlyPortEnabled = (
|
|
options.enable_insecure_kubelet_readonly_port
|
|
)
|
|
|
|
# Apply nodePoolAutoconfig on both autopilot and standard clusters.
|
|
# pylint: disable=line-too-long
|
|
if (
|
|
options.autoprovisioning_enable_insecure_kubelet_readonly_port
|
|
is not None
|
|
):
|
|
if cluster.nodePoolAutoConfig is None:
|
|
cluster.nodePoolAutoConfig = self.messages.NodePoolAutoConfig()
|
|
|
|
if cluster.nodePoolAutoConfig.nodeKubeletConfig is None:
|
|
cluster.nodePoolAutoConfig.nodeKubeletConfig = (
|
|
self.messages.NodeKubeletConfig()
|
|
)
|
|
|
|
cluster.nodePoolAutoConfig.nodeKubeletConfig.insecureKubeletReadonlyPortEnabled = (
|
|
options.autoprovisioning_enable_insecure_kubelet_readonly_port
|
|
)
|
|
|
|
if options.enable_gcfs:
|
|
if cluster.nodePoolDefaults is None:
|
|
cluster.nodePoolDefaults = self.messages.NodePoolDefaults()
|
|
if cluster.nodePoolDefaults.nodeConfigDefaults is None:
|
|
cluster.nodePoolDefaults.nodeConfigDefaults = (
|
|
self.messages.NodeConfigDefaults()
|
|
)
|
|
cluster.nodePoolDefaults.nodeConfigDefaults.gcfsConfig = (
|
|
self.messages.GcfsConfig(enabled=options.enable_gcfs)
|
|
)
|
|
|
|
if options.containerd_config_from_file is not None:
|
|
if cluster.nodePoolDefaults is None:
|
|
cluster.nodePoolDefaults = self.messages.NodePoolDefaults()
|
|
if cluster.nodePoolDefaults.nodeConfigDefaults is None:
|
|
cluster.nodePoolDefaults.nodeConfigDefaults = (
|
|
self.messages.NodeConfigDefaults()
|
|
)
|
|
cluster.nodePoolDefaults.nodeConfigDefaults.containerdConfig = (
|
|
self.messages.ContainerdConfig()
|
|
)
|
|
util.LoadContainerdConfigFromYAML(
|
|
cluster.nodePoolDefaults.nodeConfigDefaults.containerdConfig,
|
|
options.containerd_config_from_file,
|
|
self.messages,
|
|
)
|
|
|
|
if options.autoprovisioning_network_tags:
|
|
if cluster.nodePoolAutoConfig is None:
|
|
cluster.nodePoolAutoConfig = self.messages.NodePoolAutoConfig()
|
|
cluster.nodePoolAutoConfig.networkTags = self.messages.NetworkTags(
|
|
tags=options.autoprovisioning_network_tags
|
|
)
|
|
|
|
if options.autoprovisioning_resource_manager_tags is not None:
|
|
if cluster.nodePoolAutoConfig is None:
|
|
cluster.nodePoolAutoConfig = self.messages.NodePoolAutoConfig()
|
|
rm_tags = self._ResourceManagerTags(
|
|
options.autoprovisioning_resource_manager_tags
|
|
)
|
|
cluster.nodePoolAutoConfig.resourceManagerTags = rm_tags
|
|
|
|
if options.enable_image_streaming:
|
|
if cluster.nodePoolDefaults is None:
|
|
cluster.nodePoolDefaults = self.messages.NodePoolDefaults()
|
|
if cluster.nodePoolDefaults.nodeConfigDefaults is None:
|
|
cluster.nodePoolDefaults.nodeConfigDefaults = (
|
|
self.messages.NodeConfigDefaults()
|
|
)
|
|
cluster.nodePoolDefaults.nodeConfigDefaults.gcfsConfig = (
|
|
self.messages.GcfsConfig(enabled=options.enable_image_streaming)
|
|
)
|
|
|
|
if options.maintenance_interval:
|
|
if cluster.nodePoolDefaults is None:
|
|
cluster.nodePoolDefaults = self.messages.NodePoolDefaults()
|
|
if cluster.nodePoolDefaults.nodeConfigDefaults is None:
|
|
cluster.nodePoolDefaults.nodeConfigDefaults = (
|
|
self.messages.NodeConfigDefaults()
|
|
)
|
|
cluster.nodePoolDefaults.nodeConfigDefaults.stableFleetConfig = (
|
|
_GetStableFleetConfig(options, self.messages)
|
|
)
|
|
|
|
if options.enable_mesh_certificates:
|
|
if not options.workload_pool:
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='workload-pool', opt='enable-mesh-certificates'
|
|
)
|
|
)
|
|
if cluster.meshCertificates is None:
|
|
cluster.meshCertificates = self.messages.MeshCertificates()
|
|
cluster.meshCertificates.enableCertificates = (
|
|
options.enable_mesh_certificates
|
|
)
|
|
|
|
_AddNotificationConfigToCluster(cluster, options, self.messages)
|
|
|
|
cluster.loggingConfig = _GetLoggingConfig(options, self.messages)
|
|
cluster.monitoringConfig = _GetMonitoringConfig(
|
|
options, self.messages, False, None
|
|
)
|
|
if options.managed_otel_scope:
|
|
cluster.managedOpentelemetryConfig = _GetManagedOpenTelemetryConfig(
|
|
options, self.messages
|
|
)
|
|
|
|
if options.enable_service_externalips is not None:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig()
|
|
cluster.networkConfig.serviceExternalIpsConfig = (
|
|
self.messages.ServiceExternalIPsConfig(
|
|
enabled=options.enable_service_externalips
|
|
)
|
|
)
|
|
|
|
if options.enable_identity_service:
|
|
cluster.identityServiceConfig = self.messages.IdentityServiceConfig(
|
|
enabled=options.enable_identity_service
|
|
)
|
|
|
|
if options.enable_workload_config_audit is not None:
|
|
if cluster.protectConfig is None:
|
|
cluster.protectConfig = self.messages.ProtectConfig(
|
|
workloadConfig=self.messages.WorkloadConfig()
|
|
)
|
|
if options.enable_workload_config_audit:
|
|
cluster.protectConfig.workloadConfig.auditMode = (
|
|
self.messages.WorkloadConfig.AuditModeValueValuesEnum.BASIC
|
|
)
|
|
else:
|
|
cluster.protectConfig.workloadConfig.auditMode = (
|
|
self.messages.WorkloadConfig.AuditModeValueValuesEnum.DISABLED
|
|
)
|
|
|
|
if options.enable_workload_vulnerability_scanning is not None:
|
|
if cluster.protectConfig is None:
|
|
cluster.protectConfig = self.messages.ProtectConfig()
|
|
if options.enable_workload_vulnerability_scanning:
|
|
cluster.protectConfig.workloadVulnerabilityMode = (
|
|
self.messages.ProtectConfig.WorkloadVulnerabilityModeValueValuesEnum.BASIC
|
|
)
|
|
else:
|
|
cluster.protectConfig.workloadVulnerabilityMode = (
|
|
self.messages.ProtectConfig.WorkloadVulnerabilityModeValueValuesEnum.DISABLED
|
|
)
|
|
|
|
if options.hpa_profile is not None:
|
|
if cluster.podAutoscaling is None:
|
|
cluster.podAutoscaling = self.messages.PodAutoscaling()
|
|
if options.hpa_profile.lower() == 'performance':
|
|
cluster.podAutoscaling.hpaProfile = (
|
|
self.messages.PodAutoscaling.HpaProfileValueValuesEnum.PERFORMANCE
|
|
)
|
|
elif options.hpa_profile.lower() == 'none':
|
|
cluster.podAutoscaling.hpaProfile = (
|
|
self.messages.PodAutoscaling.HpaProfileValueValuesEnum.NONE
|
|
)
|
|
|
|
if options.managed_config is not None:
|
|
if options.managed_config.lower() == 'autofleet':
|
|
cluster.managedConfig = self.messages.ManagedConfig(
|
|
type=self.messages.ManagedConfig.TypeValueValuesEnum.AUTOFLEET
|
|
)
|
|
elif options.managed_config.lower() == 'disabled':
|
|
cluster.managedConfig = self.messages.ManagedConfig(
|
|
type=self.messages.ManagedConfig.TypeValueValuesEnum.DISABLED
|
|
)
|
|
else:
|
|
raise util.Error(
|
|
MANGED_CONFIG_TYPE_NOT_SUPPORTED.format(type=options.managed_config)
|
|
)
|
|
|
|
if options.enable_fleet:
|
|
if cluster.fleet is None:
|
|
cluster.fleet = self.messages.Fleet()
|
|
cluster.fleet.project = cluster_ref.projectId
|
|
if options.membership_type is not None:
|
|
cluster.fleet = _GetFleetMembershipType(
|
|
options, self.messages, cluster.fleet
|
|
)
|
|
|
|
if options.fleet_project:
|
|
if cluster.fleet is None:
|
|
cluster.fleet = self.messages.Fleet()
|
|
cluster.fleet.project = options.fleet_project
|
|
if options.membership_type is not None:
|
|
cluster.fleet = _GetFleetMembershipType(
|
|
options, self.messages, cluster.fleet
|
|
)
|
|
|
|
if options.logging_variant is not None:
|
|
if cluster.nodePoolDefaults is None:
|
|
cluster.nodePoolDefaults = self.messages.NodePoolDefaults()
|
|
if cluster.nodePoolDefaults.nodeConfigDefaults is None:
|
|
cluster.nodePoolDefaults.nodeConfigDefaults = (
|
|
self.messages.NodeConfigDefaults()
|
|
)
|
|
if cluster.nodePoolDefaults.nodeConfigDefaults.loggingConfig is None:
|
|
cluster.nodePoolDefaults.nodeConfigDefaults.loggingConfig = (
|
|
self.messages.NodePoolLoggingConfig()
|
|
)
|
|
cluster.nodePoolDefaults.nodeConfigDefaults.loggingConfig.variantConfig = self.messages.LoggingVariantConfig(
|
|
variant=VariantConfigEnumFromString(
|
|
self.messages, options.logging_variant
|
|
)
|
|
)
|
|
|
|
if options.enable_cost_allocation:
|
|
cluster.costManagementConfig = self.messages.CostManagementConfig(
|
|
enabled=True
|
|
)
|
|
|
|
if options.enable_multi_networking:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig(
|
|
enableMultiNetworking=options.enable_multi_networking
|
|
)
|
|
else:
|
|
cluster.networkConfig.enableMultiNetworking = (
|
|
options.enable_multi_networking
|
|
)
|
|
|
|
if options.compliance is not None:
|
|
if cluster.compliancePostureConfig is None:
|
|
cluster.compliancePostureConfig = (
|
|
self.messages.CompliancePostureConfig()
|
|
)
|
|
if options.compliance.lower() == 'enabled':
|
|
cluster.compliancePostureConfig.mode = (
|
|
self.messages.CompliancePostureConfig.ModeValueValuesEnum.ENABLED
|
|
)
|
|
elif options.compliance.lower() == 'disabled':
|
|
cluster.compliancePostureConfig.mode = (
|
|
self.messages.CompliancePostureConfig.ModeValueValuesEnum.DISABLED
|
|
)
|
|
else:
|
|
raise util.Error(
|
|
COMPLIANCE_MODE_NOT_SUPPORTED.format(
|
|
mode=options.compliance.lower()
|
|
)
|
|
)
|
|
|
|
if options.compliance_standards is not None:
|
|
# --compliance=disabled and --compliance-standards=a,b,c are mutually
|
|
# exclusive.
|
|
if (
|
|
options.compliance is not None
|
|
and options.compliance.lower() == 'disabled'
|
|
):
|
|
raise util.Error(COMPLIANCE_DISABLED_CONFIGURATION)
|
|
|
|
if options.compliance is None:
|
|
cluster.compliancePostureConfig = (
|
|
self.messages.CompliancePostureConfig()
|
|
)
|
|
|
|
cluster.compliancePostureConfig.complianceStandards = [
|
|
self.messages.ComplianceStandard(standard=standard)
|
|
for standard in options.compliance_standards.split(',')
|
|
]
|
|
|
|
if options.enable_security_posture is not None:
|
|
if cluster.securityPostureConfig is None:
|
|
cluster.securityPostureConfig = self.messages.SecurityPostureConfig()
|
|
if options.enable_security_posture:
|
|
cluster.securityPostureConfig.mode = (
|
|
self.messages.SecurityPostureConfig.ModeValueValuesEnum.BASIC
|
|
)
|
|
else:
|
|
cluster.securityPostureConfig.mode = (
|
|
self.messages.SecurityPostureConfig.ModeValueValuesEnum.DISABLED
|
|
)
|
|
|
|
if options.security_posture is not None:
|
|
if cluster.securityPostureConfig is None:
|
|
cluster.securityPostureConfig = self.messages.SecurityPostureConfig()
|
|
if options.security_posture.lower() == 'enterprise':
|
|
cluster.securityPostureConfig.mode = (
|
|
self.messages.SecurityPostureConfig.ModeValueValuesEnum.ENTERPRISE
|
|
)
|
|
elif options.security_posture.lower() == 'standard':
|
|
cluster.securityPostureConfig.mode = (
|
|
self.messages.SecurityPostureConfig.ModeValueValuesEnum.BASIC
|
|
)
|
|
elif options.security_posture.lower() == 'disabled':
|
|
cluster.securityPostureConfig.mode = (
|
|
self.messages.SecurityPostureConfig.ModeValueValuesEnum.DISABLED
|
|
)
|
|
else:
|
|
raise util.Error(
|
|
SECURITY_POSTURE_MODE_NOT_SUPPORTED.format(
|
|
mode=options.security_posture.lower()
|
|
)
|
|
)
|
|
|
|
if options.workload_vulnerability_scanning is not None:
|
|
if cluster.securityPostureConfig is None:
|
|
cluster.securityPostureConfig = self.messages.SecurityPostureConfig()
|
|
if options.workload_vulnerability_scanning.lower() == 'standard':
|
|
cluster.securityPostureConfig.vulnerabilityMode = (
|
|
self.messages.SecurityPostureConfig.VulnerabilityModeValueValuesEnum.VULNERABILITY_BASIC
|
|
)
|
|
elif options.workload_vulnerability_scanning.lower() == 'disabled':
|
|
cluster.securityPostureConfig.vulnerabilityMode = (
|
|
self.messages.SecurityPostureConfig.VulnerabilityModeValueValuesEnum.VULNERABILITY_DISABLED
|
|
)
|
|
elif options.workload_vulnerability_scanning.lower() == 'enterprise':
|
|
cluster.securityPostureConfig.vulnerabilityMode = (
|
|
self.messages.SecurityPostureConfig.VulnerabilityModeValueValuesEnum.VULNERABILITY_ENTERPRISE
|
|
)
|
|
else:
|
|
raise util.Error(
|
|
WORKLOAD_VULNERABILITY_SCANNING_MODE_NOT_SUPPORTED.format(
|
|
mode=options.workload_vulnerability_scanning.lower()
|
|
)
|
|
)
|
|
|
|
if options.enable_runtime_vulnerability_insight is not None:
|
|
if cluster.runtimeVulnerabilityInsightConfig is None:
|
|
cluster.runtimeVulnerabilityInsightConfig = (
|
|
self.messages.RuntimeVulnerabilityInsightConfig()
|
|
)
|
|
if options.enable_runtime_vulnerability_insight:
|
|
cluster.runtimeVulnerabilityInsightConfig.mode = (
|
|
self.messages.RuntimeVulnerabilityInsightConfig.ModeValueValuesEnum.PREMIUM_VULNERABILITY_SCAN
|
|
)
|
|
else:
|
|
cluster.runtimeVulnerabilityInsightConfig.mode = (
|
|
self.messages.RuntimeVulnerabilityInsightConfig.ModeValueValuesEnum.DISABLED
|
|
)
|
|
|
|
if options.network_performance_config:
|
|
perf = self._GetClusterNetworkPerformanceConfig(options)
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig(
|
|
networkPerformanceConfig=perf
|
|
)
|
|
else:
|
|
cluster.networkConfig.networkPerformanceConfig = perf
|
|
|
|
if options.enable_k8s_beta_apis:
|
|
cluster.enableK8sBetaApis = self.messages.K8sBetaAPIConfig()
|
|
cluster.enableK8sBetaApis.enabledApis = options.enable_k8s_beta_apis
|
|
|
|
if options.host_maintenance_interval:
|
|
if cluster.nodePoolDefaults is None:
|
|
cluster.nodePoolDefaults = self.messages.NodePoolDefaults()
|
|
if cluster.nodePoolDefaults.nodeConfigDefaults is None:
|
|
cluster.nodePoolDefaults.nodeConfigDefaults = (
|
|
self.messages.NodeConfigDefaults()
|
|
)
|
|
cluster.nodePoolDefaults.nodeConfigDefaults.hostMaintenancePolicy = (
|
|
_GetHostMaintenancePolicy(options, self.messages, CLUSTER)
|
|
)
|
|
|
|
if options.in_transit_encryption is not None:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig()
|
|
cluster.networkConfig.inTransitEncryptionConfig = (
|
|
util.GetCreateInTransitEncryptionConfigMapper(
|
|
self.messages
|
|
).GetEnumForChoice(options.in_transit_encryption)
|
|
)
|
|
|
|
if options.enable_secret_manager is not None:
|
|
if cluster.secretManagerConfig is None:
|
|
cluster.secretManagerConfig = self.messages.SecretManagerConfig()
|
|
cluster.secretManagerConfig.enabled = options.enable_secret_manager
|
|
if options.enable_secret_manager_rotation is not None:
|
|
if cluster.secretManagerConfig is None:
|
|
cluster.secretManagerConfig = self.messages.SecretManagerConfig()
|
|
if cluster.secretManagerConfig.rotationConfig is None:
|
|
cluster.secretManagerConfig.rotationConfig = (
|
|
self.messages.RotationConfig()
|
|
)
|
|
cluster.secretManagerConfig.rotationConfig.enabled = (
|
|
options.enable_secret_manager_rotation
|
|
)
|
|
if options.secret_manager_rotation_interval is not None:
|
|
if cluster.secretManagerConfig is None:
|
|
cluster.secretManagerConfig = self.messages.SecretManagerConfig()
|
|
if cluster.secretManagerConfig.rotationConfig is None:
|
|
cluster.secretManagerConfig.rotationConfig = (
|
|
self.messages.RotationConfig()
|
|
)
|
|
cluster.secretManagerConfig.rotationConfig.rotationInterval = (
|
|
options.secret_manager_rotation_interval
|
|
)
|
|
|
|
if options.enable_secret_sync is not None:
|
|
if cluster.secretSyncConfig is None:
|
|
cluster.secretSyncConfig = self.messages.SecretSyncConfig()
|
|
cluster.secretSyncConfig.enabled = options.enable_secret_sync
|
|
if options.enable_secret_sync_rotation is not None:
|
|
if cluster.secretSyncConfig is None:
|
|
cluster.secretSyncConfig = self.messages.SecretSyncConfig()
|
|
if cluster.secretSyncConfig.rotationConfig is None:
|
|
cluster.secretSyncConfig.rotationConfig = (
|
|
self.messages.SyncRotationConfig()
|
|
)
|
|
cluster.secretSyncConfig.rotationConfig.enabled = (
|
|
options.enable_secret_sync_rotation
|
|
)
|
|
if options.secret_sync_rotation_interval is not None:
|
|
if cluster.secretSyncConfig is None:
|
|
cluster.secretSyncConfig = self.messages.SecretSyncConfig()
|
|
if cluster.secretSyncConfig.rotationConfig is None:
|
|
cluster.secretSyncConfig.rotationConfig = (
|
|
self.messages.SyncRotationConfig()
|
|
)
|
|
cluster.secretSyncConfig.rotationConfig.rotationInterval = (
|
|
options.secret_sync_rotation_interval
|
|
)
|
|
|
|
if options.enable_cilium_clusterwide_network_policy is not None:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig()
|
|
cluster.networkConfig.enableCiliumClusterwideNetworkPolicy = (
|
|
options.enable_cilium_clusterwide_network_policy
|
|
)
|
|
|
|
if options.enable_fqdn_network_policy is not None:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig()
|
|
cluster.networkConfig.enableFqdnNetworkPolicy = (
|
|
options.enable_fqdn_network_policy
|
|
)
|
|
|
|
if options.enable_insecure_binding_system_authenticated is not None:
|
|
if cluster.rbacBindingConfig is None:
|
|
cluster.rbacBindingConfig = self.messages.RBACBindingConfig()
|
|
cluster.rbacBindingConfig.enableInsecureBindingSystemAuthenticated = (
|
|
options.enable_insecure_binding_system_authenticated
|
|
)
|
|
|
|
if options.enable_insecure_binding_system_unauthenticated is not None:
|
|
if cluster.rbacBindingConfig is None:
|
|
cluster.rbacBindingConfig = self.messages.RBACBindingConfig()
|
|
cluster.rbacBindingConfig.enableInsecureBindingSystemUnauthenticated = (
|
|
options.enable_insecure_binding_system_unauthenticated
|
|
)
|
|
|
|
if options.autopilot_privileged_admission is not None:
|
|
if cluster.autopilot is None:
|
|
cluster.autopilot = self.messages.Autopilot()
|
|
cluster.autopilot.enabled = False
|
|
if cluster.autopilot.privilegedAdmissionConfig is None:
|
|
cluster.autopilot.privilegedAdmissionConfig = self.messages.PrivilegedAdmissionConfig(
|
|
# Permit either the flag array value or, if the array is empty,
|
|
# set to the actual empty value of [""] (allow nothing).
|
|
allowlistPaths=options.autopilot_privileged_admission
|
|
or ['']
|
|
)
|
|
if options.cluster_ca is not None:
|
|
if cluster.userManagedKeysConfig is None:
|
|
cluster.userManagedKeysConfig = self.messages.UserManagedKeysConfig()
|
|
cluster.userManagedKeysConfig.clusterCa = options.cluster_ca
|
|
if options.aggregation_ca is not None:
|
|
if cluster.userManagedKeysConfig is None:
|
|
cluster.userManagedKeysConfig = self.messages.UserManagedKeysConfig()
|
|
cluster.userManagedKeysConfig.aggregationCa = options.aggregation_ca
|
|
if options.etcd_peer_ca is not None:
|
|
if cluster.userManagedKeysConfig is None:
|
|
cluster.userManagedKeysConfig = self.messages.UserManagedKeysConfig()
|
|
cluster.userManagedKeysConfig.etcdPeerCa = options.etcd_peer_ca
|
|
if options.etcd_api_ca is not None:
|
|
if cluster.userManagedKeysConfig is None:
|
|
cluster.userManagedKeysConfig = self.messages.UserManagedKeysConfig()
|
|
cluster.userManagedKeysConfig.etcdApiCa = options.etcd_api_ca
|
|
if options.service_account_verification_keys is not None:
|
|
if cluster.userManagedKeysConfig is None:
|
|
cluster.userManagedKeysConfig = self.messages.UserManagedKeysConfig()
|
|
cluster.userManagedKeysConfig.serviceAccountVerificationKeys.extend(
|
|
options.service_account_verification_keys
|
|
)
|
|
if options.service_account_signing_keys is not None:
|
|
if cluster.userManagedKeysConfig is None:
|
|
cluster.userManagedKeysConfig = self.messages.UserManagedKeysConfig()
|
|
cluster.userManagedKeysConfig.serviceAccountSigningKeys.extend(
|
|
options.service_account_signing_keys
|
|
)
|
|
if options.control_plane_disk_encryption_key is not None:
|
|
if cluster.userManagedKeysConfig is None:
|
|
cluster.userManagedKeysConfig = self.messages.UserManagedKeysConfig()
|
|
cluster.userManagedKeysConfig.controlPlaneDiskEncryptionKey = (
|
|
options.control_plane_disk_encryption_key
|
|
)
|
|
if options.gkeops_etcd_backup_encryption_key is not None:
|
|
if cluster.userManagedKeysConfig is None:
|
|
cluster.userManagedKeysConfig = self.messages.UserManagedKeysConfig()
|
|
cluster.userManagedKeysConfig.gkeopsEtcdBackupEncryptionKey = (
|
|
options.gkeops_etcd_backup_encryption_key
|
|
)
|
|
if options.disable_l4_lb_firewall_reconciliation is not None:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig()
|
|
cluster.networkConfig.disableL4LbFirewallReconciliation = (
|
|
options.disable_l4_lb_firewall_reconciliation
|
|
)
|
|
|
|
if options.tier is not None:
|
|
cluster.enterpriseConfig = _GetEnterpriseConfig(options, self.messages)
|
|
|
|
self._ParseControlPlaneEndpointsConfig(options, cluster)
|
|
|
|
if options.enable_private_nodes is not None:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig()
|
|
cluster.networkConfig.defaultEnablePrivateNodes = (
|
|
options.enable_private_nodes
|
|
)
|
|
|
|
if options.anonymous_authentication_config is not None:
|
|
cluster.anonymousAuthenticationConfig = _GetAnonymousAuthenticationConfig(
|
|
options, self.messages
|
|
)
|
|
|
|
if options.enable_auto_ipam is not None:
|
|
if cluster.ipAllocationPolicy is None:
|
|
cluster.ipAllocationPolicy = self.messages.IPAllocationPolicy()
|
|
cluster.ipAllocationPolicy.autoIpamConfig = self.messages.AutoIpamConfig(
|
|
enabled=True
|
|
)
|
|
|
|
if options.network_tier is not None:
|
|
if cluster.ipAllocationPolicy is None:
|
|
cluster.ipAllocationPolicy = self.messages.IPAllocationPolicy()
|
|
cluster.ipAllocationPolicy.networkTierConfig = _GetNetworkTierConfig(
|
|
options, self.messages
|
|
)
|
|
|
|
if options.control_plane_egress_mode is not None:
|
|
if cluster.controlPlaneEgress is None:
|
|
cluster.controlPlaneEgress = self.messages.ControlPlaneEgress()
|
|
cluster.controlPlaneEgress = _GetControlPlaneEgress(
|
|
options, self.messages
|
|
)
|
|
|
|
if options.enable_kernel_module_signature_enforcement is not None:
|
|
if options.autopilot:
|
|
if cluster.nodePoolAutoConfig is None:
|
|
cluster.nodePoolAutoConfig = self.messages.NodePoolAutoConfig()
|
|
_AddKernelModuleSignatureEnforcementToNodeConfig(
|
|
cluster.nodePoolAutoConfig, options, self.messages
|
|
)
|
|
|
|
return cluster
|
|
|
|
def _GetClusterNetworkPerformanceConfig(self, options):
|
|
network_perf_args = options.network_performance_config
|
|
network_perf_configs = self.messages.ClusterNetworkPerformanceConfig()
|
|
|
|
for config in network_perf_args:
|
|
total_tier = config.get('total-egress-bandwidth-tier', '').upper()
|
|
if total_tier:
|
|
network_perf_configs.totalEgressBandwidthTier = self.messages.ClusterNetworkPerformanceConfig.TotalEgressBandwidthTierValueValuesEnum(
|
|
total_tier
|
|
)
|
|
|
|
return network_perf_configs
|
|
|
|
def ParseNodeConfig(self, options):
|
|
"""Creates node config based on node config options."""
|
|
node_config = self.messages.NodeConfig()
|
|
if options.node_machine_type:
|
|
node_config.machineType = options.node_machine_type
|
|
if options.node_disk_size_gb:
|
|
node_config.diskSizeGb = options.node_disk_size_gb
|
|
if options.disk_type:
|
|
node_config.diskType = options.disk_type
|
|
if options.node_source_image:
|
|
raise util.Error('cannot specify node source image in container v1 api')
|
|
if (
|
|
options.boot_disk_provisioned_iops
|
|
or options.boot_disk_provisioned_throughput
|
|
):
|
|
node_config.bootDisk = self.ParseBootDiskConfig(options)
|
|
|
|
NodeIdentityOptionsToNodeConfig(options, node_config)
|
|
|
|
if options.local_ssd_count:
|
|
node_config.localSsdCount = options.local_ssd_count
|
|
self._AddLocalSSDVolumeConfigsToNodeConfig(node_config, options)
|
|
self._AddEphemeralStorageToNodeConfig(node_config, options)
|
|
self._AddEphemeralStorageLocalSsdToNodeConfig(node_config, options)
|
|
self._AddLocalNvmeSsdBlockToNodeConfig(node_config, options)
|
|
self._AddEnableConfidentialStorageToNodeConfig(node_config, options)
|
|
self._AddStoragePoolsToNodeConfig(node_config, options)
|
|
self._AddLocalSsdEncryptionModeToNodeConfig(node_config, options)
|
|
|
|
if options.tags:
|
|
node_config.tags = options.tags
|
|
else:
|
|
node_config.tags = []
|
|
|
|
if options.image_type:
|
|
node_config.imageType = options.image_type
|
|
|
|
self.ParseCustomNodeConfig(options, node_config)
|
|
|
|
_AddNodeLabelsToNodeConfig(node_config, options)
|
|
_AddLabelsToNodeConfig(node_config, options)
|
|
_AddMetadataToNodeConfig(node_config, options)
|
|
self._AddNodeTaintsToNodeConfig(node_config, options)
|
|
|
|
if options.resource_manager_tags is not None:
|
|
tags = options.resource_manager_tags
|
|
node_config.resourceManagerTags = self._ResourceManagerTags(tags)
|
|
|
|
if options.preemptible:
|
|
node_config.preemptible = options.preemptible
|
|
|
|
if options.spot:
|
|
node_config.spot = options.spot
|
|
|
|
self.ParseAcceleratorOptions(options, node_config)
|
|
|
|
if options.min_cpu_platform is not None:
|
|
node_config.minCpuPlatform = options.min_cpu_platform
|
|
|
|
self._AddWorkloadMetadataToNodeConfig(node_config, options, self.messages)
|
|
_AddLinuxNodeConfigToNodeConfig(node_config, options, self.messages)
|
|
_AddShieldedInstanceConfigToNodeConfig(node_config, options, self.messages)
|
|
_AddReservationAffinityToNodeConfig(node_config, options, self.messages)
|
|
|
|
if options.system_config_from_file is not None:
|
|
util.LoadSystemConfigFromYAML(
|
|
node_config,
|
|
options.system_config_from_file,
|
|
options.enable_insecure_kubelet_readonly_port,
|
|
self.messages,
|
|
)
|
|
|
|
if options.enable_insecure_kubelet_readonly_port is None:
|
|
if (
|
|
node_config.kubeletConfig is not None
|
|
and node_config.kubeletConfig.insecureKubeletReadonlyPortEnabled
|
|
is not None
|
|
):
|
|
options.enable_insecure_kubelet_readonly_port = (
|
|
node_config.kubeletConfig.insecureKubeletReadonlyPortEnabled
|
|
)
|
|
|
|
self.ParseAdvancedMachineFeatures(options, node_config)
|
|
|
|
if options.gvnic is not None:
|
|
gvnic = self.messages.VirtualNIC(enabled=options.gvnic)
|
|
node_config.gvnic = gvnic
|
|
|
|
if options.gpudirect_strategy is not None:
|
|
if options.gpudirect_strategy == 'RDMA':
|
|
node_config.gpuDirectConfig = self.messages.GPUDirectConfig(
|
|
gpuDirectStrategy=(
|
|
self.messages.GPUDirectConfig.GpuDirectStrategyValueValuesEnum.RDMA
|
|
)
|
|
)
|
|
elif options.gpudirect_strategy == 'TCPX':
|
|
node_config.gpuDirectConfig = self.messages.GPUDirectConfig(
|
|
gpuDirectStrategy=(
|
|
self.messages.GPUDirectConfig.GpuDirectStrategyValueValuesEnum.TCPX
|
|
)
|
|
)
|
|
|
|
if options.max_run_duration is not None:
|
|
node_config.maxRunDuration = options.max_run_duration
|
|
|
|
if options.consolidation_delay is not None:
|
|
node_config.consolidationDelay = options.consolidation_delay
|
|
|
|
if options.flex_start is not None:
|
|
node_config.flexStart = options.flex_start
|
|
|
|
if options.enable_lustre_multi_nic is not None:
|
|
if node_config.lustreConfig is None:
|
|
node_config.lustreConfig = self.messages.LustreConfig()
|
|
node_config.lustreConfig.multiRail = self.messages.MultiRail(
|
|
enabled=options.enable_lustre_multi_nic
|
|
)
|
|
|
|
return node_config
|
|
|
|
def ParseBootDiskConfig(self, options):
|
|
boot_disk_config = self.messages.BootDisk()
|
|
if options.boot_disk_provisioned_iops:
|
|
boot_disk_config.provisionedIops = options.boot_disk_provisioned_iops
|
|
if options.boot_disk_provisioned_throughput:
|
|
boot_disk_config.provisionedThroughput = (
|
|
options.boot_disk_provisioned_throughput
|
|
)
|
|
return boot_disk_config
|
|
|
|
def ParseAdvancedMachineFeatures(self, options, node_config):
|
|
"""Parses advanced machine feature node config options."""
|
|
features = self.messages.AdvancedMachineFeatures()
|
|
if options.threads_per_core:
|
|
features.threadsPerCore = options.threads_per_core
|
|
if options.enable_nested_virtualization:
|
|
features.enableNestedVirtualization = options.enable_nested_virtualization
|
|
if options.performance_monitoring_unit:
|
|
features.performanceMonitoringUnit = (
|
|
features.PerformanceMonitoringUnitValueValuesEnum(
|
|
options.performance_monitoring_unit.upper()
|
|
)
|
|
)
|
|
|
|
if (
|
|
options.threads_per_core
|
|
or options.enable_nested_virtualization
|
|
or options.performance_monitoring_unit
|
|
):
|
|
node_config.advancedMachineFeatures = features
|
|
|
|
def ParseCustomNodeConfig(self, options, node_config):
|
|
"""Parses custom node config options."""
|
|
custom_config = self.messages.CustomImageConfig()
|
|
if options.image:
|
|
custom_config.image = options.image
|
|
if options.image_project:
|
|
custom_config.imageProject = options.image_project
|
|
if options.image_family:
|
|
custom_config.imageFamily = options.image_family
|
|
if options.image or options.image_project or options.image_family:
|
|
node_config.nodeImageConfig = custom_config
|
|
|
|
def ParseNodePools(self, options, node_config):
|
|
"""Creates a list of node pools for the cluster by parsing options.
|
|
|
|
Args:
|
|
options: cluster creation options
|
|
node_config: node configuration for nodes in the node pools
|
|
|
|
Returns:
|
|
List of node pools.
|
|
"""
|
|
max_nodes_per_pool = (
|
|
options.max_nodes_per_pool or DEFAULT_MAX_NODES_PER_POOL
|
|
)
|
|
pools = (options.num_nodes + max_nodes_per_pool - 1) // max_nodes_per_pool
|
|
if pools == 1:
|
|
pool_names = ['default-pool'] # pool consistency with server default
|
|
else:
|
|
# default-pool-0, -1, ...
|
|
pool_names = ['default-pool-{0}'.format(i) for i in range(0, pools)]
|
|
|
|
pools = []
|
|
per_pool = (options.num_nodes + len(pool_names) - 1) // len(pool_names)
|
|
to_add = options.num_nodes
|
|
for name in pool_names:
|
|
nodes = per_pool if (to_add > per_pool) else to_add
|
|
pool = self.messages.NodePool(
|
|
name=name,
|
|
initialNodeCount=nodes,
|
|
config=node_config,
|
|
version=options.node_version,
|
|
management=self._GetNodeManagement(options),
|
|
)
|
|
if options.enable_autoscaling:
|
|
pool.autoscaling = self.messages.NodePoolAutoscaling(
|
|
enabled=options.enable_autoscaling,
|
|
minNodeCount=options.min_nodes,
|
|
maxNodeCount=options.max_nodes,
|
|
totalMinNodeCount=options.total_min_nodes,
|
|
totalMaxNodeCount=options.total_max_nodes,
|
|
)
|
|
if options.location_policy is not None:
|
|
pool.autoscaling.locationPolicy = LocationPolicyEnumFromString(
|
|
self.messages, options.location_policy
|
|
)
|
|
if options.max_pods_per_node:
|
|
if not options.enable_ip_alias:
|
|
raise util.Error(MAX_PODS_PER_NODE_WITHOUT_IP_ALIAS_ERROR_MSG)
|
|
pool.maxPodsConstraint = self.messages.MaxPodsConstraint(
|
|
maxPodsPerNode=options.max_pods_per_node
|
|
)
|
|
if (
|
|
options.max_surge_upgrade is not None
|
|
or options.max_unavailable_upgrade is not None
|
|
):
|
|
pool.upgradeSettings = self.messages.UpgradeSettings()
|
|
pool.upgradeSettings.maxSurge = options.max_surge_upgrade
|
|
pool.upgradeSettings.maxUnavailable = options.max_unavailable_upgrade
|
|
if (
|
|
options.placement_type == 'COMPACT'
|
|
or options.placement_policy is not None
|
|
):
|
|
pool.placementPolicy = self.messages.PlacementPolicy()
|
|
if options.placement_type == 'COMPACT':
|
|
pool.placementPolicy.type = (
|
|
self.messages.PlacementPolicy.TypeValueValuesEnum.COMPACT
|
|
)
|
|
if options.placement_policy is not None:
|
|
pool.placementPolicy.policyName = options.placement_policy
|
|
if options.enable_queued_provisioning is not None:
|
|
pool.queuedProvisioning = self.messages.QueuedProvisioning()
|
|
pool.queuedProvisioning.enabled = options.enable_queued_provisioning
|
|
pools.append(pool)
|
|
to_add -= nodes
|
|
return pools
|
|
|
|
def ParseAcceleratorOptions(self, options, node_config):
|
|
"""Parses accrelerator options for the nodes in the cluster."""
|
|
if options.accelerators is not None:
|
|
type_name = options.accelerators['type']
|
|
# Accelerator count defaults to 1.
|
|
count = int(options.accelerators.get('count', 1))
|
|
accelerator_config = self.messages.AcceleratorConfig(
|
|
acceleratorType=type_name, acceleratorCount=count
|
|
)
|
|
|
|
gpu_partition_size = options.accelerators.get('gpu-partition-size', '')
|
|
if gpu_partition_size:
|
|
accelerator_config.gpuPartitionSize = gpu_partition_size
|
|
|
|
max_time_shared_clients_per_gpu = int(
|
|
options.accelerators.get('max-time-shared-clients-per-gpu', 0)
|
|
)
|
|
if max_time_shared_clients_per_gpu:
|
|
accelerator_config.maxTimeSharedClientsPerGpu = (
|
|
max_time_shared_clients_per_gpu
|
|
)
|
|
|
|
gpu_sharing_strategy = options.accelerators.get(
|
|
'gpu-sharing-strategy', None
|
|
)
|
|
max_shared_clients_per_gpu = options.accelerators.get(
|
|
'max-shared-clients-per-gpu', None
|
|
)
|
|
if max_shared_clients_per_gpu or gpu_sharing_strategy:
|
|
if max_shared_clients_per_gpu is None:
|
|
# The validation for this field is handled in the server.
|
|
max_shared_clients_per_gpu = 2
|
|
else:
|
|
max_shared_clients_per_gpu = int(max_shared_clients_per_gpu)
|
|
|
|
strategy_enum = (
|
|
self.messages.GPUSharingConfig.GpuSharingStrategyValueValuesEnum
|
|
)
|
|
if gpu_sharing_strategy is None:
|
|
# The GPU sharing strategy will be time-sharing by default.
|
|
gpu_sharing_strategy = strategy_enum.TIME_SHARING
|
|
elif gpu_sharing_strategy == 'time-sharing':
|
|
gpu_sharing_strategy = strategy_enum.TIME_SHARING
|
|
elif gpu_sharing_strategy == 'mps':
|
|
gpu_sharing_strategy = strategy_enum.MPS
|
|
else:
|
|
raise util.Error(GPU_SHARING_STRATEGY_ERROR_MSG)
|
|
|
|
gpu_sharing_config = self.messages.GPUSharingConfig(
|
|
maxSharedClientsPerGpu=max_shared_clients_per_gpu,
|
|
gpuSharingStrategy=gpu_sharing_strategy,
|
|
)
|
|
accelerator_config.gpuSharingConfig = gpu_sharing_config
|
|
|
|
gpu_driver_version = options.accelerators.get('gpu-driver-version', None)
|
|
if gpu_driver_version is not None:
|
|
if gpu_driver_version.lower() == 'default':
|
|
gpu_driver_version = (
|
|
self.messages.GPUDriverInstallationConfig.GpuDriverVersionValueValuesEnum.DEFAULT
|
|
)
|
|
elif gpu_driver_version.lower() == 'latest':
|
|
gpu_driver_version = (
|
|
self.messages.GPUDriverInstallationConfig.GpuDriverVersionValueValuesEnum.LATEST
|
|
)
|
|
elif gpu_driver_version.lower() == 'disabled':
|
|
gpu_driver_version = (
|
|
self.messages.GPUDriverInstallationConfig.GpuDriverVersionValueValuesEnum.INSTALLATION_DISABLED
|
|
)
|
|
else:
|
|
raise util.Error(GPU_DRIVER_VERSION_ERROR_MSG)
|
|
|
|
gpu_driver_installation_config = (
|
|
self.messages.GPUDriverInstallationConfig(
|
|
gpuDriverVersion=gpu_driver_version
|
|
)
|
|
)
|
|
accelerator_config.gpuDriverInstallationConfig = (
|
|
gpu_driver_installation_config
|
|
)
|
|
|
|
node_config.accelerators = [
|
|
accelerator_config,
|
|
]
|
|
|
|
def ParseResourceLabels(self, options, cluster):
|
|
"""Parses resource labels options for the cluster."""
|
|
if options.labels is not None:
|
|
labels = self.messages.Cluster.ResourceLabelsValue()
|
|
props = []
|
|
for k, v in sorted(six.iteritems(options.labels)):
|
|
props.append(labels.AdditionalProperty(key=k, value=v))
|
|
labels.additionalProperties = props
|
|
cluster.resourceLabels = labels
|
|
|
|
def ParseIPAliasOptions(self, options, cluster):
|
|
"""Parses the options for IP Alias."""
|
|
ip_alias_only_options = [
|
|
('services-ipv4-cidr', options.services_ipv4_cidr),
|
|
('create-subnetwork', options.create_subnetwork),
|
|
('cluster-secondary-range-name', options.cluster_secondary_range_name),
|
|
(
|
|
'services-secondary-range-name',
|
|
options.services_secondary_range_name,
|
|
),
|
|
(
|
|
'disable-pod-cidr-overprovision',
|
|
options.disable_pod_cidr_overprovision,
|
|
),
|
|
('stack-type', options.stack_type),
|
|
('ipv6-access-type', options.ipv6_access_type),
|
|
]
|
|
if not options.enable_ip_alias:
|
|
for name, opt in ip_alias_only_options:
|
|
if opt:
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='enable-ip-alias', opt=name
|
|
)
|
|
)
|
|
|
|
if options.subnetwork and options.create_subnetwork is not None:
|
|
raise util.Error(CREATE_SUBNETWORK_WITH_SUBNETWORK_ERROR_MSG)
|
|
|
|
if options.enable_ip_alias:
|
|
subnetwork_name = None
|
|
node_ipv4_cidr = None
|
|
|
|
if options.create_subnetwork is not None:
|
|
for key in options.create_subnetwork:
|
|
if key not in ['name', 'range']:
|
|
raise util.Error(
|
|
CREATE_SUBNETWORK_INVALID_KEY_ERROR_MSG.format(key=key)
|
|
)
|
|
subnetwork_name = options.create_subnetwork.get('name', None)
|
|
node_ipv4_cidr = options.create_subnetwork.get('range', None)
|
|
|
|
policy = self.messages.IPAllocationPolicy(
|
|
useIpAliases=options.enable_ip_alias,
|
|
createSubnetwork=options.create_subnetwork is not None,
|
|
subnetworkName=subnetwork_name,
|
|
clusterIpv4CidrBlock=options.cluster_ipv4_cidr,
|
|
nodeIpv4CidrBlock=node_ipv4_cidr,
|
|
servicesIpv4CidrBlock=options.services_ipv4_cidr,
|
|
clusterSecondaryRangeName=options.cluster_secondary_range_name,
|
|
servicesSecondaryRangeName=options.services_secondary_range_name,
|
|
)
|
|
if options.disable_pod_cidr_overprovision is not None:
|
|
policy.podCidrOverprovisionConfig = (
|
|
self.messages.PodCIDROverprovisionConfig(
|
|
disable=options.disable_pod_cidr_overprovision
|
|
)
|
|
)
|
|
if options.tpu_ipv4_cidr:
|
|
policy.tpuIpv4CidrBlock = options.tpu_ipv4_cidr
|
|
if options.stack_type is not None:
|
|
policy.stackType = util.GetCreateStackTypeMapper(
|
|
self.messages
|
|
).GetEnumForChoice(options.stack_type)
|
|
if options.ipv6_access_type is not None:
|
|
policy.ipv6AccessType = util.GetIpv6AccessTypeMapper(
|
|
self.messages
|
|
).GetEnumForChoice(options.ipv6_access_type)
|
|
|
|
cluster.clusterIpv4Cidr = None
|
|
cluster.ipAllocationPolicy = policy
|
|
elif options.enable_ip_alias is not None:
|
|
cluster.ipAllocationPolicy = self.messages.IPAllocationPolicy(
|
|
useRoutes=True
|
|
)
|
|
|
|
return cluster
|
|
|
|
def ParseAllowRouteOverlapOptions(self, options, cluster):
|
|
"""Parse the options for allow route overlap."""
|
|
if not options.allow_route_overlap:
|
|
return
|
|
if options.enable_ip_alias is None:
|
|
raise util.Error(ALLOW_ROUTE_OVERLAP_WITHOUT_EXPLICIT_NETWORK_MODE)
|
|
# Validate required flags are set.
|
|
if options.cluster_ipv4_cidr is None:
|
|
raise util.Error(ALLOW_ROUTE_OVERLAP_WITHOUT_CLUSTER_CIDR_ERROR_MSG)
|
|
if options.enable_ip_alias and options.services_ipv4_cidr is None:
|
|
raise util.Error(ALLOW_ROUTE_OVERLAP_WITHOUT_SERVICES_CIDR_ERROR_MSG)
|
|
|
|
# Fill in corresponding field.
|
|
if cluster.ipAllocationPolicy is None:
|
|
policy = self.messages.IPAllocationPolicy(allowRouteOverlap=True)
|
|
cluster.ipAllocationPolicy = policy
|
|
else:
|
|
cluster.ipAllocationPolicy.allowRouteOverlap = True
|
|
|
|
def ParsePrivateClusterOptions(self, options, cluster):
|
|
"""Parses the options for Private Clusters (for backward compatibility)."""
|
|
if (
|
|
options.enable_private_nodes is not None
|
|
and options.private_cluster is not None
|
|
):
|
|
raise util.Error(ENABLE_PRIVATE_NODES_WITH_PRIVATE_CLUSTER_ERROR_MSG)
|
|
|
|
if options.enable_private_nodes is None:
|
|
options.enable_private_nodes = options.private_cluster
|
|
|
|
if options.enable_private_nodes and not options.enable_ip_alias:
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='enable-ip-alias', opt='enable-private-nodes'
|
|
)
|
|
)
|
|
|
|
if options.enable_private_endpoint and not options.enable_private_nodes:
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='enable-private-nodes', opt='enable-private-endpoint'
|
|
)
|
|
)
|
|
|
|
if options.master_ipv4_cidr and not options.enable_private_nodes:
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='enable-private-nodes', opt='master-ipv4-cidr'
|
|
)
|
|
)
|
|
|
|
if options.master_ipv4_cidr:
|
|
config = self.messages.PrivateClusterConfig(
|
|
enablePrivateNodes=options.enable_private_nodes,
|
|
enablePrivateEndpoint=options.enable_private_endpoint,
|
|
masterIpv4CidrBlock=options.master_ipv4_cidr,
|
|
)
|
|
cluster.privateClusterConfig = config
|
|
return cluster
|
|
|
|
def ParseTpuOptions(self, options, cluster):
|
|
"""Parses the options for TPUs."""
|
|
if options.enable_tpu and not options.enable_ip_alias:
|
|
# Raises error if use --enable-tpu without --enable-ip-alias.
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='enable-ip-alias', opt='enable-tpu'
|
|
)
|
|
)
|
|
|
|
if not options.enable_tpu and options.tpu_ipv4_cidr:
|
|
# Raises error if use --tpu-ipv4-cidr without --enable-tpu.
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='enable-tpu', opt='tpu-ipv4-cidr'
|
|
)
|
|
)
|
|
|
|
if not options.enable_tpu and options.enable_tpu_service_networking:
|
|
# Raises error if use --enable-tpu-service-networking without
|
|
# --enable-tpu.
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='enable-tpu', opt='enable-tpu-service-networking'
|
|
)
|
|
)
|
|
|
|
if options.enable_tpu:
|
|
cluster.enableTpu = options.enable_tpu
|
|
if options.enable_tpu_service_networking:
|
|
tpu_config = self.messages.TpuConfig(
|
|
enabled=options.enable_tpu,
|
|
ipv4CidrBlock=options.tpu_ipv4_cidr,
|
|
useServiceNetworking=options.enable_tpu_service_networking,
|
|
)
|
|
cluster.tpuConfig = tpu_config
|
|
|
|
def ParseMasterAuthorizedNetworkOptions(self, options, cluster):
|
|
"""Parses the options for master authorized networks."""
|
|
if (
|
|
options.master_authorized_networks
|
|
and not options.enable_master_authorized_networks
|
|
):
|
|
# Raise error if use --master-authorized-networks without
|
|
# --enable-master-authorized-networks.
|
|
raise util.Error(MISMATCH_AUTHORIZED_NETWORKS_ERROR_MSG)
|
|
elif options.enable_master_authorized_networks is None:
|
|
if (
|
|
cluster.controlPlaneEndpointsConfig is not None
|
|
and cluster.controlPlaneEndpointsConfig.ipEndpointsConfig is not None
|
|
):
|
|
(
|
|
cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.authorizedNetworksConfig
|
|
) = None
|
|
elif not options.enable_master_authorized_networks:
|
|
authorized_networks = self.messages.MasterAuthorizedNetworksConfig(
|
|
enabled=False
|
|
)
|
|
self._InitIPEndpointsConfigIfRequired(cluster)
|
|
(
|
|
cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.authorizedNetworksConfig
|
|
) = authorized_networks
|
|
else:
|
|
authorized_networks = self.messages.MasterAuthorizedNetworksConfig(
|
|
enabled=options.enable_master_authorized_networks
|
|
)
|
|
if options.master_authorized_networks:
|
|
for network in options.master_authorized_networks:
|
|
authorized_networks.cidrBlocks.append(
|
|
self.messages.CidrBlock(cidrBlock=network)
|
|
)
|
|
self._InitIPEndpointsConfigIfRequired(cluster)
|
|
(
|
|
cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.authorizedNetworksConfig
|
|
) = authorized_networks
|
|
|
|
if options.enable_google_cloud_access is not None:
|
|
self._InitIPEndpointsConfigIfRequired(cluster)
|
|
if (
|
|
cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.authorizedNetworksConfig
|
|
) is None:
|
|
(
|
|
cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.authorizedNetworksConfig
|
|
) = self.messages.MasterAuthorizedNetworksConfig(enabled=False)
|
|
(
|
|
cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.authorizedNetworksConfig.gcpPublicCidrsAccessEnabled
|
|
) = options.enable_google_cloud_access
|
|
|
|
if options.enable_authorized_networks_on_private_endpoint is not None:
|
|
self._InitIPEndpointsConfigIfRequired(cluster)
|
|
if (
|
|
cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.authorizedNetworksConfig
|
|
) is None:
|
|
(
|
|
cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.authorizedNetworksConfig
|
|
) = self.messages.MasterAuthorizedNetworksConfig(enabled=False)
|
|
(
|
|
cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.authorizedNetworksConfig.privateEndpointEnforcementEnabled
|
|
) = options.enable_authorized_networks_on_private_endpoint
|
|
|
|
def ParseClusterDNSOptions(self, options, is_update=False, cluster_ref=None):
|
|
"""Parses the options for ClusterDNS."""
|
|
if options.cluster_dns is None:
|
|
if options.cluster_dns_scope:
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='cluster-dns', opt='cluster-dns-scope'
|
|
)
|
|
)
|
|
if options.cluster_dns_domain:
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='cluster-dns', opt='cluster-dns-domain'
|
|
)
|
|
)
|
|
|
|
# Check if the request has no flags related to DNS.
|
|
if (
|
|
options.cluster_dns is None
|
|
and options.cluster_dns_scope is None
|
|
and options.cluster_dns_domain is None
|
|
and (not is_update or options.disable_additive_vpc_scope is None)
|
|
and options.additive_vpc_scope_dns_domain is None
|
|
):
|
|
return
|
|
|
|
dns_config = self.messages.DNSConfig()
|
|
# Use current config as base for updates
|
|
if is_update:
|
|
cluster = self.GetCluster(cluster_ref)
|
|
if cluster.networkConfig and cluster.networkConfig.dnsConfig:
|
|
dns_config = cluster.networkConfig.dnsConfig
|
|
|
|
if options.cluster_dns is not None:
|
|
provider_enum = self.messages.DNSConfig.ClusterDnsValueValuesEnum
|
|
if options.cluster_dns.lower() == 'clouddns':
|
|
desired_cluster_dns = provider_enum.CLOUD_DNS
|
|
elif options.cluster_dns.lower() == 'kubedns':
|
|
desired_cluster_dns = provider_enum.KUBE_DNS
|
|
else: # 'default' or not specified
|
|
desired_cluster_dns = provider_enum.PLATFORM_DEFAULT
|
|
|
|
if desired_cluster_dns != dns_config.clusterDns:
|
|
if is_update:
|
|
console_io.PromptContinue(
|
|
message=(
|
|
'All the node-pools in the cluster need to be re-created '
|
|
'by the user to start using the new DNS provider. It is '
|
|
'highly recommended to perform this step shortly after '
|
|
'completing the update.'
|
|
),
|
|
cancel_on_no=True,
|
|
)
|
|
dns_config.clusterDns = desired_cluster_dns
|
|
|
|
if options.cluster_dns_scope is not None:
|
|
scope_enum = self.messages.DNSConfig.ClusterDnsScopeValueValuesEnum
|
|
if options.cluster_dns_scope.lower() == 'cluster':
|
|
dns_config.clusterDnsScope = scope_enum.CLUSTER_SCOPE
|
|
else:
|
|
dns_config.clusterDnsScope = scope_enum.VPC_SCOPE
|
|
|
|
if options.cluster_dns_domain is not None:
|
|
dns_config.clusterDnsDomain = options.cluster_dns_domain
|
|
|
|
if options.additive_vpc_scope_dns_domain is not None:
|
|
dns_config.additiveVpcScopeDnsDomain = (
|
|
options.additive_vpc_scope_dns_domain
|
|
)
|
|
|
|
if is_update and options.disable_additive_vpc_scope:
|
|
dns_config.additiveVpcScopeDnsDomain = ''
|
|
|
|
return dns_config
|
|
|
|
def ParseGatewayOptions(self, options):
|
|
"""Parses the options for Gateway."""
|
|
|
|
if options.gateway_api is None:
|
|
return None
|
|
gateway_config = self.messages.GatewayAPIConfig()
|
|
channel_enum = self.messages.GatewayAPIConfig.ChannelValueValuesEnum
|
|
if options.gateway_api.lower() == 'disabled':
|
|
gateway_config.channel = channel_enum.CHANNEL_DISABLED
|
|
elif options.gateway_api.lower() == 'standard':
|
|
gateway_config.channel = channel_enum.CHANNEL_STANDARD
|
|
else:
|
|
gateway_config.channel = channel_enum.CHANNEL_DISABLED
|
|
|
|
return gateway_config
|
|
|
|
def CreateCluster(self, cluster_ref, options):
|
|
"""Handles CreateCluster options that are specific to a release track.
|
|
|
|
Overridden in each release track.
|
|
|
|
Args:
|
|
cluster_ref: Name and location of the cluster.
|
|
options: An UpdateClusterOptions containining the user-specified options.
|
|
|
|
Returns:
|
|
The operation to be executed.
|
|
"""
|
|
cluster = self.CreateClusterCommon(cluster_ref, options)
|
|
if (
|
|
options.enable_autoprovisioning is not None
|
|
or options.autoscaling_profile is not None
|
|
or options.enable_default_compute_class is not None
|
|
):
|
|
cluster.autoscaling = self.CreateClusterAutoscalingCommon(
|
|
cluster_ref, options, False
|
|
)
|
|
if options.addons:
|
|
# CloudRun is disabled by default.
|
|
if any((v in options.addons) for v in CLOUDRUN_ADDONS):
|
|
if not options.enable_stackdriver_kubernetes and (
|
|
(
|
|
options.monitoring is not None
|
|
and SYSTEM not in options.monitoring
|
|
)
|
|
or (options.logging is not None and SYSTEM not in options.logging)
|
|
):
|
|
raise util.Error(CLOUDRUN_STACKDRIVER_KUBERNETES_DISABLED_ERROR_MSG)
|
|
if INGRESS not in options.addons:
|
|
raise util.Error(CLOUDRUN_INGRESS_KUBERNETES_DISABLED_ERROR_MSG)
|
|
load_balancer_type = _GetCloudRunLoadBalancerType(
|
|
options, self.messages
|
|
)
|
|
cluster.addonsConfig.cloudRunConfig = self.messages.CloudRunConfig(
|
|
disabled=False, loadBalancerType=load_balancer_type
|
|
)
|
|
|
|
req = self.messages.CreateClusterRequest(
|
|
parent=ProjectLocation(cluster_ref.projectId, cluster_ref.zone),
|
|
cluster=cluster,
|
|
)
|
|
operation = self.client.projects_locations_clusters.Create(req)
|
|
return self.ParseOperation(operation.name, cluster_ref.zone)
|
|
|
|
def CreateClusterAutoscalingCommon(self, cluster_ref, options, for_update):
|
|
"""Create cluster's autoscaling configuration.
|
|
|
|
Args:
|
|
cluster_ref: Cluster reference.
|
|
options: Either CreateClusterOptions or UpdateClusterOptions.
|
|
for_update: Is function executed for update operation.
|
|
|
|
Returns:
|
|
Cluster's autoscaling configuration.
|
|
"""
|
|
|
|
# Patch cluster autoscaling if cluster_ref is provided.
|
|
autoscaling = self.messages.ClusterAutoscaling()
|
|
if for_update:
|
|
cluster = self.GetCluster(cluster_ref) if cluster_ref else None
|
|
if cluster and cluster.autoscaling:
|
|
autoscaling.enableNodeAutoprovisioning = (
|
|
cluster.autoscaling.enableNodeAutoprovisioning
|
|
)
|
|
autoscaling.defaultComputeClassConfig = (
|
|
cluster.autoscaling.defaultComputeClassConfig
|
|
)
|
|
else:
|
|
autoscaling.enableNodeAutoprovisioning = options.enable_autoprovisioning
|
|
|
|
if options.enable_default_compute_class is not None:
|
|
autoscaling.defaultComputeClassConfig = (
|
|
self.messages.DefaultComputeClassConfig(
|
|
enabled=options.enable_default_compute_class,
|
|
)
|
|
)
|
|
resource_limits = []
|
|
if options.autoprovisioning_config_file is not None:
|
|
util.ValidateAutoprovisioningConfigFile(
|
|
options.autoprovisioning_config_file
|
|
)
|
|
# Create using config file only.
|
|
config = yaml.load(options.autoprovisioning_config_file)
|
|
resource_limits = config.get(RESOURCE_LIMITS)
|
|
service_account = config.get(SERVICE_ACCOUNT)
|
|
scopes = config.get(SCOPES)
|
|
max_surge_upgrade = None
|
|
max_unavailable_upgrade = None
|
|
upgrade_settings = config.get(UPGRADE_SETTINGS)
|
|
if upgrade_settings:
|
|
max_surge_upgrade = upgrade_settings.get(MAX_SURGE_UPGRADE)
|
|
max_unavailable_upgrade = upgrade_settings.get(MAX_UNAVAILABLE_UPGRADE)
|
|
management_settings = config.get(NODE_MANAGEMENT)
|
|
enable_autoupgrade = None
|
|
enable_autorepair = None
|
|
if management_settings:
|
|
enable_autoupgrade = management_settings.get(ENABLE_AUTO_UPGRADE)
|
|
enable_autorepair = management_settings.get(ENABLE_AUTO_REPAIR)
|
|
autoprovisioning_locations = config.get(AUTOPROVISIONING_LOCATIONS)
|
|
min_cpu_platform = config.get(MIN_CPU_PLATFORM)
|
|
autoprovisioning_image_type = config.get(IMAGE_TYPE)
|
|
boot_disk_kms_key = config.get(BOOT_DISK_KMS_KEY)
|
|
disk_type = config.get(DISK_TYPE)
|
|
disk_size_gb = config.get(DISK_SIZE_GB)
|
|
shielded_instance_config = config.get(SHIELDED_INSTANCE_CONFIG)
|
|
enable_secure_boot = None
|
|
enable_integrity_monitoring = None
|
|
if shielded_instance_config:
|
|
enable_secure_boot = shielded_instance_config.get(ENABLE_SECURE_BOOT)
|
|
enable_integrity_monitoring = shielded_instance_config.get(
|
|
ENABLE_INTEGRITY_MONITORING
|
|
)
|
|
else:
|
|
resource_limits = self.ResourceLimitsFromFlags(options)
|
|
service_account = options.autoprovisioning_service_account
|
|
scopes = options.autoprovisioning_scopes
|
|
max_surge_upgrade = options.autoprovisioning_max_surge_upgrade
|
|
max_unavailable_upgrade = options.autoprovisioning_max_unavailable_upgrade
|
|
enable_autoupgrade = options.enable_autoprovisioning_autoupgrade
|
|
enable_autorepair = options.enable_autoprovisioning_autorepair
|
|
autoprovisioning_locations = options.autoprovisioning_locations
|
|
min_cpu_platform = options.autoprovisioning_min_cpu_platform
|
|
autoprovisioning_image_type = options.autoprovisioning_image_type
|
|
boot_disk_kms_key = None
|
|
disk_type = None
|
|
disk_size_gb = None
|
|
enable_secure_boot = None
|
|
enable_integrity_monitoring = None
|
|
|
|
if options.enable_autoprovisioning is not None:
|
|
autoscaling.enableNodeAutoprovisioning = options.enable_autoprovisioning
|
|
if resource_limits is None:
|
|
resource_limits = []
|
|
autoscaling.resourceLimits = resource_limits
|
|
if scopes is None:
|
|
scopes = []
|
|
management = None
|
|
upgrade_settings = None
|
|
if (
|
|
max_surge_upgrade is not None
|
|
or max_unavailable_upgrade is not None
|
|
or options.enable_autoprovisioning_blue_green_upgrade
|
|
or options.enable_autoprovisioning_surge_upgrade
|
|
or options.autoprovisioning_standard_rollout_policy is not None
|
|
or options.autoprovisioning_node_pool_soak_duration is not None
|
|
):
|
|
upgrade_settings = self.UpdateUpgradeSettingsForNAP(
|
|
options, max_surge_upgrade, max_unavailable_upgrade
|
|
)
|
|
if enable_autorepair is not None or enable_autoupgrade is not None:
|
|
management = self.messages.NodeManagement(
|
|
autoUpgrade=enable_autoupgrade, autoRepair=enable_autorepair
|
|
)
|
|
shielded_instance_config = None
|
|
if (
|
|
enable_secure_boot is not None
|
|
or enable_integrity_monitoring is not None
|
|
):
|
|
shielded_instance_config = self.messages.ShieldedInstanceConfig()
|
|
shielded_instance_config.enableSecureBoot = enable_secure_boot
|
|
shielded_instance_config.enableIntegrityMonitoring = (
|
|
enable_integrity_monitoring
|
|
)
|
|
if for_update:
|
|
autoscaling.autoprovisioningNodePoolDefaults = (
|
|
self.messages.AutoprovisioningNodePoolDefaults(
|
|
serviceAccount=service_account,
|
|
oauthScopes=scopes,
|
|
upgradeSettings=upgrade_settings,
|
|
management=management,
|
|
minCpuPlatform=min_cpu_platform,
|
|
bootDiskKmsKey=boot_disk_kms_key,
|
|
diskSizeGb=disk_size_gb,
|
|
diskType=disk_type,
|
|
imageType=autoprovisioning_image_type,
|
|
shieldedInstanceConfig=shielded_instance_config,
|
|
)
|
|
)
|
|
else:
|
|
autoscaling.autoprovisioningNodePoolDefaults = (
|
|
self.messages.AutoprovisioningNodePoolDefaults(
|
|
serviceAccount=service_account,
|
|
oauthScopes=scopes,
|
|
upgradeSettings=upgrade_settings,
|
|
management=management,
|
|
minCpuPlatform=min_cpu_platform,
|
|
bootDiskKmsKey=boot_disk_kms_key,
|
|
diskSizeGb=disk_size_gb,
|
|
diskType=disk_type,
|
|
imageType=autoprovisioning_image_type,
|
|
shieldedInstanceConfig=shielded_instance_config,
|
|
)
|
|
)
|
|
if autoprovisioning_locations:
|
|
autoscaling.autoprovisioningLocations = sorted(
|
|
autoprovisioning_locations
|
|
)
|
|
|
|
if options.autoscaling_profile is not None:
|
|
autoscaling.autoscalingProfile = self.CreateAutoscalingProfileCommon(
|
|
options
|
|
)
|
|
|
|
self.ValidateClusterAutoscaling(autoscaling, for_update)
|
|
return autoscaling
|
|
|
|
def UpdateUpgradeSettingsForNAP(self, options, max_surge, max_unavailable):
|
|
"""Updates upgrade settings for autoprovisioned node pool."""
|
|
|
|
if (
|
|
options.enable_autoprovisioning_surge_upgrade
|
|
and options.enable_autoprovisioning_blue_green_upgrade
|
|
):
|
|
raise util.Error(
|
|
'UpgradeSettings must contain only one of:'
|
|
' --enable-autoprovisioning-surge-upgrade,'
|
|
' --enable-autoprovisioning-blue-green-upgrade'
|
|
)
|
|
|
|
upgrade_settings = self.messages.UpgradeSettings()
|
|
upgrade_settings.maxSurge = max_surge
|
|
upgrade_settings.maxUnavailable = max_unavailable
|
|
if options.enable_autoprovisioning_surge_upgrade:
|
|
upgrade_settings.strategy = (
|
|
self.messages.UpgradeSettings.StrategyValueValuesEnum.SURGE
|
|
)
|
|
if options.enable_autoprovisioning_blue_green_upgrade:
|
|
upgrade_settings.strategy = (
|
|
self.messages.UpgradeSettings.StrategyValueValuesEnum.BLUE_GREEN
|
|
)
|
|
if (
|
|
options.autoprovisioning_standard_rollout_policy is not None
|
|
or options.autoprovisioning_node_pool_soak_duration is not None
|
|
):
|
|
upgrade_settings.blueGreenSettings = self.UpdateBlueGreenSettingsForNAP(
|
|
upgrade_settings, options
|
|
)
|
|
return upgrade_settings
|
|
|
|
def UpdateBlueGreenSettingsForNAP(self, upgrade_settings, options):
|
|
"""Update blue green settings field in upgrade_settings for autoprovisioned node pool."""
|
|
blue_green_settings = (
|
|
upgrade_settings.blueGreenSettings or self.messages.BlueGreenSettings()
|
|
)
|
|
if options.autoprovisioning_node_pool_soak_duration is not None:
|
|
blue_green_settings.nodePoolSoakDuration = (
|
|
options.autoprovisioning_node_pool_soak_duration
|
|
)
|
|
|
|
if options.autoprovisioning_standard_rollout_policy is not None:
|
|
standard_rollout_policy = (
|
|
blue_green_settings.standardRolloutPolicy
|
|
or self.messages.StandardRolloutPolicy()
|
|
)
|
|
|
|
if (
|
|
'batch-node-count' in options.autoprovisioning_standard_rollout_policy
|
|
and 'batch-percent'
|
|
in options.autoprovisioning_standard_rollout_policy
|
|
):
|
|
raise util.Error(
|
|
'Autoprovisioning StandardRolloutPolicy must contain only one of:'
|
|
' batch-node-count, batch-percent'
|
|
)
|
|
|
|
standard_rollout_policy.batchPercentage = (
|
|
standard_rollout_policy.batchNodeCount
|
|
) = None
|
|
if 'batch-node-count' in options.autoprovisioning_standard_rollout_policy:
|
|
standard_rollout_policy.batchNodeCount = (
|
|
options.autoprovisioning_standard_rollout_policy['batch-node-count']
|
|
)
|
|
elif 'batch-percent' in options.autoprovisioning_standard_rollout_policy:
|
|
standard_rollout_policy.batchPercentage = (
|
|
options.autoprovisioning_standard_rollout_policy['batch-percent']
|
|
)
|
|
|
|
if (
|
|
'batch-soak-duration'
|
|
in options.autoprovisioning_standard_rollout_policy
|
|
):
|
|
standard_rollout_policy.batchSoakDuration = (
|
|
options.autoprovisioning_standard_rollout_policy[
|
|
'batch-soak-duration'
|
|
]
|
|
)
|
|
blue_green_settings.standardRolloutPolicy = standard_rollout_policy
|
|
return blue_green_settings
|
|
|
|
def CreateAutoscalingProfileCommon(self, options):
|
|
"""Create and validate cluster's autoscaling profile configuration.
|
|
|
|
Args:
|
|
options: Either CreateClusterOptions or UpdateClusterOptions.
|
|
|
|
Returns:
|
|
Cluster's autoscaling profile configuration.
|
|
"""
|
|
|
|
cluster_autoscaling = self.messages.ClusterAutoscaling
|
|
profiles_enum = cluster_autoscaling.AutoscalingProfileValueValuesEnum
|
|
valid_choices = [
|
|
arg_utils.EnumNameToChoice(n)
|
|
for n in profiles_enum.names()
|
|
if n != 'profile-unspecified'
|
|
]
|
|
return arg_utils.ChoiceToEnum(
|
|
choice=arg_utils.EnumNameToChoice(options.autoscaling_profile),
|
|
enum_type=profiles_enum,
|
|
valid_choices=valid_choices,
|
|
)
|
|
|
|
def ValidateClusterAutoscaling(self, autoscaling, for_update):
|
|
"""Validate cluster autoscaling configuration.
|
|
|
|
Args:
|
|
autoscaling: autoscaling configuration to be validated.
|
|
for_update: Is function executed for update operation.
|
|
|
|
Raises:
|
|
Error if the new configuration is invalid.
|
|
"""
|
|
if autoscaling.enableNodeAutoprovisioning:
|
|
if not for_update or autoscaling.resourceLimits:
|
|
cpu_found = any(
|
|
limit.resourceType == 'cpu' for limit in autoscaling.resourceLimits
|
|
)
|
|
mem_found = any(
|
|
limit.resourceType == 'memory'
|
|
for limit in autoscaling.resourceLimits
|
|
)
|
|
if not cpu_found or not mem_found:
|
|
raise util.Error(NO_AUTOPROVISIONING_LIMITS_ERROR_MSG)
|
|
defaults = autoscaling.autoprovisioningNodePoolDefaults
|
|
if defaults:
|
|
if defaults.upgradeSettings:
|
|
max_surge_found = defaults.upgradeSettings.maxSurge is not None
|
|
max_unavailable_found = (
|
|
defaults.upgradeSettings.maxUnavailable is not None
|
|
)
|
|
if max_unavailable_found != max_surge_found:
|
|
raise util.Error(BOTH_AUTOPROVISIONING_UPGRADE_SETTINGS_ERROR_MSG)
|
|
if defaults.management:
|
|
auto_upgrade_found = defaults.management.autoUpgrade is not None
|
|
auto_repair_found = defaults.management.autoRepair is not None
|
|
if auto_repair_found != auto_upgrade_found:
|
|
raise util.Error(
|
|
BOTH_AUTOPROVISIONING_MANAGEMENT_SETTINGS_ERROR_MSG
|
|
)
|
|
if defaults.shieldedInstanceConfig:
|
|
secure_boot_found = (
|
|
defaults.shieldedInstanceConfig.enableSecureBoot is not None
|
|
)
|
|
integrity_monitoring_found = (
|
|
defaults.shieldedInstanceConfig.enableIntegrityMonitoring
|
|
is not None
|
|
)
|
|
if secure_boot_found != integrity_monitoring_found:
|
|
raise util.Error(
|
|
BOTH_AUTOPROVISIONING_SHIELDED_INSTANCE_SETTINGS_ERROR_MSG
|
|
)
|
|
elif autoscaling.resourceLimits:
|
|
raise util.Error(LIMITS_WITHOUT_AUTOPROVISIONING_MSG)
|
|
elif autoscaling.autoprovisioningNodePoolDefaults and (
|
|
autoscaling.autoprovisioningNodePoolDefaults.serviceAccount
|
|
or autoscaling.autoprovisioningNodePoolDefaults.oauthScopes
|
|
):
|
|
raise util.Error(DEFAULTS_WITHOUT_AUTOPROVISIONING_MSG)
|
|
|
|
def _GetClusterTelemetryType(
|
|
self, options, logging_service, monitoring_service
|
|
):
|
|
"""Gets the cluster telemetry from create options."""
|
|
# If enable_stackdriver_kubernetes is set to false cluster telemetry
|
|
# will be set to DISABLED.
|
|
if (
|
|
options.enable_stackdriver_kubernetes is not None
|
|
and not options.enable_stackdriver_kubernetes
|
|
):
|
|
return self.messages.ClusterTelemetry.TypeValueValuesEnum.DISABLED
|
|
|
|
# If either logging service or monitoring service is explicitly disabled we
|
|
# do not set the cluster telemtry.
|
|
if options.enable_stackdriver_kubernetes and (
|
|
logging_service == 'none' or monitoring_service == 'none'
|
|
):
|
|
return None
|
|
|
|
# When enable_stackdriver_kubernetes is set to true and neither logging nor
|
|
# monitoring service are explicitly disabled we set the Cluster Telemetry
|
|
# to ENABLED.
|
|
if (
|
|
options.enable_stackdriver_kubernetes
|
|
and logging_service != 'none'
|
|
and monitoring_service != 'none'
|
|
):
|
|
return self.messages.ClusterTelemetry.TypeValueValuesEnum.ENABLED
|
|
|
|
# When enable_logging_monitoring_system_only is set to true we set the
|
|
# telemetry to SYSTEM_ONLY. In case of SYSTEM_ONLY it's not possible to
|
|
# disable either logging or monitoring.
|
|
if options.enable_logging_monitoring_system_only:
|
|
return self.messages.ClusterTelemetry.TypeValueValuesEnum.SYSTEM_ONLY
|
|
return None
|
|
|
|
def ResourceLimitsFromFlags(self, options):
|
|
"""Create cluster's autoscaling resource limits from command line flags.
|
|
|
|
Args:
|
|
options: Either CreateClusterOptions or UpdateClusterOptions.
|
|
|
|
Returns:
|
|
Cluster's new autoscaling resource limits.
|
|
"""
|
|
new_resource_limits = []
|
|
if options.min_cpu is not None or options.max_cpu is not None:
|
|
new_resource_limits.append(
|
|
self.messages.ResourceLimit(
|
|
resourceType='cpu',
|
|
minimum=options.min_cpu,
|
|
maximum=options.max_cpu,
|
|
)
|
|
)
|
|
if options.min_memory is not None or options.max_memory is not None:
|
|
new_resource_limits.append(
|
|
self.messages.ResourceLimit(
|
|
resourceType='memory',
|
|
minimum=options.min_memory,
|
|
maximum=options.max_memory,
|
|
)
|
|
)
|
|
if options.max_accelerator is not None:
|
|
accelerator_type = options.max_accelerator.get('type')
|
|
min_count = 0
|
|
if options.min_accelerator is not None:
|
|
if options.min_accelerator.get('type') != accelerator_type:
|
|
raise util.Error(MISMATCH_ACCELERATOR_TYPE_LIMITS_ERROR_MSG)
|
|
min_count = options.min_accelerator.get('count', 0)
|
|
new_resource_limits.append(
|
|
self.messages.ResourceLimit(
|
|
resourceType=options.max_accelerator.get('type'),
|
|
minimum=min_count,
|
|
maximum=options.max_accelerator.get('count', 0),
|
|
)
|
|
)
|
|
return new_resource_limits
|
|
|
|
def UpdateClusterCommon(self, cluster_ref, options):
|
|
"""Returns an UpdateCluster operation."""
|
|
update = None
|
|
if not options.version:
|
|
options.version = '-'
|
|
if options.update_nodes:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNodeVersion=options.version,
|
|
desiredNodePoolId=options.node_pool,
|
|
desiredImageType=options.image_type,
|
|
desiredImage=options.image,
|
|
desiredImageProject=options.image_project,
|
|
)
|
|
# security_profile may be set in upgrade command
|
|
if options.security_profile is not None:
|
|
update.securityProfile = self.messages.SecurityProfile(
|
|
name=options.security_profile
|
|
)
|
|
elif options.update_master:
|
|
update = self.messages.ClusterUpdate(desiredMasterVersion=options.version)
|
|
# security_profile may be set in upgrade command
|
|
if options.security_profile is not None:
|
|
update.securityProfile = self.messages.SecurityProfile(
|
|
name=options.security_profile
|
|
)
|
|
# control_plane_soak_duration may be set in upgrade command for rollback
|
|
# safe upgrades
|
|
if options.control_plane_soak_duration is not None:
|
|
update.desiredRollbackSafeUpgrade = self.messages.RollbackSafeUpgrade(
|
|
controlPlaneSoakDuration=options.control_plane_soak_duration
|
|
)
|
|
elif options.enable_stackdriver_kubernetes:
|
|
update = self.messages.ClusterUpdate()
|
|
update.desiredLoggingService = 'logging.googleapis.com/kubernetes'
|
|
update.desiredMonitoringService = 'monitoring.googleapis.com/kubernetes'
|
|
elif options.enable_stackdriver_kubernetes is not None:
|
|
update = self.messages.ClusterUpdate()
|
|
update.desiredLoggingService = 'none'
|
|
update.desiredMonitoringService = 'none'
|
|
elif options.monitoring_service or options.logging_service:
|
|
update = self.messages.ClusterUpdate()
|
|
if options.monitoring_service:
|
|
update.desiredMonitoringService = options.monitoring_service
|
|
if options.logging_service:
|
|
update.desiredLoggingService = options.logging_service
|
|
elif (
|
|
options.logging
|
|
or options.monitoring
|
|
or options.enable_managed_prometheus
|
|
or options.disable_managed_prometheus
|
|
or options.auto_monitoring_scope
|
|
or options.enable_dataplane_v2_metrics
|
|
or options.disable_dataplane_v2_metrics
|
|
or options.enable_dataplane_v2_flow_observability
|
|
or options.disable_dataplane_v2_flow_observability
|
|
or options.dataplane_v2_observability_mode
|
|
):
|
|
logging = _GetLoggingConfig(options, self.messages)
|
|
# Fix incorrectly omitting required field.
|
|
if (
|
|
(
|
|
options.dataplane_v2_observability_mode
|
|
or options.enable_dataplane_v2_flow_observability
|
|
or options.disable_dataplane_v2_flow_observability
|
|
)
|
|
and options.enable_dataplane_v2_metrics is None
|
|
and options.disable_dataplane_v2_metrics is None
|
|
):
|
|
cluster = self.GetCluster(cluster_ref)
|
|
if (
|
|
cluster
|
|
and cluster.monitoringConfig
|
|
and cluster.monitoringConfig.advancedDatapathObservabilityConfig
|
|
):
|
|
if (
|
|
cluster.monitoringConfig.advancedDatapathObservabilityConfig.enableMetrics
|
|
):
|
|
options.enable_dataplane_v2_metrics = True
|
|
else:
|
|
options.disable_dataplane_v2_metrics = True
|
|
|
|
monitoring = None
|
|
if options.auto_monitoring_scope:
|
|
cluster = self.GetCluster(cluster_ref)
|
|
|
|
if cluster is None:
|
|
raise util.Error(
|
|
'Cannot enable Auto Monitoring. The cluster does not exist.'
|
|
)
|
|
|
|
if (
|
|
cluster.monitoringConfig.managedPrometheusConfig is None
|
|
or not cluster.monitoringConfig.managedPrometheusConfig.enabled
|
|
) and options.auto_monitoring_scope == 'ALL':
|
|
|
|
raise util.Error(
|
|
AUTO_MONITORING_NOT_SUPPORTED_WITHOUT_MANAGED_PROMETHEUS
|
|
)
|
|
|
|
if cluster.monitoringConfig.managedPrometheusConfig.enabled:
|
|
monitoring = _GetMonitoringConfig(options, self.messages, True, True)
|
|
else:
|
|
monitoring = _GetMonitoringConfig(options, self.messages, True, False)
|
|
else:
|
|
monitoring = _GetMonitoringConfig(options, self.messages, False, None)
|
|
|
|
update = self.messages.ClusterUpdate()
|
|
if logging:
|
|
update.desiredLoggingConfig = logging
|
|
if monitoring:
|
|
update.desiredMonitoringConfig = monitoring
|
|
elif options.disable_addons:
|
|
disable_node_local_dns = options.disable_addons.get(NODELOCALDNS)
|
|
addons = self._AddonsConfig(
|
|
disable_ingress=options.disable_addons.get(INGRESS),
|
|
disable_hpa=options.disable_addons.get(HPA),
|
|
disable_dashboard=options.disable_addons.get(DASHBOARD),
|
|
disable_network_policy=options.disable_addons.get(NETWORK_POLICY),
|
|
enable_node_local_dns=not disable_node_local_dns
|
|
if disable_node_local_dns is not None
|
|
else None,
|
|
)
|
|
if options.disable_addons.get(CONFIGCONNECTOR) is not None:
|
|
addons.configConnectorConfig = self.messages.ConfigConnectorConfig(
|
|
enabled=(not options.disable_addons.get(CONFIGCONNECTOR))
|
|
)
|
|
if options.disable_addons.get(GCEPDCSIDRIVER) is not None:
|
|
addons.gcePersistentDiskCsiDriverConfig = (
|
|
self.messages.GcePersistentDiskCsiDriverConfig(
|
|
enabled=not options.disable_addons.get(GCEPDCSIDRIVER)
|
|
)
|
|
)
|
|
if options.disable_addons.get(GCPFILESTORECSIDRIVER) is not None:
|
|
addons.gcpFilestoreCsiDriverConfig = (
|
|
self.messages.GcpFilestoreCsiDriverConfig(
|
|
enabled=not options.disable_addons.get(GCPFILESTORECSIDRIVER)
|
|
)
|
|
)
|
|
if options.disable_addons.get(GCSFUSECSIDRIVER) is not None:
|
|
addons.gcsFuseCsiDriverConfig = self.messages.GcsFuseCsiDriverConfig(
|
|
enabled=not options.disable_addons.get(GCSFUSECSIDRIVER)
|
|
)
|
|
if options.disable_addons.get(STATEFULHA) is not None:
|
|
addons.statefulHaConfig = self.messages.StatefulHAConfig(
|
|
enabled=not options.disable_addons.get(STATEFULHA)
|
|
)
|
|
if options.disable_addons.get(PARALLELSTORECSIDRIVER) is not None:
|
|
addons.parallelstoreCsiDriverConfig = (
|
|
self.messages.ParallelstoreCsiDriverConfig(
|
|
enabled=not options.disable_addons.get(PARALLELSTORECSIDRIVER)
|
|
)
|
|
)
|
|
if options.disable_addons.get(HIGHSCALECHECKPOINTING) is not None:
|
|
addons.highScaleCheckpointingConfig = (
|
|
self.messages.HighScaleCheckpointingConfig(
|
|
enabled=not options.disable_addons.get(HIGHSCALECHECKPOINTING)
|
|
)
|
|
)
|
|
if options.disable_addons.get(LUSTRECSIDRIVER) is not None:
|
|
addons.lustreCsiDriverConfig = self.messages.LustreCsiDriverConfig(
|
|
enabled=not options.disable_addons.get(LUSTRECSIDRIVER)
|
|
)
|
|
if options.disable_addons.get(BACKUPRESTORE) is not None:
|
|
addons.gkeBackupAgentConfig = self.messages.GkeBackupAgentConfig(
|
|
enabled=not options.disable_addons.get(BACKUPRESTORE)
|
|
)
|
|
if options.disable_addons.get(RAYOPERATOR) is not None:
|
|
addons.rayOperatorConfig = self.messages.RayOperatorConfig(
|
|
enabled=not options.disable_addons.get(RAYOPERATOR)
|
|
)
|
|
update = self.messages.ClusterUpdate(desiredAddonsConfig=addons)
|
|
elif (
|
|
options.enable_ray_cluster_logging is not None
|
|
or options.enable_ray_cluster_monitoring is not None
|
|
or options.enable_legacy_lustre_port is not None
|
|
or options.disable_multi_nic_lustre is not None
|
|
):
|
|
addons = self._AddonsConfig(options, self.messages)
|
|
|
|
if options.enable_ray_cluster_logging is not None:
|
|
addons.rayOperatorConfig.rayClusterLoggingConfig = (
|
|
self.messages.RayClusterLoggingConfig(
|
|
enabled=options.enable_ray_cluster_logging
|
|
)
|
|
)
|
|
|
|
if options.enable_ray_cluster_monitoring is not None:
|
|
addons.rayOperatorConfig.rayClusterMonitoringConfig = (
|
|
self.messages.RayClusterMonitoringConfig(
|
|
enabled=options.enable_ray_cluster_monitoring
|
|
)
|
|
)
|
|
|
|
if options.enable_legacy_lustre_port is not None:
|
|
addons.lustreCsiDriverConfig.enableLegacyLustrePort = (
|
|
options.enable_legacy_lustre_port
|
|
)
|
|
|
|
if options.disable_multi_nic_lustre is not None:
|
|
addons.lustreCsiDriverConfig.disableMultiNic = (
|
|
options.disable_multi_nic_lustre
|
|
)
|
|
|
|
update = self.messages.ClusterUpdate(desiredAddonsConfig=addons)
|
|
elif options.enable_autoscaling is not None:
|
|
# For update, we can either enable or disable.
|
|
autoscaling = self.messages.NodePoolAutoscaling(
|
|
enabled=options.enable_autoscaling
|
|
)
|
|
if options.enable_autoscaling:
|
|
autoscaling.minNodeCount = options.min_nodes
|
|
autoscaling.maxNodeCount = options.max_nodes
|
|
autoscaling.totalMinNodeCount = options.total_min_nodes
|
|
autoscaling.totalMaxNodeCount = options.total_max_nodes
|
|
if options.location_policy is not None:
|
|
autoscaling.locationPolicy = LocationPolicyEnumFromString(
|
|
self.messages, options.location_policy
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNodePoolId=options.node_pool,
|
|
desiredNodePoolAutoscaling=autoscaling,
|
|
)
|
|
elif options.locations:
|
|
update = self.messages.ClusterUpdate(desiredLocations=options.locations)
|
|
elif (
|
|
options.enable_autoprovisioning is not None
|
|
or options.autoscaling_profile is not None
|
|
or options.enable_default_compute_class is not None
|
|
):
|
|
autoscaling = self.CreateClusterAutoscalingCommon(
|
|
cluster_ref, options, True
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredClusterAutoscaling=autoscaling
|
|
)
|
|
elif options.enable_pod_security_policy is not None:
|
|
config = self.messages.PodSecurityPolicyConfig(
|
|
enabled=options.enable_pod_security_policy
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredPodSecurityPolicyConfig=config
|
|
)
|
|
elif options.enable_vertical_pod_autoscaling is not None:
|
|
vertical_pod_autoscaling = self.messages.VerticalPodAutoscaling(
|
|
enabled=options.enable_vertical_pod_autoscaling
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredVerticalPodAutoscaling=vertical_pod_autoscaling
|
|
)
|
|
elif options.resource_usage_bigquery_dataset is not None:
|
|
export_config = self.messages.ResourceUsageExportConfig(
|
|
bigqueryDestination=self.messages.BigQueryDestination(
|
|
datasetId=options.resource_usage_bigquery_dataset
|
|
)
|
|
)
|
|
if options.enable_network_egress_metering:
|
|
export_config.enableNetworkEgressMetering = True
|
|
if options.enable_resource_consumption_metering is not None:
|
|
export_config.consumptionMeteringConfig = (
|
|
self.messages.ConsumptionMeteringConfig(
|
|
enabled=options.enable_resource_consumption_metering
|
|
)
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredResourceUsageExportConfig=export_config
|
|
)
|
|
elif options.enable_network_egress_metering is not None:
|
|
raise util.Error(ENABLE_NETWORK_EGRESS_METERING_ERROR_MSG)
|
|
elif options.enable_resource_consumption_metering is not None:
|
|
raise util.Error(ENABLE_RESOURCE_CONSUMPTION_METERING_ERROR_MSG)
|
|
elif options.clear_resource_usage_bigquery_dataset is not None:
|
|
export_config = self.messages.ResourceUsageExportConfig()
|
|
update = self.messages.ClusterUpdate(
|
|
desiredResourceUsageExportConfig=export_config
|
|
)
|
|
elif options.security_profile is not None:
|
|
# security_profile is set in update command
|
|
security_profile = self.messages.SecurityProfile(
|
|
name=options.security_profile
|
|
)
|
|
update = self.messages.ClusterUpdate(securityProfile=security_profile)
|
|
elif options.enable_intra_node_visibility is not None:
|
|
intra_node_visibility_config = self.messages.IntraNodeVisibilityConfig(
|
|
enabled=options.enable_intra_node_visibility
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredIntraNodeVisibilityConfig=intra_node_visibility_config
|
|
)
|
|
elif options.managed_otel_scope:
|
|
managed_otel_config = _GetManagedOpenTelemetryConfig(
|
|
options, self.messages
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredManagedOpentelemetryConfig=managed_otel_config
|
|
)
|
|
|
|
if options.enable_pod_snapshots is not None:
|
|
addons = self.messages.AddonsConfig(
|
|
podSnapshotConfig=self.messages.PodSnapshotConfig(
|
|
enabled=options.enable_pod_snapshots
|
|
)
|
|
)
|
|
update = self.messages.ClusterUpdate(desiredAddonsConfig=addons)
|
|
|
|
if options.enable_slice_controller is not None:
|
|
addons = self.messages.AddonsConfig(
|
|
sliceControllerConfig=self.messages.SliceControllerConfig(
|
|
enabled=options.enable_slice_controller
|
|
)
|
|
)
|
|
update = self.messages.ClusterUpdate(desiredAddonsConfig=addons)
|
|
|
|
if (
|
|
options.security_profile is not None
|
|
and options.security_profile_runtime_rules is not None
|
|
):
|
|
update.securityProfile.disableRuntimeRules = (
|
|
not options.security_profile_runtime_rules
|
|
)
|
|
if (
|
|
options.master_authorized_networks
|
|
and not options.enable_master_authorized_networks
|
|
):
|
|
# Raise error if use --master-authorized-networks without
|
|
# --enable-master-authorized-networks.
|
|
raise util.Error(MISMATCH_AUTHORIZED_NETWORKS_ERROR_MSG)
|
|
|
|
if options.database_encryption_key:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredDatabaseEncryption=self.messages.DatabaseEncryption(
|
|
keyName=options.database_encryption_key,
|
|
state=self.messages.DatabaseEncryption.StateValueValuesEnum.ENCRYPTED,
|
|
)
|
|
)
|
|
|
|
elif options.disable_database_encryption:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredDatabaseEncryption=self.messages.DatabaseEncryption(
|
|
state=self.messages.DatabaseEncryption.StateValueValuesEnum.DECRYPTED
|
|
)
|
|
)
|
|
|
|
if options.enable_shielded_nodes is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredShieldedNodes=self.messages.ShieldedNodes(
|
|
enabled=options.enable_shielded_nodes
|
|
)
|
|
)
|
|
if options.enable_tpu is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredTpuConfig=_GetTpuConfigForClusterUpdate(options, self.messages)
|
|
)
|
|
|
|
if options.release_channel is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredReleaseChannel=_GetReleaseChannel(options, self.messages)
|
|
)
|
|
|
|
if options.patch_update is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
gkeAutoUpgradeConfig=_GetGkeAutoUpgradeConfig(options, self.messages)
|
|
)
|
|
|
|
if options.disable_default_snat is not None:
|
|
disable_default_snat = self.messages.DefaultSnatStatus(
|
|
disabled=options.disable_default_snat
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredDefaultSnatStatus=disable_default_snat
|
|
)
|
|
if options.enable_l4_ilb_subsetting is not None:
|
|
ilb_subsettting_config = self.messages.ILBSubsettingConfig(
|
|
enabled=options.enable_l4_ilb_subsetting
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredL4ilbSubsettingConfig=ilb_subsettting_config
|
|
)
|
|
if options.private_ipv6_google_access_type is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredPrivateIpv6GoogleAccess=util.GetPrivateIpv6GoogleAccessTypeMapperForUpdate(
|
|
self.messages, hidden=False
|
|
).GetEnumForChoice(
|
|
options.private_ipv6_google_access_type
|
|
)
|
|
)
|
|
|
|
dns_config = self.ParseClusterDNSOptions(
|
|
options, is_update=True, cluster_ref=cluster_ref
|
|
)
|
|
if dns_config is not None:
|
|
update = self.messages.ClusterUpdate(desiredDnsConfig=dns_config)
|
|
|
|
gateway_config = self.ParseGatewayOptions(options)
|
|
if gateway_config is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredGatewayApiConfig=gateway_config
|
|
)
|
|
|
|
if options.notification_config is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNotificationConfig=_GetNotificationConfigForClusterUpdate(
|
|
options, self.messages
|
|
)
|
|
)
|
|
|
|
if options.disable_autopilot is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAutopilot=self.messages.Autopilot(enabled=False)
|
|
)
|
|
|
|
if options.security_group is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAuthenticatorGroupsConfig=self.messages.AuthenticatorGroupsConfig(
|
|
enabled=True, securityGroup=options.security_group
|
|
)
|
|
)
|
|
|
|
if options.enable_gcfs is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredGcfsConfig=self.messages.GcfsConfig(
|
|
enabled=options.enable_gcfs
|
|
)
|
|
)
|
|
|
|
if options.autoprovisioning_network_tags is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNodePoolAutoConfigNetworkTags=self.messages.NetworkTags(
|
|
tags=options.autoprovisioning_network_tags
|
|
)
|
|
)
|
|
|
|
if options.autoprovisioning_resource_manager_tags is not None:
|
|
tags = options.autoprovisioning_resource_manager_tags
|
|
rm_tags = self._ResourceManagerTags(tags)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNodePoolAutoConfigResourceManagerTags=rm_tags
|
|
)
|
|
|
|
if options.enable_image_streaming is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredGcfsConfig=self.messages.GcfsConfig(
|
|
enabled=options.enable_image_streaming
|
|
)
|
|
)
|
|
|
|
if options.enable_mesh_certificates is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredMeshCertificates=self.messages.MeshCertificates(
|
|
enableCertificates=options.enable_mesh_certificates
|
|
)
|
|
)
|
|
|
|
if options.maintenance_interval is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredStableFleetConfig=_GetStableFleetConfig(options, self.messages)
|
|
)
|
|
|
|
if options.enable_service_externalips is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredServiceExternalIpsConfig=self.messages.ServiceExternalIPsConfig(
|
|
enabled=options.enable_service_externalips
|
|
)
|
|
)
|
|
|
|
if options.enable_identity_service is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredIdentityServiceConfig=self.messages.IdentityServiceConfig(
|
|
enabled=options.enable_identity_service
|
|
)
|
|
)
|
|
|
|
if (
|
|
options.enable_workload_config_audit is not None
|
|
or options.enable_workload_vulnerability_scanning is not None
|
|
):
|
|
protect_config = self.messages.ProtectConfig()
|
|
if options.enable_workload_config_audit is not None:
|
|
protect_config.workloadConfig = self.messages.WorkloadConfig()
|
|
if options.enable_workload_config_audit:
|
|
protect_config.workloadConfig.auditMode = (
|
|
self.messages.WorkloadConfig.AuditModeValueValuesEnum.BASIC
|
|
)
|
|
else:
|
|
protect_config.workloadConfig.auditMode = (
|
|
self.messages.WorkloadConfig.AuditModeValueValuesEnum.DISABLED
|
|
)
|
|
|
|
if options.enable_workload_vulnerability_scanning is not None:
|
|
if options.enable_workload_vulnerability_scanning:
|
|
protect_config.workloadVulnerabilityMode = (
|
|
self.messages.ProtectConfig.WorkloadVulnerabilityModeValueValuesEnum.BASIC
|
|
)
|
|
else:
|
|
protect_config.workloadVulnerabilityMode = (
|
|
self.messages.ProtectConfig.WorkloadVulnerabilityModeValueValuesEnum.DISABLED
|
|
)
|
|
update = self.messages.ClusterUpdate(desiredProtectConfig=protect_config)
|
|
|
|
if options.hpa_profile is not None:
|
|
if options.hpa_profile == 'performance':
|
|
pod_autoscaling_config = self.messages.PodAutoscaling(
|
|
hpaProfile=self.messages.PodAutoscaling.HpaProfileValueValuesEnum.PERFORMANCE
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredPodAutoscaling=pod_autoscaling_config
|
|
)
|
|
elif options.hpa_profile == 'none':
|
|
pod_autoscaling_config = self.messages.PodAutoscaling(
|
|
hpaProfile=self.messages.PodAutoscaling.HpaProfileValueValuesEnum.NONE
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredPodAutoscaling=pod_autoscaling_config
|
|
)
|
|
|
|
if options.logging_variant is not None:
|
|
logging_config = self.messages.NodePoolLoggingConfig()
|
|
logging_config.variantConfig = self.messages.LoggingVariantConfig(
|
|
variant=VariantConfigEnumFromString(
|
|
self.messages, options.logging_variant
|
|
)
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNodePoolLoggingConfig=logging_config
|
|
)
|
|
|
|
if (
|
|
options.additional_pod_ipv4_ranges
|
|
or options.removed_additional_pod_ipv4_ranges
|
|
):
|
|
update = self.messages.ClusterUpdate()
|
|
if options.additional_pod_ipv4_ranges:
|
|
update.additionalPodRangesConfig = (
|
|
self.messages.AdditionalPodRangesConfig(
|
|
podRangeNames=options.additional_pod_ipv4_ranges
|
|
)
|
|
)
|
|
if options.removed_additional_pod_ipv4_ranges:
|
|
update.removedAdditionalPodRangesConfig = (
|
|
self.messages.AdditionalPodRangesConfig(
|
|
podRangeNames=options.removed_additional_pod_ipv4_ranges
|
|
)
|
|
)
|
|
|
|
if options.stack_type is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredStackType=util.GetUpdateStackTypeMapper(
|
|
self.messages
|
|
).GetEnumForChoice(options.stack_type)
|
|
)
|
|
|
|
if options.enable_cost_allocation is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredCostManagementConfig=self.messages.CostManagementConfig(
|
|
enabled=options.enable_cost_allocation
|
|
)
|
|
)
|
|
membership_types = {
|
|
'LIGHTWEIGHT': (
|
|
self.messages.Fleet.MembershipTypeValueValuesEnum.LIGHTWEIGHT
|
|
),
|
|
'MEMBERSHIP_TYPE_UNSPECIFIED': (
|
|
self.messages.Fleet.MembershipTypeValueValuesEnum.MEMBERSHIP_TYPE_UNSPECIFIED
|
|
),
|
|
}
|
|
if options.enable_fleet:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredFleet=self.messages.Fleet(
|
|
project=cluster_ref.projectId,
|
|
membershipType=membership_types.get(
|
|
options.membership_type, None
|
|
),
|
|
)
|
|
)
|
|
|
|
if options.fleet_project:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredFleet=self.messages.Fleet(
|
|
project=options.fleet_project,
|
|
membershipType=membership_types.get(
|
|
options.membership_type, None
|
|
),
|
|
)
|
|
)
|
|
|
|
if options.unset_membership_type:
|
|
fleet_project = options.fleet_project or cluster_ref.projectId
|
|
update = self.messages.ClusterUpdate(
|
|
desiredFleet=self.messages.Fleet(
|
|
membershipType=self.messages.Fleet.MembershipTypeValueValuesEnum.MEMBERSHIP_TYPE_UNSPECIFIED,
|
|
project=fleet_project,
|
|
),
|
|
)
|
|
|
|
if options.enable_k8s_beta_apis is not None:
|
|
config_obj = self.messages.K8sBetaAPIConfig()
|
|
config_obj.enabledApis = options.enable_k8s_beta_apis
|
|
update = self.messages.ClusterUpdate(desiredK8sBetaApis=config_obj)
|
|
|
|
if options.clear_fleet_project:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredFleet=self.messages.Fleet(project='')
|
|
)
|
|
|
|
if (
|
|
options.compliance is not None
|
|
or options.compliance_standards is not None
|
|
):
|
|
# --compliance=disabled and --compliance-standards=a,b,c are mutually
|
|
# exclusive.
|
|
if options.compliance == 'disabled' and options.compliance_standards:
|
|
raise util.Error(COMPLIANCE_DISABLED_CONFIGURATION)
|
|
|
|
# Desired configuration to set.
|
|
compliance_update = self.messages.CompliancePostureConfig()
|
|
# Current configuration, if any.
|
|
cluster = self.GetCluster(cluster_ref)
|
|
|
|
compliance_mode = (
|
|
options.compliance.lower() if options.compliance else None
|
|
)
|
|
if (
|
|
compliance_mode is None
|
|
): # If not provided, look for current configuration.
|
|
if cluster.compliancePostureConfig is not None:
|
|
compliance_update.mode = cluster.compliancePostureConfig.mode
|
|
elif compliance_mode == 'disabled':
|
|
compliance_update.mode = (
|
|
self.messages.CompliancePostureConfig.ModeValueValuesEnum.DISABLED
|
|
)
|
|
elif compliance_mode == 'enabled':
|
|
compliance_update.mode = (
|
|
self.messages.CompliancePostureConfig.ModeValueValuesEnum.ENABLED
|
|
)
|
|
else: # Invalid input.
|
|
raise util.Error(
|
|
COMPLIANCE_MODE_NOT_SUPPORTED.format(mode=options.compliance)
|
|
)
|
|
|
|
if options.compliance_standards is None:
|
|
# If not provided, look for current configuration.
|
|
if cluster.compliancePostureConfig is not None:
|
|
compliance_update.complianceStandards = (
|
|
cluster.compliancePostureConfig.complianceStandards
|
|
)
|
|
# Otherwise do nothing.
|
|
elif not options.compliance_standards: # Empty input is invalid.
|
|
raise util.Error(
|
|
COMPLIANCE_INVALID_STANDARDS_CONFIGURATION.format(
|
|
standards=options.compliance_standards
|
|
)
|
|
)
|
|
else: # If a list, build new standards configuration.
|
|
compliance_update.complianceStandards = [
|
|
self.messages.ComplianceStandard(standard=standard)
|
|
for standard in options.compliance_standards.split(',')
|
|
]
|
|
|
|
update = self.messages.ClusterUpdate(
|
|
desiredCompliancePostureConfig=compliance_update
|
|
)
|
|
|
|
if options.enable_security_posture is not None:
|
|
security_posture_config = self.messages.SecurityPostureConfig()
|
|
if options.enable_security_posture:
|
|
security_posture_config.mode = (
|
|
self.messages.SecurityPostureConfig.ModeValueValuesEnum.BASIC
|
|
)
|
|
else:
|
|
security_posture_config.mode = (
|
|
self.messages.SecurityPostureConfig.ModeValueValuesEnum.DISABLED
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredSecurityPostureConfig=security_posture_config
|
|
)
|
|
|
|
if options.security_posture is not None:
|
|
security_posture_config = self.messages.SecurityPostureConfig()
|
|
if options.security_posture.lower() == 'enterprise':
|
|
security_posture_config.mode = (
|
|
self.messages.SecurityPostureConfig.ModeValueValuesEnum.ENTERPRISE
|
|
)
|
|
elif options.security_posture.lower() == 'standard':
|
|
security_posture_config.mode = (
|
|
self.messages.SecurityPostureConfig.ModeValueValuesEnum.BASIC
|
|
)
|
|
elif options.security_posture.lower() == 'disabled':
|
|
security_posture_config.mode = (
|
|
self.messages.SecurityPostureConfig.ModeValueValuesEnum.DISABLED
|
|
)
|
|
else:
|
|
raise util.Error(
|
|
SECURITY_POSTURE_MODE_NOT_SUPPORTED.format(
|
|
mode=options.security_posture.lower()
|
|
)
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredSecurityPostureConfig=security_posture_config
|
|
)
|
|
|
|
if options.workload_vulnerability_scanning is not None:
|
|
security_posture_config = self.messages.SecurityPostureConfig()
|
|
if options.workload_vulnerability_scanning.lower() == 'standard':
|
|
security_posture_config.vulnerabilityMode = (
|
|
self.messages.SecurityPostureConfig.VulnerabilityModeValueValuesEnum.VULNERABILITY_BASIC
|
|
)
|
|
elif options.workload_vulnerability_scanning.lower() == 'disabled':
|
|
security_posture_config.vulnerabilityMode = (
|
|
self.messages.SecurityPostureConfig.VulnerabilityModeValueValuesEnum.VULNERABILITY_DISABLED
|
|
)
|
|
elif options.workload_vulnerability_scanning.lower() == 'enterprise':
|
|
security_posture_config.vulnerabilityMode = (
|
|
self.messages.SecurityPostureConfig.VulnerabilityModeValueValuesEnum.VULNERABILITY_ENTERPRISE
|
|
)
|
|
else:
|
|
raise util.Error(
|
|
WORKLOAD_VULNERABILITY_SCANNING_MODE_NOT_SUPPORTED.format(
|
|
mode=options.workload_vulnerability_scanning.lower()
|
|
)
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredSecurityPostureConfig=security_posture_config
|
|
)
|
|
|
|
if options.enable_runtime_vulnerability_insight is not None:
|
|
runtime_vulnerability_insight_config = (
|
|
self.messages.RuntimeVulnerabilityInsightConfig()
|
|
)
|
|
if options.enable_runtime_vulnerability_insight:
|
|
runtime_vulnerability_insight_config.mode = (
|
|
self.messages.RuntimeVulnerabilityInsightConfig.ModeValueValuesEnum.PREMIUM_VULNERABILITY_SCAN
|
|
)
|
|
else:
|
|
runtime_vulnerability_insight_config.mode = (
|
|
self.messages.RuntimeVulnerabilityInsightConfig.ModeValueValuesEnum.DISABLED
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredRuntimeVulnerabilityInsightConfig=(
|
|
runtime_vulnerability_insight_config
|
|
)
|
|
)
|
|
|
|
if options.network_performance_config:
|
|
perf = self._GetClusterNetworkPerformanceConfig(options)
|
|
update = self.messages.ClusterUpdate(desiredNetworkPerformanceConfig=perf)
|
|
|
|
if options.workload_policies is not None:
|
|
workload_policies = self.messages.WorkloadPolicyConfig()
|
|
if options.workload_policies == 'allow-net-admin':
|
|
workload_policies.allowNetAdmin = True
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAutopilotWorkloadPolicyConfig=workload_policies
|
|
)
|
|
|
|
if options.remove_workload_policies is not None:
|
|
workload_policies = self.messages.WorkloadPolicyConfig()
|
|
if options.remove_workload_policies == 'allow-net-admin':
|
|
workload_policies.allowNetAdmin = False
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAutopilotWorkloadPolicyConfig=workload_policies
|
|
)
|
|
|
|
if options.host_maintenance_interval is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredHostMaintenancePolicy=_GetHostMaintenancePolicy(
|
|
options, self.messages, CLUSTER
|
|
)
|
|
)
|
|
|
|
if options.in_transit_encryption is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredInTransitEncryptionConfig=util.GetUpdateInTransitEncryptionConfigMapper(
|
|
self.messages
|
|
).GetEnumForChoice(
|
|
options.in_transit_encryption
|
|
)
|
|
)
|
|
|
|
if options.enable_multi_networking is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredEnableMultiNetworking=options.enable_multi_networking
|
|
)
|
|
|
|
if options.containerd_config_from_file is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredContainerdConfig=self.messages.ContainerdConfig()
|
|
)
|
|
util.LoadContainerdConfigFromYAML(
|
|
update.desiredContainerdConfig,
|
|
options.containerd_config_from_file,
|
|
self.messages,
|
|
)
|
|
|
|
if (
|
|
options.enable_secret_manager_rotation is not None
|
|
or options.secret_manager_rotation_interval is not None
|
|
or options.enable_secret_manager is not None
|
|
):
|
|
old_cluster = self.GetCluster(cluster_ref)
|
|
secret_manager_config = old_cluster.secretManagerConfig
|
|
if options.enable_secret_manager is not None:
|
|
if secret_manager_config is None:
|
|
secret_manager_config = self.messages.SecretManagerConfig()
|
|
secret_manager_config.enabled = options.enable_secret_manager
|
|
if options.enable_secret_manager_rotation is not None:
|
|
if secret_manager_config is None:
|
|
secret_manager_config = self.messages.SecretManagerConfig()
|
|
if secret_manager_config.rotationConfig is None:
|
|
secret_manager_config.rotationConfig = self.messages.RotationConfig()
|
|
secret_manager_config.rotationConfig.enabled = (
|
|
options.enable_secret_manager_rotation
|
|
)
|
|
if options.secret_manager_rotation_interval is not None:
|
|
if secret_manager_config is None:
|
|
secret_manager_config = self.messages.SecretManagerConfig()
|
|
if secret_manager_config.rotationConfig is None:
|
|
secret_manager_config.rotationConfig = self.messages.RotationConfig()
|
|
secret_manager_config.rotationConfig.rotationInterval = (
|
|
options.secret_manager_rotation_interval
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredSecretManagerConfig=secret_manager_config
|
|
)
|
|
|
|
if (
|
|
options.enable_secret_sync is not None
|
|
or options.secret_sync_rotation_interval is not None
|
|
or options.enable_secret_sync_rotation is not None
|
|
):
|
|
old_cluster = self.GetCluster(cluster_ref)
|
|
secret_sync_config = old_cluster.secretSyncConfig
|
|
if options.enable_secret_sync is not None:
|
|
if secret_sync_config is None:
|
|
secret_sync_config = self.messages.SecretSyncConfig()
|
|
secret_sync_config.enabled = options.enable_secret_sync
|
|
if options.enable_secret_sync_rotation is not None:
|
|
if secret_sync_config is None:
|
|
secret_sync_config = self.messages.SecretSyncConfig()
|
|
if secret_sync_config.rotationConfig is None:
|
|
secret_sync_config.rotationConfig = self.messages.SyncRotationConfig()
|
|
secret_sync_config.rotationConfig.enabled = (
|
|
options.enable_secret_sync_rotation
|
|
)
|
|
if options.secret_sync_rotation_interval is not None:
|
|
if secret_sync_config is None:
|
|
secret_sync_config = self.messages.SecretSyncConfig()
|
|
if secret_sync_config.rotationConfig is None:
|
|
secret_sync_config.rotationConfig = self.messages.RotationConfig()
|
|
secret_sync_config.rotationConfig.rotationInterval = (
|
|
options.secret_sync_rotation_interval
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredSecretSyncConfig=secret_sync_config
|
|
)
|
|
|
|
if options.enable_cilium_clusterwide_network_policy is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredEnableCiliumClusterwideNetworkPolicy=(
|
|
options.enable_cilium_clusterwide_network_policy
|
|
)
|
|
)
|
|
|
|
if options.enable_fqdn_network_policy is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredEnableFqdnNetworkPolicy=options.enable_fqdn_network_policy
|
|
)
|
|
|
|
if (
|
|
options.enable_insecure_binding_system_authenticated is not None
|
|
or options.enable_insecure_binding_system_unauthenticated is not None
|
|
):
|
|
confg = self.messages.RBACBindingConfig()
|
|
if options.enable_insecure_binding_system_authenticated is not None:
|
|
confg.enableInsecureBindingSystemAuthenticated = (
|
|
options.enable_insecure_binding_system_authenticated
|
|
)
|
|
if options.enable_insecure_binding_system_unauthenticated is not None:
|
|
confg.enableInsecureBindingSystemUnauthenticated = (
|
|
options.enable_insecure_binding_system_unauthenticated
|
|
)
|
|
update = self.messages.ClusterUpdate(desiredRBACBindingConfig=confg)
|
|
|
|
if options.autopilot_privileged_admission is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredPrivilegedAdmissionConfig=self.messages.PrivilegedAdmissionConfig(
|
|
allowlistPaths=options.autopilot_privileged_admission or ['']
|
|
)
|
|
)
|
|
|
|
if options.enable_private_nodes is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredDefaultEnablePrivateNodes=options.enable_private_nodes
|
|
)
|
|
|
|
if (
|
|
options.enable_dns_access is not None
|
|
or options.enable_ip_access is not None
|
|
or options.enable_master_global_access is not None
|
|
or options.enable_private_endpoint is not None
|
|
or options.enable_master_authorized_networks is not None
|
|
or options.enable_google_cloud_access is not None
|
|
or options.enable_authorized_networks_on_private_endpoint is not None
|
|
or options.enable_k8s_tokens_via_dns is not None
|
|
or options.enable_k8s_certs_via_dns is not None
|
|
):
|
|
cp_endpoints_config = self._GetDesiredControlPlaneEndpointsConfig(
|
|
cluster_ref, options
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredControlPlaneEndpointsConfig=cp_endpoints_config
|
|
)
|
|
|
|
if (
|
|
options.additional_ip_ranges is not None
|
|
or options.remove_additional_ip_ranges is not None
|
|
):
|
|
cluster = self.GetCluster(cluster_ref)
|
|
desired_ip_ranges = {}
|
|
desired_statuses = {}
|
|
if cluster.ipAllocationPolicy:
|
|
config = cluster.ipAllocationPolicy.additionalIpRangesConfigs
|
|
if config:
|
|
for ip_range in config:
|
|
secondary_ranges = set(ip_range.podIpv4RangeNames)
|
|
desired_ip_ranges[ip_range.subnetwork] = secondary_ranges
|
|
desired_statuses[ip_range.subnetwork] = ip_range.status
|
|
|
|
if options.additional_ip_ranges is not None:
|
|
for ip_range in options.additional_ip_ranges:
|
|
subnetwork = SubnetworkNameToPath(
|
|
ip_range['subnetwork'], cluster_ref.projectId, cluster_ref.zone
|
|
)
|
|
secondary_ranges = (
|
|
desired_ip_ranges[subnetwork]
|
|
if subnetwork in desired_ip_ranges
|
|
else set()
|
|
)
|
|
secondary_ranges.add(ip_range['pod-ipv4-range'])
|
|
desired_ip_ranges[subnetwork] = secondary_ranges
|
|
desired_statuses[subnetwork] = None
|
|
|
|
if options.remove_additional_ip_ranges is not None:
|
|
for ip_remove in options.remove_additional_ip_ranges:
|
|
subnetwork = SubnetworkNameToPath(
|
|
ip_remove['subnetwork'], cluster_ref.projectId, cluster_ref.zone
|
|
)
|
|
if subnetwork not in desired_ip_ranges:
|
|
raise util.Error(
|
|
ADDITIONAL_SUBNETWORKS_NOT_FOUND.format(subnetwork=subnetwork)
|
|
)
|
|
if 'pod-ipv4-range' in ip_remove:
|
|
removed_range = ip_remove['pod-ipv4-range']
|
|
try:
|
|
desired_ip_ranges[subnetwork].remove(removed_range)
|
|
if not desired_ip_ranges[subnetwork]:
|
|
desired_ip_ranges.pop(subnetwork)
|
|
except KeyError:
|
|
raise util.Error(
|
|
ADDITIONAL_SUBNETWORKS_POD_RANG_ENOT_FOUND.format(
|
|
range=removed_range
|
|
)
|
|
)
|
|
else:
|
|
desired_ip_ranges.pop(subnetwork)
|
|
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAdditionalIpRangesConfig=self.messages.DesiredAdditionalIPRangesConfig(
|
|
additionalIpRangesConfigs=[
|
|
self.messages.AdditionalIPRangesConfig(
|
|
subnetwork=subnetwork,
|
|
podIpv4RangeNames=list(secondary_ranges),
|
|
status=desired_statuses[subnetwork],
|
|
)
|
|
for subnetwork, secondary_ranges in desired_ip_ranges.items()
|
|
]
|
|
)
|
|
)
|
|
|
|
if (
|
|
options.drain_additional_ip_ranges is not None
|
|
or options.undrain_additional_ip_ranges is not None
|
|
):
|
|
cluster = self.GetCluster(cluster_ref)
|
|
desired_ip_ranges = {}
|
|
desired_statuses = {}
|
|
if cluster.ipAllocationPolicy:
|
|
config = cluster.ipAllocationPolicy.additionalIpRangesConfigs
|
|
if config:
|
|
for ip_range in config:
|
|
secondary_ranges = set(ip_range.podIpv4RangeNames)
|
|
desired_ip_ranges[ip_range.subnetwork] = secondary_ranges
|
|
desired_statuses[ip_range.subnetwork] = ip_range.status
|
|
|
|
if options.drain_additional_ip_ranges is not None:
|
|
for subnet_to_drain in options.drain_additional_ip_ranges:
|
|
subnetwork = SubnetworkNameToPath(
|
|
subnet_to_drain['subnetwork'],
|
|
cluster_ref.projectId,
|
|
cluster_ref.zone,
|
|
)
|
|
if subnetwork not in desired_ip_ranges:
|
|
raise util.Error(
|
|
ADDITIONAL_SUBNETWORKS_NOT_FOUND.format(subnetwork=subnetwork)
|
|
)
|
|
secondary_ranges = desired_ip_ranges[subnetwork]
|
|
desired_ip_ranges[subnetwork] = secondary_ranges
|
|
desired_statuses[subnetwork] = (
|
|
self.messages.AdditionalIPRangesConfig.StatusValueValuesEnum.DRAINING
|
|
)
|
|
|
|
if options.undrain_additional_ip_ranges is not None:
|
|
for subnet_to_undrain in options.undrain_additional_ip_ranges:
|
|
subnetwork = SubnetworkNameToPath(
|
|
subnet_to_undrain['subnetwork'],
|
|
cluster_ref.projectId,
|
|
cluster_ref.zone,
|
|
)
|
|
if subnetwork not in desired_ip_ranges:
|
|
raise util.Error(
|
|
ADDITIONAL_SUBNETWORKS_NOT_FOUND.format(subnetwork=subnetwork)
|
|
)
|
|
secondary_ranges = desired_ip_ranges[subnetwork]
|
|
desired_ip_ranges[subnetwork] = secondary_ranges
|
|
desired_statuses[subnetwork] = (
|
|
self.messages.AdditionalIPRangesConfig.StatusValueValuesEnum.ACTIVE
|
|
)
|
|
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAdditionalIpRangesConfig=self.messages.DesiredAdditionalIPRangesConfig(
|
|
additionalIpRangesConfigs=[
|
|
self.messages.AdditionalIPRangesConfig(
|
|
subnetwork=subnetwork,
|
|
podIpv4RangeNames=list(secondary_ranges),
|
|
status=desired_statuses[subnetwork],
|
|
)
|
|
for subnetwork, secondary_ranges in desired_ip_ranges.items()
|
|
]
|
|
)
|
|
)
|
|
if options.disable_l4_lb_firewall_reconciliation:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredDisableL4LbFirewallReconciliation=True
|
|
)
|
|
if options.enable_l4_lb_firewall_reconciliation:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredDisableL4LbFirewallReconciliation=False
|
|
)
|
|
|
|
if options.tier is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredEnterpriseConfig=_GetDesiredEnterpriseConfig(
|
|
options, self.messages
|
|
)
|
|
)
|
|
|
|
if options.enable_autopilot_compatibility_auditing is not None:
|
|
workload_policies = self.messages.WorkloadPolicyConfig()
|
|
workload_policies.autopilotCompatibilityAuditingEnabled = (
|
|
options.enable_autopilot_compatibility_auditing
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAutopilotWorkloadPolicyConfig=workload_policies
|
|
)
|
|
|
|
if options.service_account_verification_keys is not None:
|
|
cluster = self.GetCluster(cluster_ref)
|
|
updated_user_managed_keys_config = self.messages.UserManagedKeysConfig()
|
|
if cluster.userManagedKeysConfig is not None:
|
|
updated_user_managed_keys_config = cluster.userManagedKeysConfig
|
|
updated_user_managed_keys_config.serviceAccountVerificationKeys = (
|
|
options.service_account_verification_keys
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredUserManagedKeysConfig=updated_user_managed_keys_config
|
|
)
|
|
|
|
if options.service_account_signing_keys is not None:
|
|
cluster = self.GetCluster(cluster_ref)
|
|
updated_user_managed_keys_config = self.messages.UserManagedKeysConfig()
|
|
if cluster.userManagedKeysConfig is not None:
|
|
updated_user_managed_keys_config = cluster.userManagedKeysConfig
|
|
updated_user_managed_keys_config.serviceAccountSigningKeys = (
|
|
options.service_account_signing_keys
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredUserManagedKeysConfig=updated_user_managed_keys_config
|
|
)
|
|
if options.control_plane_disk_encryption_key is not None:
|
|
cluster = self.GetCluster(cluster_ref)
|
|
updated_user_managed_keys_config = self.messages.UserManagedKeysConfig()
|
|
if cluster.userManagedKeysConfig is not None:
|
|
updated_user_managed_keys_config = cluster.userManagedKeysConfig
|
|
updated_user_managed_keys_config.controlPlaneDiskEncryptionKey = (
|
|
options.control_plane_disk_encryption_key
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredUserManagedKeysConfig=updated_user_managed_keys_config
|
|
)
|
|
if options.disable_auto_ipam:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAutoIpamConfig=self.messages.AutoIpamConfig(enabled=False)
|
|
)
|
|
if options.enable_auto_ipam:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAutoIpamConfig=self.messages.AutoIpamConfig(enabled=True)
|
|
)
|
|
if options.anonymous_authentication_config is not None:
|
|
modes = {
|
|
'LIMITED': (
|
|
self.messages.DesiredAnonymousAuthenticationConfig.ModeValueValuesEnum.LIMITED
|
|
),
|
|
'ENABLED': (
|
|
self.messages.DesiredAnonymousAuthenticationConfig.ModeValueValuesEnum.ENABLED
|
|
),
|
|
}
|
|
config = self.messages.DesiredAnonymousAuthenticationConfig()
|
|
config.mode = modes[options.anonymous_authentication_config]
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAnonymousAuthenticationConfig=config
|
|
)
|
|
if options.network_tier is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNetworkTierConfig=_GetNetworkTierConfig(options, self.messages)
|
|
)
|
|
|
|
if options.control_plane_egress_mode is not None:
|
|
modes = {
|
|
'NONE': (
|
|
self.messages.DesiredControlPlaneEgress.ModeValueValuesEnum.NONE
|
|
),
|
|
'VIA_CONTROL_PLANE': (
|
|
self.messages.DesiredControlPlaneEgress.ModeValueValuesEnum.VIA_CONTROL_PLANE
|
|
),
|
|
}
|
|
config = self.messages.DesiredControlPlaneEgress()
|
|
config.mode = modes[options.control_plane_egress_mode]
|
|
update = self.messages.ClusterUpdate(desiredControlPlaneEgress=config)
|
|
|
|
if options.autopilot_general_profile:
|
|
autopilot_general_profile_enum = _GetAutopilotGeneralProfileEnum(
|
|
options, self.messages
|
|
)
|
|
if autopilot_general_profile_enum:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredClusterAutoscaling=self.messages.ClusterAutoscaling(
|
|
autopilotGeneralProfile=autopilot_general_profile_enum
|
|
)
|
|
)
|
|
|
|
return update
|
|
|
|
def UpdateCluster(self, cluster_ref, options):
|
|
"""Handles UpdateCluster options that are specific to a release track.
|
|
|
|
Overridden in each release track.
|
|
|
|
Args:
|
|
cluster_ref: Name and location of the cluster.
|
|
options: An UpdateClusterOptions containining the user-specified options.
|
|
|
|
Returns:
|
|
The operation to be executed.
|
|
"""
|
|
|
|
update = self.UpdateClusterCommon(cluster_ref, options)
|
|
|
|
if options.workload_pool:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredWorkloadIdentityConfig=self.messages.WorkloadIdentityConfig(
|
|
workloadPool=options.workload_pool
|
|
)
|
|
)
|
|
elif options.disable_workload_identity:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredWorkloadIdentityConfig=self.messages.WorkloadIdentityConfig(
|
|
workloadPool=''
|
|
)
|
|
)
|
|
|
|
if not update:
|
|
# if reached here, it's possible:
|
|
# - someone added update flags but not handled
|
|
# - none of the update flags specified from command line
|
|
# so raise an error with readable message like:
|
|
# Nothing to update
|
|
# to catch this error.
|
|
raise util.Error(NOTHING_TO_UPDATE_ERROR_MSG)
|
|
|
|
if options.disable_addons is not None:
|
|
if any(
|
|
(options.disable_addons.get(v) is not None) for v in CLOUDRUN_ADDONS
|
|
):
|
|
load_balancer_type = _GetCloudRunLoadBalancerType(
|
|
options, self.messages
|
|
)
|
|
update.desiredAddonsConfig.cloudRunConfig = (
|
|
self.messages.CloudRunConfig(
|
|
disabled=any(
|
|
options.disable_addons.get(v) or False
|
|
for v in CLOUDRUN_ADDONS
|
|
),
|
|
loadBalancerType=load_balancer_type,
|
|
)
|
|
)
|
|
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def SetLoggingService(self, cluster_ref, logging_service):
|
|
op = self.client.projects_locations_clusters.SetLogging(
|
|
self.messages.SetLoggingServiceRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
loggingService=logging_service,
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def SetLegacyAuthorization(self, cluster_ref, enable_legacy_authorization):
|
|
op = self.client.projects_locations_clusters.SetLegacyAbac(
|
|
self.messages.SetLegacyAbacRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
enabled=bool(enable_legacy_authorization),
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def _AddonsConfig(
|
|
self,
|
|
disable_ingress=None,
|
|
disable_hpa=None,
|
|
disable_dashboard=None,
|
|
disable_network_policy=None,
|
|
enable_node_local_dns=None,
|
|
enable_gcepd_csi_driver=None,
|
|
enable_filestore_csi_driver=None,
|
|
enable_application_manager=None,
|
|
enable_cloud_build=None,
|
|
enable_backup_restore=None,
|
|
enable_gcsfuse_csi_driver=None,
|
|
enable_stateful_ha=None,
|
|
enable_parallelstore_csi_driver=None,
|
|
enable_high_scale_checkpointing=None,
|
|
enable_lustre_csi_driver=None,
|
|
enable_pod_snapshots=None,
|
|
enable_ray_operator=None,
|
|
enable_slice_controller=None,
|
|
):
|
|
"""Generates an AddonsConfig object given specific parameters.
|
|
|
|
Args:
|
|
disable_ingress: whether to disable the GCLB ingress controller.
|
|
disable_hpa: whether to disable the horizontal pod autoscaling controller.
|
|
disable_dashboard: whether to disable the Kubernetes Dashboard.
|
|
disable_network_policy: whether to disable NetworkPolicy enforcement.
|
|
enable_node_local_dns: whether to enable NodeLocalDNS cache.
|
|
enable_gcepd_csi_driver: whether to enable GcePersistentDiskCsiDriver.
|
|
enable_filestore_csi_driver: wherher to enable GcpFilestoreCsiDriver.
|
|
enable_application_manager: whether to enable ApplicationManager.
|
|
enable_cloud_build: whether to enable CloudBuild.
|
|
enable_backup_restore: whether to enable BackupRestore.
|
|
enable_gcsfuse_csi_driver: whether to enable GcsFuseCsiDriver.
|
|
enable_stateful_ha: whether to enable StatefulHA addon.
|
|
enable_parallelstore_csi_driver: whether to enable ParallelstoreCsiDriver.
|
|
enable_high_scale_checkpointing: whether to enable HighScaleCheckpointing.
|
|
enable_lustre_csi_driver: whether to enable LustreCsiDriver.
|
|
enable_pod_snapshots: whether to enable PodSnapshots.
|
|
enable_ray_operator: whether to enable RayOperator.
|
|
enable_slice_controller: whether to enable SliceController.
|
|
|
|
Returns:
|
|
An AddonsConfig object that contains the options defining what addons to
|
|
run in the cluster.
|
|
"""
|
|
addons = self.messages.AddonsConfig()
|
|
if disable_ingress is not None:
|
|
addons.httpLoadBalancing = self.messages.HttpLoadBalancing(
|
|
disabled=disable_ingress
|
|
)
|
|
if disable_hpa is not None:
|
|
addons.horizontalPodAutoscaling = self.messages.HorizontalPodAutoscaling(
|
|
disabled=disable_hpa
|
|
)
|
|
if disable_dashboard is not None:
|
|
addons.kubernetesDashboard = self.messages.KubernetesDashboard(
|
|
disabled=disable_dashboard
|
|
)
|
|
# Network policy is disabled by default.
|
|
if disable_network_policy is not None:
|
|
addons.networkPolicyConfig = self.messages.NetworkPolicyConfig(
|
|
disabled=disable_network_policy
|
|
)
|
|
if enable_node_local_dns is not None:
|
|
addons.dnsCacheConfig = self.messages.DnsCacheConfig(
|
|
enabled=enable_node_local_dns
|
|
)
|
|
if enable_gcepd_csi_driver:
|
|
addons.gcePersistentDiskCsiDriverConfig = (
|
|
self.messages.GcePersistentDiskCsiDriverConfig(enabled=True)
|
|
)
|
|
if enable_filestore_csi_driver:
|
|
addons.gcpFilestoreCsiDriverConfig = (
|
|
self.messages.GcpFilestoreCsiDriverConfig(enabled=True)
|
|
)
|
|
if enable_application_manager:
|
|
addons.kalmConfig = self.messages.KalmConfig(enabled=True)
|
|
if enable_cloud_build:
|
|
addons.cloudBuildConfig = self.messages.CloudBuildConfig(enabled=True)
|
|
if enable_backup_restore:
|
|
addons.gkeBackupAgentConfig = self.messages.GkeBackupAgentConfig(
|
|
enabled=True
|
|
)
|
|
if enable_gcsfuse_csi_driver:
|
|
addons.gcsFuseCsiDriverConfig = self.messages.GcsFuseCsiDriverConfig(
|
|
enabled=True
|
|
)
|
|
if enable_stateful_ha:
|
|
addons.statefulHaConfig = self.messages.StatefulHAConfig(enabled=True)
|
|
if enable_parallelstore_csi_driver:
|
|
addons.parallelstoreCsiDriverConfig = (
|
|
self.messages.ParallelstoreCsiDriverConfig(enabled=True)
|
|
)
|
|
if enable_high_scale_checkpointing:
|
|
addons.highScaleCheckpointingConfig = (
|
|
self.messages.HighScaleCheckpointingConfig(enabled=True)
|
|
)
|
|
if enable_lustre_csi_driver:
|
|
addons.lustreCsiDriverConfig = self.messages.LustreCsiDriverConfig(
|
|
enabled=True
|
|
)
|
|
if enable_pod_snapshots is not None:
|
|
addons.podSnapshotConfig = self.messages.PodSnapshotConfig(
|
|
enabled=enable_pod_snapshots
|
|
)
|
|
if enable_ray_operator:
|
|
addons.rayOperatorConfig = self.messages.RayOperatorConfig(enabled=True)
|
|
if enable_slice_controller:
|
|
addons.sliceControllerConfig = self.messages.SliceControllerConfig(
|
|
enabled=True
|
|
)
|
|
|
|
return addons
|
|
|
|
def _AddLocalSSDVolumeConfigsToNodeConfig(self, node_config, options):
|
|
"""Add LocalSSDVolumeConfigs to nodeConfig."""
|
|
if not options.local_ssd_volume_configs:
|
|
return
|
|
format_enum = self.messages.LocalSsdVolumeConfig.FormatValueValuesEnum
|
|
local_ssd_volume_configs_list = []
|
|
for config in options.local_ssd_volume_configs:
|
|
count = int(config['count'])
|
|
ssd_type = config['type'].lower()
|
|
if config['format'].lower() == 'fs':
|
|
ssd_format = format_enum.FS
|
|
elif config['format'].lower() == 'block':
|
|
ssd_format = format_enum.BLOCK
|
|
else:
|
|
raise util.Error(
|
|
LOCAL_SSD_INCORRECT_FORMAT_ERROR_MSG.format(
|
|
err_format=config['format']
|
|
)
|
|
)
|
|
local_ssd_volume_configs_list.append(
|
|
self.messages.LocalSsdVolumeConfig(
|
|
count=count, type=ssd_type, format=ssd_format
|
|
)
|
|
)
|
|
node_config.localSsdVolumeConfigs = local_ssd_volume_configs_list
|
|
|
|
def _AddEphemeralStorageToNodeConfig(self, node_config, options):
|
|
if options.ephemeral_storage is None:
|
|
return
|
|
config = options.ephemeral_storage
|
|
count = None
|
|
if 'local-ssd-count' in config:
|
|
count = config['local-ssd-count']
|
|
node_config.ephemeralStorageConfig = self.messages.EphemeralStorageConfig(
|
|
localSsdCount=count
|
|
)
|
|
|
|
def _AddEphemeralStorageLocalSsdToNodeConfig(self, node_config, options):
|
|
"""Add EphemeralStorageLocalSsdConfig to nodeConfig."""
|
|
# pylint: disable=line-too-long
|
|
if (
|
|
options.ephemeral_storage_local_ssd is None
|
|
and options.data_cache_count is None
|
|
):
|
|
return
|
|
elif (
|
|
options.ephemeral_storage_local_ssd is None
|
|
and options.data_cache_count is not None
|
|
):
|
|
node_config.ephemeralStorageLocalSsdConfig = (
|
|
self.messages.EphemeralStorageLocalSsdConfig(
|
|
dataCacheCount=int(options.data_cache_count)
|
|
)
|
|
)
|
|
return
|
|
config = options.ephemeral_storage_local_ssd
|
|
count = None
|
|
if 'count' in config:
|
|
count = config['count']
|
|
dcount = None
|
|
if options.data_cache_count is not None:
|
|
dcount = int(options.data_cache_count)
|
|
node_config.ephemeralStorageLocalSsdConfig = (
|
|
self.messages.EphemeralStorageLocalSsdConfig(
|
|
localSsdCount=count, dataCacheCount=dcount
|
|
)
|
|
)
|
|
# pylint: enable=line-too-long
|
|
|
|
def _AddLocalNvmeSsdBlockToNodeConfig(self, node_config, options):
|
|
if options.local_nvme_ssd_block is None:
|
|
return
|
|
config = options.local_nvme_ssd_block
|
|
count = None
|
|
if 'count' in config:
|
|
count = config['count']
|
|
node_config.localNvmeSsdBlockConfig = self.messages.LocalNvmeSsdBlockConfig(
|
|
localSsdCount=count
|
|
)
|
|
|
|
def _AddEnableConfidentialStorageToNodeConfig(self, node_config, options):
|
|
if not options.enable_confidential_storage:
|
|
return
|
|
node_config.enableConfidentialStorage = options.enable_confidential_storage
|
|
|
|
def _AddStoragePoolsToNodeConfig(self, node_config, options):
|
|
if not options.storage_pools:
|
|
return
|
|
node_config.storagePools = options.storage_pools
|
|
|
|
def _AddLocalSsdEncryptionModeToNodeConfig(self, node_config, options):
|
|
"""Add localSsdEncryptionMode to nodeConfig."""
|
|
if options.local_ssd_encryption_mode is not None:
|
|
if options.local_ssd_encryption_mode == 'EPHEMERAL_KEY_ENCRYPTION':
|
|
node_config.localSsdEncryptionMode = (
|
|
node_config.LocalSsdEncryptionModeValueValuesEnum.EPHEMERAL_KEY_ENCRYPTION
|
|
)
|
|
elif options.local_ssd_encryption_mode == 'STANDARD_ENCRYPTION':
|
|
node_config.localSsdEncryptionMode = (
|
|
node_config.LocalSsdEncryptionModeValueValuesEnum.STANDARD_ENCRYPTION
|
|
)
|
|
|
|
def _AddNodeTaintsToNodeConfig(self, node_config, options):
|
|
"""Add nodeTaints to nodeConfig."""
|
|
if options.node_taints is None:
|
|
return
|
|
taints = []
|
|
effect_enum = self.messages.NodeTaint.EffectValueValuesEnum
|
|
for key, value in sorted(six.iteritems(options.node_taints)):
|
|
strs = value.split(':')
|
|
if len(strs) != 2:
|
|
raise util.Error(
|
|
NODE_TAINT_INCORRECT_FORMAT_ERROR_MSG.format(key=key, value=value)
|
|
)
|
|
value = strs[0]
|
|
taint_effect = strs[1]
|
|
if taint_effect == 'NoSchedule':
|
|
effect = effect_enum.NO_SCHEDULE
|
|
elif taint_effect == 'PreferNoSchedule':
|
|
effect = effect_enum.PREFER_NO_SCHEDULE
|
|
elif taint_effect == 'NoExecute':
|
|
effect = effect_enum.NO_EXECUTE
|
|
else:
|
|
raise util.Error(
|
|
NODE_TAINT_INCORRECT_EFFECT_ERROR_MSG.format(effect=strs[1])
|
|
)
|
|
taints.append(
|
|
self.messages.NodeTaint(key=key, value=value, effect=effect)
|
|
)
|
|
|
|
node_config.taints = taints
|
|
|
|
def _ResourceManagerTags(self, tags):
|
|
if tags is None:
|
|
return
|
|
rm_tags = self.messages.ResourceManagerTags.TagsValue()
|
|
props = []
|
|
for key, value in six.iteritems(tags):
|
|
props.append(rm_tags.AdditionalProperty(key=key, value=value))
|
|
rm_tags.additionalProperties = props
|
|
return self.messages.ResourceManagerTags(tags=rm_tags)
|
|
|
|
def _AddWorkloadMetadataToNodeConfig(self, node_config, options, messages):
|
|
"""Adds WorkLoadMetadata to NodeConfig."""
|
|
if options.workload_metadata is not None:
|
|
option = options.workload_metadata
|
|
if option == 'GCE_METADATA':
|
|
node_config.workloadMetadataConfig = messages.WorkloadMetadataConfig(
|
|
mode=messages.WorkloadMetadataConfig.ModeValueValuesEnum.GCE_METADATA
|
|
)
|
|
elif option == 'GKE_METADATA':
|
|
node_config.workloadMetadataConfig = messages.WorkloadMetadataConfig(
|
|
mode=messages.WorkloadMetadataConfig.ModeValueValuesEnum.GKE_METADATA
|
|
)
|
|
else:
|
|
raise util.Error(
|
|
UNKNOWN_WORKLOAD_METADATA_ERROR_MSG.format(option=option)
|
|
)
|
|
elif options.workload_metadata_from_node is not None:
|
|
option = options.workload_metadata_from_node
|
|
if option == 'GCE_METADATA':
|
|
node_config.workloadMetadataConfig = messages.WorkloadMetadataConfig(
|
|
mode=messages.WorkloadMetadataConfig.ModeValueValuesEnum.GCE_METADATA
|
|
)
|
|
elif option == 'GKE_METADATA':
|
|
node_config.workloadMetadataConfig = messages.WorkloadMetadataConfig(
|
|
mode=messages.WorkloadMetadataConfig.ModeValueValuesEnum.GKE_METADATA
|
|
)
|
|
# the following options are deprecated
|
|
elif option == 'SECURE':
|
|
node_config.workloadMetadataConfig = messages.WorkloadMetadataConfig(
|
|
nodeMetadata=messages.WorkloadMetadataConfig.NodeMetadataValueValuesEnum.SECURE
|
|
)
|
|
elif option == 'EXPOSED':
|
|
node_config.workloadMetadataConfig = messages.WorkloadMetadataConfig(
|
|
nodeMetadata=messages.WorkloadMetadataConfig.NodeMetadataValueValuesEnum.EXPOSE
|
|
)
|
|
elif option == 'GKE_METADATA_SERVER':
|
|
node_config.workloadMetadataConfig = messages.WorkloadMetadataConfig(
|
|
nodeMetadata=messages.WorkloadMetadataConfig.NodeMetadataValueValuesEnum.GKE_METADATA_SERVER
|
|
)
|
|
else:
|
|
raise util.Error(
|
|
UNKNOWN_WORKLOAD_METADATA_ERROR_MSG.format(option=option)
|
|
)
|
|
|
|
def SetNetworkPolicyCommon(self, options):
|
|
"""Returns a SetNetworkPolicy operation."""
|
|
return self.messages.NetworkPolicy(
|
|
enabled=options.enabled,
|
|
# Only Calico is currently supported as a network policy provider.
|
|
provider=self.messages.NetworkPolicy.ProviderValueValuesEnum.CALICO,
|
|
)
|
|
|
|
def SetNetworkPolicy(self, cluster_ref, options):
|
|
netpol = self.SetNetworkPolicyCommon(options)
|
|
req = self.messages.SetNetworkPolicyRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
networkPolicy=netpol,
|
|
)
|
|
return self.ParseOperation(
|
|
self.client.projects_locations_clusters.SetNetworkPolicy(req).name,
|
|
cluster_ref.zone,
|
|
)
|
|
|
|
def SetMasterAuthCommon(self, options):
|
|
"""Returns a SetMasterAuth action."""
|
|
update = self.messages.MasterAuth(
|
|
username=options.username, password=options.password
|
|
)
|
|
if options.action == SetMasterAuthOptions.SET_PASSWORD:
|
|
action = (
|
|
self.messages.SetMasterAuthRequest.ActionValueValuesEnum.SET_PASSWORD
|
|
)
|
|
elif options.action == SetMasterAuthOptions.GENERATE_PASSWORD:
|
|
action = (
|
|
self.messages.SetMasterAuthRequest.ActionValueValuesEnum.GENERATE_PASSWORD
|
|
)
|
|
else: # options.action == SetMasterAuthOptions.SET_USERNAME
|
|
action = (
|
|
self.messages.SetMasterAuthRequest.ActionValueValuesEnum.SET_USERNAME
|
|
)
|
|
return update, action
|
|
|
|
def SetMasterAuth(self, cluster_ref, options):
|
|
update, action = self.SetMasterAuthCommon(options)
|
|
req = self.messages.SetMasterAuthRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
action=action,
|
|
update=update,
|
|
)
|
|
op = self.client.projects_locations_clusters.SetMasterAuth(req)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def StartIpRotation(self, cluster_ref, rotate_credentials):
|
|
operation = self.client.projects_locations_clusters.StartIpRotation(
|
|
self.messages.StartIPRotationRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
rotateCredentials=rotate_credentials,
|
|
)
|
|
)
|
|
return self.ParseOperation(operation.name, cluster_ref.zone)
|
|
|
|
def CompleteIpRotation(self, cluster_ref):
|
|
operation = self.client.projects_locations_clusters.CompleteIpRotation(
|
|
self.messages.CompleteIPRotationRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
)
|
|
)
|
|
)
|
|
return self.ParseOperation(operation.name, cluster_ref.zone)
|
|
|
|
def _SendMaintenancePolicyRequest(self, cluster_ref, policy):
|
|
"""Given a policy, sends a SetMaintenancePolicy request and returns the operation."""
|
|
req = self.messages.SetMaintenancePolicyRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
maintenancePolicy=policy,
|
|
)
|
|
operation = self.client.projects_locations_clusters.SetMaintenancePolicy(
|
|
req
|
|
)
|
|
return self.ParseOperation(operation.name, cluster_ref.zone)
|
|
|
|
def SetDailyMaintenanceWindow(
|
|
self, cluster_ref, existing_policy, maintenance_window
|
|
):
|
|
"""Sets the daily maintenance window for a cluster."""
|
|
# Special behavior for removing the window. This actually removes the
|
|
# recurring window too, if set (since anyone using this command if there's
|
|
# actually a recurring window probably intends that!).
|
|
if maintenance_window == 'None':
|
|
daily_window = None
|
|
else:
|
|
daily_window = self.messages.DailyMaintenanceWindow(
|
|
startTime=maintenance_window
|
|
)
|
|
|
|
if existing_policy is None:
|
|
existing_policy = self.messages.MaintenancePolicy()
|
|
if existing_policy.window is None:
|
|
existing_policy.window = self.messages.MaintenanceWindow()
|
|
|
|
# Temporary until in GA:
|
|
if hasattr(existing_policy.window, 'recurringWindow'):
|
|
existing_policy.window.recurringWindow = None
|
|
existing_policy.window.dailyMaintenanceWindow = daily_window
|
|
|
|
return self._SendMaintenancePolicyRequest(cluster_ref, existing_policy)
|
|
|
|
def DeleteCluster(self, cluster_ref):
|
|
"""Delete a running cluster.
|
|
|
|
Args:
|
|
cluster_ref: cluster Resource to describe
|
|
|
|
Returns:
|
|
Cluster message.
|
|
Raises:
|
|
Error: if cluster cannot be found or caller is missing permissions. Will
|
|
attempt to find similar clusters in other zones for a more useful error
|
|
if the user has list permissions.
|
|
"""
|
|
try:
|
|
operation = self.client.projects_locations_clusters.Delete(
|
|
self.messages.ContainerProjectsLocationsClustersDeleteRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
)
|
|
)
|
|
)
|
|
return self.ParseOperation(operation.name, cluster_ref.zone)
|
|
except apitools_exceptions.HttpNotFoundError as error:
|
|
api_error = exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
# Cluster couldn't be found, maybe user got the location wrong?
|
|
self.CheckClusterOtherZones(cluster_ref, api_error)
|
|
|
|
def ListClusters(self, project, location=None):
|
|
if not location:
|
|
location = '-'
|
|
req = self.messages.ContainerProjectsLocationsClustersListRequest(
|
|
parent=ProjectLocation(project, location)
|
|
)
|
|
return self.client.projects_locations_clusters.List(req)
|
|
|
|
def CreateNodePoolCommon(self, node_pool_ref, options):
|
|
"""Returns a CreateNodePool operation."""
|
|
node_config = self.messages.NodeConfig()
|
|
if options.machine_type:
|
|
node_config.machineType = options.machine_type
|
|
if options.disk_size_gb:
|
|
node_config.diskSizeGb = options.disk_size_gb
|
|
if options.disk_type:
|
|
node_config.diskType = options.disk_type
|
|
if options.image_type:
|
|
node_config.imageType = options.image_type
|
|
if (
|
|
options.boot_disk_provisioned_iops
|
|
or options.boot_disk_provisioned_throughput
|
|
):
|
|
node_config.bootDisk = self.ParseBootDiskConfig(options)
|
|
|
|
self.ParseAdvancedMachineFeatures(options, node_config)
|
|
|
|
custom_config = self.messages.CustomImageConfig()
|
|
if options.image:
|
|
custom_config.image = options.image
|
|
if options.image_project:
|
|
custom_config.imageProject = options.image_project
|
|
if options.image_family:
|
|
custom_config.imageFamily = options.image_family
|
|
if options.image or options.image_project or options.image_family:
|
|
node_config.nodeImageConfig = custom_config
|
|
|
|
NodeIdentityOptionsToNodeConfig(options, node_config)
|
|
|
|
if options.local_ssd_count:
|
|
node_config.localSsdCount = options.local_ssd_count
|
|
self._AddLocalSSDVolumeConfigsToNodeConfig(node_config, options)
|
|
self._AddEphemeralStorageToNodeConfig(node_config, options)
|
|
self._AddEphemeralStorageLocalSsdToNodeConfig(node_config, options)
|
|
self._AddLocalNvmeSsdBlockToNodeConfig(node_config, options)
|
|
self._AddStoragePoolsToNodeConfig(node_config, options)
|
|
self._AddLocalSsdEncryptionModeToNodeConfig(node_config, options)
|
|
if options.enable_confidential_storage:
|
|
node_config.enableConfidentialStorage = (
|
|
options.enable_confidential_storage
|
|
)
|
|
if options.boot_disk_kms_key:
|
|
node_config.bootDiskKmsKey = options.boot_disk_kms_key
|
|
if options.tags:
|
|
node_config.tags = options.tags
|
|
else:
|
|
node_config.tags = []
|
|
|
|
self.ParseAcceleratorOptions(options, node_config)
|
|
|
|
_AddMetadataToNodeConfig(node_config, options)
|
|
_AddLabelsToNodeConfig(node_config, options)
|
|
_AddNodeLabelsToNodeConfig(node_config, options)
|
|
self._AddNodeTaintsToNodeConfig(node_config, options)
|
|
|
|
if options.resource_manager_tags is not None:
|
|
tags = options.resource_manager_tags
|
|
node_config.resourceManagerTags = self._ResourceManagerTags(tags)
|
|
|
|
if options.preemptible:
|
|
node_config.preemptible = options.preemptible
|
|
|
|
if options.spot:
|
|
node_config.spot = options.spot
|
|
|
|
if options.min_cpu_platform is not None:
|
|
node_config.minCpuPlatform = options.min_cpu_platform
|
|
|
|
if options.node_group is not None:
|
|
node_config.nodeGroup = options.node_group
|
|
|
|
if options.enable_gcfs is not None:
|
|
gcfs_config = self.messages.GcfsConfig(enabled=options.enable_gcfs)
|
|
node_config.gcfsConfig = gcfs_config
|
|
|
|
if options.enable_image_streaming is not None:
|
|
gcfs_config = self.messages.GcfsConfig(
|
|
enabled=options.enable_image_streaming
|
|
)
|
|
node_config.gcfsConfig = gcfs_config
|
|
|
|
if options.gvnic is not None:
|
|
gvnic = self.messages.VirtualNIC(enabled=options.gvnic)
|
|
node_config.gvnic = gvnic
|
|
|
|
if options.max_run_duration is not None:
|
|
node_config.maxRunDuration = options.max_run_duration
|
|
|
|
if options.consolidation_delay is not None:
|
|
node_config.consolidationDelay = options.consolidation_delay
|
|
|
|
if options.flex_start is not None:
|
|
node_config.flexStart = options.flex_start
|
|
|
|
if options.enable_confidential_nodes:
|
|
confidential_nodes = self.messages.ConfidentialNodes(
|
|
enabled=options.enable_confidential_nodes
|
|
)
|
|
node_config.confidentialNodes = confidential_nodes
|
|
|
|
if options.confidential_node_type is not None:
|
|
confidential_nodes = self.messages.ConfidentialNodes(
|
|
enabled=options.enable_confidential_nodes,
|
|
confidentialInstanceType=_ConfidentialNodeTypeEnumFromString(
|
|
options, self.messages, for_node_pool=True
|
|
),
|
|
)
|
|
node_config.confidentialNodes = confidential_nodes
|
|
|
|
if options.enable_fast_socket is not None:
|
|
fast_socket = self.messages.FastSocket(enabled=options.enable_fast_socket)
|
|
node_config.fastSocket = fast_socket
|
|
|
|
if options.maintenance_interval:
|
|
node_config.stableFleetConfig = _GetStableFleetConfig(
|
|
options, self.messages
|
|
)
|
|
|
|
if options.logging_variant is not None:
|
|
logging_config = self.messages.NodePoolLoggingConfig()
|
|
logging_config.variantConfig = self.messages.LoggingVariantConfig(
|
|
variant=VariantConfigEnumFromString(
|
|
self.messages, options.logging_variant
|
|
)
|
|
)
|
|
node_config.loggingConfig = logging_config
|
|
|
|
if options.host_maintenance_interval or options.opportunistic_maintenance:
|
|
node_config.hostMaintenancePolicy = _GetHostMaintenancePolicy(
|
|
options, self.messages, NODEPOOL
|
|
)
|
|
|
|
if options.containerd_config_from_file is not None:
|
|
node_config.containerdConfig = self.messages.ContainerdConfig()
|
|
util.LoadContainerdConfigFromYAML(
|
|
node_config.containerdConfig,
|
|
options.containerd_config_from_file,
|
|
self.messages,
|
|
)
|
|
|
|
self._AddWorkloadMetadataToNodeConfig(node_config, options, self.messages)
|
|
_AddLinuxNodeConfigToNodeConfig(node_config, options, self.messages)
|
|
_AddShieldedInstanceConfigToNodeConfig(node_config, options, self.messages)
|
|
_AddReservationAffinityToNodeConfig(node_config, options, self.messages)
|
|
_AddSandboxConfigToNodeConfig(node_config, options, self.messages)
|
|
_AddWindowsNodeConfigToNodeConfig(node_config, options, self.messages)
|
|
|
|
if options.runner_pool_control_mode == 'confidential':
|
|
node_config.runnerPoolControl = self.messages.RunnerPoolControl(
|
|
mode=self.messages.RunnerPoolControl.ModeValueValuesEnum.CONFIDENTIAL
|
|
)
|
|
elif options.control_node_pool:
|
|
node_config.runnerPoolConfig = self.messages.RunnerPoolConfig(
|
|
controlNodePool=options.control_node_pool,
|
|
attestation=self.messages.AttestationConfig(),
|
|
)
|
|
if options.enable_attestation:
|
|
node_config.runnerPoolConfig.attestation.mode = (
|
|
self.messages.AttestationConfig.ModeValueValuesEnum.ENABLED
|
|
)
|
|
else:
|
|
node_config.runnerPoolConfig.attestation.mode = (
|
|
self.messages.AttestationConfig.ModeValueValuesEnum.DISABLED
|
|
)
|
|
if options.tee_policy:
|
|
node_config.runnerPoolConfig.attestation.teePolicy = options.tee_policy
|
|
elif options.enable_attestation or options.tee_policy:
|
|
raise util.Error(
|
|
'--enable-attestation and --tee-policy can only be specified with '
|
|
'--control-node-pool.'
|
|
)
|
|
|
|
# if we are creating a multi-host TPU (tpu_topology or a resource policy
|
|
# is specified) and num_nodes is not specified, calculate the
|
|
# num_nodes based on the topology as the new default. If not
|
|
# a multi-host TPU, default num_nodes to 3.
|
|
if options.num_nodes is None:
|
|
tpu_topology = None
|
|
|
|
is_tpu = options.machine_type in TPU_MACHINE_TYPES
|
|
if options.tpu_topology is not None:
|
|
tpu_topology = options.tpu_topology
|
|
elif is_tpu and options.placement_policy is not None:
|
|
resource_policy = self.GetResourcePolicy(
|
|
project=node_pool_ref.projectId,
|
|
location=node_pool_ref.zone,
|
|
policy_name=options.placement_policy,
|
|
)
|
|
if (
|
|
resource_policy.workloadPolicy
|
|
and resource_policy.workloadPolicy.acceleratorTopology
|
|
):
|
|
tpu_topology = resource_policy.workloadPolicy.acceleratorTopology
|
|
|
|
if tpu_topology:
|
|
options.num_nodes = TpuTopologyToNumNodes(
|
|
tpu_topology, options.machine_type
|
|
)
|
|
else:
|
|
options.num_nodes = 3
|
|
|
|
pool = self.messages.NodePool(
|
|
name=node_pool_ref.nodePoolId,
|
|
initialNodeCount=options.num_nodes,
|
|
config=node_config,
|
|
version=options.node_version,
|
|
management=self._GetNodeManagement(options),
|
|
)
|
|
|
|
if options.enable_autoscaling or options.enable_autoprovisioning:
|
|
pool.autoscaling = self.messages.NodePoolAutoscaling()
|
|
|
|
if options.enable_autoscaling:
|
|
pool.autoscaling.enabled = options.enable_autoscaling
|
|
pool.autoscaling.minNodeCount = options.min_nodes
|
|
pool.autoscaling.maxNodeCount = options.max_nodes
|
|
pool.autoscaling.totalMinNodeCount = options.total_min_nodes
|
|
pool.autoscaling.totalMaxNodeCount = options.total_max_nodes
|
|
if options.location_policy is not None:
|
|
pool.autoscaling.locationPolicy = LocationPolicyEnumFromString(
|
|
self.messages, options.location_policy
|
|
)
|
|
|
|
if options.enable_best_effort_provision:
|
|
pool.bestEffortProvisioning = self.messages.BestEffortProvisioning()
|
|
pool.bestEffortProvisioning.enabled = True
|
|
pool.bestEffortProvisioning.minProvisionNodes = (
|
|
options.min_provision_nodes
|
|
)
|
|
|
|
if options.enable_autoprovisioning:
|
|
pool.autoscaling.autoprovisioned = options.enable_autoprovisioning
|
|
|
|
if options.max_pods_per_node is not None:
|
|
pool.maxPodsConstraint = self.messages.MaxPodsConstraint(
|
|
maxPodsPerNode=options.max_pods_per_node
|
|
)
|
|
|
|
if (
|
|
options.enable_surge_upgrade
|
|
or options.enable_blue_green_upgrade
|
|
or options.max_surge_upgrade is not None
|
|
or options.max_unavailable_upgrade is not None
|
|
or options.standard_rollout_policy is not None
|
|
or options.autoscaled_rollout_policy is not None
|
|
or options.node_pool_soak_duration is not None
|
|
):
|
|
pool.upgradeSettings = self.messages.UpgradeSettings()
|
|
pool.upgradeSettings = self.UpdateUpgradeSettings(
|
|
None, options, pool=pool
|
|
)
|
|
|
|
if options.node_locations is not None:
|
|
pool.locations = sorted(options.node_locations)
|
|
|
|
if options.system_config_from_file is not None:
|
|
util.LoadSystemConfigFromYAML(
|
|
node_config,
|
|
options.system_config_from_file,
|
|
options.enable_insecure_kubelet_readonly_port,
|
|
self.messages,
|
|
)
|
|
|
|
if options.enable_insecure_kubelet_readonly_port is not None:
|
|
if node_config.kubeletConfig is None:
|
|
node_config.kubeletConfig = self.messages.NodeKubeletConfig()
|
|
node_config.kubeletConfig.insecureKubeletReadonlyPortEnabled = (
|
|
options.enable_insecure_kubelet_readonly_port
|
|
)
|
|
|
|
pool.networkConfig = self._GetNetworkConfig(options)
|
|
|
|
if options.network_performance_config:
|
|
pool.networkConfig.networkPerformanceConfig = (
|
|
self._GetNetworkPerformanceConfig(options)
|
|
)
|
|
|
|
if (
|
|
options.placement_type == 'COMPACT'
|
|
or options.placement_policy is not None
|
|
):
|
|
pool.placementPolicy = self.messages.PlacementPolicy()
|
|
if options.placement_type == 'COMPACT':
|
|
pool.placementPolicy.type = (
|
|
self.messages.PlacementPolicy.TypeValueValuesEnum.COMPACT
|
|
)
|
|
if options.placement_policy is not None:
|
|
pool.placementPolicy.policyName = options.placement_policy
|
|
|
|
if options.gpudirect_strategy is not None:
|
|
if options.gpudirect_strategy == 'RDMA':
|
|
node_config.gpuDirectConfig = self.messages.GPUDirectConfig(
|
|
gpuDirectStrategy=(
|
|
self.messages.GPUDirectConfig.GpuDirectStrategyValueValuesEnum.RDMA
|
|
)
|
|
)
|
|
elif options.gpudirect_strategy == 'TCPX':
|
|
node_config.gpuDirectConfig = self.messages.GPUDirectConfig(
|
|
gpuDirectStrategy=(
|
|
self.messages.GPUDirectConfig.GpuDirectStrategyValueValuesEnum.TCPX
|
|
)
|
|
)
|
|
|
|
if options.tpu_topology:
|
|
if pool.placementPolicy is None:
|
|
pool.placementPolicy = self.messages.PlacementPolicy()
|
|
pool.placementPolicy.tpuTopology = options.tpu_topology
|
|
|
|
if options.enable_queued_provisioning is not None:
|
|
pool.queuedProvisioning = self.messages.QueuedProvisioning()
|
|
pool.queuedProvisioning.enabled = options.enable_queued_provisioning
|
|
|
|
# Explicitly check None for empty list
|
|
if options.sole_tenant_node_affinity_file is not None:
|
|
node_config.soleTenantConfig = (
|
|
util.LoadSoleTenantConfigFromNodeAffinityYaml(
|
|
options.sole_tenant_node_affinity_file, self.messages
|
|
)
|
|
)
|
|
if options.sole_tenant_min_node_cpus is not None:
|
|
if node_config.soleTenantConfig is None:
|
|
node_config.soleTenantConfig = self.messages.SoleTenantConfig()
|
|
node_config.soleTenantConfig.minNodeCpus = (
|
|
options.sole_tenant_min_node_cpus
|
|
)
|
|
|
|
if options.secondary_boot_disks is not None:
|
|
mode_enum = self.messages.SecondaryBootDisk.ModeValueValuesEnum
|
|
mode_map = {
|
|
'CONTAINER_IMAGE_CACHE': mode_enum.CONTAINER_IMAGE_CACHE,
|
|
}
|
|
node_config.secondaryBootDisks = []
|
|
for disk_config in options.secondary_boot_disks:
|
|
disk_image = disk_config['disk-image']
|
|
|
|
# convert mode string to corresponding enum value
|
|
mode = None
|
|
if 'mode' in disk_config:
|
|
if disk_config['mode'] in mode_map:
|
|
mode = mode_map[disk_config['mode']]
|
|
else:
|
|
mode = mode_enum.MODE_UNSPECIFIED
|
|
|
|
node_config.secondaryBootDisks.append(
|
|
self.messages.SecondaryBootDisk(
|
|
diskImage=disk_image,
|
|
mode=mode,
|
|
)
|
|
)
|
|
|
|
if options.enable_lustre_multi_nic is not None:
|
|
if node_config.lustreConfig is None:
|
|
node_config.lustreConfig = self.messages.LustreConfig()
|
|
node_config.lustreConfig.multiRail = self.messages.MultiRail(
|
|
enabled=options.enable_lustre_multi_nic
|
|
)
|
|
|
|
return pool
|
|
|
|
def CreateNodePool(self, node_pool_ref, options):
|
|
"""CreateNodePool creates a node pool and returns the operation."""
|
|
pool = self.CreateNodePoolCommon(node_pool_ref, options)
|
|
req = self.messages.CreateNodePoolRequest(
|
|
nodePool=pool,
|
|
parent=ProjectLocationCluster(
|
|
node_pool_ref.projectId, node_pool_ref.zone, node_pool_ref.clusterId
|
|
),
|
|
)
|
|
operation = self.client.projects_locations_clusters_nodePools.Create(req)
|
|
return self.ParseOperation(operation.name, node_pool_ref.zone)
|
|
|
|
def ListNodePools(self, cluster_ref):
|
|
req = self.messages.ContainerProjectsLocationsClustersNodePoolsListRequest(
|
|
parent=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
)
|
|
)
|
|
return self.client.projects_locations_clusters_nodePools.List(req)
|
|
|
|
def GetNodePool(self, node_pool_ref):
|
|
req = self.messages.ContainerProjectsLocationsClustersNodePoolsGetRequest(
|
|
name=ProjectLocationClusterNodePool(
|
|
node_pool_ref.projectId,
|
|
node_pool_ref.zone,
|
|
node_pool_ref.clusterId,
|
|
node_pool_ref.nodePoolId,
|
|
)
|
|
)
|
|
return self.client.projects_locations_clusters_nodePools.Get(req)
|
|
|
|
def GetNodePoolUpgradeInfo(self, node_pool_ref):
|
|
"""Get node pool upgrade info.
|
|
|
|
Args:
|
|
node_pool_ref: NodePool Resource to get upgrade info for.
|
|
|
|
Returns:
|
|
NodePool Upgrade Info message.
|
|
"""
|
|
req = self.messages.ContainerProjectsLocationsClustersNodePoolsFetchNodePoolUpgradeInfoRequest(
|
|
name=ProjectLocationClusterNodePool(
|
|
node_pool_ref.projectId,
|
|
node_pool_ref.zone,
|
|
node_pool_ref.clusterId,
|
|
node_pool_ref.nodePoolId,
|
|
)
|
|
)
|
|
return self.client.projects_locations_clusters_nodePools.FetchNodePoolUpgradeInfo(
|
|
req
|
|
)
|
|
|
|
def UpdateNodePoolNodeManagement(self, node_pool_ref, options):
|
|
"""Updates node pool's node management configuration.
|
|
|
|
Args:
|
|
node_pool_ref: node pool Resource to update.
|
|
options: node pool update options
|
|
|
|
Returns:
|
|
Updated node management configuration.
|
|
"""
|
|
pool = self.GetNodePool(node_pool_ref)
|
|
node_management = pool.management
|
|
if node_management is None:
|
|
node_management = self.messages.NodeManagement()
|
|
if options.enable_autorepair is not None:
|
|
node_management.autoRepair = options.enable_autorepair
|
|
if options.enable_autoupgrade is not None:
|
|
node_management.autoUpgrade = options.enable_autoupgrade
|
|
return node_management
|
|
|
|
def UpdateNodePoolAutoscaling(self, node_pool_ref, options):
|
|
"""Update node pool's autoscaling configuration.
|
|
|
|
Args:
|
|
node_pool_ref: node pool Resource to update.
|
|
options: node pool update options
|
|
|
|
Returns:
|
|
Updated autoscaling configuration for the node pool.
|
|
"""
|
|
pool = self.GetNodePool(node_pool_ref)
|
|
autoscaling = pool.autoscaling
|
|
if autoscaling is None:
|
|
autoscaling = self.messages.NodePoolAutoscaling()
|
|
if options.enable_autoscaling is not None:
|
|
autoscaling.enabled = options.enable_autoscaling
|
|
if not autoscaling.enabled:
|
|
# clear limits and autoprovisioned when disabling autoscaling
|
|
autoscaling.minNodeCount = 0
|
|
autoscaling.maxNodeCount = 0
|
|
autoscaling.totalMinNodeCount = 0
|
|
autoscaling.totalMaxNodeCount = 0
|
|
autoscaling.autoprovisioned = False
|
|
autoscaling.locationPolicy = (
|
|
self.messages.NodePoolAutoscaling.LocationPolicyValueValuesEnum.LOCATION_POLICY_UNSPECIFIED
|
|
)
|
|
if options.enable_autoprovisioning is not None:
|
|
autoscaling.autoprovisioned = options.enable_autoprovisioning
|
|
if autoscaling.autoprovisioned:
|
|
# clear min nodes limit when enabling autoprovisioning
|
|
autoscaling.minNodeCount = 0
|
|
autoscaling.totalMinNodeCount = 0
|
|
if options.max_nodes is not None:
|
|
autoscaling.maxNodeCount = options.max_nodes
|
|
if options.min_nodes is not None:
|
|
autoscaling.minNodeCount = options.min_nodes
|
|
if options.total_max_nodes is not None:
|
|
autoscaling.totalMaxNodeCount = options.total_max_nodes
|
|
if options.total_min_nodes is not None:
|
|
autoscaling.totalMinNodeCount = options.total_min_nodes
|
|
if options.location_policy is not None:
|
|
autoscaling.locationPolicy = LocationPolicyEnumFromString(
|
|
self.messages, options.location_policy
|
|
)
|
|
return autoscaling
|
|
|
|
def UpdateBlueGreenSettings(self, upgrade_settings, options):
|
|
"""Update blue green settings field in upgrade_settings."""
|
|
if (
|
|
options.standard_rollout_policy is not None
|
|
and options.autoscaled_rollout_policy is not None
|
|
):
|
|
raise util.Error(
|
|
'BlueGreenSettings must contain only one of:'
|
|
' --standard-rollout-policy, --autoscaled-rollout-policy'
|
|
)
|
|
blue_green_settings = (
|
|
upgrade_settings.blueGreenSettings or self.messages.BlueGreenSettings()
|
|
)
|
|
if options.node_pool_soak_duration is not None:
|
|
blue_green_settings.nodePoolSoakDuration = options.node_pool_soak_duration
|
|
|
|
if options.standard_rollout_policy is not None:
|
|
standard_rollout_policy = (
|
|
blue_green_settings.standardRolloutPolicy
|
|
or self.messages.StandardRolloutPolicy()
|
|
)
|
|
|
|
if (
|
|
'batch-node-count' in options.standard_rollout_policy
|
|
and 'batch-percent' in options.standard_rollout_policy
|
|
):
|
|
raise util.Error(
|
|
'StandardRolloutPolicy must contain only one of: batch-node-count,'
|
|
' batch-percent'
|
|
)
|
|
|
|
standard_rollout_policy.batchNodeCount = None
|
|
standard_rollout_policy.batchPercentage = None
|
|
if 'batch-node-count' in options.standard_rollout_policy:
|
|
standard_rollout_policy.batchNodeCount = (
|
|
options.standard_rollout_policy['batch-node-count']
|
|
)
|
|
elif 'batch-percent' in options.standard_rollout_policy:
|
|
standard_rollout_policy.batchPercentage = (
|
|
options.standard_rollout_policy['batch-percent']
|
|
)
|
|
|
|
if 'batch-soak-duration' in options.standard_rollout_policy:
|
|
standard_rollout_policy.batchSoakDuration = (
|
|
options.standard_rollout_policy['batch-soak-duration']
|
|
)
|
|
blue_green_settings.standardRolloutPolicy = standard_rollout_policy
|
|
blue_green_settings.autoscaledRolloutPolicy = None
|
|
elif options.autoscaled_rollout_policy is not None:
|
|
autoscaled_rollout_policy = (
|
|
blue_green_settings.autoscaledRolloutPolicy
|
|
or self.messages.AutoscaledRolloutPolicy()
|
|
)
|
|
|
|
autoscaled_rollout_policy.waitForDrainDuration = None
|
|
if 'wait-for-drain-duration' in options.autoscaled_rollout_policy:
|
|
autoscaled_rollout_policy.waitForDrainDuration = (
|
|
options.autoscaled_rollout_policy['wait-for-drain-duration']
|
|
)
|
|
blue_green_settings.autoscaledRolloutPolicy = autoscaled_rollout_policy
|
|
blue_green_settings.standardRolloutPolicy = None
|
|
|
|
return blue_green_settings
|
|
|
|
def UpdateUpgradeSettings(self, node_pool_ref, options, pool=None):
|
|
"""Updates node pool's upgrade settings."""
|
|
if pool is None:
|
|
pool = self.GetNodePool(node_pool_ref)
|
|
|
|
if options.enable_surge_upgrade and options.enable_blue_green_upgrade:
|
|
raise util.Error(
|
|
'UpgradeSettings must contain only one of: --enable-surge-upgrade,'
|
|
' --enable-blue-green-upgrade'
|
|
)
|
|
|
|
upgrade_settings = pool.upgradeSettings
|
|
if upgrade_settings is None:
|
|
upgrade_settings = self.messages.UpgradeSettings()
|
|
if options.max_surge_upgrade is not None:
|
|
upgrade_settings.maxSurge = options.max_surge_upgrade
|
|
if options.max_unavailable_upgrade is not None:
|
|
upgrade_settings.maxUnavailable = options.max_unavailable_upgrade
|
|
if options.enable_surge_upgrade:
|
|
upgrade_settings.strategy = (
|
|
self.messages.UpgradeSettings.StrategyValueValuesEnum.SURGE
|
|
)
|
|
if options.enable_blue_green_upgrade:
|
|
upgrade_settings.strategy = (
|
|
self.messages.UpgradeSettings.StrategyValueValuesEnum.BLUE_GREEN
|
|
)
|
|
if (
|
|
options.standard_rollout_policy is not None
|
|
or options.node_pool_soak_duration is not None
|
|
or options.autoscaled_rollout_policy is not None
|
|
):
|
|
upgrade_settings.blueGreenSettings = self.UpdateBlueGreenSettings(
|
|
upgrade_settings, options
|
|
)
|
|
return upgrade_settings
|
|
|
|
def UpdateNodePoolRequest(self, node_pool_ref, options):
|
|
"""Creates an UpdateNodePoolRequest from the provided options.
|
|
|
|
Arguments:
|
|
node_pool_ref: The node pool to act on.
|
|
options: UpdateNodePoolOptions with the user-specified options.
|
|
|
|
Returns:
|
|
|
|
An UpdateNodePoolRequest.
|
|
"""
|
|
|
|
update_request = self.messages.UpdateNodePoolRequest(
|
|
name=ProjectLocationClusterNodePool(
|
|
node_pool_ref.projectId,
|
|
node_pool_ref.zone,
|
|
node_pool_ref.clusterId,
|
|
node_pool_ref.nodePoolId,
|
|
)
|
|
)
|
|
|
|
self.ParseAcceleratorOptions(options, update_request)
|
|
|
|
if (
|
|
options.workload_metadata is not None
|
|
or options.workload_metadata_from_node is not None
|
|
):
|
|
self._AddWorkloadMetadataToNodeConfig(
|
|
update_request, options, self.messages
|
|
)
|
|
elif options.node_locations is not None:
|
|
update_request.locations = sorted(options.node_locations)
|
|
elif (
|
|
options.enable_blue_green_upgrade
|
|
or options.enable_surge_upgrade
|
|
or options.max_surge_upgrade is not None
|
|
or options.max_unavailable_upgrade is not None
|
|
or options.standard_rollout_policy is not None
|
|
or options.node_pool_soak_duration is not None
|
|
or options.autoscaled_rollout_policy is not None
|
|
):
|
|
update_request.upgradeSettings = self.UpdateUpgradeSettings(
|
|
node_pool_ref, options
|
|
)
|
|
elif (
|
|
options.system_config_from_file is not None
|
|
or options.enable_insecure_kubelet_readonly_port is not None
|
|
):
|
|
node_config = self.messages.NodeConfig()
|
|
if options.system_config_from_file is not None:
|
|
util.LoadSystemConfigFromYAML(
|
|
node_config,
|
|
options.system_config_from_file,
|
|
options.enable_insecure_kubelet_readonly_port,
|
|
self.messages,
|
|
)
|
|
if options.enable_insecure_kubelet_readonly_port is not None:
|
|
if node_config.kubeletConfig is None:
|
|
node_config.kubeletConfig = self.messages.NodeKubeletConfig()
|
|
node_config.kubeletConfig.insecureKubeletReadonlyPortEnabled = (
|
|
options.enable_insecure_kubelet_readonly_port
|
|
)
|
|
|
|
# set the update request
|
|
update_request.linuxNodeConfig = node_config.linuxNodeConfig
|
|
update_request.kubeletConfig = node_config.kubeletConfig
|
|
|
|
elif options.containerd_config_from_file is not None:
|
|
containerd_config = self.messages.ContainerdConfig()
|
|
util.LoadContainerdConfigFromYAML(
|
|
containerd_config, options.containerd_config_from_file, self.messages
|
|
)
|
|
update_request.containerdConfig = containerd_config
|
|
elif options.labels is not None:
|
|
resource_labels = self.messages.ResourceLabels()
|
|
labels = resource_labels.LabelsValue()
|
|
props = []
|
|
for key, value in six.iteritems(options.labels):
|
|
props.append(labels.AdditionalProperty(key=key, value=value))
|
|
labels.additionalProperties = props
|
|
resource_labels.labels = labels
|
|
update_request.resourceLabels = resource_labels
|
|
elif options.node_labels is not None:
|
|
node_labels = self.messages.NodeLabels()
|
|
labels = node_labels.LabelsValue()
|
|
props = []
|
|
for key, value in six.iteritems(options.node_labels):
|
|
props.append(labels.AdditionalProperty(key=key, value=value))
|
|
labels.additionalProperties = props
|
|
node_labels.labels = labels
|
|
update_request.labels = node_labels
|
|
elif options.node_taints is not None:
|
|
taints = []
|
|
effect_enum = self.messages.NodeTaint.EffectValueValuesEnum
|
|
for key, value in sorted(six.iteritems(options.node_taints)):
|
|
strs = value.split(':')
|
|
if len(strs) != 2:
|
|
raise util.Error(
|
|
NODE_TAINT_INCORRECT_FORMAT_ERROR_MSG.format(key=key, value=value)
|
|
)
|
|
value = strs[0]
|
|
taint_effect = strs[1]
|
|
if taint_effect == 'NoSchedule':
|
|
effect = effect_enum.NO_SCHEDULE
|
|
elif taint_effect == 'PreferNoSchedule':
|
|
effect = effect_enum.PREFER_NO_SCHEDULE
|
|
elif taint_effect == 'NoExecute':
|
|
effect = effect_enum.NO_EXECUTE
|
|
else:
|
|
raise util.Error(
|
|
NODE_TAINT_INCORRECT_EFFECT_ERROR_MSG.format(effect=strs[1])
|
|
)
|
|
taints.append(
|
|
self.messages.NodeTaint(key=key, value=value, effect=effect)
|
|
)
|
|
node_taints = self.messages.NodeTaints()
|
|
node_taints.taints = taints
|
|
update_request.taints = node_taints
|
|
elif options.tags is not None:
|
|
node_tags = self.messages.NetworkTags()
|
|
node_tags.tags = options.tags
|
|
update_request.tags = node_tags
|
|
elif options.enable_private_nodes is not None:
|
|
network_config = self.messages.NodeNetworkConfig()
|
|
network_config.enablePrivateNodes = options.enable_private_nodes
|
|
update_request.nodeNetworkConfig = network_config
|
|
elif options.enable_gcfs is not None:
|
|
gcfs_config = self.messages.GcfsConfig(enabled=options.enable_gcfs)
|
|
update_request.gcfsConfig = gcfs_config
|
|
elif options.gvnic is not None:
|
|
gvnic = self.messages.VirtualNIC(enabled=options.gvnic)
|
|
update_request.gvnic = gvnic
|
|
elif options.max_run_duration is not None:
|
|
update_request.maxRunDuration = options.max_run_duration
|
|
elif options.consolidation_delay is not None:
|
|
update_request.consolidationDelay = options.consolidation_delay
|
|
elif options.flex_start is not None:
|
|
update_request.flexStart = options.flex_start
|
|
elif options.enable_image_streaming is not None:
|
|
gcfs_config = self.messages.GcfsConfig(
|
|
enabled=options.enable_image_streaming
|
|
)
|
|
update_request.gcfsConfig = gcfs_config
|
|
elif options.network_performance_config is not None:
|
|
network_config = self.messages.NodeNetworkConfig()
|
|
network_config.networkPerformanceConfig = (
|
|
self._GetNetworkPerformanceConfig(options)
|
|
)
|
|
update_request.nodeNetworkConfig = network_config
|
|
elif options.enable_confidential_nodes is not None:
|
|
confidential_nodes = self.messages.ConfidentialNodes(
|
|
enabled=options.enable_confidential_nodes
|
|
)
|
|
update_request.confidentialNodes = confidential_nodes
|
|
elif options.confidential_node_type is not None:
|
|
confidential_nodes = self.messages.ConfidentialNodes(
|
|
confidentialInstanceType=_ConfidentialNodeTypeEnumFromString(
|
|
options, self.messages, for_node_pool=True
|
|
)
|
|
)
|
|
update_request.confidentialNodes = confidential_nodes
|
|
elif options.enable_fast_socket is not None:
|
|
fast_socket = self.messages.FastSocket(enabled=options.enable_fast_socket)
|
|
update_request.fastSocket = fast_socket
|
|
elif options.logging_variant is not None:
|
|
logging_config = self.messages.NodePoolLoggingConfig()
|
|
logging_config.variantConfig = self.messages.LoggingVariantConfig(
|
|
variant=VariantConfigEnumFromString(
|
|
self.messages, options.logging_variant
|
|
)
|
|
)
|
|
update_request.loggingConfig = logging_config
|
|
elif options.windows_os_version is not None:
|
|
windows_node_config = self.messages.WindowsNodeConfig()
|
|
if options.windows_os_version == 'ltsc2022':
|
|
windows_node_config.osVersion = (
|
|
self.messages.WindowsNodeConfig.OsVersionValueValuesEnum.OS_VERSION_LTSC2022
|
|
)
|
|
else:
|
|
windows_node_config.osVersion = (
|
|
self.messages.WindowsNodeConfig.OsVersionValueValuesEnum.OS_VERSION_LTSC2019
|
|
)
|
|
update_request.windowsNodeConfig = windows_node_config
|
|
elif options.resource_manager_tags is not None:
|
|
tags = options.resource_manager_tags
|
|
update_request.resourceManagerTags = self._ResourceManagerTags(tags)
|
|
elif (
|
|
options.machine_type is not None
|
|
or options.disk_type is not None
|
|
or options.disk_size_gb is not None
|
|
or options.provisioned_iops is not None
|
|
or options.provisioned_throughput is not None
|
|
):
|
|
update_request.machineType = options.machine_type
|
|
update_request.diskType = options.disk_type
|
|
update_request.diskSizeGb = options.disk_size_gb
|
|
# This is nested because iops/throughput are grouped with disk type/size.
|
|
# In the future they will all modify the BootDisk message.
|
|
if (
|
|
options.provisioned_iops is not None
|
|
or options.provisioned_throughput is not None
|
|
):
|
|
boot_disk_cfg = self.messages.BootDisk()
|
|
if options.provisioned_iops is not None:
|
|
boot_disk_cfg.provisionedIops = options.provisioned_iops
|
|
if options.provisioned_throughput is not None:
|
|
boot_disk_cfg.provisionedThroughput = options.provisioned_throughput
|
|
update_request.bootDisk = boot_disk_cfg
|
|
|
|
elif options.enable_queued_provisioning is not None:
|
|
update_request.queuedProvisioning = self.messages.QueuedProvisioning()
|
|
update_request.queuedProvisioning.enabled = (
|
|
options.enable_queued_provisioning
|
|
)
|
|
elif options.storage_pools is not None:
|
|
update_request.storagePools = options.storage_pools
|
|
elif options.enable_kernel_module_signature_enforcement is not None:
|
|
_AddKernelModuleSignatureEnforcementToNodeConfig(
|
|
update_request, options, self.messages
|
|
)
|
|
elif options.enable_lustre_multi_nic is not None:
|
|
update_request.lustreConfig = self.messages.LustreConfig()
|
|
update_request.lustreConfig.multiRail = self.messages.MultiRail(
|
|
enabled=options.enable_lustre_multi_nic
|
|
)
|
|
return update_request
|
|
|
|
def UpdateNodePool(self, node_pool_ref, options):
|
|
"""Updates nodePool on a cluster."""
|
|
if options.IsAutoscalingUpdate():
|
|
autoscaling = self.UpdateNodePoolAutoscaling(node_pool_ref, options)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNodePoolId=node_pool_ref.nodePoolId,
|
|
desiredNodePoolAutoscaling=autoscaling,
|
|
)
|
|
operation = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
node_pool_ref.projectId,
|
|
node_pool_ref.zone,
|
|
node_pool_ref.clusterId,
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(operation.name, node_pool_ref.zone)
|
|
elif options.IsNodePoolManagementUpdate():
|
|
management = self.UpdateNodePoolNodeManagement(node_pool_ref, options)
|
|
req = self.messages.SetNodePoolManagementRequest(
|
|
name=ProjectLocationClusterNodePool(
|
|
node_pool_ref.projectId,
|
|
node_pool_ref.zone,
|
|
node_pool_ref.clusterId,
|
|
node_pool_ref.nodePoolId,
|
|
),
|
|
management=management,
|
|
)
|
|
operation = (
|
|
self.client.projects_locations_clusters_nodePools.SetManagement(req)
|
|
)
|
|
elif options.IsUpdateNodePoolRequest():
|
|
req = self.UpdateNodePoolRequest(node_pool_ref, options)
|
|
operation = self.client.projects_locations_clusters_nodePools.Update(req)
|
|
else:
|
|
raise util.Error('Unhandled node pool update mode')
|
|
|
|
return self.ParseOperation(operation.name, node_pool_ref.zone)
|
|
|
|
def DeleteNodePool(self, node_pool_ref):
|
|
operation = self.client.projects_locations_clusters_nodePools.Delete(
|
|
self.messages.ContainerProjectsLocationsClustersNodePoolsDeleteRequest(
|
|
name=ProjectLocationClusterNodePool(
|
|
node_pool_ref.projectId,
|
|
node_pool_ref.zone,
|
|
node_pool_ref.clusterId,
|
|
node_pool_ref.nodePoolId,
|
|
)
|
|
)
|
|
)
|
|
return self.ParseOperation(operation.name, node_pool_ref.zone)
|
|
|
|
def RollbackUpgrade(self, node_pool_ref, respect_pdb=None):
|
|
"""Rolls back an upgrade for a node pool."""
|
|
operation = self.client.projects_locations_clusters_nodePools.Rollback(
|
|
self.messages.RollbackNodePoolUpgradeRequest(
|
|
name=ProjectLocationClusterNodePool(
|
|
node_pool_ref.projectId,
|
|
node_pool_ref.zone,
|
|
node_pool_ref.clusterId,
|
|
node_pool_ref.nodePoolId,
|
|
),
|
|
respectPdb=respect_pdb,
|
|
)
|
|
)
|
|
return self.ParseOperation(operation.name, node_pool_ref.zone)
|
|
|
|
def CompleteNodePoolUpgrade(self, node_pool_ref):
|
|
req = self.messages.ContainerProjectsLocationsClustersNodePoolsCompleteUpgradeRequest(
|
|
name=ProjectLocationClusterNodePool(
|
|
node_pool_ref.projectId,
|
|
node_pool_ref.zone,
|
|
node_pool_ref.clusterId,
|
|
node_pool_ref.nodePoolId,
|
|
)
|
|
)
|
|
return self.client.projects_locations_clusters_nodePools.CompleteUpgrade(
|
|
req
|
|
)
|
|
|
|
def CancelOperation(self, op_ref):
|
|
req = self.messages.CancelOperationRequest(
|
|
name=ProjectLocationOperation(
|
|
op_ref.projectId, op_ref.zone, op_ref.operationId
|
|
)
|
|
)
|
|
return self.client.projects_locations_operations.Cancel(req)
|
|
|
|
def IsRunning(self, cluster):
|
|
return cluster.status == self.messages.Cluster.StatusValueValuesEnum.RUNNING
|
|
|
|
def IsDegraded(self, cluster):
|
|
return (
|
|
cluster.status == self.messages.Cluster.StatusValueValuesEnum.DEGRADED
|
|
)
|
|
|
|
def GetDegradedWarning(self, cluster):
|
|
if cluster.conditions:
|
|
codes = [condition.code for condition in cluster.conditions]
|
|
messages = [condition.message for condition in cluster.conditions]
|
|
return ('Codes: {0}\nMessages: {1}.').format(codes, messages)
|
|
else:
|
|
return gke_constants.DEFAULT_DEGRADED_WARNING
|
|
|
|
def ListOperations(self, project, location=None):
|
|
if not location:
|
|
location = '-'
|
|
req = self.messages.ContainerProjectsLocationsOperationsListRequest(
|
|
parent=ProjectLocation(project, location)
|
|
)
|
|
return self.client.projects_locations_operations.List(req)
|
|
|
|
def IsOperationFinished(self, operation):
|
|
return (
|
|
operation.status == self.messages.Operation.StatusValueValuesEnum.DONE
|
|
)
|
|
|
|
def GetServerConfig(self, project, location):
|
|
req = self.messages.ContainerProjectsLocationsGetServerConfigRequest(
|
|
name=ProjectLocation(project, location)
|
|
)
|
|
return self.client.projects_locations.GetServerConfig(req)
|
|
|
|
def ResizeNodePool(self, cluster_ref, pool_name, size):
|
|
req = self.messages.SetNodePoolSizeRequest(
|
|
name=ProjectLocationClusterNodePool(
|
|
cluster_ref.projectId,
|
|
cluster_ref.zone,
|
|
cluster_ref.clusterId,
|
|
pool_name,
|
|
),
|
|
nodeCount=size,
|
|
)
|
|
operation = self.client.projects_locations_clusters_nodePools.SetSize(req)
|
|
return self.ParseOperation(operation.name, cluster_ref.zone)
|
|
|
|
def _GetNodeManagement(self, options):
|
|
"""Gets a wrapper containing the options for how nodes are managed.
|
|
|
|
Args:
|
|
options: node management options
|
|
|
|
Returns:
|
|
A NodeManagement object that contains the options indicating how nodes
|
|
are managed. This is currently quite simple, containing only two options.
|
|
However, there are more options planned for node management.
|
|
"""
|
|
if options.enable_autorepair is None and options.enable_autoupgrade is None:
|
|
return None
|
|
|
|
node_management = self.messages.NodeManagement()
|
|
node_management.autoRepair = options.enable_autorepair
|
|
node_management.autoUpgrade = options.enable_autoupgrade
|
|
return node_management
|
|
|
|
def _GetNetworkConfig(self, options):
|
|
"""Gets a wrapper containing the network config for the node pool.
|
|
|
|
Args:
|
|
options: Network config options
|
|
|
|
Returns:
|
|
A NetworkConfig object that contains the options for how the network
|
|
for the nodepool needs to be configured.
|
|
"""
|
|
if (
|
|
options.pod_ipv4_range is None
|
|
and options.create_pod_ipv4_range is None
|
|
and options.enable_private_nodes is None
|
|
and options.network_performance_config is None
|
|
and options.disable_pod_cidr_overprovision is None
|
|
and options.additional_node_network is None
|
|
and options.additional_pod_network is None
|
|
and options.accelerator_network_profile is None
|
|
):
|
|
return None
|
|
|
|
network_config = self.messages.NodeNetworkConfig()
|
|
if options.pod_ipv4_range is not None:
|
|
network_config.podRange = options.pod_ipv4_range
|
|
if options.create_pod_ipv4_range is not None:
|
|
for key in options.create_pod_ipv4_range:
|
|
if key not in ['name', 'range']:
|
|
raise util.Error(
|
|
CREATE_POD_RANGE_INVALID_KEY_ERROR_MSG.format(key=key)
|
|
)
|
|
network_config.createPodRange = True
|
|
network_config.podRange = options.create_pod_ipv4_range.get('name', None)
|
|
network_config.podIpv4CidrBlock = options.create_pod_ipv4_range.get(
|
|
'range', None
|
|
)
|
|
if options.enable_private_nodes is not None:
|
|
network_config.enablePrivateNodes = options.enable_private_nodes
|
|
if options.disable_pod_cidr_overprovision is not None:
|
|
network_config.podCidrOverprovisionConfig = (
|
|
self.messages.PodCIDROverprovisionConfig(
|
|
disable=options.disable_pod_cidr_overprovision
|
|
)
|
|
)
|
|
|
|
if options.additional_node_network is not None:
|
|
network_config.additionalNodeNetworkConfigs = []
|
|
for node_network_option in options.additional_node_network:
|
|
node_network_config_msg = self.messages.AdditionalNodeNetworkConfig()
|
|
node_network_config_msg.network = node_network_option['network']
|
|
node_network_config_msg.subnetwork = node_network_option['subnetwork']
|
|
network_config.additionalNodeNetworkConfigs.append(
|
|
node_network_config_msg
|
|
)
|
|
|
|
if options.additional_pod_network is not None:
|
|
network_config.additionalPodNetworkConfigs = []
|
|
for pod_network_option in options.additional_pod_network:
|
|
pod_network_config_msg = self.messages.AdditionalPodNetworkConfig()
|
|
pod_network_config_msg.subnetwork = pod_network_option.get(
|
|
'subnetwork', None
|
|
)
|
|
pod_network_config_msg.secondaryPodRange = pod_network_option[
|
|
'pod-ipv4-range'
|
|
]
|
|
pod_network_config_msg.maxPodsPerNode = self.messages.MaxPodsConstraint(
|
|
maxPodsPerNode=pod_network_option.get('max-pods-per-node', None)
|
|
)
|
|
network_config.additionalPodNetworkConfigs.append(
|
|
pod_network_config_msg
|
|
)
|
|
|
|
if options.accelerator_network_profile is not None:
|
|
network_config.acceleratorNetworkProfile = (
|
|
options.accelerator_network_profile
|
|
)
|
|
|
|
return network_config
|
|
|
|
def _GetNetworkPerformanceConfig(self, options):
|
|
"""Get NetworkPerformanceConfig message for the instance."""
|
|
|
|
network_perf_args = options.network_performance_config
|
|
network_perf_configs = self.messages.NetworkPerformanceConfig()
|
|
|
|
for config in network_perf_args:
|
|
total_tier = config.get('total-egress-bandwidth-tier', '').upper()
|
|
if total_tier:
|
|
network_perf_configs.totalEgressBandwidthTier = self.messages.NetworkPerformanceConfig.TotalEgressBandwidthTierValueValuesEnum(
|
|
total_tier
|
|
)
|
|
|
|
return network_perf_configs
|
|
|
|
def UpdateLabelsCommon(self, cluster_ref, update_labels):
|
|
"""Update labels on a cluster.
|
|
|
|
Args:
|
|
cluster_ref: cluster to update.
|
|
update_labels: labels to set.
|
|
|
|
Returns:
|
|
Operation ref for label set operation.
|
|
"""
|
|
clus = None
|
|
try:
|
|
clus = self.GetCluster(cluster_ref)
|
|
except apitools_exceptions.HttpNotFoundError:
|
|
pass
|
|
except apitools_exceptions.HttpError as error:
|
|
raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
|
|
labels = self.messages.SetLabelsRequest.ResourceLabelsValue()
|
|
props = []
|
|
for k, v in sorted(six.iteritems(update_labels)):
|
|
props.append(labels.AdditionalProperty(key=k, value=v))
|
|
labels.additionalProperties = props
|
|
return labels, clus.labelFingerprint
|
|
|
|
def UpdateLabels(self, cluster_ref, update_labels):
|
|
"""Updates labels for a cluster."""
|
|
labels, fingerprint = self.UpdateLabelsCommon(cluster_ref, update_labels)
|
|
operation = self.client.projects_locations_clusters.SetResourceLabels(
|
|
self.messages.SetLabelsRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
resourceLabels=labels,
|
|
labelFingerprint=fingerprint,
|
|
)
|
|
)
|
|
return self.ParseOperation(operation.name, cluster_ref.zone)
|
|
|
|
def RemoveLabelsCommon(self, cluster_ref, remove_labels):
|
|
"""Removes labels from a cluster.
|
|
|
|
Args:
|
|
cluster_ref: cluster to update.
|
|
remove_labels: labels to remove.
|
|
|
|
Returns:
|
|
Operation ref for label set operation.
|
|
"""
|
|
clus = None
|
|
try:
|
|
clus = self.GetCluster(cluster_ref)
|
|
except apitools_exceptions.HttpNotFoundError:
|
|
pass
|
|
except apitools_exceptions.HttpError as error:
|
|
raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
|
|
clus_labels = {}
|
|
if clus.resourceLabels:
|
|
for item in clus.resourceLabels.additionalProperties:
|
|
clus_labels[item.key] = str(item.value)
|
|
|
|
# if clusLabels empty, nothing to do
|
|
if not clus_labels:
|
|
raise util.Error(NO_LABELS_ON_CLUSTER_ERROR_MSG.format(cluster=clus.name))
|
|
|
|
for k in remove_labels:
|
|
try:
|
|
clus_labels.pop(k)
|
|
except KeyError:
|
|
# if at least one label not found on cluster, raise error
|
|
raise util.Error(
|
|
NO_SUCH_LABEL_ERROR_MSG.format(cluster=clus.name, name=k)
|
|
)
|
|
|
|
labels = self.messages.SetLabelsRequest.ResourceLabelsValue()
|
|
for k, v in sorted(six.iteritems(clus_labels)):
|
|
labels.additionalProperties.append(
|
|
labels.AdditionalProperty(key=k, value=v)
|
|
)
|
|
return labels, clus.labelFingerprint
|
|
|
|
def RemoveLabels(self, cluster_ref, remove_labels):
|
|
"""Removes labels from a cluster."""
|
|
labels, fingerprint = self.RemoveLabelsCommon(cluster_ref, remove_labels)
|
|
operation = self.client.projects_locations_clusters.SetResourceLabels(
|
|
self.messages.SetLabelsRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
resourceLabels=labels,
|
|
labelFingerprint=fingerprint,
|
|
)
|
|
)
|
|
return self.ParseOperation(operation.name, cluster_ref.zone)
|
|
|
|
def GetIamPolicy(self, cluster_ref):
|
|
raise NotImplementedError('GetIamPolicy is not overridden')
|
|
|
|
def SetIamPolicy(self, cluster_ref):
|
|
raise NotImplementedError('GetIamPolicy is not overridden')
|
|
|
|
def SetRecurringMaintenanceWindow(
|
|
self,
|
|
cluster_ref,
|
|
existing_policy,
|
|
window_start,
|
|
window_end,
|
|
window_recurrence,
|
|
):
|
|
"""Sets a recurring maintenance window as the maintenance policy for a cluster.
|
|
|
|
Args:
|
|
cluster_ref: The cluster to update.
|
|
existing_policy: The existing maintenance policy, if any.
|
|
window_start: Start time of the window as a datetime.datetime.
|
|
window_end: End time of the window as a datetime.datetime.
|
|
window_recurrence: RRULE str defining how the window will recur.
|
|
|
|
Returns:
|
|
The operation from this cluster update.
|
|
"""
|
|
recurring_window = self.messages.RecurringTimeWindow(
|
|
window=self.messages.TimeWindow(
|
|
startTime=window_start.isoformat(), endTime=window_end.isoformat()
|
|
),
|
|
recurrence=window_recurrence,
|
|
)
|
|
if existing_policy is None:
|
|
existing_policy = self.messages.MaintenancePolicy()
|
|
if existing_policy.window is None:
|
|
existing_policy.window = self.messages.MaintenanceWindow()
|
|
existing_policy.window.dailyMaintenanceWindow = None
|
|
existing_policy.window.recurringWindow = recurring_window
|
|
return self._SendMaintenancePolicyRequest(cluster_ref, existing_policy)
|
|
|
|
def RemoveMaintenanceWindow(self, cluster_ref, existing_policy):
|
|
"""Removes the recurring or daily maintenance policy."""
|
|
if (
|
|
existing_policy is None
|
|
or existing_policy.window is None
|
|
or (
|
|
existing_policy.window.dailyMaintenanceWindow is None
|
|
and existing_policy.window.recurringWindow is None
|
|
)
|
|
):
|
|
raise util.Error(NOTHING_TO_UPDATE_ERROR_MSG)
|
|
existing_policy.window.dailyMaintenanceWindow = None
|
|
existing_policy.window.recurringWindow = None
|
|
return self._SendMaintenancePolicyRequest(cluster_ref, existing_policy)
|
|
|
|
def _NormalizeMaintenanceExclusionsForPolicy(self, policy):
|
|
"""Given a maintenance policy (can be None), return a normalized form.
|
|
|
|
This makes it easier to add and remove blackouts because the blackouts
|
|
list will definitely exist.
|
|
|
|
Args:
|
|
policy: The policy to normalize.
|
|
|
|
Returns:
|
|
The modified policy (note: modifies in place, but there might not have
|
|
even been an existing policy).
|
|
"""
|
|
empty_excl = self.messages.MaintenanceWindow.MaintenanceExclusionsValue()
|
|
if policy is None:
|
|
policy = self.messages.MaintenancePolicy(
|
|
window=self.messages.MaintenanceWindow(
|
|
maintenanceExclusions=empty_excl
|
|
)
|
|
)
|
|
elif policy.window is None:
|
|
# Shouldn't happen due to defaulting on the server, but easy enough to
|
|
# handle.
|
|
policy.window = self.messages.MaintenanceWindow(
|
|
maintenanceExclusions=empty_excl
|
|
)
|
|
elif policy.window.maintenanceExclusions is None:
|
|
policy.window.maintenanceExclusions = empty_excl
|
|
return policy
|
|
|
|
def _GetMaintenanceExclusionNames(self, maintenance_policy):
|
|
"""Returns a list of maintenance exclusion names from the policy."""
|
|
return [
|
|
p.key
|
|
for p in maintenance_policy.window.maintenanceExclusions.additionalProperties
|
|
]
|
|
|
|
def AddMaintenanceExclusion(
|
|
self,
|
|
cluster_ref,
|
|
existing_policy,
|
|
window_name,
|
|
window_start,
|
|
window_end,
|
|
window_scope,
|
|
window_until_end_of_support,
|
|
):
|
|
"""Adds a maintenance exclusion to the cluster's maintenance policy.
|
|
|
|
Args:
|
|
cluster_ref: The cluster to update.
|
|
existing_policy: The existing maintenance policy, if any.
|
|
window_name: Unique name for the exclusion. Can be None (will be
|
|
autogenerated if so).
|
|
window_start: Start time of the window as a datetime.datetime. Can be
|
|
None.
|
|
window_end: End time of the window as a datetime.datetime.
|
|
window_scope: Scope that the current exclusion will apply to.
|
|
window_until_end_of_support: End time of the window is the end of the
|
|
cluster version's support.
|
|
|
|
Returns:
|
|
Operation from this cluster update.
|
|
|
|
Raises:
|
|
Error if a maintenance exclusion of that name already exists.
|
|
"""
|
|
existing_policy = self._NormalizeMaintenanceExclusionsForPolicy(
|
|
existing_policy
|
|
)
|
|
|
|
if window_start is None:
|
|
window_start = times.Now(times.UTC)
|
|
if window_name is None:
|
|
# Collisions from this shouldn't be an issue because this has millisecond
|
|
# resolution.
|
|
window_name = 'generated-exclusion-' + times.Now(times.UTC).isoformat()
|
|
|
|
if window_name in self._GetMaintenanceExclusionNames(existing_policy):
|
|
raise util.Error(
|
|
'A maintenance exclusion named {0} already exists.'.format(
|
|
window_name
|
|
)
|
|
)
|
|
if (window_end is not None and window_until_end_of_support) or (
|
|
window_end is None and not window_until_end_of_support
|
|
):
|
|
raise util.Error(
|
|
'Maintenance exclusion must contain exactly one of:'
|
|
' --add-maintenance-exclusion-end,'
|
|
' --add-maintenance-exclusion-until-end-of-support'
|
|
)
|
|
|
|
# Note: we're using external/python/gcloud_deps/apitools/base/protorpclite
|
|
# which does *not* handle maps very nicely. We actually have a
|
|
# MaintenanceExclusionsValue field that has a repeated additionalProperties
|
|
# field that has key and value fields. See
|
|
# third_party/apis/container/v1alpha1/container_v1alpha1_messages.py.
|
|
exclusions = existing_policy.window.maintenanceExclusions
|
|
end_time = None
|
|
if window_end:
|
|
end_time = window_end.isoformat()
|
|
window = self.messages.TimeWindow(
|
|
startTime=window_start.isoformat(), endTime=end_time
|
|
)
|
|
if window_scope is not None:
|
|
if window_scope == 'no_upgrades':
|
|
window.maintenanceExclusionOptions = self.messages.MaintenanceExclusionOptions(
|
|
scope=self.messages.MaintenanceExclusionOptions.ScopeValueValuesEnum.NO_UPGRADES
|
|
)
|
|
if window_scope == 'no_minor_upgrades':
|
|
window.maintenanceExclusionOptions = self.messages.MaintenanceExclusionOptions(
|
|
scope=self.messages.MaintenanceExclusionOptions.ScopeValueValuesEnum.NO_MINOR_UPGRADES
|
|
)
|
|
if window_scope == 'no_minor_or_node_upgrades':
|
|
window.maintenanceExclusionOptions = self.messages.MaintenanceExclusionOptions(
|
|
scope=self.messages.MaintenanceExclusionOptions.ScopeValueValuesEnum.NO_MINOR_OR_NODE_UPGRADES
|
|
)
|
|
if window_until_end_of_support:
|
|
if window.maintenanceExclusionOptions is None:
|
|
window.maintenanceExclusionOptions = self.messages.MaintenanceExclusionOptions(
|
|
endTimeBehavior=(
|
|
self.messages.MaintenanceExclusionOptions.EndTimeBehaviorValueValuesEnum.UNTIL_END_OF_SUPPORT
|
|
) # pylint: disable=line-too-long
|
|
)
|
|
else:
|
|
window.maintenanceExclusionOptions.endTimeBehavior = (
|
|
self.messages.MaintenanceExclusionOptions.EndTimeBehaviorValueValuesEnum.UNTIL_END_OF_SUPPORT
|
|
) # pylint: disable=line-too-long
|
|
|
|
exclusions.additionalProperties.append(
|
|
exclusions.AdditionalProperty(key=window_name, value=window)
|
|
)
|
|
return self._SendMaintenancePolicyRequest(cluster_ref, existing_policy)
|
|
|
|
def RemoveMaintenanceExclusion(
|
|
self, cluster_ref, existing_policy, exclusion_name
|
|
):
|
|
"""Removes a maintenance exclusion from the maintenance policy by name."""
|
|
existing_policy = self._NormalizeMaintenanceExclusionsForPolicy(
|
|
existing_policy
|
|
)
|
|
existing_exclusions = self._GetMaintenanceExclusionNames(existing_policy)
|
|
if exclusion_name not in existing_exclusions:
|
|
message = (
|
|
'No maintenance exclusion with name {0} exists. Existing '
|
|
'exclusions: {1}.'
|
|
).format(exclusion_name, ', '.join(existing_exclusions))
|
|
raise util.Error(message)
|
|
|
|
props = []
|
|
for ex in existing_policy.window.maintenanceExclusions.additionalProperties:
|
|
if ex.key != exclusion_name:
|
|
props.append(ex)
|
|
existing_policy.window.maintenanceExclusions.additionalProperties = props
|
|
|
|
return self._SendMaintenancePolicyRequest(cluster_ref, existing_policy)
|
|
|
|
def ListUsableSubnets(self, project_ref, network_project, filter_arg):
|
|
"""List usable subnets for a given project.
|
|
|
|
Args:
|
|
project_ref: project where clusters will be created.
|
|
network_project: project ID where clusters will be created.
|
|
filter_arg: value of filter flag.
|
|
|
|
Returns:
|
|
Response containing the list of subnetworks and a next page token.
|
|
"""
|
|
filters = []
|
|
if network_project is not None:
|
|
filters.append('networkProjectId=' + network_project)
|
|
|
|
if filter_arg is not None:
|
|
filters.append(filter_arg)
|
|
|
|
filters = ' AND '.join(filters)
|
|
|
|
req = self.messages.ContainerProjectsAggregatedUsableSubnetworksListRequest(
|
|
# parent example: 'projects/abc'
|
|
parent=project_ref.RelativeName(),
|
|
# max pageSize accepted by GKE
|
|
pageSize=500,
|
|
filter=filters,
|
|
)
|
|
return self.client.projects_aggregated_usableSubnetworks.List(req)
|
|
|
|
def ModifyCrossConnectSubnetworks(
|
|
self,
|
|
cluster_ref,
|
|
existing_cross_connect_config,
|
|
add_subnetworks=None,
|
|
remove_subnetworks=None,
|
|
clear_all_subnetworks=None,
|
|
):
|
|
"""Add/Remove/Clear cross connect subnetworks and schedule cluster update request."""
|
|
items = existing_cross_connect_config.items
|
|
if clear_all_subnetworks:
|
|
items = []
|
|
if remove_subnetworks:
|
|
items = [x for x in items if x.subnetwork not in remove_subnetworks]
|
|
if add_subnetworks:
|
|
existing_subnetworks = set([x.subnetwork for x in items])
|
|
items.extend([
|
|
self.messages.CrossConnectItem(subnetwork=subnetwork)
|
|
for subnetwork in add_subnetworks
|
|
if subnetwork not in existing_subnetworks
|
|
])
|
|
|
|
cross_connect_config = self.messages.CrossConnectConfig(
|
|
fingerprint=existing_cross_connect_config.fingerprint, items=items
|
|
)
|
|
private_cluster_config = self.messages.PrivateClusterConfig(
|
|
crossConnectConfig=cross_connect_config
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredPrivateClusterConfig=private_cluster_config
|
|
)
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def ModifyGoogleCloudAccess(
|
|
self, cluster_ref, existing_authorized_networks, goole_cloud_access
|
|
):
|
|
"""Update enable_google_cloud_access and schedule cluster update request."""
|
|
authorized_networks = self.messages.MasterAuthorizedNetworksConfig(
|
|
enabled=existing_authorized_networks.enabled,
|
|
cidrBlocks=existing_authorized_networks.cidrBlocks,
|
|
gcpPublicCidrsAccessEnabled=goole_cloud_access,
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredMasterAuthorizedNetworksConfig=authorized_networks
|
|
)
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def ModifyInsecureKubeletReadonlyPortEnabled(
|
|
self, cluster_ref, readonly_port_enabled
|
|
):
|
|
"""Updates default for Kubelet Readonly Port on new node-pools."""
|
|
nkc = self.messages.NodeKubeletConfig(
|
|
insecureKubeletReadonlyPortEnabled=readonly_port_enabled,
|
|
)
|
|
update = self.messages.ClusterUpdate()
|
|
update.desiredNodeKubeletConfig = nkc
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def ModifyKernelModuleSignatureEnforcement(
|
|
self, cluster_ref, enable_kernel_module_signature_enforcement
|
|
):
|
|
"""Updates default for Kernel Module Signature Enforcement on new node-pools."""
|
|
lnc = self.messages.LinuxNodeConfig()
|
|
module_loading_config = self.messages.NodeKernelModuleLoading()
|
|
policy_enum = self.messages.NodeKernelModuleLoading.PolicyValueValuesEnum
|
|
if enable_kernel_module_signature_enforcement:
|
|
module_loading_config.policy = policy_enum.ENFORCE_SIGNED_MODULES
|
|
else:
|
|
module_loading_config.policy = policy_enum.DO_NOT_ENFORCE_SIGNED_MODULES
|
|
lnc.nodeKernelModuleLoading = module_loading_config
|
|
update = self.messages.ClusterUpdate()
|
|
update.desiredNodePoolAutoConfigLinuxNodeConfig = lnc
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def ModifyAutoprovisioningInsecureKubeletReadonlyPortEnabled(
|
|
self, cluster_ref, request_roport_enabled
|
|
):
|
|
"""Updates the kubelet readonly port on autoprovsioned node-pools or on autopilot clusters."""
|
|
nkc = self.messages.NodeKubeletConfig(
|
|
insecureKubeletReadonlyPortEnabled=request_roport_enabled,
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNodePoolAutoConfigKubeletConfig=nkc,
|
|
)
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def ModifyBinaryAuthorization(
|
|
self,
|
|
cluster_ref,
|
|
existing_binauthz_config,
|
|
enable_binauthz,
|
|
binauthz_evaluation_mode,
|
|
binauthz_policy_bindings,
|
|
):
|
|
"""Updates the binary_authorization message."""
|
|
|
|
# If the --(no-)binauthz-enabled flag is present the evaluation mode and
|
|
# policy fields are set to None (if the user is enabling binauthz and
|
|
# is currently using a platform policy evaluation mode the user is prompted
|
|
# before performing this action). If either the --binauthz-evaluation-mode
|
|
# or --binauthz-policy-bindings flags are passed the enabled field is set to
|
|
# False and existing fields not overridden by a flag are preserved.
|
|
if existing_binauthz_config is not None:
|
|
binary_authorization = self.messages.BinaryAuthorization(
|
|
evaluationMode=existing_binauthz_config.evaluationMode,
|
|
policyBindings=existing_binauthz_config.policyBindings,
|
|
)
|
|
else:
|
|
binary_authorization = self.messages.BinaryAuthorization()
|
|
|
|
if enable_binauthz is not None:
|
|
if enable_binauthz and BinauthzEvaluationModeRequiresPolicy(
|
|
self.messages, binary_authorization.evaluationMode
|
|
):
|
|
console_io.PromptContinue(
|
|
message=(
|
|
'This will cause the current version of Binary Authorization to'
|
|
' be downgraded (not recommended).'
|
|
),
|
|
cancel_on_no=True,
|
|
)
|
|
binary_authorization = self.messages.BinaryAuthorization(
|
|
enabled=enable_binauthz
|
|
)
|
|
else:
|
|
if binauthz_evaluation_mode is not None:
|
|
binary_authorization.evaluationMode = (
|
|
util.GetBinauthzEvaluationModeMapper(
|
|
self.messages, hidden=False
|
|
).GetEnumForChoice(binauthz_evaluation_mode)
|
|
)
|
|
|
|
# Clear the policy and policyBindings field if the updated evaluation
|
|
# mode does not require a policy.
|
|
if not BinauthzEvaluationModeRequiresPolicy(
|
|
self.messages, binary_authorization.evaluationMode
|
|
):
|
|
binary_authorization.policyBindings = []
|
|
if binauthz_policy_bindings is not None:
|
|
# New policy bindings passed to the cluster update command override
|
|
# existing policy bindings.
|
|
binary_authorization.policyBindings = []
|
|
for binding in binauthz_policy_bindings:
|
|
binary_authorization.policyBindings.append(
|
|
self.messages.PolicyBinding(
|
|
name=binding['name'],
|
|
enforcementMode=self.messages.PolicyBinding.EnforcementModeValueValuesEnum( # pylint:disable=g-long-ternary
|
|
binding['enforcement-mode']
|
|
)
|
|
if 'enforcement-mode' in binding
|
|
else None,
|
|
)
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredBinaryAuthorization=binary_authorization
|
|
)
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def ModifyRayClusterLoggingConfig(
|
|
self, cluster_ref, enable_ray_cluster_logging
|
|
):
|
|
"""Enables Ray cluster log collection when using RayOperator addon."""
|
|
|
|
ray_operator_config = self.messages.RayOperatorConfig(
|
|
enabled=True,
|
|
rayClusterLoggingConfig=self.messages.RayClusterLoggingConfig(
|
|
enabled=enable_ray_cluster_logging
|
|
),
|
|
)
|
|
addons_config = self.messages.AddonsConfig(
|
|
rayOperatorConfig=ray_operator_config
|
|
)
|
|
update = self.messages.ClusterUpdate(desiredAddonsConfig=addons_config)
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def ModifyRayClusterMonitoringConfig(
|
|
self, cluster_ref, enable_ray_cluster_monitoring
|
|
):
|
|
"""Enables Ray cluster metrics collection when using RayOperator addon."""
|
|
|
|
ray_operator_config = self.messages.RayOperatorConfig(
|
|
enabled=True,
|
|
rayClusterMonitoringConfig=self.messages.RayClusterMonitoringConfig(
|
|
enabled=enable_ray_cluster_monitoring
|
|
),
|
|
)
|
|
addons_config = self.messages.AddonsConfig(
|
|
rayOperatorConfig=ray_operator_config
|
|
)
|
|
update = self.messages.ClusterUpdate(desiredAddonsConfig=addons_config)
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def ModifyRBACBindingConfig(
|
|
self,
|
|
cluster_ref,
|
|
enable_insecure_binding_system_authenticated,
|
|
enable_insecure_binding_system_unauthenticated,
|
|
):
|
|
"""Modify the RBACBindingConfig message."""
|
|
rbac_binding_config = self.messages.RBACBindingConfig()
|
|
if enable_insecure_binding_system_authenticated is not None:
|
|
rbac_binding_config.enableInsecureBindingSystemAuthenticated = (
|
|
enable_insecure_binding_system_authenticated
|
|
)
|
|
if enable_insecure_binding_system_unauthenticated is not None:
|
|
rbac_binding_config.enableInsecureBindingSystemUnauthenticated = (
|
|
enable_insecure_binding_system_unauthenticated
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredRbacBindingConfig=rbac_binding_config
|
|
)
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def ModifyAutoprovisioningCgroupMode(self, cluster_ref, cgroup_mode):
|
|
"""Updates the cgroup mode on autoprovisioned node-pools or on autopilot clusters."""
|
|
# pylint: disable=line-too-long
|
|
cgroup_mode_map = {
|
|
'default': (
|
|
self.messages.LinuxNodeConfig.CgroupModeValueValuesEnum.CGROUP_MODE_UNSPECIFIED
|
|
),
|
|
'v1': (
|
|
self.messages.LinuxNodeConfig.CgroupModeValueValuesEnum.CGROUP_MODE_V1
|
|
),
|
|
'v2': (
|
|
self.messages.LinuxNodeConfig.CgroupModeValueValuesEnum.CGROUP_MODE_V2
|
|
),
|
|
}
|
|
linux_config = self.messages.LinuxNodeConfig(
|
|
cgroupMode=cgroup_mode_map[cgroup_mode]
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNodePoolAutoConfigLinuxNodeConfig=linux_config
|
|
)
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def ModifyAnonymousAuthenticationConfig(
|
|
self, cluster_ref, anonymous_authentication_config
|
|
):
|
|
"""Updates the anonymous authentication config on the cluster."""
|
|
update = self.messages.ClusterUpdate()
|
|
available_modes = {
|
|
'LIMITED': (
|
|
self.messages.AnonymousAuthenticationConfig.ModeValueValuesEnum.LIMITED
|
|
),
|
|
'ENABLED': (
|
|
self.messages.AnonymousAuthenticationConfig.ModeValueValuesEnum.ENABLED
|
|
),
|
|
}
|
|
if anonymous_authentication_config is not None:
|
|
update.desiredAnonymousAuthenticationConfig = (
|
|
self.messages.AnonymousAuthenticationConfig(
|
|
mode=available_modes[anonymous_authentication_config]
|
|
)
|
|
)
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def ModifyLegacyLustrePortEnabled(
|
|
self, cluster_ref, enable_legacy_lustre_port
|
|
):
|
|
"""Enables legacy lustre port when using the Lustre Csi Driver add on.
|
|
|
|
Args:
|
|
cluster_ref: The cluster to update.
|
|
enable_legacy_lustre_port: Whether to enable legacy lustre port.
|
|
|
|
Returns:
|
|
Modifies LustreCsiDriverConfig and returns the operation for update.
|
|
"""
|
|
cluster = self.GetCluster(cluster_ref)
|
|
disable_multi_nic = None
|
|
if (
|
|
cluster.addonsConfig
|
|
and cluster.addonsConfig.lustreCsiDriverConfig
|
|
and cluster.addonsConfig.lustreCsiDriverConfig.disableMultiNic
|
|
):
|
|
disable_multi_nic = (
|
|
cluster.addonsConfig.lustreCsiDriverConfig.disableMultiNic
|
|
)
|
|
|
|
lustre_csi_driver_config = self.messages.LustreCsiDriverConfig(
|
|
enabled=True,
|
|
enableLegacyLustrePort=enable_legacy_lustre_port,
|
|
disableMultiNic=disable_multi_nic,
|
|
)
|
|
addons_config = self.messages.AddonsConfig(
|
|
lustreCsiDriverConfig=lustre_csi_driver_config
|
|
)
|
|
update = self.messages.ClusterUpdate(desiredAddonsConfig=addons_config)
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def ModifyMultiNicLustreDisabled(self, cluster_ref, disable_multi_nic_lustre):
|
|
"""Disables multi-nic when using the Lustre Csi Driver add on.
|
|
|
|
Args:
|
|
cluster_ref: The cluster to update.
|
|
disable_multi_nic_lustre: Whether to disable multi-nic.
|
|
|
|
Returns:
|
|
Modifies LustreCsiDriverConfig and returns the operation for update.
|
|
"""
|
|
cluster = self.GetCluster(cluster_ref)
|
|
enable_legacy_lustre_port = None
|
|
if (
|
|
cluster.addonsConfig
|
|
and cluster.addonsConfig.lustreCsiDriverConfig
|
|
and cluster.addonsConfig.lustreCsiDriverConfig.enableLegacyLustrePort
|
|
):
|
|
enable_legacy_lustre_port = (
|
|
cluster.addonsConfig.lustreCsiDriverConfig.enableLegacyLustrePort
|
|
)
|
|
|
|
lustre_csi_driver_config = self.messages.LustreCsiDriverConfig(
|
|
enabled=True,
|
|
disableMultiNic=disable_multi_nic_lustre,
|
|
enableLegacyLustrePort=enable_legacy_lustre_port,
|
|
)
|
|
addons_config = self.messages.AddonsConfig(
|
|
lustreCsiDriverConfig=lustre_csi_driver_config
|
|
)
|
|
update = self.messages.ClusterUpdate(desiredAddonsConfig=addons_config)
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def ModifyControlPlaneEgress(self, cluster_ref, control_plane_egress_mode):
|
|
"""Updates the control plane egress config on the cluster."""
|
|
update = self.messages.ClusterUpdate()
|
|
available_modes = {
|
|
'NONE': self.messages.ControlPlaneEgress.ModeValueValuesEnum.NONE,
|
|
'VIA_CONTROL_PLANE': (
|
|
self.messages.ControlPlaneEgress.ModeValueValuesEnum.VIA_CONTROL_PLANE
|
|
),
|
|
}
|
|
if control_plane_egress_mode is not None:
|
|
update.desiredControlPlaneEgress = self.messages.ControlPlaneEgress(
|
|
mode=available_modes[control_plane_egress_mode]
|
|
)
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def _GetDesiredControlPlaneEndpointsConfig(self, cluster_ref, options):
|
|
"""Gets the DesiredControlPlaneEndpointsConfig from options."""
|
|
cp_endpoints_config = self.messages.ControlPlaneEndpointsConfig()
|
|
# update dnsEndpointConfig sub-section
|
|
if (
|
|
options.enable_dns_access is not None
|
|
or options.enable_k8s_tokens_via_dns is not None
|
|
or options.enable_k8s_certs_via_dns is not None
|
|
):
|
|
cp_endpoints_config.dnsEndpointConfig = self.messages.DNSEndpointConfig()
|
|
if options.enable_dns_access is not None:
|
|
cp_endpoints_config.dnsEndpointConfig.allowExternalTraffic = (
|
|
options.enable_dns_access
|
|
)
|
|
if options.enable_k8s_tokens_via_dns is not None:
|
|
cp_endpoints_config.dnsEndpointConfig.enableK8sTokensViaDns = (
|
|
options.enable_k8s_tokens_via_dns
|
|
)
|
|
if options.enable_k8s_certs_via_dns is not None:
|
|
cp_endpoints_config.dnsEndpointConfig.enableK8sCertsViaDns = (
|
|
options.enable_k8s_certs_via_dns
|
|
)
|
|
# update ipEndpointConfig sub-section
|
|
if (
|
|
options.enable_ip_access is not None
|
|
or options.enable_master_global_access is not None
|
|
or options.enable_private_endpoint is not None
|
|
or options.enable_master_authorized_networks is not None
|
|
or options.enable_google_cloud_access is not None
|
|
or options.enable_authorized_networks_on_private_endpoint is not None
|
|
):
|
|
ip_endpoints_config = self.messages.IPEndpointsConfig()
|
|
|
|
if options.enable_ip_access is not None:
|
|
ip_endpoints_config.enabled = options.enable_ip_access
|
|
if options.enable_master_global_access is not None:
|
|
ip_endpoints_config.globalAccess = options.enable_master_global_access
|
|
if options.enable_private_endpoint is not None:
|
|
ip_endpoints_config.enablePublicEndpoint = (
|
|
not options.enable_private_endpoint
|
|
)
|
|
|
|
if (
|
|
options.enable_master_authorized_networks is not None
|
|
or options.master_authorized_networks is not None
|
|
):
|
|
if options.enable_master_authorized_networks is None:
|
|
raise util.Error(MISMATCH_AUTHORIZED_NETWORKS_ERROR_MSG)
|
|
authorized_networks = self.messages.MasterAuthorizedNetworksConfig(
|
|
enabled=options.enable_master_authorized_networks
|
|
)
|
|
if options.master_authorized_networks:
|
|
for network in options.master_authorized_networks:
|
|
authorized_networks.cidrBlocks.append(
|
|
self.messages.CidrBlock(cidrBlock=network)
|
|
)
|
|
ip_endpoints_config.authorizedNetworksConfig = authorized_networks
|
|
|
|
if options.enable_google_cloud_access is not None:
|
|
if ip_endpoints_config.authorizedNetworksConfig is None:
|
|
# preserver current state of MAN (enabled/disabled + cirds)
|
|
# if not provided in the request
|
|
cluster = self.GetCluster(cluster_ref)
|
|
authorized_networks = self.messages.MasterAuthorizedNetworksConfig(
|
|
enabled=cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.authorizedNetworksConfig.enabled,
|
|
cidrBlocks=cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.authorizedNetworksConfig.cidrBlocks,
|
|
)
|
|
ip_endpoints_config.authorizedNetworksConfig = authorized_networks
|
|
(
|
|
ip_endpoints_config.authorizedNetworksConfig.gcpPublicCidrsAccessEnabled
|
|
) = options.enable_google_cloud_access
|
|
|
|
if options.enable_authorized_networks_on_private_endpoint is not None:
|
|
if ip_endpoints_config.authorizedNetworksConfig is None:
|
|
# preserver current state of MAN (enabled/disabled + cirds)
|
|
# if not provided in the request
|
|
cluster = self.GetCluster(cluster_ref)
|
|
authorized_networks = self.messages.MasterAuthorizedNetworksConfig(
|
|
enabled=cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.authorizedNetworksConfig.enabled,
|
|
cidrBlocks=cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.authorizedNetworksConfig.cidrBlocks,
|
|
)
|
|
ip_endpoints_config.authorizedNetworksConfig = authorized_networks
|
|
(
|
|
ip_endpoints_config.authorizedNetworksConfig.privateEndpointEnforcementEnabled
|
|
) = options.enable_authorized_networks_on_private_endpoint
|
|
|
|
cp_endpoints_config.ipEndpointsConfig = ip_endpoints_config
|
|
return cp_endpoints_config
|
|
|
|
def _ParseControlPlaneEndpointsConfig(self, options, cluster):
|
|
"""Parses the options for control plane endpoints config (creation flow)."""
|
|
if options.enable_dns_access is not None:
|
|
self._InitDNSEndpointConfigIfRequired(cluster)
|
|
cluster.controlPlaneEndpointsConfig.dnsEndpointConfig.allowExternalTraffic = (
|
|
options.enable_dns_access
|
|
)
|
|
if options.enable_k8s_tokens_via_dns is not None:
|
|
self._InitDNSEndpointConfigIfRequired(cluster)
|
|
cluster.controlPlaneEndpointsConfig.dnsEndpointConfig.enableK8sTokensViaDns = (
|
|
options.enable_k8s_tokens_via_dns
|
|
)
|
|
if options.enable_k8s_certs_via_dns is not None:
|
|
self._InitDNSEndpointConfigIfRequired(cluster)
|
|
cluster.controlPlaneEndpointsConfig.dnsEndpointConfig.enableK8sCertsViaDns = (
|
|
options.enable_k8s_certs_via_dns
|
|
)
|
|
if options.enable_ip_access is not None:
|
|
self._InitIPEndpointsConfigIfRequired(cluster)
|
|
cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.enabled = (
|
|
options.enable_ip_access
|
|
)
|
|
if options.enable_master_global_access is not None:
|
|
self._InitIPEndpointsConfigIfRequired(cluster)
|
|
cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.globalAccess = (
|
|
options.enable_master_global_access
|
|
)
|
|
if options.enable_private_endpoint is not None:
|
|
self._InitIPEndpointsConfigIfRequired(cluster)
|
|
cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.enablePublicEndpoint = (
|
|
not options.enable_private_endpoint
|
|
)
|
|
|
|
if options.private_endpoint_subnetwork is not None:
|
|
self._InitIPEndpointsConfigIfRequired(cluster)
|
|
cluster.controlPlaneEndpointsConfig.ipEndpointsConfig.privateEndpointSubnetwork = (
|
|
options.private_endpoint_subnetwork
|
|
)
|
|
|
|
self.ParseMasterAuthorizedNetworkOptions(options, cluster)
|
|
|
|
def _InitDNSEndpointConfigIfRequired(self, cluster):
|
|
"""Initializes the DNSEndpointConfig on the cluster object if it is none."""
|
|
if cluster.controlPlaneEndpointsConfig is None:
|
|
cluster.controlPlaneEndpointsConfig = (
|
|
self.messages.ControlPlaneEndpointsConfig()
|
|
)
|
|
if cluster.controlPlaneEndpointsConfig.dnsEndpointConfig is None:
|
|
cluster.controlPlaneEndpointsConfig.dnsEndpointConfig = (
|
|
self.messages.DNSEndpointConfig()
|
|
)
|
|
|
|
def _InitIPEndpointsConfigIfRequired(self, cluster):
|
|
"""Initializes the IPEndpointsConfig on the cluster object if it is none."""
|
|
if cluster.controlPlaneEndpointsConfig is None:
|
|
cluster.controlPlaneEndpointsConfig = (
|
|
self.messages.ControlPlaneEndpointsConfig()
|
|
)
|
|
if cluster.controlPlaneEndpointsConfig.ipEndpointsConfig is None:
|
|
cluster.controlPlaneEndpointsConfig.ipEndpointsConfig = (
|
|
self.messages.IPEndpointsConfig()
|
|
)
|
|
|
|
|
|
class V1Adapter(APIAdapter):
|
|
"""APIAdapter for v1."""
|
|
|
|
|
|
class V1Beta1Adapter(V1Adapter):
|
|
"""APIAdapter for v1beta1."""
|
|
|
|
def CreateCluster(self, cluster_ref, options):
|
|
cluster = self.CreateClusterCommon(cluster_ref, options)
|
|
if options.addons:
|
|
# CloudRun is disabled by default.
|
|
if any((v in options.addons) for v in CLOUDRUN_ADDONS):
|
|
if not options.enable_stackdriver_kubernetes and (
|
|
(
|
|
options.monitoring is not None
|
|
and SYSTEM not in options.monitoring
|
|
)
|
|
or (options.logging is not None and SYSTEM not in options.logging)
|
|
):
|
|
raise util.Error(CLOUDRUN_STACKDRIVER_KUBERNETES_DISABLED_ERROR_MSG)
|
|
if INGRESS not in options.addons:
|
|
raise util.Error(CLOUDRUN_INGRESS_KUBERNETES_DISABLED_ERROR_MSG)
|
|
load_balancer_type = _GetCloudRunLoadBalancerType(
|
|
options, self.messages
|
|
)
|
|
cluster.addonsConfig.cloudRunConfig = self.messages.CloudRunConfig(
|
|
disabled=False, loadBalancerType=load_balancer_type
|
|
)
|
|
# CloudBuild is disabled by default.
|
|
if CLOUDBUILD in options.addons:
|
|
if not options.enable_stackdriver_kubernetes and (
|
|
(
|
|
options.monitoring is not None
|
|
and SYSTEM not in options.monitoring
|
|
)
|
|
or (options.logging is not None and SYSTEM not in options.logging)
|
|
):
|
|
raise util.Error(CLOUDBUILD_STACKDRIVER_KUBERNETES_DISABLED_ERROR_MSG)
|
|
cluster.addonsConfig.cloudBuildConfig = self.messages.CloudBuildConfig(
|
|
enabled=True
|
|
)
|
|
# BackupRestore is disabled by default.
|
|
if BACKUPRESTORE in options.addons:
|
|
cluster.addonsConfig.gkeBackupAgentConfig = (
|
|
self.messages.GkeBackupAgentConfig(enabled=True)
|
|
)
|
|
# Istio is disabled by default.
|
|
if ISTIO in options.addons:
|
|
istio_auth = self.messages.IstioConfig.AuthValueValuesEnum.AUTH_NONE
|
|
mtls = self.messages.IstioConfig.AuthValueValuesEnum.AUTH_MUTUAL_TLS
|
|
istio_config = options.istio_config
|
|
if istio_config is not None:
|
|
auth_config = istio_config.get('auth')
|
|
if auth_config is not None:
|
|
if auth_config == 'MTLS_STRICT':
|
|
istio_auth = mtls
|
|
cluster.addonsConfig.istioConfig = self.messages.IstioConfig(
|
|
disabled=False, auth=istio_auth
|
|
)
|
|
if (
|
|
options.enable_autoprovisioning is not None
|
|
or options.max_cpu is not None
|
|
or options.min_cpu is not None
|
|
or options.max_memory is not None
|
|
or options.min_memory is not None
|
|
or options.autoprovisioning_image_type is not None
|
|
or options.max_accelerator is not None
|
|
or options.min_accelerator is not None
|
|
or options.autoprovisioning_service_account is not None
|
|
or options.autoprovisioning_scopes is not None
|
|
or options.enable_autoprovisioning_surge_upgrade is not None
|
|
or options.enable_autoprovisioning_blue_green_upgrade is not None
|
|
or options.autoprovisioning_max_surge_upgrade is not None
|
|
or options.autoprovisioning_max_unavailable_upgrade is not None
|
|
or options.autoprovisioning_standard_rollout_policy is not None
|
|
or options.autoprovisioning_node_pool_soak_duration is not None
|
|
or options.enable_autoprovisioning_autoupgrade is not None
|
|
or options.enable_autoprovisioning_autorepair is not None
|
|
or options.autoprovisioning_locations is not None
|
|
or options.autoprovisioning_min_cpu_platform is not None
|
|
or options.autoscaling_profile is not None
|
|
or options.enable_default_compute_class is not None
|
|
):
|
|
cluster.autoscaling = self.CreateClusterAutoscalingCommon(
|
|
None, options, False
|
|
)
|
|
if options.enable_workload_certificates:
|
|
if not options.workload_pool:
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='workload-pool', opt='enable-workload-certificates'
|
|
)
|
|
)
|
|
if cluster.workloadCertificates is None:
|
|
cluster.workloadCertificates = self.messages.WorkloadCertificates()
|
|
cluster.workloadCertificates.enableCertificates = (
|
|
options.enable_workload_certificates
|
|
)
|
|
if options.enable_alts:
|
|
if not options.workload_pool:
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='workload-pool', opt='enable-alts'
|
|
)
|
|
)
|
|
if cluster.workloadAltsConfig is None:
|
|
cluster.workloadAltsConfig = self.messages.WorkloadALTSConfig()
|
|
cluster.workloadAltsConfig.enableAlts = options.enable_alts
|
|
if options.enable_gke_oidc:
|
|
cluster.gkeOidcConfig = self.messages.GkeOidcConfig(
|
|
enabled=options.enable_gke_oidc
|
|
)
|
|
if options.enable_identity_service:
|
|
cluster.identityServiceConfig = self.messages.IdentityServiceConfig(
|
|
enabled=options.enable_identity_service
|
|
)
|
|
if options.security_group is not None:
|
|
# The presence of the --security_group="foo" flag implies enabled=True.
|
|
cluster.authenticatorGroupsConfig = (
|
|
self.messages.AuthenticatorGroupsConfig(
|
|
enabled=True, securityGroup=options.security_group
|
|
)
|
|
)
|
|
_AddPSCPrivateClustersOptionsToClusterForCreateCluster(
|
|
cluster, options, self.messages
|
|
)
|
|
|
|
cluster_telemetry_type = self._GetClusterTelemetryType(
|
|
options, cluster.loggingService, cluster.monitoringService
|
|
)
|
|
if cluster_telemetry_type is not None:
|
|
cluster.clusterTelemetry = self.messages.ClusterTelemetry()
|
|
cluster.clusterTelemetry.type = cluster_telemetry_type
|
|
|
|
if cluster.clusterTelemetry:
|
|
cluster.loggingService = None
|
|
cluster.monitoringService = None
|
|
|
|
if options.enable_workload_monitoring_eap:
|
|
cluster.workloadMonitoringEnabledEap = True
|
|
|
|
if options.enable_service_externalips is not None:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig()
|
|
cluster.networkConfig.serviceExternalIpsConfig = (
|
|
self.messages.ServiceExternalIPsConfig(
|
|
enabled=options.enable_service_externalips
|
|
)
|
|
)
|
|
if options.identity_provider:
|
|
if options.workload_pool:
|
|
cluster.workloadIdentityConfig.identityProvider = (
|
|
options.identity_provider
|
|
)
|
|
else:
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='workload-pool', opt='identity-provider'
|
|
)
|
|
)
|
|
|
|
if options.datapath_provider is not None:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig()
|
|
if options.datapath_provider.lower() == 'legacy':
|
|
cluster.networkConfig.datapathProvider = (
|
|
self.messages.NetworkConfig.DatapathProviderValueValuesEnum.LEGACY_DATAPATH
|
|
)
|
|
elif options.datapath_provider.lower() == 'advanced':
|
|
cluster.networkConfig.datapathProvider = (
|
|
self.messages.NetworkConfig.DatapathProviderValueValuesEnum.ADVANCED_DATAPATH
|
|
)
|
|
else:
|
|
raise util.Error(
|
|
DATAPATH_PROVIDER_ILL_SPECIFIED_ERROR_MSG.format(
|
|
provider=options.datapath_provider
|
|
)
|
|
)
|
|
|
|
cluster.master = _GetMasterForClusterCreate(options, self.messages)
|
|
|
|
cluster.kubernetesObjectsExportConfig = (
|
|
_GetKubernetesObjectsExportConfigForClusterCreate(
|
|
options, self.messages
|
|
)
|
|
)
|
|
|
|
if options.enable_experimental_vertical_pod_autoscaling is not None:
|
|
cluster.verticalPodAutoscaling = self.messages.VerticalPodAutoscaling(
|
|
enableExperimentalFeatures=options.enable_experimental_vertical_pod_autoscaling
|
|
)
|
|
if options.enable_experimental_vertical_pod_autoscaling:
|
|
cluster.verticalPodAutoscaling.enabled = True
|
|
|
|
if options.enable_cost_allocation:
|
|
cluster.costManagementConfig = self.messages.CostManagementConfig(
|
|
enabled=True
|
|
)
|
|
|
|
if options.stack_type is not None:
|
|
if options.stack_type.lower() == gke_constants.IPV6_STACK_TYPE:
|
|
self._ParseIPv6Options(options, cluster)
|
|
else:
|
|
cluster.ipAllocationPolicy.stackType = util.GetCreateStackTypeMapper(
|
|
self.messages
|
|
).GetEnumForChoice(options.stack_type)
|
|
if options.ipv6_access_type is not None:
|
|
cluster.ipAllocationPolicy.ipv6AccessType = util.GetIpv6AccessTypeMapper(
|
|
self.messages
|
|
).GetEnumForChoice(options.ipv6_access_type)
|
|
|
|
req = self.messages.CreateClusterRequest(
|
|
parent=ProjectLocation(cluster_ref.projectId, cluster_ref.zone),
|
|
cluster=cluster,
|
|
)
|
|
operation = self.client.projects_locations_clusters.Create(req)
|
|
return self.ParseOperation(operation.name, cluster_ref.zone)
|
|
|
|
def CreateNodePool(self, node_pool_ref, options):
|
|
pool = self.CreateNodePoolCommon(node_pool_ref, options)
|
|
req = self.messages.CreateNodePoolRequest(
|
|
nodePool=pool,
|
|
parent=ProjectLocationCluster(
|
|
node_pool_ref.projectId, node_pool_ref.zone, node_pool_ref.clusterId
|
|
),
|
|
)
|
|
operation = self.client.projects_locations_clusters_nodePools.Create(req)
|
|
return self.ParseOperation(operation.name, node_pool_ref.zone)
|
|
|
|
def UpdateClusterCommon(self, cluster_ref, options):
|
|
"""Returns an UpdateCluster operation."""
|
|
update = None
|
|
if not options.version:
|
|
options.version = '-'
|
|
if options.update_nodes:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNodeVersion=options.version,
|
|
desiredNodePoolId=options.node_pool,
|
|
desiredImageType=options.image_type,
|
|
desiredImage=options.image,
|
|
desiredImageProject=options.image_project,
|
|
)
|
|
# security_profile may be set in upgrade command
|
|
if options.security_profile is not None:
|
|
update.securityProfile = self.messages.SecurityProfile(
|
|
name=options.security_profile
|
|
)
|
|
elif options.update_master:
|
|
update = self.messages.ClusterUpdate(desiredMasterVersion=options.version)
|
|
# security_profile may be set in upgrade command
|
|
if options.security_profile is not None:
|
|
update.securityProfile = self.messages.SecurityProfile(
|
|
name=options.security_profile
|
|
)
|
|
# control_plane_soak_duration may be set in upgrade command for rollback
|
|
# safe upgrades
|
|
if options.control_plane_soak_duration is not None:
|
|
update.desiredRollbackSafeUpgrade = self.messages.RollbackSafeUpgrade(
|
|
controlPlaneSoakDuration=options.control_plane_soak_duration
|
|
)
|
|
elif options.enable_stackdriver_kubernetes:
|
|
update = self.messages.ClusterUpdate()
|
|
update.desiredLoggingService = 'logging.googleapis.com/kubernetes'
|
|
update.desiredMonitoringService = 'monitoring.googleapis.com/kubernetes'
|
|
elif options.enable_stackdriver_kubernetes is not None:
|
|
update = self.messages.ClusterUpdate()
|
|
update.desiredLoggingService = 'none'
|
|
update.desiredMonitoringService = 'none'
|
|
elif options.monitoring_service or options.logging_service:
|
|
update = self.messages.ClusterUpdate()
|
|
if options.monitoring_service:
|
|
update.desiredMonitoringService = options.monitoring_service
|
|
if options.logging_service:
|
|
update.desiredLoggingService = options.logging_service
|
|
elif (
|
|
options.logging
|
|
or options.monitoring
|
|
or options.enable_managed_prometheus
|
|
or options.disable_managed_prometheus
|
|
or options.auto_monitoring_scope
|
|
or options.enable_dataplane_v2_metrics
|
|
or options.disable_dataplane_v2_metrics
|
|
or options.enable_dataplane_v2_flow_observability
|
|
or options.disable_dataplane_v2_flow_observability
|
|
or options.dataplane_v2_observability_mode
|
|
):
|
|
logging = _GetLoggingConfig(options, self.messages)
|
|
# Fix incorrectly omitting required field.
|
|
if (
|
|
(
|
|
options.dataplane_v2_observability_mode
|
|
or options.enable_dataplane_v2_flow_observability
|
|
or options.disable_dataplane_v2_flow_observability
|
|
)
|
|
and options.enable_dataplane_v2_metrics is None
|
|
and options.disable_dataplane_v2_metrics is None
|
|
):
|
|
cluster = self.GetCluster(cluster_ref)
|
|
if (
|
|
cluster
|
|
and cluster.monitoringConfig
|
|
and cluster.monitoringConfig.advancedDatapathObservabilityConfig
|
|
):
|
|
if (
|
|
cluster.monitoringConfig.advancedDatapathObservabilityConfig.enableMetrics
|
|
):
|
|
options.enable_dataplane_v2_metrics = True
|
|
else:
|
|
options.disable_dataplane_v2_metrics = True
|
|
|
|
monitoring = None
|
|
if options.auto_monitoring_scope:
|
|
cluster = self.GetCluster(cluster_ref)
|
|
|
|
if cluster is None:
|
|
raise util.Error(
|
|
'Cannot enable Auto Monitoring. The cluster does not exist.'
|
|
)
|
|
|
|
if (
|
|
cluster.monitoringConfig.managedPrometheusConfig is None
|
|
or not cluster.monitoringConfig.managedPrometheusConfig.enabled
|
|
) and options.auto_monitoring_scope == 'ALL':
|
|
|
|
raise util.Error(
|
|
AUTO_MONITORING_NOT_SUPPORTED_WITHOUT_MANAGED_PROMETHEUS
|
|
)
|
|
|
|
if cluster.monitoringConfig.managedPrometheusConfig.enabled:
|
|
monitoring = _GetMonitoringConfig(options, self.messages, True, True)
|
|
else:
|
|
monitoring = _GetMonitoringConfig(options, self.messages, True, False)
|
|
else:
|
|
monitoring = _GetMonitoringConfig(options, self.messages, False, None)
|
|
|
|
update = self.messages.ClusterUpdate()
|
|
if logging:
|
|
update.desiredLoggingConfig = logging
|
|
if monitoring:
|
|
update.desiredMonitoringConfig = monitoring
|
|
elif options.disable_addons or options.enable_pod_snapshots is not None:
|
|
disable_addons = options.disable_addons
|
|
if disable_addons is None:
|
|
disable_addons = {}
|
|
disable_node_local_dns = disable_addons.get(NODELOCALDNS)
|
|
addons = self._AddonsConfig(
|
|
disable_ingress=disable_addons.get(INGRESS),
|
|
disable_hpa=disable_addons.get(HPA),
|
|
disable_dashboard=disable_addons.get(DASHBOARD),
|
|
disable_network_policy=disable_addons.get(NETWORK_POLICY),
|
|
enable_node_local_dns=not disable_node_local_dns
|
|
if disable_node_local_dns is not None
|
|
else None,
|
|
enable_pod_snapshots=options.enable_pod_snapshots,
|
|
)
|
|
if disable_addons.get(CONFIGCONNECTOR) is not None:
|
|
addons.configConnectorConfig = self.messages.ConfigConnectorConfig(
|
|
enabled=(not disable_addons.get(CONFIGCONNECTOR))
|
|
)
|
|
if disable_addons.get(GCEPDCSIDRIVER) is not None:
|
|
addons.gcePersistentDiskCsiDriverConfig = (
|
|
self.messages.GcePersistentDiskCsiDriverConfig(
|
|
enabled=not disable_addons.get(GCEPDCSIDRIVER)
|
|
)
|
|
)
|
|
if disable_addons.get(GCPFILESTORECSIDRIVER) is not None:
|
|
addons.gcpFilestoreCsiDriverConfig = (
|
|
self.messages.GcpFilestoreCsiDriverConfig(
|
|
enabled=not disable_addons.get(GCPFILESTORECSIDRIVER)
|
|
)
|
|
)
|
|
if disable_addons.get(GCSFUSECSIDRIVER) is not None:
|
|
addons.gcsFuseCsiDriverConfig = self.messages.GcsFuseCsiDriverConfig(
|
|
enabled=not disable_addons.get(GCSFUSECSIDRIVER)
|
|
)
|
|
if disable_addons.get(STATEFULHA) is not None:
|
|
addons.statefulHaConfig = self.messages.StatefulHAConfig(
|
|
enabled=not disable_addons.get(STATEFULHA)
|
|
)
|
|
if disable_addons.get(PARALLELSTORECSIDRIVER) is not None:
|
|
addons.parallelstoreCsiDriverConfig = (
|
|
self.messages.ParallelstoreCsiDriverConfig(
|
|
enabled=not disable_addons.get(PARALLELSTORECSIDRIVER)
|
|
)
|
|
)
|
|
if disable_addons.get(HIGHSCALECHECKPOINTING) is not None:
|
|
addons.highScaleCheckpointingConfig = (
|
|
self.messages.HighScaleCheckpointingConfig(
|
|
enabled=not disable_addons.get(HIGHSCALECHECKPOINTING)
|
|
)
|
|
)
|
|
if disable_addons.get(LUSTRECSIDRIVER) is not None:
|
|
addons.lustreCsiDriverConfig = self.messages.LustreCsiDriverConfig(
|
|
enabled=not disable_addons.get(LUSTRECSIDRIVER)
|
|
)
|
|
if disable_addons.get(BACKUPRESTORE) is not None:
|
|
addons.gkeBackupAgentConfig = self.messages.GkeBackupAgentConfig(
|
|
enabled=not disable_addons.get(BACKUPRESTORE)
|
|
)
|
|
if disable_addons.get(RAYOPERATOR) is not None:
|
|
addons.rayOperatorConfig = self.messages.RayOperatorConfig(
|
|
enabled=not disable_addons.get(RAYOPERATOR)
|
|
)
|
|
update = self.messages.ClusterUpdate(desiredAddonsConfig=addons)
|
|
elif (
|
|
options.enable_ray_cluster_logging is not None
|
|
or options.enable_ray_cluster_monitoring is not None
|
|
or options.enable_legacy_lustre_port is not None
|
|
or options.disable_multi_nic_lustre is not None
|
|
):
|
|
addons = self._AddonsConfig(options, self.messages)
|
|
|
|
if options.enable_ray_cluster_logging is not None:
|
|
addons.rayOperatorConfig.rayClusterLoggingConfig = (
|
|
self.messages.RayClusterLoggingConfig(
|
|
enabled=options.enable_ray_cluster_logging
|
|
)
|
|
)
|
|
|
|
if options.enable_ray_cluster_monitoring is not None:
|
|
addons.rayOperatorConfig.rayClusterMonitoringConfig = (
|
|
self.messages.RayClusterMonitoringConfig(
|
|
enabled=options.enable_ray_cluster_monitoring
|
|
)
|
|
)
|
|
|
|
if options.enable_legacy_lustre_port is not None:
|
|
addons.lustreCsiDriverConfig.enableLegacyLustrePort = (
|
|
options.enable_legacy_lustre_port
|
|
)
|
|
|
|
if options.disable_multi_nic_lustre is not None:
|
|
addons.lustreCsiDriverConfig.disableMultiNic = (
|
|
options.disable_multi_nic_lustre
|
|
)
|
|
|
|
update = self.messages.ClusterUpdate(desiredAddonsConfig=addons)
|
|
elif options.enable_autoscaling is not None:
|
|
# For update, we can either enable or disable.
|
|
autoscaling = self.messages.NodePoolAutoscaling(
|
|
enabled=options.enable_autoscaling
|
|
)
|
|
if options.enable_autoscaling:
|
|
autoscaling.minNodeCount = options.min_nodes
|
|
autoscaling.maxNodeCount = options.max_nodes
|
|
autoscaling.totalMinNodeCount = options.total_min_nodes
|
|
autoscaling.totalMaxNodeCount = options.total_max_nodes
|
|
if options.location_policy is not None:
|
|
autoscaling.locationPolicy = LocationPolicyEnumFromString(
|
|
self.messages, options.location_policy
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNodePoolId=options.node_pool,
|
|
desiredNodePoolAutoscaling=autoscaling,
|
|
)
|
|
elif options.locations:
|
|
update = self.messages.ClusterUpdate(desiredLocations=options.locations)
|
|
elif (
|
|
options.enable_autoprovisioning is not None
|
|
or options.max_cpu is not None
|
|
or options.min_cpu is not None
|
|
or options.max_memory is not None
|
|
or options.min_memory is not None
|
|
or options.autoprovisioning_image_type is not None
|
|
or options.max_accelerator is not None
|
|
or options.min_accelerator is not None
|
|
or options.autoprovisioning_service_account is not None
|
|
or options.autoprovisioning_scopes is not None
|
|
or options.enable_autoprovisioning_surge_upgrade is not None
|
|
or options.enable_autoprovisioning_blue_green_upgrade is not None
|
|
or options.autoprovisioning_max_surge_upgrade is not None
|
|
or options.autoprovisioning_max_unavailable_upgrade is not None
|
|
or options.autoprovisioning_standard_rollout_policy is not None
|
|
or options.autoprovisioning_node_pool_soak_duration is not None
|
|
or options.enable_autoprovisioning_autoupgrade is not None
|
|
or options.enable_autoprovisioning_autorepair is not None
|
|
or options.autoprovisioning_locations is not None
|
|
or options.autoprovisioning_min_cpu_platform is not None
|
|
or options.autoscaling_profile is not None
|
|
or options.enable_default_compute_class is not None
|
|
):
|
|
autoscaling = self.CreateClusterAutoscalingCommon(
|
|
cluster_ref, options, True
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredClusterAutoscaling=autoscaling
|
|
)
|
|
elif options.enable_pod_security_policy is not None:
|
|
config = self.messages.PodSecurityPolicyConfig(
|
|
enabled=options.enable_pod_security_policy
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredPodSecurityPolicyConfig=config
|
|
)
|
|
elif options.enable_slice_controller is not None:
|
|
addons = self._AddonsConfig(
|
|
enable_slice_controller=options.enable_slice_controller
|
|
)
|
|
update = self.messages.ClusterUpdate(desiredAddonsConfig=addons)
|
|
elif options.enable_vertical_pod_autoscaling is not None:
|
|
vertical_pod_autoscaling = self.messages.VerticalPodAutoscaling(
|
|
enabled=options.enable_vertical_pod_autoscaling
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredVerticalPodAutoscaling=vertical_pod_autoscaling
|
|
)
|
|
elif options.resource_usage_bigquery_dataset is not None:
|
|
export_config = self.messages.ResourceUsageExportConfig(
|
|
bigqueryDestination=self.messages.BigQueryDestination(
|
|
datasetId=options.resource_usage_bigquery_dataset
|
|
)
|
|
)
|
|
if options.enable_network_egress_metering:
|
|
export_config.enableNetworkEgressMetering = True
|
|
if options.enable_resource_consumption_metering is not None:
|
|
export_config.consumptionMeteringConfig = (
|
|
self.messages.ConsumptionMeteringConfig(
|
|
enabled=options.enable_resource_consumption_metering
|
|
)
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredResourceUsageExportConfig=export_config
|
|
)
|
|
elif options.enable_network_egress_metering is not None:
|
|
raise util.Error(ENABLE_NETWORK_EGRESS_METERING_ERROR_MSG)
|
|
elif options.enable_resource_consumption_metering is not None:
|
|
raise util.Error(ENABLE_RESOURCE_CONSUMPTION_METERING_ERROR_MSG)
|
|
elif options.clear_resource_usage_bigquery_dataset is not None:
|
|
export_config = self.messages.ResourceUsageExportConfig()
|
|
update = self.messages.ClusterUpdate(
|
|
desiredResourceUsageExportConfig=export_config
|
|
)
|
|
elif options.security_profile is not None:
|
|
# security_profile is set in update command
|
|
security_profile = self.messages.SecurityProfile(
|
|
name=options.security_profile
|
|
)
|
|
update = self.messages.ClusterUpdate(securityProfile=security_profile)
|
|
elif options.enable_intra_node_visibility is not None:
|
|
intra_node_visibility_config = self.messages.IntraNodeVisibilityConfig(
|
|
enabled=options.enable_intra_node_visibility
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredIntraNodeVisibilityConfig=intra_node_visibility_config
|
|
)
|
|
elif options.managed_otel_scope:
|
|
managed_otel_config = _GetManagedOpenTelemetryConfig(
|
|
options, self.messages
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredManagedOpentelemetryConfig=managed_otel_config
|
|
)
|
|
|
|
if (
|
|
options.security_profile is not None
|
|
and options.security_profile_runtime_rules is not None
|
|
):
|
|
update.securityProfile.disableRuntimeRules = (
|
|
not options.security_profile_runtime_rules
|
|
)
|
|
if (
|
|
options.master_authorized_networks
|
|
and not options.enable_master_authorized_networks
|
|
):
|
|
# Raise error if use --master-authorized-networks without
|
|
# --enable-master-authorized-networks.
|
|
raise util.Error(MISMATCH_AUTHORIZED_NETWORKS_ERROR_MSG)
|
|
|
|
if options.database_encryption_key:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredDatabaseEncryption=self.messages.DatabaseEncryption(
|
|
keyName=options.database_encryption_key,
|
|
state=self.messages.DatabaseEncryption.StateValueValuesEnum.ENCRYPTED,
|
|
)
|
|
)
|
|
|
|
elif options.disable_database_encryption:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredDatabaseEncryption=self.messages.DatabaseEncryption(
|
|
state=self.messages.DatabaseEncryption.StateValueValuesEnum.DECRYPTED
|
|
)
|
|
)
|
|
|
|
if options.enable_shielded_nodes is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredShieldedNodes=self.messages.ShieldedNodes(
|
|
enabled=options.enable_shielded_nodes
|
|
)
|
|
)
|
|
if options.enable_tpu is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredTpuConfig=_GetTpuConfigForClusterUpdate(options, self.messages)
|
|
)
|
|
|
|
if options.release_channel is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredReleaseChannel=_GetReleaseChannel(options, self.messages)
|
|
)
|
|
|
|
if options.patch_update is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
gkeAutoUpgradeConfig=_GetGkeAutoUpgradeConfig(options, self.messages)
|
|
)
|
|
|
|
if options.disable_default_snat is not None:
|
|
disable_default_snat = self.messages.DefaultSnatStatus(
|
|
disabled=options.disable_default_snat
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredDefaultSnatStatus=disable_default_snat
|
|
)
|
|
if options.enable_l4_ilb_subsetting is not None:
|
|
ilb_subsettting_config = self.messages.ILBSubsettingConfig(
|
|
enabled=options.enable_l4_ilb_subsetting
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredL4ilbSubsettingConfig=ilb_subsettting_config
|
|
)
|
|
if options.private_ipv6_google_access_type is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredPrivateIpv6GoogleAccess=util.GetPrivateIpv6GoogleAccessTypeMapperForUpdate(
|
|
self.messages, hidden=False
|
|
).GetEnumForChoice(
|
|
options.private_ipv6_google_access_type
|
|
)
|
|
)
|
|
|
|
dns_config = self.ParseClusterDNSOptions(
|
|
options, is_update=True, cluster_ref=cluster_ref
|
|
)
|
|
if dns_config is not None:
|
|
update = self.messages.ClusterUpdate(desiredDnsConfig=dns_config)
|
|
|
|
gateway_config = self.ParseGatewayOptions(options)
|
|
if gateway_config is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredGatewayApiConfig=gateway_config
|
|
)
|
|
|
|
if options.notification_config is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNotificationConfig=_GetNotificationConfigForClusterUpdate(
|
|
options, self.messages
|
|
)
|
|
)
|
|
|
|
if options.disable_autopilot is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAutopilot=self.messages.Autopilot(enabled=False)
|
|
)
|
|
|
|
if options.security_group is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAuthenticatorGroupsConfig=self.messages.AuthenticatorGroupsConfig(
|
|
enabled=True, securityGroup=options.security_group
|
|
)
|
|
)
|
|
|
|
if options.enable_gcfs is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredGcfsConfig=self.messages.GcfsConfig(
|
|
enabled=options.enable_gcfs
|
|
)
|
|
)
|
|
|
|
if options.autoprovisioning_network_tags is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNodePoolAutoConfigNetworkTags=self.messages.NetworkTags(
|
|
tags=options.autoprovisioning_network_tags
|
|
)
|
|
)
|
|
|
|
if options.autoprovisioning_resource_manager_tags is not None:
|
|
tags = options.autoprovisioning_resource_manager_tags
|
|
rm_tags = self._ResourceManagerTags(tags)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNodePoolAutoConfigResourceManagerTags=rm_tags
|
|
)
|
|
|
|
if options.enable_image_streaming is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredGcfsConfig=self.messages.GcfsConfig(
|
|
enabled=options.enable_image_streaming
|
|
)
|
|
)
|
|
|
|
if options.enable_mesh_certificates is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredMeshCertificates=self.messages.MeshCertificates(
|
|
enableCertificates=options.enable_mesh_certificates
|
|
)
|
|
)
|
|
|
|
if options.maintenance_interval is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredStableFleetConfig=_GetStableFleetConfig(options, self.messages)
|
|
)
|
|
|
|
if options.enable_service_externalips is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredServiceExternalIpsConfig=self.messages.ServiceExternalIPsConfig(
|
|
enabled=options.enable_service_externalips
|
|
)
|
|
)
|
|
|
|
if options.enable_identity_service is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredIdentityServiceConfig=self.messages.IdentityServiceConfig(
|
|
enabled=options.enable_identity_service
|
|
)
|
|
)
|
|
|
|
if (
|
|
options.enable_workload_config_audit is not None
|
|
or options.enable_workload_vulnerability_scanning is not None
|
|
):
|
|
protect_config = self.messages.ProtectConfig()
|
|
if options.enable_workload_config_audit is not None:
|
|
protect_config.workloadConfig = self.messages.WorkloadConfig()
|
|
if options.enable_workload_config_audit:
|
|
protect_config.workloadConfig.auditMode = (
|
|
self.messages.WorkloadConfig.AuditModeValueValuesEnum.BASIC
|
|
)
|
|
else:
|
|
protect_config.workloadConfig.auditMode = (
|
|
self.messages.WorkloadConfig.AuditModeValueValuesEnum.DISABLED
|
|
)
|
|
|
|
if options.enable_workload_vulnerability_scanning is not None:
|
|
if options.enable_workload_vulnerability_scanning:
|
|
protect_config.workloadVulnerabilityMode = (
|
|
self.messages.ProtectConfig.WorkloadVulnerabilityModeValueValuesEnum.BASIC
|
|
)
|
|
else:
|
|
protect_config.workloadVulnerabilityMode = (
|
|
self.messages.ProtectConfig.WorkloadVulnerabilityModeValueValuesEnum.DISABLED
|
|
)
|
|
update = self.messages.ClusterUpdate(desiredProtectConfig=protect_config)
|
|
|
|
if options.hpa_profile is not None:
|
|
if options.hpa_profile == 'performance':
|
|
pod_autoscaling_config = self.messages.PodAutoscaling(
|
|
hpaProfile=self.messages.PodAutoscaling.HpaProfileValueValuesEnum.PERFORMANCE
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredPodAutoscaling=pod_autoscaling_config
|
|
)
|
|
elif options.hpa_profile == 'none':
|
|
pod_autoscaling_config = self.messages.PodAutoscaling(
|
|
hpaProfile=self.messages.PodAutoscaling.HpaProfileValueValuesEnum.NONE
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredPodAutoscaling=pod_autoscaling_config
|
|
)
|
|
|
|
if options.logging_variant is not None:
|
|
logging_config = self.messages.NodePoolLoggingConfig()
|
|
logging_config.variantConfig = self.messages.LoggingVariantConfig(
|
|
variant=VariantConfigEnumFromString(
|
|
self.messages, options.logging_variant
|
|
)
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNodePoolLoggingConfig=logging_config
|
|
)
|
|
|
|
if (
|
|
options.additional_pod_ipv4_ranges
|
|
or options.removed_additional_pod_ipv4_ranges
|
|
):
|
|
update = self.messages.ClusterUpdate()
|
|
if options.additional_pod_ipv4_ranges:
|
|
update.additionalPodRangesConfig = (
|
|
self.messages.AdditionalPodRangesConfig(
|
|
podRangeNames=options.additional_pod_ipv4_ranges
|
|
)
|
|
)
|
|
if options.removed_additional_pod_ipv4_ranges:
|
|
update.removedAdditionalPodRangesConfig = (
|
|
self.messages.AdditionalPodRangesConfig(
|
|
podRangeNames=options.removed_additional_pod_ipv4_ranges
|
|
)
|
|
)
|
|
|
|
if options.stack_type is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredStackType=util.GetUpdateStackTypeMapper(
|
|
self.messages
|
|
).GetEnumForChoice(options.stack_type)
|
|
)
|
|
|
|
if options.enable_cost_allocation is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredCostManagementConfig=self.messages.CostManagementConfig(
|
|
enabled=options.enable_cost_allocation
|
|
)
|
|
)
|
|
membership_types = {
|
|
'LIGHTWEIGHT': (
|
|
self.messages.Fleet.MembershipTypeValueValuesEnum.LIGHTWEIGHT
|
|
),
|
|
'MEMBERSHIP_TYPE_UNSPECIFIED': (
|
|
self.messages.Fleet.MembershipTypeValueValuesEnum.MEMBERSHIP_TYPE_UNSPECIFIED
|
|
),
|
|
}
|
|
if options.enable_fleet:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredFleet=self.messages.Fleet(
|
|
project=cluster_ref.projectId,
|
|
membershipType=membership_types.get(
|
|
options.membership_type, None
|
|
),
|
|
)
|
|
)
|
|
|
|
if options.fleet_project:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredFleet=self.messages.Fleet(
|
|
project=options.fleet_project,
|
|
membershipType=membership_types.get(
|
|
options.membership_type, None
|
|
),
|
|
)
|
|
)
|
|
|
|
if options.unset_membership_type:
|
|
fleet_project = options.fleet_project or cluster_ref.projectId
|
|
update = self.messages.ClusterUpdate(
|
|
desiredFleet=self.messages.Fleet(
|
|
membershipType=self.messages.Fleet.MembershipTypeValueValuesEnum.MEMBERSHIP_TYPE_UNSPECIFIED,
|
|
project=fleet_project,
|
|
),
|
|
)
|
|
|
|
if options.enable_k8s_beta_apis is not None:
|
|
config_obj = self.messages.K8sBetaAPIConfig()
|
|
config_obj.enabledApis = options.enable_k8s_beta_apis
|
|
update = self.messages.ClusterUpdate(desiredK8sBetaApis=config_obj)
|
|
|
|
if options.clear_fleet_project:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredFleet=self.messages.Fleet(project='')
|
|
)
|
|
|
|
if (
|
|
options.compliance is not None
|
|
or options.compliance_standards is not None
|
|
):
|
|
# --compliance=disabled and --compliance-standards=a,b,c are mutually
|
|
# exclusive.
|
|
if options.compliance == 'disabled' and options.compliance_standards:
|
|
raise util.Error(COMPLIANCE_DISABLED_CONFIGURATION)
|
|
|
|
# Desired configuration to set.
|
|
compliance_update = self.messages.CompliancePostureConfig()
|
|
# Current configuration, if any.
|
|
cluster = self.GetCluster(cluster_ref)
|
|
|
|
compliance_mode = (
|
|
options.compliance.lower() if options.compliance else None
|
|
)
|
|
if (
|
|
compliance_mode is None
|
|
): # If not provided, look for current configuration.
|
|
if cluster.compliancePostureConfig is not None:
|
|
compliance_update.mode = cluster.compliancePostureConfig.mode
|
|
elif compliance_mode == 'disabled':
|
|
compliance_update.mode = (
|
|
self.messages.CompliancePostureConfig.ModeValueValuesEnum.DISABLED
|
|
)
|
|
elif compliance_mode == 'enabled':
|
|
compliance_update.mode = (
|
|
self.messages.CompliancePostureConfig.ModeValueValuesEnum.ENABLED
|
|
)
|
|
else: # Invalid input.
|
|
raise util.Error(
|
|
COMPLIANCE_MODE_NOT_SUPPORTED.format(mode=options.compliance)
|
|
)
|
|
|
|
if options.compliance_standards is None:
|
|
# If not provided, look for current configuration.
|
|
if cluster.compliancePostureConfig is not None:
|
|
compliance_update.complianceStandards = (
|
|
cluster.compliancePostureConfig.complianceStandards
|
|
)
|
|
# Otherwise do nothing.
|
|
elif not options.compliance_standards: # Empty input is invalid.
|
|
raise util.Error(
|
|
COMPLIANCE_INVALID_STANDARDS_CONFIGURATION.format(
|
|
standards=options.compliance_standards
|
|
)
|
|
)
|
|
else: # If a list, build new standards configuration.
|
|
compliance_update.complianceStandards = [
|
|
self.messages.ComplianceStandard(standard=standard)
|
|
for standard in options.compliance_standards.split(',')
|
|
]
|
|
|
|
update = self.messages.ClusterUpdate(
|
|
desiredCompliancePostureConfig=compliance_update
|
|
)
|
|
|
|
if options.enable_security_posture is not None:
|
|
security_posture_config = self.messages.SecurityPostureConfig()
|
|
if options.enable_security_posture:
|
|
security_posture_config.mode = (
|
|
self.messages.SecurityPostureConfig.ModeValueValuesEnum.BASIC
|
|
)
|
|
else:
|
|
security_posture_config.mode = (
|
|
self.messages.SecurityPostureConfig.ModeValueValuesEnum.DISABLED
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredSecurityPostureConfig=security_posture_config
|
|
)
|
|
|
|
if options.security_posture is not None:
|
|
security_posture_config = self.messages.SecurityPostureConfig()
|
|
if options.security_posture.lower() == 'enterprise':
|
|
security_posture_config.mode = (
|
|
self.messages.SecurityPostureConfig.ModeValueValuesEnum.ENTERPRISE
|
|
)
|
|
elif options.security_posture.lower() == 'standard':
|
|
security_posture_config.mode = (
|
|
self.messages.SecurityPostureConfig.ModeValueValuesEnum.BASIC
|
|
)
|
|
elif options.security_posture.lower() == 'disabled':
|
|
security_posture_config.mode = (
|
|
self.messages.SecurityPostureConfig.ModeValueValuesEnum.DISABLED
|
|
)
|
|
else:
|
|
raise util.Error(
|
|
SECURITY_POSTURE_MODE_NOT_SUPPORTED.format(
|
|
mode=options.security_posture.lower()
|
|
)
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredSecurityPostureConfig=security_posture_config
|
|
)
|
|
|
|
if options.workload_vulnerability_scanning is not None:
|
|
security_posture_config = self.messages.SecurityPostureConfig()
|
|
if options.workload_vulnerability_scanning.lower() == 'standard':
|
|
security_posture_config.vulnerabilityMode = (
|
|
self.messages.SecurityPostureConfig.VulnerabilityModeValueValuesEnum.VULNERABILITY_BASIC
|
|
)
|
|
elif options.workload_vulnerability_scanning.lower() == 'disabled':
|
|
security_posture_config.vulnerabilityMode = (
|
|
self.messages.SecurityPostureConfig.VulnerabilityModeValueValuesEnum.VULNERABILITY_DISABLED
|
|
)
|
|
elif options.workload_vulnerability_scanning.lower() == 'enterprise':
|
|
security_posture_config.vulnerabilityMode = (
|
|
self.messages.SecurityPostureConfig.VulnerabilityModeValueValuesEnum.VULNERABILITY_ENTERPRISE
|
|
)
|
|
else:
|
|
raise util.Error(
|
|
WORKLOAD_VULNERABILITY_SCANNING_MODE_NOT_SUPPORTED.format(
|
|
mode=options.workload_vulnerability_scanning.lower()
|
|
)
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredSecurityPostureConfig=security_posture_config
|
|
)
|
|
|
|
if options.enable_runtime_vulnerability_insight is not None:
|
|
runtime_vulnerability_insight_config = (
|
|
self.messages.RuntimeVulnerabilityInsightConfig()
|
|
)
|
|
if options.enable_runtime_vulnerability_insight:
|
|
runtime_vulnerability_insight_config.mode = (
|
|
self.messages.RuntimeVulnerabilityInsightConfig.ModeValueValuesEnum.PREMIUM_VULNERABILITY_SCAN
|
|
)
|
|
else:
|
|
runtime_vulnerability_insight_config.mode = (
|
|
self.messages.RuntimeVulnerabilityInsightConfig.ModeValueValuesEnum.DISABLED
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredRuntimeVulnerabilityInsightConfig=(
|
|
runtime_vulnerability_insight_config
|
|
)
|
|
)
|
|
|
|
if options.network_performance_config:
|
|
perf = self._GetClusterNetworkPerformanceConfig(options)
|
|
update = self.messages.ClusterUpdate(desiredNetworkPerformanceConfig=perf)
|
|
|
|
if options.workload_policies is not None:
|
|
workload_policies = self.messages.WorkloadPolicyConfig()
|
|
if options.workload_policies == 'allow-net-admin':
|
|
workload_policies.allowNetAdmin = True
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAutopilotWorkloadPolicyConfig=workload_policies
|
|
)
|
|
|
|
if options.remove_workload_policies is not None:
|
|
workload_policies = self.messages.WorkloadPolicyConfig()
|
|
if options.remove_workload_policies == 'allow-net-admin':
|
|
workload_policies.allowNetAdmin = False
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAutopilotWorkloadPolicyConfig=workload_policies
|
|
)
|
|
|
|
if options.host_maintenance_interval is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredHostMaintenancePolicy=_GetHostMaintenancePolicy(
|
|
options, self.messages, CLUSTER
|
|
)
|
|
)
|
|
|
|
if options.in_transit_encryption is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredInTransitEncryptionConfig=util.GetUpdateInTransitEncryptionConfigMapper(
|
|
self.messages
|
|
).GetEnumForChoice(
|
|
options.in_transit_encryption
|
|
)
|
|
)
|
|
|
|
if options.enable_multi_networking is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredEnableMultiNetworking=options.enable_multi_networking
|
|
)
|
|
|
|
if options.containerd_config_from_file is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredContainerdConfig=self.messages.ContainerdConfig()
|
|
)
|
|
util.LoadContainerdConfigFromYAML(
|
|
update.desiredContainerdConfig,
|
|
options.containerd_config_from_file,
|
|
self.messages,
|
|
)
|
|
|
|
if (
|
|
options.enable_secret_manager_rotation is not None
|
|
or options.secret_manager_rotation_interval is not None
|
|
or options.enable_secret_manager is not None
|
|
):
|
|
old_cluster = self.GetCluster(cluster_ref)
|
|
secret_manager_config = old_cluster.secretManagerConfig
|
|
if options.enable_secret_manager is not None:
|
|
if secret_manager_config is None:
|
|
secret_manager_config = self.messages.SecretManagerConfig()
|
|
secret_manager_config.enabled = options.enable_secret_manager
|
|
if options.enable_secret_manager_rotation is not None:
|
|
if secret_manager_config is None:
|
|
secret_manager_config = self.messages.SecretManagerConfig()
|
|
if secret_manager_config.rotationConfig is None:
|
|
secret_manager_config.rotationConfig = self.messages.RotationConfig()
|
|
secret_manager_config.rotationConfig.enabled = (
|
|
options.enable_secret_manager_rotation
|
|
)
|
|
if options.secret_manager_rotation_interval is not None:
|
|
if secret_manager_config is None:
|
|
secret_manager_config = self.messages.SecretManagerConfig()
|
|
if secret_manager_config.rotationConfig is None:
|
|
secret_manager_config.rotationConfig = self.messages.RotationConfig()
|
|
secret_manager_config.rotationConfig.rotationInterval = (
|
|
options.secret_manager_rotation_interval
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredSecretManagerConfig=secret_manager_config
|
|
)
|
|
|
|
if (
|
|
options.enable_secret_sync is not None
|
|
or options.secret_sync_rotation_interval is not None
|
|
or options.enable_secret_sync_rotation is not None
|
|
):
|
|
old_cluster = self.GetCluster(cluster_ref)
|
|
secret_sync_config = old_cluster.secretSyncConfig
|
|
if options.enable_secret_sync is not None:
|
|
if secret_sync_config is None:
|
|
secret_sync_config = self.messages.SecretSyncConfig()
|
|
secret_sync_config.enabled = options.enable_secret_sync
|
|
if options.enable_secret_sync_rotation is not None:
|
|
if secret_sync_config is None:
|
|
secret_sync_config = self.messages.SecretSyncConfig()
|
|
if secret_sync_config.rotationConfig is None:
|
|
secret_sync_config.rotationConfig = self.messages.SyncRotationConfig()
|
|
secret_sync_config.rotationConfig.enabled = (
|
|
options.enable_secret_sync_rotation
|
|
)
|
|
if options.secret_sync_rotation_interval is not None:
|
|
if secret_sync_config is None:
|
|
secret_sync_config = self.messages.SecretSyncConfig()
|
|
if secret_sync_config.rotationConfig is None:
|
|
secret_sync_config.rotationConfig = self.messages.RotationConfig()
|
|
secret_sync_config.rotationConfig.rotationInterval = (
|
|
options.secret_sync_rotation_interval
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredSecretSyncConfig=secret_sync_config
|
|
)
|
|
|
|
if options.enable_cilium_clusterwide_network_policy is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredEnableCiliumClusterwideNetworkPolicy=(
|
|
options.enable_cilium_clusterwide_network_policy
|
|
)
|
|
)
|
|
|
|
if options.enable_fqdn_network_policy is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredEnableFqdnNetworkPolicy=options.enable_fqdn_network_policy
|
|
)
|
|
|
|
if (
|
|
options.enable_insecure_binding_system_authenticated is not None
|
|
or options.enable_insecure_binding_system_unauthenticated is not None
|
|
):
|
|
confg = self.messages.RBACBindingConfig()
|
|
if options.enable_insecure_binding_system_authenticated is not None:
|
|
confg.enableInsecureBindingSystemAuthenticated = (
|
|
options.enable_insecure_binding_system_authenticated
|
|
)
|
|
if options.enable_insecure_binding_system_unauthenticated is not None:
|
|
confg.enableInsecureBindingSystemUnauthenticated = (
|
|
options.enable_insecure_binding_system_unauthenticated
|
|
)
|
|
update = self.messages.ClusterUpdate(desiredRBACBindingConfig=confg)
|
|
|
|
if options.autopilot_privileged_admission is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredPrivilegedAdmissionConfig=self.messages.PrivilegedAdmissionConfig(
|
|
allowlistPaths=options.autopilot_privileged_admission or ['']
|
|
)
|
|
)
|
|
|
|
if options.enable_private_nodes is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredDefaultEnablePrivateNodes=options.enable_private_nodes
|
|
)
|
|
|
|
if (
|
|
options.enable_dns_access is not None
|
|
or options.enable_ip_access is not None
|
|
or options.enable_master_global_access is not None
|
|
or options.enable_private_endpoint is not None
|
|
or options.enable_master_authorized_networks is not None
|
|
or options.enable_google_cloud_access is not None
|
|
or options.enable_authorized_networks_on_private_endpoint is not None
|
|
or options.enable_k8s_tokens_via_dns is not None
|
|
or options.enable_k8s_certs_via_dns is not None
|
|
):
|
|
cp_endpoints_config = self._GetDesiredControlPlaneEndpointsConfig(
|
|
cluster_ref, options
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredControlPlaneEndpointsConfig=cp_endpoints_config
|
|
)
|
|
|
|
if (
|
|
options.additional_ip_ranges is not None
|
|
or options.remove_additional_ip_ranges is not None
|
|
):
|
|
cluster = self.GetCluster(cluster_ref)
|
|
desired_ip_ranges = {}
|
|
desired_statuses = {}
|
|
if cluster.ipAllocationPolicy:
|
|
config = cluster.ipAllocationPolicy.additionalIpRangesConfigs
|
|
if config:
|
|
for ip_range in config:
|
|
secondary_ranges = set(ip_range.podIpv4RangeNames)
|
|
desired_ip_ranges[ip_range.subnetwork] = secondary_ranges
|
|
desired_statuses[ip_range.subnetwork] = ip_range.status
|
|
|
|
if options.additional_ip_ranges is not None:
|
|
for ip_range in options.additional_ip_ranges:
|
|
subnetwork = SubnetworkNameToPath(
|
|
ip_range['subnetwork'], cluster_ref.projectId, cluster_ref.zone
|
|
)
|
|
secondary_ranges = (
|
|
desired_ip_ranges[subnetwork]
|
|
if subnetwork in desired_ip_ranges
|
|
else set()
|
|
)
|
|
secondary_ranges.add(ip_range['pod-ipv4-range'])
|
|
desired_ip_ranges[subnetwork] = secondary_ranges
|
|
desired_statuses[subnetwork] = None
|
|
|
|
if options.remove_additional_ip_ranges is not None:
|
|
for ip_remove in options.remove_additional_ip_ranges:
|
|
subnetwork = SubnetworkNameToPath(
|
|
ip_remove['subnetwork'], cluster_ref.projectId, cluster_ref.zone
|
|
)
|
|
if subnetwork not in desired_ip_ranges:
|
|
raise util.Error(
|
|
ADDITIONAL_SUBNETWORKS_NOT_FOUND.format(subnetwork=subnetwork)
|
|
)
|
|
if 'pod-ipv4-range' in ip_remove:
|
|
removed_range = ip_remove['pod-ipv4-range']
|
|
try:
|
|
desired_ip_ranges[subnetwork].remove(removed_range)
|
|
if not desired_ip_ranges[subnetwork]:
|
|
desired_ip_ranges.pop(subnetwork)
|
|
except KeyError:
|
|
raise util.Error(
|
|
ADDITIONAL_SUBNETWORKS_POD_RANG_ENOT_FOUND.format(
|
|
range=removed_range
|
|
)
|
|
)
|
|
else:
|
|
desired_ip_ranges.pop(subnetwork)
|
|
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAdditionalIpRangesConfig=self.messages.DesiredAdditionalIPRangesConfig(
|
|
additionalIpRangesConfigs=[
|
|
self.messages.AdditionalIPRangesConfig(
|
|
subnetwork=subnetwork,
|
|
podIpv4RangeNames=list(secondary_ranges),
|
|
status=desired_statuses[subnetwork],
|
|
)
|
|
for subnetwork, secondary_ranges in desired_ip_ranges.items()
|
|
]
|
|
)
|
|
)
|
|
|
|
if (
|
|
options.drain_additional_ip_ranges is not None
|
|
or options.undrain_additional_ip_ranges is not None
|
|
):
|
|
cluster = self.GetCluster(cluster_ref)
|
|
desired_ip_ranges = {}
|
|
desired_statuses = {}
|
|
if cluster.ipAllocationPolicy:
|
|
config = cluster.ipAllocationPolicy.additionalIpRangesConfigs
|
|
if config:
|
|
for ip_range in config:
|
|
secondary_ranges = set(ip_range.podIpv4RangeNames)
|
|
desired_ip_ranges[ip_range.subnetwork] = secondary_ranges
|
|
desired_statuses[ip_range.subnetwork] = ip_range.status
|
|
|
|
if options.drain_additional_ip_ranges is not None:
|
|
for subnet_to_drain in options.drain_additional_ip_ranges:
|
|
subnetwork = SubnetworkNameToPath(
|
|
subnet_to_drain['subnetwork'],
|
|
cluster_ref.projectId,
|
|
cluster_ref.zone,
|
|
)
|
|
if subnetwork not in desired_ip_ranges:
|
|
raise util.Error(
|
|
ADDITIONAL_SUBNETWORKS_NOT_FOUND.format(subnetwork=subnetwork)
|
|
)
|
|
secondary_ranges = desired_ip_ranges[subnetwork]
|
|
desired_ip_ranges[subnetwork] = secondary_ranges
|
|
desired_statuses[subnetwork] = (
|
|
self.messages.AdditionalIPRangesConfig.StatusValueValuesEnum.DRAINING
|
|
)
|
|
|
|
if options.undrain_additional_ip_ranges is not None:
|
|
for subnet_to_undrain in options.undrain_additional_ip_ranges:
|
|
subnetwork = SubnetworkNameToPath(
|
|
subnet_to_undrain['subnetwork'],
|
|
cluster_ref.projectId,
|
|
cluster_ref.zone,
|
|
)
|
|
if subnetwork not in desired_ip_ranges:
|
|
raise util.Error(
|
|
ADDITIONAL_SUBNETWORKS_NOT_FOUND.format(subnetwork=subnetwork)
|
|
)
|
|
secondary_ranges = desired_ip_ranges[subnetwork]
|
|
desired_ip_ranges[subnetwork] = secondary_ranges
|
|
desired_statuses[subnetwork] = (
|
|
self.messages.AdditionalIPRangesConfig.StatusValueValuesEnum.ACTIVE
|
|
)
|
|
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAdditionalIpRangesConfig=self.messages.DesiredAdditionalIPRangesConfig(
|
|
additionalIpRangesConfigs=[
|
|
self.messages.AdditionalIPRangesConfig(
|
|
subnetwork=subnetwork,
|
|
podIpv4RangeNames=list(secondary_ranges),
|
|
status=desired_statuses[subnetwork],
|
|
)
|
|
for subnetwork, secondary_ranges in desired_ip_ranges.items()
|
|
]
|
|
)
|
|
)
|
|
|
|
if options.disable_l4_lb_firewall_reconciliation:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredDisableL4LbFirewallReconciliation=True
|
|
)
|
|
if options.enable_l4_lb_firewall_reconciliation:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredDisableL4LbFirewallReconciliation=False
|
|
)
|
|
|
|
if options.tier is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredEnterpriseConfig=_GetDesiredEnterpriseConfig(
|
|
options, self.messages
|
|
)
|
|
)
|
|
|
|
if options.enable_autopilot_compatibility_auditing is not None:
|
|
workload_policies = self.messages.WorkloadPolicyConfig()
|
|
workload_policies.autopilotCompatibilityAuditingEnabled = (
|
|
options.enable_autopilot_compatibility_auditing
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAutopilotWorkloadPolicyConfig=workload_policies
|
|
)
|
|
|
|
if options.service_account_verification_keys is not None:
|
|
cluster = self.GetCluster(cluster_ref)
|
|
updated_user_managed_keys_config = self.messages.UserManagedKeysConfig()
|
|
if cluster.userManagedKeysConfig is not None:
|
|
updated_user_managed_keys_config = cluster.userManagedKeysConfig
|
|
updated_user_managed_keys_config.serviceAccountVerificationKeys = (
|
|
options.service_account_verification_keys
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredUserManagedKeysConfig=updated_user_managed_keys_config
|
|
)
|
|
|
|
if options.service_account_signing_keys is not None:
|
|
cluster = self.GetCluster(cluster_ref)
|
|
updated_user_managed_keys_config = self.messages.UserManagedKeysConfig()
|
|
if cluster.userManagedKeysConfig is not None:
|
|
updated_user_managed_keys_config = cluster.userManagedKeysConfig
|
|
updated_user_managed_keys_config.serviceAccountSigningKeys = (
|
|
options.service_account_signing_keys
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredUserManagedKeysConfig=updated_user_managed_keys_config
|
|
)
|
|
if options.control_plane_disk_encryption_key is not None:
|
|
cluster = self.GetCluster(cluster_ref)
|
|
updated_user_managed_keys_config = self.messages.UserManagedKeysConfig()
|
|
if cluster.userManagedKeysConfig is not None:
|
|
updated_user_managed_keys_config = cluster.userManagedKeysConfig
|
|
updated_user_managed_keys_config.controlPlaneDiskEncryptionKey = (
|
|
options.control_plane_disk_encryption_key
|
|
)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredUserManagedKeysConfig=updated_user_managed_keys_config
|
|
)
|
|
if options.disable_auto_ipam:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAutoIpamConfig=self.messages.AutoIpamConfig(enabled=False)
|
|
)
|
|
if options.enable_auto_ipam:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAutoIpamConfig=self.messages.AutoIpamConfig(enabled=True)
|
|
)
|
|
if options.anonymous_authentication_config is not None:
|
|
modes = {
|
|
'LIMITED': (
|
|
self.messages.DesiredAnonymousAuthenticationConfig.ModeValueValuesEnum.LIMITED
|
|
),
|
|
'ENABLED': (
|
|
self.messages.DesiredAnonymousAuthenticationConfig.ModeValueValuesEnum.ENABLED
|
|
),
|
|
}
|
|
config = self.messages.DesiredAnonymousAuthenticationConfig()
|
|
config.mode = modes[options.anonymous_authentication_config]
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAnonymousAuthenticationConfig=config
|
|
)
|
|
if options.network_tier is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNetworkTierConfig=_GetNetworkTierConfig(options, self.messages)
|
|
)
|
|
|
|
if options.autopilot_general_profile:
|
|
autopilot_general_profile_enum = _GetAutopilotGeneralProfileEnum(
|
|
options, self.messages
|
|
)
|
|
if autopilot_general_profile_enum:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredClusterAutoscaling=self.messages.ClusterAutoscaling(
|
|
autopilotGeneralProfile=autopilot_general_profile_enum
|
|
)
|
|
)
|
|
return update
|
|
|
|
def UpdateCluster(self, cluster_ref, options):
|
|
update = self.UpdateClusterCommon(cluster_ref, options)
|
|
|
|
if options.workload_pool:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredWorkloadIdentityConfig=self.messages.WorkloadIdentityConfig(
|
|
workloadPool=options.workload_pool
|
|
)
|
|
)
|
|
elif options.identity_provider:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredWorkloadIdentityConfig=self.messages.WorkloadIdentityConfig(
|
|
identityProvider=options.identity_provider
|
|
)
|
|
)
|
|
elif options.disable_workload_identity:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredWorkloadIdentityConfig=self.messages.WorkloadIdentityConfig(
|
|
workloadPool=''
|
|
)
|
|
)
|
|
|
|
if options.enable_workload_certificates is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredWorkloadCertificates=self.messages.WorkloadCertificates(
|
|
enableCertificates=options.enable_workload_certificates
|
|
)
|
|
)
|
|
|
|
if options.enable_alts is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredWorkloadAltsConfig=self.messages.WorkloadALTSConfig(
|
|
enableAlts=options.enable_alts
|
|
)
|
|
)
|
|
|
|
if options.enable_gke_oidc is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredGkeOidcConfig=self.messages.GkeOidcConfig(
|
|
enabled=options.enable_gke_oidc
|
|
)
|
|
)
|
|
|
|
if options.enable_identity_service is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredIdentityServiceConfig=self.messages.IdentityServiceConfig(
|
|
enabled=options.enable_identity_service
|
|
)
|
|
)
|
|
|
|
if options.enable_stackdriver_kubernetes:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredClusterTelemetry=self.messages.ClusterTelemetry(
|
|
type=self.messages.ClusterTelemetry.TypeValueValuesEnum.ENABLED
|
|
)
|
|
)
|
|
elif options.enable_logging_monitoring_system_only:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredClusterTelemetry=self.messages.ClusterTelemetry(
|
|
type=self.messages.ClusterTelemetry.TypeValueValuesEnum.SYSTEM_ONLY
|
|
)
|
|
)
|
|
elif options.enable_stackdriver_kubernetes is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredClusterTelemetry=self.messages.ClusterTelemetry(
|
|
type=self.messages.ClusterTelemetry.TypeValueValuesEnum.DISABLED
|
|
)
|
|
)
|
|
|
|
if options.enable_workload_monitoring_eap is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredWorkloadMonitoringEapConfig=self.messages.WorkloadMonitoringEapConfig(
|
|
enabled=options.enable_workload_monitoring_eap
|
|
)
|
|
)
|
|
|
|
if options.enable_experimental_vertical_pod_autoscaling is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredVerticalPodAutoscaling=self.messages.VerticalPodAutoscaling(
|
|
enableExperimentalFeatures=options.enable_experimental_vertical_pod_autoscaling
|
|
)
|
|
)
|
|
if options.enable_experimental_vertical_pod_autoscaling:
|
|
update.desiredVerticalPodAutoscaling.enabled = True
|
|
|
|
if options.security_group is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAuthenticatorGroupsConfig=self.messages.AuthenticatorGroupsConfig(
|
|
enabled=True, securityGroup=options.security_group
|
|
)
|
|
)
|
|
|
|
master = _GetMasterForClusterUpdate(options, self.messages)
|
|
if master is not None:
|
|
update = self.messages.ClusterUpdate(desiredMaster=master)
|
|
|
|
kubernetes_objects_export_config = (
|
|
_GetKubernetesObjectsExportConfigForClusterUpdate(
|
|
options, self.messages
|
|
)
|
|
)
|
|
if kubernetes_objects_export_config is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredKubernetesObjectsExportConfig=kubernetes_objects_export_config
|
|
)
|
|
|
|
if options.enable_service_externalips is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredServiceExternalIpsConfig=self.messages.ServiceExternalIPsConfig(
|
|
enabled=options.enable_service_externalips
|
|
)
|
|
)
|
|
|
|
if options.dataplane_v2:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredDatapathProvider=(
|
|
self.messages.ClusterUpdate.DesiredDatapathProviderValueValuesEnum.ADVANCED_DATAPATH
|
|
)
|
|
)
|
|
|
|
if options.enable_cost_allocation is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredCostManagementConfig=self.messages.CostManagementConfig(
|
|
enabled=options.enable_cost_allocation
|
|
)
|
|
)
|
|
|
|
if options.convert_to_autopilot is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAutopilot=self.messages.Autopilot(enabled=True)
|
|
)
|
|
|
|
if options.convert_to_standard is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAutopilot=self.messages.Autopilot(enabled=False)
|
|
)
|
|
|
|
if not update:
|
|
# if reached here, it's possible:
|
|
# - someone added update flags but not handled
|
|
# - none of the update flags specified from command line
|
|
# so raise an error with readable message like:
|
|
# Nothing to update
|
|
# to catch this error.
|
|
raise util.Error(NOTHING_TO_UPDATE_ERROR_MSG)
|
|
|
|
if options.disable_addons is not None:
|
|
if options.disable_addons.get(ISTIO) is not None:
|
|
istio_auth = self.messages.IstioConfig.AuthValueValuesEnum.AUTH_NONE
|
|
mtls = self.messages.IstioConfig.AuthValueValuesEnum.AUTH_MUTUAL_TLS
|
|
istio_config = options.istio_config
|
|
if istio_config is not None:
|
|
auth_config = istio_config.get('auth')
|
|
if auth_config is not None:
|
|
if auth_config == 'MTLS_STRICT':
|
|
istio_auth = mtls
|
|
update.desiredAddonsConfig.istioConfig = self.messages.IstioConfig(
|
|
disabled=options.disable_addons.get(ISTIO), auth=istio_auth
|
|
)
|
|
if any(
|
|
(options.disable_addons.get(v) is not None) for v in CLOUDRUN_ADDONS
|
|
):
|
|
load_balancer_type = _GetCloudRunLoadBalancerType(
|
|
options, self.messages
|
|
)
|
|
update.desiredAddonsConfig.cloudRunConfig = (
|
|
self.messages.CloudRunConfig(
|
|
disabled=any(
|
|
options.disable_addons.get(v) or False
|
|
for v in CLOUDRUN_ADDONS
|
|
),
|
|
loadBalancerType=load_balancer_type,
|
|
)
|
|
)
|
|
if options.disable_addons.get(APPLICATIONMANAGER) is not None:
|
|
update.desiredAddonsConfig.kalmConfig = self.messages.KalmConfig(
|
|
enabled=(not options.disable_addons.get(APPLICATIONMANAGER))
|
|
)
|
|
if options.disable_addons.get(CLOUDBUILD) is not None:
|
|
update.desiredAddonsConfig.cloudBuildConfig = (
|
|
self.messages.CloudBuildConfig(
|
|
enabled=(not options.disable_addons.get(CLOUDBUILD))
|
|
)
|
|
)
|
|
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def CompleteConvertToAutopilot(self, cluster_ref):
|
|
"""Commmit the Autopilot conversion operation.
|
|
|
|
Args:
|
|
cluster_ref: cluster resource to commit conversion.
|
|
|
|
Returns:
|
|
The operation to be executed.
|
|
|
|
Raises:
|
|
exceptions.HttpException: if cluster cannot be found or caller is missing
|
|
permissions. Will attempt to find similar clusters in other zones for a
|
|
more useful error if the user has list permissions.
|
|
"""
|
|
try:
|
|
op = self.client.projects_locations_clusters.CompleteConvertToAutopilot(
|
|
self.messages.ContainerProjectsLocationsClustersCompleteConvertToAutopilotRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
)
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
except apitools_exceptions.HttpNotFoundError as error:
|
|
api_error = exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
# Cluster couldn't be found, maybe user got the location wrong?
|
|
self.CheckClusterOtherZones(cluster_ref, api_error)
|
|
except apitools_exceptions.HttpError as error:
|
|
raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
|
|
|
|
def CreateClusterAutoscalingCommon(self, cluster_ref, options, for_update):
|
|
"""Create cluster's autoscaling configuration.
|
|
|
|
Args:
|
|
cluster_ref: Cluster reference.
|
|
options: Either CreateClusterOptions or UpdateClusterOptions.
|
|
for_update: Is function executed for update operation.
|
|
|
|
Returns:
|
|
Cluster's autoscaling configuration.
|
|
"""
|
|
|
|
# Patch cluster autoscaling if cluster_ref is provided.
|
|
autoscaling = self.messages.ClusterAutoscaling()
|
|
cluster = self.GetCluster(cluster_ref) if cluster_ref else None
|
|
if cluster and cluster.autoscaling:
|
|
autoscaling.enableNodeAutoprovisioning = (
|
|
cluster.autoscaling.enableNodeAutoprovisioning
|
|
)
|
|
autoscaling.defaultComputeClassConfig = (
|
|
cluster.autoscaling.defaultComputeClassConfig
|
|
)
|
|
|
|
if options.enable_default_compute_class is not None:
|
|
autoscaling.defaultComputeClassConfig = (
|
|
self.messages.DefaultComputeClassConfig(
|
|
enabled=options.enable_default_compute_class
|
|
)
|
|
)
|
|
|
|
resource_limits = []
|
|
if options.autoprovisioning_config_file is not None:
|
|
# Create using config file only.
|
|
config = yaml.load(options.autoprovisioning_config_file)
|
|
resource_limits = config.get(RESOURCE_LIMITS)
|
|
service_account = config.get(SERVICE_ACCOUNT)
|
|
scopes = config.get(SCOPES)
|
|
max_surge_upgrade = None
|
|
max_unavailable_upgrade = None
|
|
upgrade_settings = config.get(UPGRADE_SETTINGS)
|
|
if upgrade_settings:
|
|
max_surge_upgrade = upgrade_settings.get(MAX_SURGE_UPGRADE)
|
|
max_unavailable_upgrade = upgrade_settings.get(MAX_UNAVAILABLE_UPGRADE)
|
|
management_settings = config.get(NODE_MANAGEMENT)
|
|
enable_autoupgrade = None
|
|
enable_autorepair = None
|
|
if management_settings:
|
|
enable_autoupgrade = management_settings.get(ENABLE_AUTO_UPGRADE)
|
|
enable_autorepair = management_settings.get(ENABLE_AUTO_REPAIR)
|
|
autoprovisioning_locations = config.get(AUTOPROVISIONING_LOCATIONS)
|
|
min_cpu_platform = config.get(MIN_CPU_PLATFORM)
|
|
boot_disk_kms_key = config.get(BOOT_DISK_KMS_KEY)
|
|
disk_type = config.get(DISK_TYPE)
|
|
disk_size_gb = config.get(DISK_SIZE_GB)
|
|
autoprovisioning_image_type = config.get(IMAGE_TYPE)
|
|
shielded_instance_config = config.get(SHIELDED_INSTANCE_CONFIG)
|
|
enable_secure_boot = None
|
|
enable_integrity_monitoring = None
|
|
if shielded_instance_config:
|
|
enable_secure_boot = shielded_instance_config.get(ENABLE_SECURE_BOOT)
|
|
enable_integrity_monitoring = shielded_instance_config.get(
|
|
ENABLE_INTEGRITY_MONITORING
|
|
)
|
|
else:
|
|
resource_limits = self.ResourceLimitsFromFlags(options)
|
|
service_account = options.autoprovisioning_service_account
|
|
scopes = options.autoprovisioning_scopes
|
|
autoprovisioning_locations = options.autoprovisioning_locations
|
|
max_surge_upgrade = options.autoprovisioning_max_surge_upgrade
|
|
max_unavailable_upgrade = options.autoprovisioning_max_unavailable_upgrade
|
|
enable_autoupgrade = options.enable_autoprovisioning_autoupgrade
|
|
enable_autorepair = options.enable_autoprovisioning_autorepair
|
|
min_cpu_platform = options.autoprovisioning_min_cpu_platform
|
|
boot_disk_kms_key = None
|
|
disk_type = None
|
|
disk_size_gb = None
|
|
autoprovisioning_image_type = options.autoprovisioning_image_type
|
|
enable_secure_boot = None
|
|
enable_integrity_monitoring = None
|
|
|
|
autoscaling.enableNodeAutoprovisioning = options.enable_autoprovisioning
|
|
autoscaling.resourceLimits = resource_limits or []
|
|
if scopes is None:
|
|
scopes = []
|
|
management = None
|
|
upgrade_settings = None
|
|
if (
|
|
max_surge_upgrade is not None
|
|
or max_unavailable_upgrade is not None
|
|
or options.enable_autoprovisioning_blue_green_upgrade
|
|
or options.enable_autoprovisioning_surge_upgrade
|
|
or options.autoprovisioning_standard_rollout_policy is not None
|
|
or options.autoprovisioning_node_pool_soak_duration is not None
|
|
):
|
|
upgrade_settings = self.UpdateUpgradeSettingsForNAP(
|
|
options, max_surge_upgrade, max_unavailable_upgrade
|
|
)
|
|
if enable_autorepair is not None or enable_autoupgrade is not None:
|
|
management = self.messages.NodeManagement(
|
|
autoUpgrade=enable_autoupgrade, autoRepair=enable_autorepair
|
|
)
|
|
shielded_instance_config = None
|
|
if (
|
|
enable_secure_boot is not None
|
|
or enable_integrity_monitoring is not None
|
|
):
|
|
shielded_instance_config = self.messages.ShieldedInstanceConfig()
|
|
shielded_instance_config.enableSecureBoot = enable_secure_boot
|
|
shielded_instance_config.enableIntegrityMonitoring = (
|
|
enable_integrity_monitoring
|
|
)
|
|
if for_update:
|
|
autoscaling.autoprovisioningNodePoolDefaults = (
|
|
self.messages.AutoprovisioningNodePoolDefaults(
|
|
serviceAccount=service_account,
|
|
oauthScopes=scopes,
|
|
upgradeSettings=upgrade_settings,
|
|
management=management,
|
|
minCpuPlatform=min_cpu_platform,
|
|
bootDiskKmsKey=boot_disk_kms_key,
|
|
diskSizeGb=disk_size_gb,
|
|
diskType=disk_type,
|
|
imageType=autoprovisioning_image_type,
|
|
shieldedInstanceConfig=shielded_instance_config,
|
|
)
|
|
)
|
|
else:
|
|
autoscaling.autoprovisioningNodePoolDefaults = (
|
|
self.messages.AutoprovisioningNodePoolDefaults(
|
|
serviceAccount=service_account,
|
|
oauthScopes=scopes,
|
|
upgradeSettings=upgrade_settings,
|
|
management=management,
|
|
minCpuPlatform=min_cpu_platform,
|
|
bootDiskKmsKey=boot_disk_kms_key,
|
|
diskSizeGb=disk_size_gb,
|
|
diskType=disk_type,
|
|
imageType=autoprovisioning_image_type,
|
|
shieldedInstanceConfig=shielded_instance_config,
|
|
)
|
|
)
|
|
if autoprovisioning_locations:
|
|
autoscaling.autoprovisioningLocations = sorted(autoprovisioning_locations)
|
|
|
|
if options.autoscaling_profile is not None:
|
|
autoscaling.autoscalingProfile = self.CreateAutoscalingProfileCommon(
|
|
options
|
|
)
|
|
|
|
self.ValidateClusterAutoscaling(autoscaling, for_update)
|
|
return autoscaling
|
|
|
|
def ValidateClusterAutoscaling(self, autoscaling, for_update):
|
|
"""Validate cluster autoscaling configuration.
|
|
|
|
Args:
|
|
autoscaling: autoscaling configuration to be validated.
|
|
for_update: Is function executed for update operation.
|
|
|
|
Raises:
|
|
Error if the new configuration is invalid.
|
|
"""
|
|
if autoscaling.enableNodeAutoprovisioning:
|
|
if not for_update or autoscaling.resourceLimits:
|
|
cpu_max_set = any(
|
|
limit.resourceType == 'cpu' and limit.maximum is not None
|
|
for limit in autoscaling.resourceLimits
|
|
)
|
|
mem_max_set = any(
|
|
limit.resourceType == 'memory' and limit.maximum is not None
|
|
for limit in autoscaling.resourceLimits
|
|
)
|
|
if not cpu_max_set or not mem_max_set:
|
|
raise util.Error(NO_AUTOPROVISIONING_LIMITS_ERROR_MSG)
|
|
|
|
defaults = autoscaling.autoprovisioningNodePoolDefaults
|
|
if defaults:
|
|
if defaults.upgradeSettings:
|
|
max_surge_found = defaults.upgradeSettings.maxSurge is not None
|
|
max_unavailable_found = (
|
|
defaults.upgradeSettings.maxUnavailable is not None
|
|
)
|
|
if max_unavailable_found != max_surge_found:
|
|
raise util.Error(BOTH_AUTOPROVISIONING_UPGRADE_SETTINGS_ERROR_MSG)
|
|
if defaults.management:
|
|
auto_upgrade_found = defaults.management.autoUpgrade is not None
|
|
auto_repair_found = defaults.management.autoRepair is not None
|
|
if auto_repair_found != auto_upgrade_found:
|
|
raise util.Error(BOTH_AUTOPROVISIONING_MANAGEMENT_SETTINGS_ERROR_MSG)
|
|
if defaults.shieldedInstanceConfig:
|
|
secure_boot_found = (
|
|
defaults.shieldedInstanceConfig.enableSecureBoot is not None
|
|
)
|
|
integrity_monitoring_found = (
|
|
defaults.shieldedInstanceConfig.enableIntegrityMonitoring
|
|
is not None
|
|
)
|
|
if secure_boot_found != integrity_monitoring_found:
|
|
raise util.Error(
|
|
BOTH_AUTOPROVISIONING_SHIELDED_INSTANCE_SETTINGS_ERROR_MSG
|
|
)
|
|
|
|
def UpdateNodePool(self, node_pool_ref, options):
|
|
if options.IsAutoscalingUpdate():
|
|
autoscaling = self.UpdateNodePoolAutoscaling(node_pool_ref, options)
|
|
update = self.messages.ClusterUpdate(
|
|
desiredNodePoolId=node_pool_ref.nodePoolId,
|
|
desiredNodePoolAutoscaling=autoscaling,
|
|
)
|
|
operation = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
node_pool_ref.projectId,
|
|
node_pool_ref.zone,
|
|
node_pool_ref.clusterId,
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(operation.name, node_pool_ref.zone)
|
|
elif options.IsNodePoolManagementUpdate():
|
|
management = self.UpdateNodePoolNodeManagement(node_pool_ref, options)
|
|
req = self.messages.SetNodePoolManagementRequest(
|
|
name=ProjectLocationClusterNodePool(
|
|
node_pool_ref.projectId,
|
|
node_pool_ref.zone,
|
|
node_pool_ref.clusterId,
|
|
node_pool_ref.nodePoolId,
|
|
),
|
|
management=management,
|
|
)
|
|
operation = (
|
|
self.client.projects_locations_clusters_nodePools.SetManagement(req)
|
|
)
|
|
elif options.IsUpdateNodePoolRequest():
|
|
req = self.UpdateNodePoolRequest(node_pool_ref, options)
|
|
operation = self.client.projects_locations_clusters_nodePools.Update(req)
|
|
else:
|
|
raise util.Error('Unhandled node pool update mode')
|
|
|
|
return self.ParseOperation(operation.name, node_pool_ref.zone)
|
|
|
|
def _ParseIPv6Options(self, options, cluster):
|
|
"""Converts options for IPv6-only clusters."""
|
|
if options.enable_ip_alias is not None and not options.enable_ip_alias:
|
|
raise util.Error(ROUTE_BASED_CLUSTERS_NOT_SUPPORTED_WITH_STACK_TYPE_IPV6)
|
|
|
|
if options.subnetwork and options.create_subnetwork is not None:
|
|
raise util.Error(CREATE_SUBNETWORK_WITH_SUBNETWORK_ERROR_MSG)
|
|
|
|
subnetwork_name = None
|
|
node_ipv4_cidr = None
|
|
|
|
if options.create_subnetwork is not None:
|
|
for key in options.create_subnetwork:
|
|
if key not in ['name', 'range']:
|
|
raise util.Error(
|
|
CREATE_SUBNETWORK_INVALID_KEY_ERROR_MSG.format(key=key)
|
|
)
|
|
subnetwork_name = options.create_subnetwork.get('name', None)
|
|
node_ipv4_cidr = options.create_subnetwork.get('range', None)
|
|
|
|
policy = self.messages.IPAllocationPolicy(
|
|
createSubnetwork=options.create_subnetwork is not None,
|
|
subnetworkName=subnetwork_name,
|
|
nodeIpv4CidrBlock=node_ipv4_cidr,
|
|
stackType=(
|
|
self.messages.IPAllocationPolicy.StackTypeValueValuesEnum.IPV6
|
|
),
|
|
clusterSecondaryRangeName=options.cluster_secondary_range_name,
|
|
servicesSecondaryRangeName=options.services_secondary_range_name,
|
|
)
|
|
if options.disable_pod_cidr_overprovision is not None:
|
|
policy.podCidrOverprovisionConfig = (
|
|
self.messages.PodCIDROverprovisionConfig(
|
|
disable=options.disable_pod_cidr_overprovision
|
|
)
|
|
)
|
|
if options.ipv6_access_type is not None:
|
|
policy.ipv6AccessType = util.GetIpv6AccessTypeMapper(
|
|
self.messages
|
|
).GetEnumForChoice(options.ipv6_access_type)
|
|
|
|
cluster.ipAllocationPolicy = policy
|
|
return cluster
|
|
|
|
|
|
class V1Alpha1Adapter(V1Beta1Adapter):
|
|
"""APIAdapter for v1alpha1."""
|
|
|
|
def CreateCluster(self, cluster_ref, options):
|
|
cluster = self.CreateClusterCommon(cluster_ref, options)
|
|
if (
|
|
options.enable_autoprovisioning is not None
|
|
or options.max_cpu is not None
|
|
or options.min_cpu is not None
|
|
or options.max_memory is not None
|
|
or options.min_memory is not None
|
|
or options.autoprovisioning_image_type is not None
|
|
or options.max_accelerator is not None
|
|
or options.min_accelerator is not None
|
|
or options.autoprovisioning_service_account is not None
|
|
or options.autoprovisioning_scopes is not None
|
|
or options.enable_autoprovisioning_surge_upgrade is not None
|
|
or options.enable_autoprovisioning_blue_green_upgrade is not None
|
|
or options.autoprovisioning_max_surge_upgrade is not None
|
|
or options.autoprovisioning_max_unavailable_upgrade is not None
|
|
or options.autoprovisioning_standard_rollout_policy is not None
|
|
or options.autoprovisioning_node_pool_soak_duration is not None
|
|
or options.enable_autoprovisioning_autoupgrade is not None
|
|
or options.enable_autoprovisioning_autorepair is not None
|
|
or options.autoprovisioning_locations is not None
|
|
or options.autoprovisioning_min_cpu_platform is not None
|
|
or options.autoscaling_profile is not None
|
|
or options.enable_default_compute_class is not None
|
|
):
|
|
cluster.autoscaling = self.CreateClusterAutoscalingCommon(
|
|
None, options, False
|
|
)
|
|
if options.addons:
|
|
# CloudRun is disabled by default.
|
|
if any((v in options.addons) for v in CLOUDRUN_ADDONS):
|
|
if not options.enable_stackdriver_kubernetes and (
|
|
(
|
|
options.monitoring is not None
|
|
and SYSTEM not in options.monitoring
|
|
)
|
|
or (options.logging is not None and SYSTEM not in options.logging)
|
|
):
|
|
raise util.Error(CLOUDRUN_STACKDRIVER_KUBERNETES_DISABLED_ERROR_MSG)
|
|
if INGRESS not in options.addons:
|
|
raise util.Error(CLOUDRUN_INGRESS_KUBERNETES_DISABLED_ERROR_MSG)
|
|
enable_alpha_features = (
|
|
options.enable_cloud_run_alpha
|
|
if options.enable_cloud_run_alpha is not None
|
|
else False
|
|
)
|
|
load_balancer_type = _GetCloudRunLoadBalancerType(
|
|
options, self.messages
|
|
)
|
|
cluster.addonsConfig.cloudRunConfig = self.messages.CloudRunConfig(
|
|
disabled=False,
|
|
enableAlphaFeatures=enable_alpha_features,
|
|
loadBalancerType=load_balancer_type,
|
|
)
|
|
# Cloud Build is disabled by default.
|
|
if CLOUDBUILD in options.addons:
|
|
if not options.enable_stackdriver_kubernetes and (
|
|
(
|
|
options.monitoring is not None
|
|
and SYSTEM not in options.monitoring
|
|
)
|
|
or (options.logging is not None and SYSTEM not in options.logging)
|
|
):
|
|
raise util.Error(CLOUDBUILD_STACKDRIVER_KUBERNETES_DISABLED_ERROR_MSG)
|
|
cluster.addonsConfig.cloudBuildConfig = self.messages.CloudBuildConfig(
|
|
enabled=True
|
|
)
|
|
# BackupRestore is disabled by default.
|
|
if BACKUPRESTORE in options.addons:
|
|
cluster.addonsConfig.gkeBackupAgentConfig = (
|
|
self.messages.GkeBackupAgentConfig(enabled=True)
|
|
)
|
|
# Istio is disabled by default
|
|
if ISTIO in options.addons:
|
|
istio_auth = self.messages.IstioConfig.AuthValueValuesEnum.AUTH_NONE
|
|
mtls = self.messages.IstioConfig.AuthValueValuesEnum.AUTH_MUTUAL_TLS
|
|
istio_config = options.istio_config
|
|
if istio_config is not None:
|
|
auth_config = istio_config.get('auth')
|
|
if auth_config is not None:
|
|
if auth_config == 'MTLS_STRICT':
|
|
istio_auth = mtls
|
|
cluster.addonsConfig.istioConfig = self.messages.IstioConfig(
|
|
disabled=False, auth=istio_auth
|
|
)
|
|
if options.enable_workload_certificates:
|
|
if not options.workload_pool:
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='workload-pool', opt='enable-workload-certificates'
|
|
)
|
|
)
|
|
if cluster.workloadCertificates is None:
|
|
cluster.workloadCertificates = self.messages.WorkloadCertificates()
|
|
cluster.workloadCertificates.enableCertificates = (
|
|
options.enable_workload_certificates
|
|
)
|
|
if options.enable_alts:
|
|
if not options.workload_pool:
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='workload-pool', opt='enable-alts'
|
|
)
|
|
)
|
|
if cluster.workloadAltsConfig is None:
|
|
cluster.workloadAltsConfig = self.messages.WorkloadALTSConfig()
|
|
cluster.workloadAltsConfig.enableAlts = options.enable_alts
|
|
if options.enable_gke_oidc:
|
|
cluster.gkeOidcConfig = self.messages.GkeOidcConfig(
|
|
enabled=options.enable_gke_oidc
|
|
)
|
|
if options.enable_identity_service:
|
|
cluster.identityServiceConfig = self.messages.IdentityServiceConfig(
|
|
enabled=options.enable_identity_service
|
|
)
|
|
if options.security_profile is not None:
|
|
cluster.securityProfile = self.messages.SecurityProfile(
|
|
name=options.security_profile
|
|
)
|
|
if options.security_profile_runtime_rules is not None:
|
|
cluster.securityProfile.disableRuntimeRules = (
|
|
not options.security_profile_runtime_rules
|
|
)
|
|
if options.enable_private_ipv6_access is not None:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig(
|
|
enablePrivateIpv6Access=options.enable_private_ipv6_access
|
|
)
|
|
else:
|
|
cluster.networkConfig.enablePrivateIpv6Access = (
|
|
options.enable_private_ipv6_access
|
|
)
|
|
if options.enable_service_externalips is not None:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig()
|
|
cluster.networkConfig.serviceExternalIpsConfig = (
|
|
self.messages.ServiceExternalIPsConfig(
|
|
enabled=options.enable_service_externalips
|
|
)
|
|
)
|
|
if options.security_group is not None:
|
|
# The presence of the --security_group="foo" flag implies enabled=True.
|
|
cluster.authenticatorGroupsConfig = (
|
|
self.messages.AuthenticatorGroupsConfig(
|
|
enabled=True, securityGroup=options.security_group
|
|
)
|
|
)
|
|
_AddPSCPrivateClustersOptionsToClusterForCreateCluster(
|
|
cluster, options, self.messages
|
|
)
|
|
|
|
cluster.releaseChannel = _GetReleaseChannel(options, self.messages)
|
|
if options.enable_cost_allocation:
|
|
cluster.costManagementConfig = self.messages.CostManagementConfig(
|
|
enabled=True
|
|
)
|
|
|
|
cluster_telemetry_type = self._GetClusterTelemetryType(
|
|
options, cluster.loggingService, cluster.monitoringService
|
|
)
|
|
if cluster_telemetry_type is not None:
|
|
cluster.clusterTelemetry = self.messages.ClusterTelemetry()
|
|
cluster.clusterTelemetry.type = cluster_telemetry_type
|
|
|
|
if cluster.clusterTelemetry:
|
|
cluster.loggingService = None
|
|
cluster.monitoringService = None
|
|
|
|
if options.enable_workload_monitoring_eap:
|
|
cluster.workloadMonitoringEnabledEap = True
|
|
|
|
if options.datapath_provider is not None:
|
|
if cluster.networkConfig is None:
|
|
cluster.networkConfig = self.messages.NetworkConfig()
|
|
if options.datapath_provider.lower() == 'legacy':
|
|
cluster.networkConfig.datapathProvider = (
|
|
self.messages.NetworkConfig.DatapathProviderValueValuesEnum.LEGACY_DATAPATH
|
|
)
|
|
elif options.datapath_provider.lower() == 'advanced':
|
|
cluster.networkConfig.datapathProvider = (
|
|
self.messages.NetworkConfig.DatapathProviderValueValuesEnum.ADVANCED_DATAPATH
|
|
)
|
|
else:
|
|
raise util.Error(
|
|
DATAPATH_PROVIDER_ILL_SPECIFIED_ERROR_MSG.format(
|
|
provider=options.datapath_provider
|
|
)
|
|
)
|
|
|
|
if options.enable_experimental_vertical_pod_autoscaling is not None:
|
|
cluster.verticalPodAutoscaling = self.messages.VerticalPodAutoscaling(
|
|
enableExperimentalFeatures=options.enable_experimental_vertical_pod_autoscaling
|
|
)
|
|
if options.enable_experimental_vertical_pod_autoscaling:
|
|
cluster.verticalPodAutoscaling.enabled = True
|
|
|
|
if options.identity_provider:
|
|
if options.workload_pool:
|
|
cluster.workloadIdentityConfig.identityProvider = (
|
|
options.identity_provider
|
|
)
|
|
else:
|
|
raise util.Error(
|
|
PREREQUISITE_OPTION_ERROR_MSG.format(
|
|
prerequisite='workload-pool', opt='identity-provider'
|
|
)
|
|
)
|
|
|
|
if options.stack_type is not None:
|
|
if options.stack_type.lower() == gke_constants.IPV6_STACK_TYPE:
|
|
self._ParseIPv6Options(options, cluster)
|
|
else:
|
|
cluster.ipAllocationPolicy.stackType = util.GetCreateStackTypeMapper(
|
|
self.messages
|
|
).GetEnumForChoice(options.stack_type)
|
|
|
|
if options.ipv6_access_type is not None:
|
|
cluster.ipAllocationPolicy.ipv6AccessType = util.GetIpv6AccessTypeMapper(
|
|
self.messages
|
|
).GetEnumForChoice(options.ipv6_access_type)
|
|
cluster.master = _GetMasterForClusterCreate(options, self.messages)
|
|
|
|
cluster.kubernetesObjectsExportConfig = (
|
|
_GetKubernetesObjectsExportConfigForClusterCreate(
|
|
options, self.messages
|
|
)
|
|
)
|
|
|
|
if options.tier is not None:
|
|
cluster.enterpriseConfig = _GetEnterpriseConfig(options, self.messages)
|
|
|
|
if options.anonymous_authentication_config is not None:
|
|
cluster.anonymousAuthenticationConfig = _GetAnonymousAuthenticationConfig(
|
|
options, self.messages
|
|
)
|
|
|
|
req = self.messages.CreateClusterRequest(
|
|
parent=ProjectLocation(cluster_ref.projectId, cluster_ref.zone),
|
|
cluster=cluster,
|
|
)
|
|
operation = self.client.projects_locations_clusters.Create(req)
|
|
return self.ParseOperation(operation.name, cluster_ref.zone)
|
|
|
|
def UpdateCluster(self, cluster_ref, options):
|
|
update = self.UpdateClusterCommon(cluster_ref, options)
|
|
|
|
if options.workload_pool:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredWorkloadIdentityConfig=self.messages.WorkloadIdentityConfig(
|
|
workloadPool=options.workload_pool
|
|
)
|
|
)
|
|
elif options.identity_provider:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredWorkloadIdentityConfig=self.messages.WorkloadIdentityConfig(
|
|
identityProvider=options.identity_provider
|
|
)
|
|
)
|
|
elif options.disable_workload_identity:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredWorkloadIdentityConfig=self.messages.WorkloadIdentityConfig(
|
|
workloadPool=''
|
|
)
|
|
)
|
|
|
|
if options.enable_workload_certificates is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredWorkloadCertificates=self.messages.WorkloadCertificates(
|
|
enableCertificates=options.enable_workload_certificates
|
|
)
|
|
)
|
|
|
|
if options.enable_alts is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredWorkloadAltsConfig=self.messages.WorkloadALTSConfig(
|
|
enableAlts=options.enable_alts
|
|
)
|
|
)
|
|
|
|
if options.enable_gke_oidc is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredGkeOidcConfig=self.messages.GkeOidcConfig(
|
|
enabled=options.enable_gke_oidc
|
|
)
|
|
)
|
|
|
|
if options.enable_identity_service is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredIdentityServiceConfig=self.messages.IdentityServiceConfig(
|
|
enabled=options.enable_identity_service
|
|
)
|
|
)
|
|
|
|
if options.enable_cost_allocation is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredCostManagementConfig=self.messages.CostManagementConfig(
|
|
enabled=options.enable_cost_allocation
|
|
)
|
|
)
|
|
|
|
if options.release_channel is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredReleaseChannel=_GetReleaseChannel(options, self.messages)
|
|
)
|
|
|
|
if options.enable_stackdriver_kubernetes:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredClusterTelemetry=self.messages.ClusterTelemetry(
|
|
type=self.messages.ClusterTelemetry.TypeValueValuesEnum.ENABLED
|
|
)
|
|
)
|
|
elif options.enable_logging_monitoring_system_only:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredClusterTelemetry=self.messages.ClusterTelemetry(
|
|
type=self.messages.ClusterTelemetry.TypeValueValuesEnum.SYSTEM_ONLY
|
|
)
|
|
)
|
|
elif options.enable_stackdriver_kubernetes is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredClusterTelemetry=self.messages.ClusterTelemetry(
|
|
type=self.messages.ClusterTelemetry.TypeValueValuesEnum.DISABLED
|
|
)
|
|
)
|
|
|
|
if options.enable_workload_monitoring_eap is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredWorkloadMonitoringEapConfig=self.messages.WorkloadMonitoringEapConfig(
|
|
enabled=options.enable_workload_monitoring_eap
|
|
)
|
|
)
|
|
|
|
if options.enable_experimental_vertical_pod_autoscaling is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredVerticalPodAutoscaling=self.messages.VerticalPodAutoscaling(
|
|
enableExperimentalFeatures=options.enable_experimental_vertical_pod_autoscaling
|
|
)
|
|
)
|
|
if options.enable_experimental_vertical_pod_autoscaling:
|
|
update.desiredVerticalPodAutoscaling.enabled = True
|
|
|
|
if options.security_group is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAuthenticatorGroupsConfig=self.messages.AuthenticatorGroupsConfig(
|
|
enabled=True, securityGroup=options.security_group
|
|
)
|
|
)
|
|
|
|
master = _GetMasterForClusterUpdate(options, self.messages)
|
|
if master is not None:
|
|
update = self.messages.ClusterUpdate(desiredMaster=master)
|
|
|
|
kubernetes_objects_export_config = (
|
|
_GetKubernetesObjectsExportConfigForClusterUpdate(
|
|
options, self.messages
|
|
)
|
|
)
|
|
if kubernetes_objects_export_config is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredKubernetesObjectsExportConfig=kubernetes_objects_export_config
|
|
)
|
|
|
|
if options.enable_service_externalips is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredServiceExternalIpsConfig=self.messages.ServiceExternalIPsConfig(
|
|
enabled=options.enable_service_externalips
|
|
)
|
|
)
|
|
|
|
if options.dataplane_v2:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredDatapathProvider=(
|
|
self.messages.ClusterUpdate.DesiredDatapathProviderValueValuesEnum.ADVANCED_DATAPATH
|
|
)
|
|
)
|
|
|
|
if options.convert_to_autopilot is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAutopilot=self.messages.Autopilot(enabled=True)
|
|
)
|
|
|
|
if options.convert_to_standard is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAutopilot=self.messages.Autopilot(enabled=False)
|
|
)
|
|
|
|
if options.tier is not None:
|
|
update = self.messages.ClusterUpdate(
|
|
desiredEnterpriseConfig=_GetDesiredEnterpriseConfig(
|
|
options, self.messages
|
|
)
|
|
)
|
|
|
|
if options.anonymous_authentication_config is not None:
|
|
modes = {
|
|
'LIMITED': (
|
|
self.messages.AnonymousAuthenticationConfig.ModeValueValuesEnum.LIMITED
|
|
),
|
|
'ENABLED': (
|
|
self.messages.AnonymousAuthenticationConfig.ModeValueValuesEnum.ENABLED
|
|
),
|
|
}
|
|
if options.anonymous_authentication_config not in modes:
|
|
raise util.Error(
|
|
ANONYMOUS_AUTHENTICATION_MODE_NOT_SUPPORTED.format(
|
|
mode=options.anonymous_authentication_config
|
|
)
|
|
)
|
|
anon_auth_config = self.messages.AnonymousAuthenticationConfig()
|
|
anon_auth_config.mode = modes[options.anonymous_authentication_config]
|
|
update = self.messages.ClusterUpdate(
|
|
desiredAnonymousAuthenticationConfig=anon_auth_config
|
|
)
|
|
|
|
if not update:
|
|
# if reached here, it's possible:
|
|
# - someone added update flags but not handled
|
|
# - none of the update flags specified from command line
|
|
# so raise an error with readable message like:
|
|
# Nothing to update
|
|
# to catch this error.
|
|
raise util.Error(NOTHING_TO_UPDATE_ERROR_MSG)
|
|
|
|
if options.disable_addons is not None:
|
|
if options.disable_addons.get(ISTIO) is not None:
|
|
istio_auth = self.messages.IstioConfig.AuthValueValuesEnum.AUTH_NONE
|
|
mtls = self.messages.IstioConfig.AuthValueValuesEnum.AUTH_MUTUAL_TLS
|
|
istio_config = options.istio_config
|
|
if istio_config is not None:
|
|
auth_config = istio_config.get('auth')
|
|
if auth_config is not None:
|
|
if auth_config == 'MTLS_STRICT':
|
|
istio_auth = mtls
|
|
update.desiredAddonsConfig.istioConfig = self.messages.IstioConfig(
|
|
disabled=options.disable_addons.get(ISTIO), auth=istio_auth
|
|
)
|
|
if any(
|
|
(options.disable_addons.get(v) is not None) for v in CLOUDRUN_ADDONS
|
|
):
|
|
load_balancer_type = _GetCloudRunLoadBalancerType(
|
|
options, self.messages
|
|
)
|
|
update.desiredAddonsConfig.cloudRunConfig = (
|
|
self.messages.CloudRunConfig(
|
|
disabled=any(
|
|
options.disable_addons.get(v) or False
|
|
for v in CLOUDRUN_ADDONS
|
|
),
|
|
loadBalancerType=load_balancer_type,
|
|
)
|
|
)
|
|
if options.disable_addons.get(APPLICATIONMANAGER) is not None:
|
|
update.desiredAddonsConfig.kalmConfig = self.messages.KalmConfig(
|
|
enabled=(not options.disable_addons.get(APPLICATIONMANAGER))
|
|
)
|
|
if options.disable_addons.get(CLOUDBUILD) is not None:
|
|
update.desiredAddonsConfig.cloudBuildConfig = (
|
|
self.messages.CloudBuildConfig(
|
|
enabled=(not options.disable_addons.get(CLOUDBUILD))
|
|
)
|
|
)
|
|
|
|
op = self.client.projects_locations_clusters.Update(
|
|
self.messages.UpdateClusterRequest(
|
|
name=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
update=update,
|
|
)
|
|
)
|
|
return self.ParseOperation(op.name, cluster_ref.zone)
|
|
|
|
def CreateNodePool(self, node_pool_ref, options):
|
|
pool = self.CreateNodePoolCommon(node_pool_ref, options)
|
|
req = self.messages.CreateNodePoolRequest(
|
|
nodePool=pool,
|
|
parent=ProjectLocationCluster(
|
|
node_pool_ref.projectId, node_pool_ref.zone, node_pool_ref.clusterId
|
|
),
|
|
)
|
|
operation = self.client.projects_locations_clusters_nodePools.Create(req)
|
|
return self.ParseOperation(operation.name, node_pool_ref.zone)
|
|
|
|
def CreateClusterAutoscalingCommon(self, cluster_ref, options, for_update):
|
|
"""Create cluster's autoscaling configuration.
|
|
|
|
Args:
|
|
cluster_ref: Cluster reference.
|
|
options: Either CreateClusterOptions or UpdateClusterOptions.
|
|
for_update: Is function executed for update operation.
|
|
|
|
Returns:
|
|
Cluster's autoscaling configuration.
|
|
"""
|
|
# Patch cluster autoscaling if cluster_ref is provided.
|
|
cluster = None
|
|
autoscaling = self.messages.ClusterAutoscaling()
|
|
if cluster_ref:
|
|
cluster = self.GetCluster(cluster_ref)
|
|
if cluster and cluster.autoscaling:
|
|
autoscaling.enableNodeAutoprovisioning = (
|
|
cluster.autoscaling.enableNodeAutoprovisioning
|
|
)
|
|
|
|
resource_limits = []
|
|
if options.autoprovisioning_config_file is not None:
|
|
# Create using config file only.
|
|
config = yaml.load(options.autoprovisioning_config_file)
|
|
resource_limits = config.get(RESOURCE_LIMITS)
|
|
service_account = config.get(SERVICE_ACCOUNT)
|
|
scopes = config.get(SCOPES)
|
|
max_surge_upgrade = None
|
|
max_unavailable_upgrade = None
|
|
upgrade_settings = config.get(UPGRADE_SETTINGS)
|
|
if upgrade_settings:
|
|
max_surge_upgrade = upgrade_settings.get(MAX_SURGE_UPGRADE)
|
|
max_unavailable_upgrade = upgrade_settings.get(MAX_UNAVAILABLE_UPGRADE)
|
|
management_settings = config.get(NODE_MANAGEMENT)
|
|
enable_autoupgrade = None
|
|
enable_autorepair = None
|
|
if management_settings is not None:
|
|
enable_autoupgrade = management_settings.get(ENABLE_AUTO_UPGRADE)
|
|
enable_autorepair = management_settings.get(ENABLE_AUTO_REPAIR)
|
|
autoprovisioning_locations = config.get(AUTOPROVISIONING_LOCATIONS)
|
|
min_cpu_platform = config.get(MIN_CPU_PLATFORM)
|
|
boot_disk_kms_key = config.get(BOOT_DISK_KMS_KEY)
|
|
disk_type = config.get(DISK_TYPE)
|
|
disk_size_gb = config.get(DISK_SIZE_GB)
|
|
autoprovisioning_image_type = config.get(IMAGE_TYPE)
|
|
shielded_instance_config = config.get(SHIELDED_INSTANCE_CONFIG)
|
|
enable_secure_boot = None
|
|
enable_integrity_monitoring = None
|
|
if shielded_instance_config:
|
|
enable_secure_boot = shielded_instance_config.get(ENABLE_SECURE_BOOT)
|
|
enable_integrity_monitoring = shielded_instance_config.get(
|
|
ENABLE_INTEGRITY_MONITORING
|
|
)
|
|
else:
|
|
resource_limits = self.ResourceLimitsFromFlags(options)
|
|
service_account = options.autoprovisioning_service_account
|
|
scopes = options.autoprovisioning_scopes
|
|
autoprovisioning_locations = options.autoprovisioning_locations
|
|
max_surge_upgrade = options.autoprovisioning_max_surge_upgrade
|
|
max_unavailable_upgrade = options.autoprovisioning_max_unavailable_upgrade
|
|
enable_autoupgrade = options.enable_autoprovisioning_autoupgrade
|
|
enable_autorepair = options.enable_autoprovisioning_autorepair
|
|
min_cpu_platform = options.autoprovisioning_min_cpu_platform
|
|
boot_disk_kms_key = None
|
|
disk_type = None
|
|
disk_size_gb = None
|
|
autoprovisioning_image_type = options.autoprovisioning_image_type
|
|
enable_secure_boot = None
|
|
enable_integrity_monitoring = None
|
|
|
|
autoscaling.enableNodeAutoprovisioning = options.enable_autoprovisioning
|
|
if resource_limits is None:
|
|
resource_limits = []
|
|
autoscaling.resourceLimits = resource_limits
|
|
if scopes is None:
|
|
scopes = []
|
|
management = None
|
|
upgrade_settings = None
|
|
if (
|
|
max_surge_upgrade is not None
|
|
or max_unavailable_upgrade is not None
|
|
or options.enable_autoprovisioning_blue_green_upgrade
|
|
or options.enable_autoprovisioning_surge_upgrade
|
|
or options.autoprovisioning_standard_rollout_policy is not None
|
|
or options.autoprovisioning_node_pool_soak_duration is not None
|
|
):
|
|
upgrade_settings = self.UpdateUpgradeSettingsForNAP(
|
|
options, max_surge_upgrade, max_unavailable_upgrade
|
|
)
|
|
if enable_autorepair is not None or enable_autorepair is not None:
|
|
management = self.messages.NodeManagement(
|
|
autoUpgrade=enable_autoupgrade, autoRepair=enable_autorepair
|
|
)
|
|
shielded_instance_config = None
|
|
if (
|
|
enable_secure_boot is not None
|
|
or enable_integrity_monitoring is not None
|
|
):
|
|
shielded_instance_config = self.messages.ShieldedInstanceConfig()
|
|
shielded_instance_config.enableSecureBoot = enable_secure_boot
|
|
shielded_instance_config.enableIntegrityMonitoring = (
|
|
enable_integrity_monitoring
|
|
)
|
|
|
|
if for_update:
|
|
autoscaling.autoprovisioningNodePoolDefaults = (
|
|
self.messages.AutoprovisioningNodePoolDefaults(
|
|
serviceAccount=service_account,
|
|
oauthScopes=scopes,
|
|
upgradeSettings=upgrade_settings,
|
|
management=management,
|
|
minCpuPlatform=min_cpu_platform,
|
|
bootDiskKmsKey=boot_disk_kms_key,
|
|
diskSizeGb=disk_size_gb,
|
|
diskType=disk_type,
|
|
imageType=autoprovisioning_image_type,
|
|
shieldedInstanceConfig=shielded_instance_config,
|
|
)
|
|
)
|
|
else:
|
|
autoscaling.autoprovisioningNodePoolDefaults = (
|
|
self.messages.AutoprovisioningNodePoolDefaults(
|
|
serviceAccount=service_account,
|
|
oauthScopes=scopes,
|
|
upgradeSettings=upgrade_settings,
|
|
management=management,
|
|
minCpuPlatform=min_cpu_platform,
|
|
bootDiskKmsKey=boot_disk_kms_key,
|
|
diskSizeGb=disk_size_gb,
|
|
diskType=disk_type,
|
|
imageType=autoprovisioning_image_type,
|
|
shieldedInstanceConfig=shielded_instance_config,
|
|
)
|
|
)
|
|
|
|
if autoprovisioning_locations:
|
|
autoscaling.autoprovisioningLocations = sorted(autoprovisioning_locations)
|
|
|
|
if options.autoscaling_profile is not None:
|
|
autoscaling.autoscalingProfile = self.CreateAutoscalingProfileCommon(
|
|
options
|
|
)
|
|
|
|
if options.enable_default_compute_class is not None:
|
|
autoscaling.defaultComputeClassConfig = (
|
|
self.messages.DefaultComputeClassConfig(
|
|
enabled=options.enable_default_compute_class
|
|
)
|
|
)
|
|
|
|
self.ValidateClusterAutoscaling(autoscaling, for_update)
|
|
return autoscaling
|
|
|
|
def ParseNodePools(self, options, node_config):
|
|
"""Creates a list of node pools for the cluster by parsing options.
|
|
|
|
Args:
|
|
options: cluster creation options
|
|
node_config: node configuration for nodes in the node pools
|
|
|
|
Returns:
|
|
List of node pools.
|
|
"""
|
|
max_nodes_per_pool = (
|
|
options.max_nodes_per_pool or DEFAULT_MAX_NODES_PER_POOL
|
|
)
|
|
num_pools = (
|
|
options.num_nodes + max_nodes_per_pool - 1
|
|
) // max_nodes_per_pool
|
|
# pool consistency with server default
|
|
node_pool_name = options.node_pool_name or 'default-pool'
|
|
|
|
if num_pools == 1:
|
|
pool_names = [node_pool_name]
|
|
else:
|
|
# default-pool-0, -1, ... or some-pool-0, -1 where some-pool is user
|
|
# supplied
|
|
pool_names = [
|
|
'{0}-{1}'.format(node_pool_name, i) for i in range(0, num_pools)
|
|
]
|
|
|
|
pools = []
|
|
nodes_per_pool = (options.num_nodes + num_pools - 1) // len(pool_names)
|
|
to_add = options.num_nodes
|
|
for name in pool_names:
|
|
nodes = nodes_per_pool if (to_add > nodes_per_pool) else to_add
|
|
pool = self.messages.NodePool(
|
|
name=name,
|
|
initialNodeCount=nodes,
|
|
config=node_config,
|
|
version=options.node_version,
|
|
management=self._GetNodeManagement(options),
|
|
)
|
|
if options.enable_autoscaling:
|
|
pool.autoscaling = self.messages.NodePoolAutoscaling(
|
|
enabled=options.enable_autoscaling,
|
|
minNodeCount=options.min_nodes,
|
|
maxNodeCount=options.max_nodes,
|
|
totalMinNodeCount=options.total_min_nodes,
|
|
totalMaxNodeCount=options.total_max_nodes,
|
|
)
|
|
if options.location_policy is not None:
|
|
pool.autoscaling.locationPolicy = LocationPolicyEnumFromString(
|
|
self.messages, options.location_policy
|
|
)
|
|
if options.max_pods_per_node:
|
|
if not options.enable_ip_alias:
|
|
raise util.Error(MAX_PODS_PER_NODE_WITHOUT_IP_ALIAS_ERROR_MSG)
|
|
pool.maxPodsConstraint = self.messages.MaxPodsConstraint(
|
|
maxPodsPerNode=options.max_pods_per_node
|
|
)
|
|
if (
|
|
options.max_surge_upgrade is not None
|
|
or options.max_unavailable_upgrade is not None
|
|
):
|
|
pool.upgradeSettings = self.messages.UpgradeSettings()
|
|
pool.upgradeSettings.maxSurge = options.max_surge_upgrade
|
|
pool.upgradeSettings.maxUnavailable = options.max_unavailable_upgrade
|
|
if (
|
|
options.placement_type == 'COMPACT'
|
|
or options.placement_policy is not None
|
|
):
|
|
pool.placementPolicy = self.messages.PlacementPolicy()
|
|
if options.placement_type == 'COMPACT':
|
|
pool.placementPolicy.type = (
|
|
self.messages.PlacementPolicy.TypeValueValuesEnum.COMPACT
|
|
)
|
|
if options.placement_policy is not None:
|
|
pool.placementPolicy.policyName = options.placement_policy
|
|
if options.enable_queued_provisioning is not None:
|
|
pool.queuedProvisioning = self.messages.QueuedProvisioning()
|
|
pool.queuedProvisioning.enabled = options.enable_queued_provisioning
|
|
pools.append(pool)
|
|
to_add -= nodes
|
|
return pools
|
|
|
|
def GetIamPolicy(self, cluster_ref):
|
|
return self.client.projects.GetIamPolicy(
|
|
self.messages.ContainerProjectsGetIamPolicyRequest(
|
|
resource=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
)
|
|
)
|
|
)
|
|
|
|
def SetIamPolicy(self, cluster_ref, policy):
|
|
return self.client.projects.SetIamPolicy(
|
|
self.messages.ContainerProjectsSetIamPolicyRequest(
|
|
googleIamV1SetIamPolicyRequest=self.messages.GoogleIamV1SetIamPolicyRequest(
|
|
policy=policy
|
|
),
|
|
resource=ProjectLocationCluster(
|
|
cluster_ref.projectId, cluster_ref.zone, cluster_ref.clusterId
|
|
),
|
|
)
|
|
)
|
|
|
|
|
|
def _GetCloudRunLoadBalancerType(options, messages):
|
|
"""Gets the Cloud Run load balancer type."""
|
|
if options.cloud_run_config is not None:
|
|
input_load_balancer_type = options.cloud_run_config.get(
|
|
'load-balancer-type'
|
|
)
|
|
if input_load_balancer_type is not None:
|
|
if input_load_balancer_type == 'INTERNAL':
|
|
return (
|
|
messages.CloudRunConfig.LoadBalancerTypeValueValuesEnum.LOAD_BALANCER_TYPE_INTERNAL
|
|
)
|
|
return (
|
|
messages.CloudRunConfig.LoadBalancerTypeValueValuesEnum.LOAD_BALANCER_TYPE_EXTERNAL
|
|
)
|
|
return None
|
|
|
|
|
|
def _AddMetadataToNodeConfig(node_config, options):
|
|
if not options.metadata:
|
|
return
|
|
metadata = node_config.MetadataValue()
|
|
props = []
|
|
for key, value in six.iteritems(options.metadata):
|
|
props.append(metadata.AdditionalProperty(key=key, value=value))
|
|
metadata.additionalProperties = props
|
|
node_config.metadata = metadata
|
|
|
|
|
|
def _AddLabelsToNodeConfig(node_config, options):
|
|
node_config.resourceLabels = labels_util.ParseCreateArgs(
|
|
options, node_config.ResourceLabelsValue
|
|
)
|
|
|
|
|
|
def _AddNodeLabelsToNodeConfig(node_config, options):
|
|
if options.node_labels is None:
|
|
return
|
|
labels = node_config.LabelsValue()
|
|
props = []
|
|
for key, value in six.iteritems(options.node_labels):
|
|
props.append(labels.AdditionalProperty(key=key, value=value))
|
|
labels.additionalProperties = props
|
|
node_config.labels = labels
|
|
|
|
|
|
def _AddLinuxNodeConfigToNodeConfig(node_config, options, messages):
|
|
"""Adds LinuxNodeConfig to NodeConfig."""
|
|
|
|
# Linux kernel parameters (sysctls).
|
|
if options.linux_sysctls:
|
|
if not node_config.linuxNodeConfig:
|
|
node_config.linuxNodeConfig = messages.LinuxNodeConfig()
|
|
linux_sysctls = node_config.linuxNodeConfig.SysctlsValue()
|
|
props = []
|
|
for key, value in six.iteritems(options.linux_sysctls):
|
|
props.append(linux_sysctls.AdditionalProperty(key=key, value=value))
|
|
linux_sysctls.additionalProperties = props
|
|
|
|
node_config.linuxNodeConfig.sysctls = linux_sysctls
|
|
|
|
_AddKernelModuleSignatureEnforcementToNodeConfig(
|
|
node_config, options, messages
|
|
)
|
|
|
|
|
|
def _AddKernelModuleSignatureEnforcementToNodeConfig(
|
|
node_config, options, messages
|
|
):
|
|
"""Adds KernelModuleSignatureEnforcement to NodeConfig."""
|
|
if options.enable_kernel_module_signature_enforcement is not None:
|
|
if not node_config.linuxNodeConfig:
|
|
node_config.linuxNodeConfig = messages.LinuxNodeConfig()
|
|
module_loading_config = messages.NodeKernelModuleLoading()
|
|
policy_enum = messages.NodeKernelModuleLoading.PolicyValueValuesEnum
|
|
if options.enable_kernel_module_signature_enforcement:
|
|
module_loading_config.policy = policy_enum.ENFORCE_SIGNED_MODULES
|
|
else:
|
|
module_loading_config.policy = policy_enum.DO_NOT_ENFORCE_SIGNED_MODULES
|
|
|
|
node_config.linuxNodeConfig.nodeKernelModuleLoading = module_loading_config
|
|
|
|
|
|
def _AddWindowsNodeConfigToNodeConfig(node_config, options, messages):
|
|
"""Adds WindowsNodeConfig to NodeConfig."""
|
|
|
|
if options.windows_os_version is not None:
|
|
if node_config.windowsNodeConfig is None:
|
|
node_config.windowsNodeConfig = messages.WindowsNodeConfig()
|
|
if options.windows_os_version == 'ltsc2022':
|
|
node_config.windowsNodeConfig.osVersion = (
|
|
messages.WindowsNodeConfig.OsVersionValueValuesEnum.OS_VERSION_LTSC2022
|
|
)
|
|
else:
|
|
node_config.windowsNodeConfig.osVersion = (
|
|
messages.WindowsNodeConfig.OsVersionValueValuesEnum.OS_VERSION_LTSC2019
|
|
)
|
|
|
|
|
|
def _AddShieldedInstanceConfigToNodeConfig(node_config, options, messages):
|
|
"""Adds ShieldedInstanceConfig to NodeConfig."""
|
|
if (
|
|
options.shielded_secure_boot is not None
|
|
or options.shielded_integrity_monitoring is not None
|
|
):
|
|
|
|
# Setting any of the ShieldedInstanceConfig options here
|
|
# overrides the defaulting on the server.
|
|
#
|
|
# Require all or none of the ShieldedInstanceConfig fields to be
|
|
# set.
|
|
secure_boot_set = options.shielded_secure_boot is not None
|
|
integrity_monitoring_set = options.shielded_integrity_monitoring is not None
|
|
if secure_boot_set != integrity_monitoring_set:
|
|
raise util.Error(BOTH_SHIELDED_INSTANCE_SETTINGS_ERROR_MSG)
|
|
|
|
node_config.shieldedInstanceConfig = messages.ShieldedInstanceConfig()
|
|
if options.shielded_secure_boot is not None:
|
|
node_config.shieldedInstanceConfig.enableSecureBoot = (
|
|
options.shielded_secure_boot
|
|
)
|
|
if options.shielded_integrity_monitoring is not None:
|
|
node_config.shieldedInstanceConfig.enableIntegrityMonitoring = (
|
|
options.shielded_integrity_monitoring
|
|
)
|
|
|
|
|
|
def _AddReservationAffinityToNodeConfig(node_config, options, messages):
|
|
"""Adds ReservationAffinity to NodeConfig."""
|
|
affinity = options.reservation_affinity
|
|
if options.reservation and affinity != 'specific':
|
|
raise util.Error(
|
|
RESERVATION_AFFINITY_NON_SPECIFIC_WITH_RESERVATION_NAME_ERROR_MSG.format(
|
|
affinity=affinity
|
|
)
|
|
)
|
|
|
|
if not options.reservation and affinity == 'specific':
|
|
raise util.Error(
|
|
RESERVATION_AFFINITY_SPECIFIC_WITHOUT_RESERVATION_NAME_ERROR_MSG
|
|
)
|
|
|
|
if affinity == 'none':
|
|
node_config.reservationAffinity = messages.ReservationAffinity(
|
|
consumeReservationType=messages.ReservationAffinity.ConsumeReservationTypeValueValuesEnum.NO_RESERVATION
|
|
)
|
|
elif affinity == 'any':
|
|
node_config.reservationAffinity = messages.ReservationAffinity(
|
|
consumeReservationType=messages.ReservationAffinity.ConsumeReservationTypeValueValuesEnum.ANY_RESERVATION
|
|
)
|
|
elif affinity == 'specific':
|
|
node_config.reservationAffinity = messages.ReservationAffinity(
|
|
consumeReservationType=messages.ReservationAffinity.ConsumeReservationTypeValueValuesEnum.SPECIFIC_RESERVATION,
|
|
key='compute.googleapis.com/reservation-name',
|
|
values=[options.reservation],
|
|
)
|
|
|
|
|
|
def _AddSandboxConfigToNodeConfig(node_config, options, messages):
|
|
"""Adds SandboxConfig to NodeConfig."""
|
|
if options.sandbox is not None:
|
|
if 'type' not in options.sandbox:
|
|
raise util.Error(SANDBOX_TYPE_NOT_PROVIDED)
|
|
sandbox_types = {
|
|
'unspecified': messages.SandboxConfig.TypeValueValuesEnum.UNSPECIFIED,
|
|
'gvisor': messages.SandboxConfig.TypeValueValuesEnum.GVISOR,
|
|
}
|
|
if options.sandbox['type'] not in sandbox_types:
|
|
raise util.Error(
|
|
SANDBOX_TYPE_NOT_SUPPORTED.format(type=options.sandbox['type'])
|
|
)
|
|
node_config.sandboxConfig = messages.SandboxConfig(
|
|
type=sandbox_types[options.sandbox['type']]
|
|
)
|
|
|
|
|
|
def _GetStableFleetConfig(options, messages):
|
|
"""Get StableFleetConfig from options."""
|
|
if options.maintenance_interval is not None:
|
|
maintenance_interval_types = {
|
|
'UNSPECIFIED': (
|
|
messages.StableFleetConfig.MaintenanceIntervalValueValuesEnum.MAINTENANCE_INTERVAL_UNSPECIFIED
|
|
),
|
|
'PERIODIC': (
|
|
messages.StableFleetConfig.MaintenanceIntervalValueValuesEnum.PERIODIC
|
|
),
|
|
'AS_NEEDED': (
|
|
messages.StableFleetConfig.MaintenanceIntervalValueValuesEnum.AS_NEEDED
|
|
),
|
|
}
|
|
if options.maintenance_interval not in maintenance_interval_types:
|
|
raise util.Error(
|
|
MAINTENANCE_INTERVAL_TYPE_NOT_SUPPORTED.format(
|
|
type=options.maintenance_interval
|
|
)
|
|
)
|
|
return messages.StableFleetConfig(
|
|
maintenanceInterval=maintenance_interval_types[
|
|
options.maintenance_interval
|
|
]
|
|
)
|
|
|
|
|
|
def _AddNotificationConfigToCluster(cluster, options, messages):
|
|
"""Adds notification config to Cluster."""
|
|
nc = options.notification_config
|
|
if nc is not None:
|
|
pubsub = messages.PubSub()
|
|
if 'pubsub' in nc:
|
|
pubsub.enabled = nc['pubsub'] == 'ENABLED'
|
|
if 'pubsub-topic' in nc:
|
|
pubsub.topic = nc['pubsub-topic']
|
|
if 'filter' in nc:
|
|
pubsub.filter = _GetFilterFromArg(nc['filter'], messages)
|
|
|
|
cluster.notificationConfig = messages.NotificationConfig(pubsub=pubsub)
|
|
|
|
|
|
def _GetFilterFromArg(filter_arg, messages):
|
|
"""Gets a Filter message object from a filter phrase."""
|
|
if not filter_arg:
|
|
return None
|
|
flag_event_types_to_enum = {
|
|
'upgradeevent': (
|
|
messages.Filter.EventTypeValueListEntryValuesEnum.UPGRADE_EVENT
|
|
),
|
|
'upgradeinfoevent': (
|
|
messages.Filter.EventTypeValueListEntryValuesEnum.UPGRADE_INFO_EVENT
|
|
),
|
|
'upgradeavailableevent': (
|
|
messages.Filter.EventTypeValueListEntryValuesEnum.UPGRADE_AVAILABLE_EVENT
|
|
),
|
|
'securitybulletinevent': (
|
|
messages.Filter.EventTypeValueListEntryValuesEnum.SECURITY_BULLETIN_EVENT
|
|
),
|
|
}
|
|
to_return = messages.Filter()
|
|
for event_type in filter_arg.split('|'):
|
|
event_type = event_type.lower()
|
|
if flag_event_types_to_enum[event_type]:
|
|
to_return.eventType.append(flag_event_types_to_enum[event_type])
|
|
return to_return
|
|
|
|
|
|
def _GetReleaseChannel(options, messages):
|
|
"""Gets the ReleaseChannel from options."""
|
|
if options.release_channel is not None:
|
|
channels = {
|
|
'rapid': messages.ReleaseChannel.ChannelValueValuesEnum.RAPID,
|
|
'regular': messages.ReleaseChannel.ChannelValueValuesEnum.REGULAR,
|
|
'stable': messages.ReleaseChannel.ChannelValueValuesEnum.STABLE,
|
|
'extended': messages.ReleaseChannel.ChannelValueValuesEnum.EXTENDED,
|
|
'None': messages.ReleaseChannel.ChannelValueValuesEnum.UNSPECIFIED,
|
|
}
|
|
return messages.ReleaseChannel(channel=channels[options.release_channel])
|
|
|
|
|
|
def _GetGkeAutoUpgradeConfig(options, messages):
|
|
"""Gets the PatchMode from options."""
|
|
if options.patch_update is not None:
|
|
patch_modes = {
|
|
'accelerated': (
|
|
messages.GkeAutoUpgradeConfig.PatchModeValueValuesEnum.ACCELERATED
|
|
),
|
|
'default': (
|
|
messages.GkeAutoUpgradeConfig.PatchModeValueValuesEnum.PATCH_MODE_UNSPECIFIED
|
|
),
|
|
}
|
|
return messages.GkeAutoUpgradeConfig(
|
|
patchMode=patch_modes[options.patch_update[0]]
|
|
)
|
|
|
|
|
|
def _GetNotificationConfigForClusterUpdate(options, messages):
|
|
"""Gets the NotificationConfig from update options."""
|
|
nc = options.notification_config
|
|
if nc is not None:
|
|
pubsub = messages.PubSub()
|
|
if 'pubsub' in nc:
|
|
pubsub.enabled = nc['pubsub'] == 'ENABLED'
|
|
if 'pubsub-topic' in nc:
|
|
pubsub.topic = nc['pubsub-topic']
|
|
if 'filter' in nc:
|
|
pubsub.filter = _GetFilterFromArg(nc['filter'], messages)
|
|
return messages.NotificationConfig(pubsub=pubsub)
|
|
|
|
|
|
def _GetTpuConfigForClusterUpdate(options, messages):
|
|
"""Gets the TpuConfig from update options."""
|
|
if options.enable_tpu is not None:
|
|
if options.tpu_ipv4_cidr and options.enable_tpu_service_networking:
|
|
raise util.Error(TPU_SERVING_MODE_ERROR)
|
|
return messages.TpuConfig(
|
|
enabled=options.enable_tpu,
|
|
ipv4CidrBlock=options.tpu_ipv4_cidr,
|
|
useServiceNetworking=options.enable_tpu_service_networking,
|
|
)
|
|
|
|
|
|
def _GetMasterForClusterCreate(options, messages):
|
|
"""Gets the Master from create options."""
|
|
if (
|
|
options.master_logs is not None
|
|
or options.enable_master_metrics is not None
|
|
):
|
|
config = messages.MasterSignalsConfig()
|
|
|
|
if options.master_logs is not None:
|
|
if APISERVER in options.master_logs:
|
|
config.logEnabledComponents.append(
|
|
messages.MasterSignalsConfig.LogEnabledComponentsValueListEntryValuesEnum.APISERVER
|
|
)
|
|
if SCHEDULER in options.master_logs:
|
|
config.logEnabledComponents.append(
|
|
messages.MasterSignalsConfig.LogEnabledComponentsValueListEntryValuesEnum.SCHEDULER
|
|
)
|
|
if CONTROLLER_MANAGER in options.master_logs:
|
|
config.logEnabledComponents.append(
|
|
messages.MasterSignalsConfig.LogEnabledComponentsValueListEntryValuesEnum.CONTROLLER_MANAGER
|
|
)
|
|
if ADDON_MANAGER in options.master_logs:
|
|
config.logEnabledComponents.append(
|
|
messages.MasterSignalsConfig.LogEnabledComponentsValueListEntryValuesEnum.ADDON_MANAGER
|
|
)
|
|
if options.enable_master_metrics is not None:
|
|
config.enableMetrics = options.enable_master_metrics
|
|
return messages.Master(signalsConfig=config)
|
|
|
|
|
|
def _GetMasterForClusterUpdate(options, messages):
|
|
"""Gets the Master from update options."""
|
|
if options.no_master_logs:
|
|
options.master_logs = []
|
|
if options.master_logs is not None:
|
|
config = messages.MasterSignalsConfig()
|
|
if APISERVER in options.master_logs:
|
|
config.logEnabledComponents.append(
|
|
messages.MasterSignalsConfig.LogEnabledComponentsValueListEntryValuesEnum.APISERVER
|
|
)
|
|
if SCHEDULER in options.master_logs:
|
|
config.logEnabledComponents.append(
|
|
messages.MasterSignalsConfig.LogEnabledComponentsValueListEntryValuesEnum.SCHEDULER
|
|
)
|
|
if CONTROLLER_MANAGER in options.master_logs:
|
|
config.logEnabledComponents.append(
|
|
messages.MasterSignalsConfig.LogEnabledComponentsValueListEntryValuesEnum.CONTROLLER_MANAGER
|
|
)
|
|
if ADDON_MANAGER in options.master_logs:
|
|
config.logEnabledComponents.append(
|
|
messages.MasterSignalsConfig.LogEnabledComponentsValueListEntryValuesEnum.ADDON_MANAGER
|
|
)
|
|
return messages.Master(signalsConfig=config)
|
|
|
|
if options.enable_master_metrics is not None:
|
|
config = messages.MasterSignalsConfig(
|
|
enableMetrics=options.enable_master_metrics,
|
|
logEnabledComponents=[
|
|
messages.MasterSignalsConfig.LogEnabledComponentsValueListEntryValuesEnum.COMPONENT_UNSPECIFIED
|
|
],
|
|
)
|
|
return messages.Master(signalsConfig=config)
|
|
|
|
|
|
def _GetLoggingConfig(options, messages):
|
|
"""Gets the LoggingConfig from create and update options."""
|
|
if options.logging is None:
|
|
return None
|
|
|
|
# TODO(b/195524749): Validate the input in flags.py after Control Plane
|
|
# Signals is GA.
|
|
if any(c not in LOGGING_OPTIONS for c in options.logging):
|
|
raise util.Error(
|
|
'['
|
|
+ ', '.join(options.logging)
|
|
+ '] contains option(s) that are not supported for logging.'
|
|
)
|
|
|
|
config = messages.LoggingComponentConfig()
|
|
if NONE in options.logging:
|
|
if len(options.logging) > 1:
|
|
raise util.Error('Cannot include other values when None is specified.')
|
|
return messages.LoggingConfig(componentConfig=config)
|
|
if SYSTEM not in options.logging:
|
|
raise util.Error('Must include system logging if any logging is enabled.')
|
|
config.enableComponents.append(
|
|
messages.LoggingComponentConfig.EnableComponentsValueListEntryValuesEnum.SYSTEM_COMPONENTS
|
|
)
|
|
if WORKLOAD in options.logging:
|
|
config.enableComponents.append(
|
|
messages.LoggingComponentConfig.EnableComponentsValueListEntryValuesEnum.WORKLOADS
|
|
)
|
|
if API_SERVER in options.logging:
|
|
config.enableComponents.append(
|
|
messages.LoggingComponentConfig.EnableComponentsValueListEntryValuesEnum.APISERVER
|
|
)
|
|
if SCHEDULER in options.logging:
|
|
config.enableComponents.append(
|
|
messages.LoggingComponentConfig.EnableComponentsValueListEntryValuesEnum.SCHEDULER
|
|
)
|
|
if CONTROLLER_MANAGER in options.logging:
|
|
config.enableComponents.append(
|
|
messages.LoggingComponentConfig.EnableComponentsValueListEntryValuesEnum.CONTROLLER_MANAGER
|
|
)
|
|
if ADDON_MANAGER in options.logging:
|
|
config.enableComponents.append(
|
|
messages.LoggingComponentConfig.EnableComponentsValueListEntryValuesEnum.ADDON_MANAGER
|
|
)
|
|
if KCP_SSHD in options.logging:
|
|
config.enableComponents.append(
|
|
messages.LoggingComponentConfig.EnableComponentsValueListEntryValuesEnum.KCP_SSHD
|
|
)
|
|
if KCP_CONNECTION in options.logging:
|
|
config.enableComponents.append(
|
|
messages.LoggingComponentConfig.EnableComponentsValueListEntryValuesEnum.KCP_CONNECTION
|
|
)
|
|
if KCP_HPA in options.logging:
|
|
config.enableComponents.append(
|
|
messages.LoggingComponentConfig.EnableComponentsValueListEntryValuesEnum.KCP_HPA
|
|
)
|
|
|
|
return messages.LoggingConfig(componentConfig=config)
|
|
|
|
|
|
def _GetHostMaintenancePolicy(options, messages, op_type):
|
|
"""Get HostMaintenancePolicy from options."""
|
|
parsed_maintenance_interval = None
|
|
parsed_opportunistic_maintenance = None
|
|
|
|
if options.host_maintenance_interval is not None:
|
|
maintenance_interval_types = {
|
|
'UNSPECIFIED': (
|
|
messages.HostMaintenancePolicy.MaintenanceIntervalValueValuesEnum.MAINTENANCE_INTERVAL_UNSPECIFIED
|
|
),
|
|
'PERIODIC': (
|
|
messages.HostMaintenancePolicy.MaintenanceIntervalValueValuesEnum.PERIODIC
|
|
),
|
|
'AS_NEEDED': (
|
|
messages.HostMaintenancePolicy.MaintenanceIntervalValueValuesEnum.AS_NEEDED
|
|
),
|
|
}
|
|
if options.host_maintenance_interval not in maintenance_interval_types:
|
|
raise util.Error(
|
|
HOST_MAINTENANCE_INTERVAL_TYPE_NOT_SUPPORTED.format(
|
|
type=options.host_maintenance_interval
|
|
)
|
|
)
|
|
parsed_maintenance_interval = maintenance_interval_types[
|
|
options.host_maintenance_interval
|
|
]
|
|
# opportunistic maintenance is only supported for node pools
|
|
if op_type == NODEPOOL and options.opportunistic_maintenance is not None:
|
|
if not re.search(
|
|
r's$', options.opportunistic_maintenance['node-idle-time']
|
|
):
|
|
raise util.Error(
|
|
OPPORTUNISTIC_MAINTENANCE_FIELD_NOT_SUPPORTED.format(
|
|
field='node-idle-time',
|
|
value=options.opportunistic_maintenance['node-idle-time'],
|
|
)
|
|
)
|
|
if not re.search(r's$', options.opportunistic_maintenance['window']):
|
|
raise util.Error(
|
|
OPPORTUNISTIC_MAINTENANCE_FIELD_NOT_SUPPORTED.format(
|
|
field='window', value=options.opportunistic_maintenance['window']
|
|
)
|
|
)
|
|
parsed_opportunistic_maintenance = (
|
|
messages.OpportunisticMaintenanceStrategy(
|
|
nodeIdleTimeWindow=options.opportunistic_maintenance[
|
|
'node-idle-time'
|
|
],
|
|
maintenanceAvailabilityWindow=options.opportunistic_maintenance[
|
|
'window'
|
|
],
|
|
minNodesPerPool=options.opportunistic_maintenance['min-nodes'],
|
|
)
|
|
)
|
|
return messages.HostMaintenancePolicy(
|
|
maintenanceInterval=parsed_maintenance_interval,
|
|
opportunisticMaintenanceStrategy=parsed_opportunistic_maintenance,
|
|
)
|
|
|
|
|
|
def _GetManagedOpenTelemetryConfig(options, messages):
|
|
"""Gets the ManagedOpenTelemetryConfig from create and update options."""
|
|
scope = None
|
|
otel_scope = options.managed_otel_scope
|
|
scope_value_enum = messages.ManagedOpenTelemetryConfig.ScopeValueValuesEnum
|
|
if otel_scope == 'NONE':
|
|
scope = scope_value_enum.NONE
|
|
elif otel_scope == 'COLLECTION_AND_INSTRUMENTATION_COMPONENTS':
|
|
scope = scope_value_enum.COLLECTION_AND_INSTRUMENTATION_COMPONENTS
|
|
return messages.ManagedOpenTelemetryConfig(scope=scope)
|
|
|
|
|
|
def _GetMonitoringConfig(options, messages, is_update, is_prometheus_enabled):
|
|
"""Gets the MonitoringConfig from create and update options."""
|
|
|
|
comp = None
|
|
prom = None
|
|
adv_obs = None
|
|
config = messages.MonitoringConfig()
|
|
|
|
if options.enable_managed_prometheus is not None:
|
|
prom = messages.ManagedPrometheusConfig(
|
|
enabled=options.enable_managed_prometheus
|
|
)
|
|
if options.auto_monitoring_scope is not None:
|
|
scope = None
|
|
if options.auto_monitoring_scope == 'ALL':
|
|
scope = messages.AutoMonitoringConfig.ScopeValueValuesEnum.ALL
|
|
elif options.auto_monitoring_scope == 'NONE':
|
|
scope = messages.AutoMonitoringConfig.ScopeValueValuesEnum.NONE
|
|
prom.autoMonitoringConfig = messages.AutoMonitoringConfig(scope=scope)
|
|
config.managedPrometheusConfig = prom
|
|
# for update or when auto_monitoring_scope is set without
|
|
# managed_prometheus enabled
|
|
if (
|
|
options.enable_managed_prometheus is None
|
|
and options.auto_monitoring_scope is not None
|
|
):
|
|
if (
|
|
not is_update
|
|
and options.enable_managed_prometheus is None
|
|
and options.auto_monitoring_scope != 'NONE'
|
|
and not options.autopilot
|
|
):
|
|
raise util.Error(AUTO_MONITORING_NOT_SUPPORTED_WITHOUT_MANAGED_PROMETHEUS)
|
|
elif is_update:
|
|
scope = None
|
|
if options.auto_monitoring_scope == 'ALL':
|
|
scope = messages.AutoMonitoringConfig.ScopeValueValuesEnum.ALL
|
|
elif options.auto_monitoring_scope == 'NONE':
|
|
scope = messages.AutoMonitoringConfig.ScopeValueValuesEnum.NONE
|
|
|
|
prom = messages.ManagedPrometheusConfig(enabled=is_prometheus_enabled)
|
|
prom.autoMonitoringConfig = messages.AutoMonitoringConfig(scope=scope)
|
|
elif options.autopilot:
|
|
prom = messages.ManagedPrometheusConfig(enabled=True)
|
|
scope = None
|
|
if options.auto_monitoring_scope == 'ALL':
|
|
scope = messages.AutoMonitoringConfig.ScopeValueValuesEnum.ALL
|
|
elif options.auto_monitoring_scope == 'NONE':
|
|
scope = messages.AutoMonitoringConfig.ScopeValueValuesEnum.NONE
|
|
prom.autoMonitoringConfig = messages.AutoMonitoringConfig(scope=scope)
|
|
else: # when prometheus is not enabled and user it trying to set scope to
|
|
# NONE in a create cluster command.
|
|
prom = messages.ManagedPrometheusConfig(enabled=False)
|
|
prom.autoMonitoringConfig = messages.AutoMonitoringConfig(
|
|
scope=messages.AutoMonitoringConfig.ScopeValueValuesEnum.NONE
|
|
)
|
|
|
|
config.managedPrometheusConfig = prom
|
|
|
|
# Disable flag only on cluster updates, check first.
|
|
if hasattr(options, 'disable_managed_prometheus'):
|
|
if options.disable_managed_prometheus is not None:
|
|
prom = messages.ManagedPrometheusConfig(
|
|
enabled=(not options.disable_managed_prometheus)
|
|
)
|
|
prom.autoMonitoringConfig = None
|
|
config.managedPrometheusConfig = prom
|
|
if options.monitoring is not None:
|
|
# TODO(b/195524749): Validate the input in flags.py after Control Plane
|
|
# Signals is GA.
|
|
if any(c not in MONITORING_OPTIONS for c in options.monitoring):
|
|
raise util.Error(
|
|
'['
|
|
+ ', '.join(options.monitoring)
|
|
+ '] contains option(s) that are not supported for monitoring.'
|
|
)
|
|
|
|
comp = messages.MonitoringComponentConfig()
|
|
if NONE in options.monitoring:
|
|
if len(options.monitoring) > 1:
|
|
raise util.Error('Cannot include other values when None is specified.')
|
|
else:
|
|
config.componentConfig = comp
|
|
return config
|
|
if SYSTEM not in options.monitoring:
|
|
raise util.Error(
|
|
'Must include system monitoring if any monitoring is enabled.'
|
|
)
|
|
comp.enableComponents.append(
|
|
messages.MonitoringComponentConfig.EnableComponentsValueListEntryValuesEnum.SYSTEM_COMPONENTS
|
|
)
|
|
|
|
if WORKLOAD in options.monitoring:
|
|
comp.enableComponents.append(
|
|
messages.MonitoringComponentConfig.EnableComponentsValueListEntryValuesEnum.WORKLOADS
|
|
)
|
|
if API_SERVER in options.monitoring:
|
|
comp.enableComponents.append(
|
|
messages.MonitoringComponentConfig.EnableComponentsValueListEntryValuesEnum.APISERVER
|
|
)
|
|
if SCHEDULER in options.monitoring:
|
|
comp.enableComponents.append(
|
|
messages.MonitoringComponentConfig.EnableComponentsValueListEntryValuesEnum.SCHEDULER
|
|
)
|
|
if CONTROLLER_MANAGER in options.monitoring:
|
|
comp.enableComponents.append(
|
|
messages.MonitoringComponentConfig.EnableComponentsValueListEntryValuesEnum.CONTROLLER_MANAGER
|
|
)
|
|
if STORAGE in options.monitoring:
|
|
comp.enableComponents.append(
|
|
messages.MonitoringComponentConfig.EnableComponentsValueListEntryValuesEnum.STORAGE
|
|
)
|
|
if HPA_COMPONENT in options.monitoring:
|
|
comp.enableComponents.append(
|
|
messages.MonitoringComponentConfig.EnableComponentsValueListEntryValuesEnum.HPA
|
|
)
|
|
if POD in options.monitoring:
|
|
comp.enableComponents.append(
|
|
messages.MonitoringComponentConfig.EnableComponentsValueListEntryValuesEnum.POD
|
|
)
|
|
if DAEMONSET in options.monitoring:
|
|
comp.enableComponents.append(
|
|
messages.MonitoringComponentConfig.EnableComponentsValueListEntryValuesEnum.DAEMONSET
|
|
)
|
|
if DEPLOYMENT in options.monitoring:
|
|
comp.enableComponents.append(
|
|
messages.MonitoringComponentConfig.EnableComponentsValueListEntryValuesEnum.DEPLOYMENT
|
|
)
|
|
if STATEFULSET in options.monitoring:
|
|
comp.enableComponents.append(
|
|
messages.MonitoringComponentConfig.EnableComponentsValueListEntryValuesEnum.STATEFULSET
|
|
)
|
|
if CADVISOR in options.monitoring:
|
|
comp.enableComponents.append(
|
|
messages.MonitoringComponentConfig.EnableComponentsValueListEntryValuesEnum.CADVISOR
|
|
)
|
|
if KUBELET in options.monitoring:
|
|
comp.enableComponents.append(
|
|
messages.MonitoringComponentConfig.EnableComponentsValueListEntryValuesEnum.KUBELET
|
|
)
|
|
if DCGM in options.monitoring:
|
|
comp.enableComponents.append(
|
|
messages.MonitoringComponentConfig.EnableComponentsValueListEntryValuesEnum.DCGM
|
|
)
|
|
if JOBSET in options.monitoring:
|
|
comp.enableComponents.append(
|
|
messages.MonitoringComponentConfig.EnableComponentsValueListEntryValuesEnum.JOBSET
|
|
)
|
|
|
|
config.componentConfig = comp
|
|
|
|
if options.enable_dataplane_v2_metrics:
|
|
adv_obs = messages.AdvancedDatapathObservabilityConfig(enableMetrics=True)
|
|
|
|
if options.disable_dataplane_v2_metrics:
|
|
adv_obs = messages.AdvancedDatapathObservabilityConfig(enableMetrics=False)
|
|
|
|
if options.dataplane_v2_observability_mode:
|
|
relay_mode = None
|
|
opts_name = options.dataplane_v2_observability_mode.upper()
|
|
if opts_name == 'DISABLED':
|
|
relay_mode = (
|
|
messages.AdvancedDatapathObservabilityConfig.RelayModeValueValuesEnum.DISABLED
|
|
)
|
|
elif opts_name == 'INTERNAL_CLUSTER_SERVICE':
|
|
relay_mode = (
|
|
messages.AdvancedDatapathObservabilityConfig.RelayModeValueValuesEnum.INTERNAL_CLUSTER_SERVICE
|
|
)
|
|
elif opts_name == 'INTERNAL_VPC_LB':
|
|
relay_mode = (
|
|
messages.AdvancedDatapathObservabilityConfig.RelayModeValueValuesEnum.INTERNAL_VPC_LB
|
|
)
|
|
elif opts_name == 'EXTERNAL_LB':
|
|
relay_mode = (
|
|
messages.AdvancedDatapathObservabilityConfig.RelayModeValueValuesEnum.EXTERNAL_LB
|
|
)
|
|
else:
|
|
raise util.Error(
|
|
DPV2_OBS_ERROR_MSG.format(
|
|
mode=options.dataplane_v2_observability_mode
|
|
)
|
|
)
|
|
if adv_obs:
|
|
adv_obs = messages.AdvancedDatapathObservabilityConfig(
|
|
enableMetrics=adv_obs.enableMetrics, relayMode=relay_mode
|
|
)
|
|
else:
|
|
adv_obs = messages.AdvancedDatapathObservabilityConfig(
|
|
relayMode=relay_mode
|
|
)
|
|
|
|
if options.enable_dataplane_v2_flow_observability:
|
|
if adv_obs:
|
|
adv_obs = messages.AdvancedDatapathObservabilityConfig(
|
|
enableMetrics=adv_obs.enableMetrics, enableRelay=True
|
|
)
|
|
else:
|
|
adv_obs = messages.AdvancedDatapathObservabilityConfig(enableRelay=True)
|
|
|
|
if options.disable_dataplane_v2_flow_observability:
|
|
if adv_obs:
|
|
adv_obs = messages.AdvancedDatapathObservabilityConfig(
|
|
enableMetrics=adv_obs.enableMetrics, enableRelay=False
|
|
)
|
|
else:
|
|
adv_obs = messages.AdvancedDatapathObservabilityConfig(enableRelay=False)
|
|
|
|
if comp is None and prom is None and adv_obs is None:
|
|
return None
|
|
|
|
if hasattr(config, 'advancedDatapathObservabilityConfig'):
|
|
config.advancedDatapathObservabilityConfig = adv_obs
|
|
|
|
return config
|
|
|
|
|
|
def _GetKubernetesObjectsExportConfigForClusterCreate(options, messages):
|
|
"""Gets the KubernetesObjectsExportConfig from create options."""
|
|
if (
|
|
options.kubernetes_objects_changes_target is not None
|
|
or options.kubernetes_objects_snapshots_target is not None
|
|
):
|
|
config = messages.KubernetesObjectsExportConfig()
|
|
if options.kubernetes_objects_changes_target is not None:
|
|
config.kubernetesObjectsChangesTarget = (
|
|
options.kubernetes_objects_changes_target
|
|
)
|
|
if options.kubernetes_objects_snapshots_target is not None:
|
|
config.kubernetesObjectsSnapshotsTarget = (
|
|
options.kubernetes_objects_snapshots_target
|
|
)
|
|
return config
|
|
|
|
|
|
def _GetKubernetesObjectsExportConfigForClusterUpdate(options, messages):
|
|
"""Gets the KubernetesObjectsExportConfig from update options."""
|
|
if (
|
|
options.kubernetes_objects_changes_target is not None
|
|
or options.kubernetes_objects_snapshots_target is not None
|
|
):
|
|
changes_target = None
|
|
snapshots_target = None
|
|
if options.kubernetes_objects_changes_target is not None:
|
|
changes_target = options.kubernetes_objects_changes_target
|
|
if changes_target == 'NONE':
|
|
changes_target = ''
|
|
if options.kubernetes_objects_snapshots_target is not None:
|
|
snapshots_target = options.kubernetes_objects_snapshots_target
|
|
if snapshots_target == 'NONE':
|
|
snapshots_target = ''
|
|
return messages.KubernetesObjectsExportConfig(
|
|
kubernetesObjectsSnapshotsTarget=snapshots_target,
|
|
kubernetesObjectsChangesTarget=changes_target,
|
|
)
|
|
|
|
|
|
def _AddPSCPrivateClustersOptionsToClusterForCreateCluster(
|
|
cluster, options, messages
|
|
):
|
|
"""Adds all PSC private cluster options to cluster during create cluster."""
|
|
if options.cross_connect_subnetworks is not None:
|
|
items = []
|
|
cluster.privateClusterConfig = messages.PrivateClusterConfig(
|
|
enablePrivateNodes=options.enable_private_nodes
|
|
)
|
|
for subnetwork in sorted(options.cross_connect_subnetworks):
|
|
items.append(messages.CrossConnectItem(subnetwork=subnetwork))
|
|
cluster.privateClusterConfig.crossConnectConfig = (
|
|
messages.CrossConnectConfig(items=items)
|
|
)
|
|
|
|
|
|
def LocationPolicyEnumFromString(messages, location_policy):
|
|
"""Converts a location policy string to an enum value."""
|
|
location_policy_enum = (
|
|
messages.NodePoolAutoscaling.LocationPolicyValueValuesEnum.LOCATION_POLICY_UNSPECIFIED
|
|
)
|
|
if location_policy == 'BALANCED':
|
|
location_policy_enum = (
|
|
messages.NodePoolAutoscaling.LocationPolicyValueValuesEnum.BALANCED
|
|
)
|
|
elif location_policy == 'ANY':
|
|
location_policy_enum = (
|
|
messages.NodePoolAutoscaling.LocationPolicyValueValuesEnum.ANY
|
|
)
|
|
return location_policy_enum
|
|
|
|
|
|
def ProjectLocation(project, location):
|
|
return 'projects/' + project + '/locations/' + location
|
|
|
|
|
|
def ProjectLocationCluster(project, location, cluster):
|
|
return ProjectLocation(project, location) + '/clusters/' + cluster
|
|
|
|
|
|
def ProjectLocationClusterNodePool(project, location, cluster, nodepool):
|
|
return (
|
|
ProjectLocationCluster(project, location, cluster)
|
|
+ '/nodePools/'
|
|
+ nodepool
|
|
)
|
|
|
|
|
|
def ProjectLocationOperation(project, location, operation):
|
|
return ProjectLocation(project, location) + '/operations/' + operation
|
|
|
|
|
|
def ProjectLocationSubnetwork(project, region, subnetwork):
|
|
return (
|
|
'projects/'
|
|
+ project
|
|
+ '/regions/'
|
|
+ region
|
|
+ '/subnetworks/'
|
|
+ subnetwork
|
|
)
|
|
|
|
|
|
def SubnetworkNameToPath(subnetwork, project, location):
|
|
"""Converts a subnetwork name to a subnetwork path."""
|
|
match = re.match(SUBNETWORK_URL_PATTERN + '$', subnetwork)
|
|
if match:
|
|
subnetwork = match[1]
|
|
parts = subnetwork.split('/')
|
|
if (
|
|
len(parts) == 6
|
|
and parts[0] == 'projects'
|
|
and parts[2] == 'regions'
|
|
and parts[4] == 'subnetworks'
|
|
):
|
|
return subnetwork
|
|
if re.match(ZONE_PATTERN, location):
|
|
location = location[: location.rfind('-')]
|
|
return ProjectLocationSubnetwork(project, location, subnetwork)
|
|
|
|
|
|
def TpuTopologyToNumNodes(tpu_topology, machine_type):
|
|
"""Calculates the number of nodes needed for a given TPU topology and machine type."""
|
|
match = re.fullmatch(TPU_TOPOLOGY_PATTERN, tpu_topology)
|
|
if not match:
|
|
raise util.Error(
|
|
TPU_TOPOLOGY_INCORRECT_FORMAT_ERROR_MSG.format(topology=tpu_topology)
|
|
)
|
|
|
|
result = functools.reduce(operator.mul, map(int, tpu_topology.split('x')))
|
|
|
|
chips_match = re.search(r'(\d+)t$', machine_type)
|
|
if not chips_match:
|
|
raise util.Error(
|
|
MACHINE_TYPE_INCORRECT_FORMAT_ERROR_MSG.format(
|
|
machine_type=machine_type
|
|
)
|
|
)
|
|
num_chips_per_vm = int(chips_match.group(1))
|
|
|
|
return result // num_chips_per_vm
|
|
|
|
|
|
def NormalizeBinauthzMode(mode):
|
|
"""Converts an evaluation or enforcement mode to lowercase format.
|
|
|
|
e.g. Converts 'PROJECT_SINGLETON_POLICY_ENFORCE' to
|
|
'project-singleton-policy-enforce'
|
|
|
|
Args:
|
|
mode: An evaluation or enforcement mode.
|
|
|
|
Returns:
|
|
The mode in lowercase form.
|
|
"""
|
|
return mode.replace('_', '-').lower()
|
|
|
|
|
|
def GetBinauthzEvaluationModeOptions(messages, release_track):
|
|
"""Returns all valid options for --binauthz-evaluation-mode."""
|
|
# Only expose DISABLED AND PROJECT_SINGLETON_POLICY_ENFORCE evaluation modes
|
|
# in the GA track.
|
|
if release_track == base.ReleaseTrack.GA:
|
|
return ['DISABLED', 'PROJECT_SINGLETON_POLICY_ENFORCE']
|
|
options = list(
|
|
messages.BinaryAuthorization.EvaluationModeValueValuesEnum.to_dict()
|
|
)
|
|
options.remove('EVALUATION_MODE_UNSPECIFIED')
|
|
return sorted(options)
|
|
|
|
|
|
def BinauthzEvaluationModeRequiresPolicy(messages, evaluation_mode):
|
|
evaluation_mode_enum = (
|
|
messages.BinaryAuthorization.EvaluationModeValueValuesEnum
|
|
)
|
|
if evaluation_mode in (
|
|
evaluation_mode_enum.EVALUATION_MODE_UNSPECIFIED,
|
|
evaluation_mode_enum.DISABLED,
|
|
evaluation_mode_enum.PROJECT_SINGLETON_POLICY_ENFORCE,
|
|
):
|
|
return False
|
|
return True
|
|
|
|
|
|
def GetBinauthzEnforcementModeOptions(messages):
|
|
"""Returns all valid options for the enforcement-mode dict key."""
|
|
options = list(
|
|
messages.PolicyBinding.EnforcementModeValueValuesEnum.to_dict()
|
|
)
|
|
options.remove('ENFORCEMENT_MODE_UNSPECIFIED')
|
|
return sorted(options)
|
|
|
|
|
|
def VariantConfigEnumFromString(messages, variant):
|
|
"""Converts a logging variant string to an enum value.
|
|
|
|
Args:
|
|
messages: The API messages module.
|
|
variant: The logging variant string.
|
|
|
|
Returns:
|
|
The logging variant enum value.
|
|
"""
|
|
variant_config_enum = (
|
|
messages.LoggingVariantConfig.VariantValueValuesEnum.VARIANT_UNSPECIFIED
|
|
)
|
|
if variant == 'DEFAULT':
|
|
variant_config_enum = (
|
|
messages.LoggingVariantConfig.VariantValueValuesEnum.DEFAULT
|
|
)
|
|
elif variant == 'MAX_THROUGHPUT':
|
|
variant_config_enum = (
|
|
messages.LoggingVariantConfig.VariantValueValuesEnum.MAX_THROUGHPUT
|
|
)
|
|
return variant_config_enum
|
|
|
|
|
|
def _GetAnonymousAuthenticationConfig(options, messages):
|
|
"""Configures the AnonymousAuthenticationConfig from options."""
|
|
config = messages.AnonymousAuthenticationConfig()
|
|
if options.anonymous_authentication_config is not None:
|
|
modes = {
|
|
'LIMITED': (
|
|
messages.AnonymousAuthenticationConfig.ModeValueValuesEnum.LIMITED
|
|
),
|
|
'ENABLED': (
|
|
messages.AnonymousAuthenticationConfig.ModeValueValuesEnum.ENABLED
|
|
),
|
|
}
|
|
if options.anonymous_authentication_config not in modes:
|
|
raise util.Error(
|
|
ANONYMOUS_AUTHENTICATION_MODE_NOT_SUPPORTED.format(
|
|
mode=options.anonymous_authentication_config
|
|
)
|
|
)
|
|
config.mode = modes[options.anonymous_authentication_config]
|
|
return config
|
|
|
|
|
|
def _GetFleetMembershipType(options, messages, fleet):
|
|
"""Configures the Fleet MembershipType from options and fleet."""
|
|
if options.membership_type is not None:
|
|
types = {
|
|
'LIGHTWEIGHT': messages.Fleet.MembershipTypeValueValuesEnum.LIGHTWEIGHT,
|
|
'MEMBERSHIP_TYPE_UNSPECIFIED': (
|
|
messages.Fleet.MembershipTypeValueValuesEnum.MEMBERSHIP_TYPE_UNSPECIFIED
|
|
),
|
|
}
|
|
if options.membership_type not in types:
|
|
raise util.Error(
|
|
MEMBERSHIP_TYPE_NOT_SUPPORTED.format(type=options.membership_type)
|
|
)
|
|
fleet.membershipType = types[options.membership_type]
|
|
return fleet
|
|
|
|
|
|
def _GetEnterpriseConfig(options, messages):
|
|
"""Gets the EnterpriseConfig from options."""
|
|
enterprise_config = messages.EnterpriseConfig()
|
|
if options.tier is not None:
|
|
tiers = {
|
|
'standard': (
|
|
messages.EnterpriseConfig.DesiredTierValueValuesEnum.STANDARD
|
|
),
|
|
'enterprise': (
|
|
messages.EnterpriseConfig.DesiredTierValueValuesEnum.ENTERPRISE
|
|
),
|
|
}
|
|
if options.tier not in tiers:
|
|
raise util.Error(CLUSTER_TIER_NOT_SUPPORTED.format(tier=options.tier))
|
|
enterprise_config.desiredTier = tiers[options.tier]
|
|
return enterprise_config
|
|
|
|
|
|
def _GetDesiredEnterpriseConfig(options, messages):
|
|
"""Gets the DesiredEnterpriseConfig from options."""
|
|
desired_enterprise_config = messages.DesiredEnterpriseConfig()
|
|
if options.tier is not None:
|
|
tiers = {
|
|
'standard': (
|
|
messages.DesiredEnterpriseConfig.DesiredTierValueValuesEnum.STANDARD
|
|
),
|
|
'enterprise': (
|
|
messages.DesiredEnterpriseConfig.DesiredTierValueValuesEnum.ENTERPRISE
|
|
),
|
|
}
|
|
if options.tier not in tiers:
|
|
raise util.Error(CLUSTER_TIER_NOT_SUPPORTED.format(tier=options.tier))
|
|
desired_enterprise_config.desiredTier = tiers[options.tier]
|
|
return desired_enterprise_config
|
|
|
|
|
|
def _ConfidentialNodeTypeEnumFromString(options, messages, for_node_pool=False):
|
|
"""Converts a confidential node type string to an enum value."""
|
|
if options.confidential_node_type.lower() == 'sev':
|
|
return (
|
|
messages.ConfidentialNodes.ConfidentialInstanceTypeValueValuesEnum.SEV
|
|
)
|
|
elif options.confidential_node_type.lower() == 'sev_snp':
|
|
return (
|
|
messages.ConfidentialNodes.ConfidentialInstanceTypeValueValuesEnum.SEV_SNP
|
|
)
|
|
elif options.confidential_node_type.lower() == 'tdx':
|
|
return (
|
|
messages.ConfidentialNodes.ConfidentialInstanceTypeValueValuesEnum.TDX
|
|
)
|
|
elif options.confidential_node_type.lower() == 'disabled':
|
|
return (
|
|
messages.ConfidentialNodes.ConfidentialInstanceTypeValueValuesEnum.CONFIDENTIAL_INSTANCE_TYPE_UNSPECIFIED
|
|
)
|
|
else:
|
|
choices = ['sev', 'sev_snp', 'tdx']
|
|
if for_node_pool:
|
|
choices.append('disabled')
|
|
raise util.Error(
|
|
CONFIDENTIAL_NODE_TYPE_NOT_SUPPORTED.format(
|
|
type=options.confidential_node_type.lower(), choices=choices
|
|
)
|
|
)
|
|
|
|
|
|
def _GetNetworkTierConfig(options, messages):
|
|
"""Gets the NetworkTierConfig from options."""
|
|
network_tier_config = messages.NetworkTierConfig()
|
|
if options.network_tier is not None:
|
|
network_tiers = {
|
|
'standard': (
|
|
messages.NetworkTierConfig.NetworkTierValueValuesEnum.NETWORK_TIER_STANDARD
|
|
),
|
|
'premium': (
|
|
messages.NetworkTierConfig.NetworkTierValueValuesEnum.NETWORK_TIER_PREMIUM
|
|
),
|
|
'network-default': (
|
|
messages.NetworkTierConfig.NetworkTierValueValuesEnum.NETWORK_TIER_DEFAULT
|
|
),
|
|
}
|
|
if options.network_tier not in network_tiers:
|
|
raise util.Error(
|
|
NETWORK_TIER_NOT_SUPPORTED.format(network_tier=options.network_tier)
|
|
)
|
|
network_tier_config.networkTier = network_tiers[options.network_tier]
|
|
return network_tier_config
|
|
|
|
|
|
def _GetControlPlaneEgress(options, messages):
|
|
"""Gets the ControlPlaneEgress from options."""
|
|
control_plane_egress = messages.ControlPlaneEgress()
|
|
if options.control_plane_egress_mode is not None:
|
|
control_plane_egress_modes = {
|
|
'NONE': messages.ControlPlaneEgress.ModeValueValuesEnum.NONE,
|
|
'VIA_CONTROL_PLANE': (
|
|
messages.ControlPlaneEgress.ModeValueValuesEnum.VIA_CONTROL_PLANE
|
|
),
|
|
}
|
|
if options.control_plane_egress_mode not in control_plane_egress_modes:
|
|
raise util.Error(
|
|
CONTROL_PLANE_EGRESS_NOT_SUPPORTED.format(
|
|
control_plane_egress_mode=options.control_plane_egress_mode
|
|
)
|
|
)
|
|
control_plane_egress.mode = control_plane_egress_modes[
|
|
options.control_plane_egress_mode
|
|
]
|
|
return control_plane_egress
|
|
|
|
|
|
def _GetAutopilotGeneralProfileEnum(options, messages):
|
|
"""Converts the user-provided autopilot-general-profile to the API enum.
|
|
|
|
Args:
|
|
options: Either CreateClusterOptions or UpdateClusterOptions.
|
|
messages: The API messages module.
|
|
|
|
Returns:
|
|
The ClusterAutoscaling.AutopilotGeneralProfileValueValuesEnum value or None.
|
|
Raises:
|
|
util.Error: if an invalid profile is provided.
|
|
"""
|
|
if options.autopilot_general_profile is None:
|
|
return None
|
|
|
|
profile_map = {
|
|
'none': (
|
|
messages.ClusterAutoscaling.AutopilotGeneralProfileValueValuesEnum.AUTOPILOT_GENERAL_PROFILE_UNSPECIFIED
|
|
),
|
|
'no-performance': (
|
|
messages.ClusterAutoscaling.AutopilotGeneralProfileValueValuesEnum.NO_PERFORMANCE
|
|
),
|
|
}
|
|
user_input = options.autopilot_general_profile.lower()
|
|
if user_input in profile_map:
|
|
return profile_map[user_input]
|
|
else:
|
|
# This case should be prevented by the YAML's enum validation,
|
|
# but serves as a safeguard.
|
|
raise util.Error(
|
|
AUTOPILOT_GENERAL_PROFILE_NOT_SUPPORTED.format(
|
|
profile=user_input, choices=list(profile_map.keys())
|
|
)
|
|
)
|