Skip to content

Commit

Permalink
{AKS} Update v2 managed cluster decorator - part 2 (#4982)
Browse files Browse the repository at this point in the history
  • Loading branch information
FumingZhang authored Jun 14, 2022
1 parent 0bf987a commit fc460d0
Show file tree
Hide file tree
Showing 4 changed files with 1,063 additions and 225 deletions.
230 changes: 163 additions & 67 deletions src/aks-preview/azext_aks_preview/managed_cluster_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
)
from azure.cli.command_modules.acs._helpers import (
check_is_msi_cluster,
safe_list_get,
format_parameter_name_to_option_name,
safe_lower,
)
from azure.cli.command_modules.acs._validators import extract_comma_separated_string
from azure.cli.command_modules.acs._validators import (
extract_comma_separated_string,
)
from azure.cli.command_modules.acs.managed_cluster_decorator import (
AKSManagedClusterContext,
AKSManagedClusterCreateDecorator,
Expand All @@ -26,6 +28,7 @@
)
from azure.cli.core import AzCommandsLoader
from azure.cli.core.azclierror import (
ArgumentUsageError,
InvalidArgumentValueError,
MutuallyExclusiveArgumentError,
RequiredArgumentMissingError,
Expand All @@ -39,7 +42,9 @@

from azext_aks_preview._helpers import get_cluster_snapshot_by_snapshot_id
from azext_aks_preview._loadbalancer import create_load_balancer_profile
from azext_aks_preview._loadbalancer import update_load_balancer_profile as _update_load_balancer_profile
from azext_aks_preview._loadbalancer import (
update_load_balancer_profile as _update_load_balancer_profile,
)
from azext_aks_preview._podidentity import (
_fill_defaults_for_pod_identity_profile,
_is_pod_identity_addon_enabled,
Expand Down Expand Up @@ -816,13 +821,15 @@ def get_kubernetes_version(self) -> str:
return self._get_kubernetes_version(read_only=False)

def get_disk_driver(self) -> Optional[ManagedClusterStorageProfileDiskCSIDriver]:
"""Obtrain the value of storage_profile.disk_csi_driver
"""Obtain the value of storage_profile.disk_csi_driver
:return: Optional[ManagedClusterStorageProfileDiskCSIDriver]
"""
enable_disk_driver = self.raw_param.get("enable_disk_driver")
disable_disk_driver = self.raw_param.get("disable_disk_driver")
if not enable_disk_driver and not disable_disk_driver:
disk_driver_version = self.raw_param.get("disk_driver_version")

if not enable_disk_driver and not disable_disk_driver and not disk_driver_version:
return None
profile = self.models.ManagedClusterStorageProfileDiskCSIDriver()

Expand All @@ -832,25 +839,45 @@ def get_disk_driver(self) -> Optional[ManagedClusterStorageProfileDiskCSIDriver]
"--disable-disk-driver at the same time."
)

if disable_disk_driver and disk_driver_version:
raise ArgumentUsageError(
"The parameter --disable-disk-driver cannot be used "
"when --disk-driver-version is specified.")

if self.decorator_mode == DecoratorMode.UPDATE and disk_driver_version and not enable_disk_driver:
raise ArgumentUsageError(
"Parameter --enable-disk-driver is required "
"when --disk-driver-version is specified during update.")

if self.decorator_mode == DecoratorMode.CREATE:
if disable_disk_driver:
profile.enabled = False
else:
profile.enabled = True
if disk_driver_version:
profile.version = disk_driver_version

if self.decorator_mode == DecoratorMode.UPDATE:
if enable_disk_driver:
profile.enabled = True
if disk_driver_version:
profile.version = disk_driver_version
elif disable_disk_driver:
msg = "Please make sure there are no existing PVs and PVCs that are used by AzureDisk CSI driver before disabling."
if not self.get_yes() and not prompt_y_n(msg, default="n"):
raise DecoratorEarlyExitException()
profile.enabled = False

return profile

def get_file_driver(self) -> Optional[ManagedClusterStorageProfileFileCSIDriver]:
"""Obtrain the value of storage_profile.file_csi_driver
"""Obtain the value of storage_profile.file_csi_driver
:return: Optional[ManagedClusterStorageProfileFileCSIDriver]
"""
enable_file_driver = self.raw_param.get("enable_file_driver")
disable_file_driver = self.raw_param.get("disable_file_driver")

if not enable_file_driver and not disable_file_driver:
return None
profile = self.models.ManagedClusterStorageProfileFileCSIDriver()
Expand All @@ -869,19 +896,24 @@ def get_file_driver(self) -> Optional[ManagedClusterStorageProfileFileCSIDriver]
if enable_file_driver:
profile.enabled = True
elif disable_file_driver:
msg = "Please make sure there are no existing PVs and PVCs that are used by AzureFile CSI driver before disabling."
if not self.get_yes() and not prompt_y_n(msg, default="n"):
raise DecoratorEarlyExitException()
profile.enabled = False

return profile

def get_snapshot_controller(self) -> Optional[ManagedClusterStorageProfileSnapshotController]:
"""Obtrain the value of storage_profile.snapshot_controller
"""Obtain the value of storage_profile.snapshot_controller
:return: Optional[ManagedClusterStorageProfileSnapshotController]
"""
enable_snapshot_controller = self.raw_param.get("enable_snapshot_controller")
disable_snapshot_controller = self.raw_param.get("disable_snapshot_controller")

if not enable_snapshot_controller and not disable_snapshot_controller:
return None

profile = self.models.ManagedClusterStorageProfileSnapshotController()

if enable_snapshot_controller and disable_snapshot_controller:
Expand All @@ -898,12 +930,16 @@ def get_snapshot_controller(self) -> Optional[ManagedClusterStorageProfileSnapsh
if enable_snapshot_controller:
profile.enabled = True
elif disable_snapshot_controller:
msg = "Please make sure there are no existing VolumeSnapshots, VolumeSnapshotClasses and VolumeSnapshotContents " \
"that are used by the snapshot controller before disabling."
if not self.get_yes() and not prompt_y_n(msg, default="n"):
raise DecoratorEarlyExitException()
profile.enabled = False

return profile

def get_storage_profile(self) -> Optional[ManagedClusterStorageProfile]:
"""Obtrain the value of storage_profile.
"""Obtain the value of storage_profile.
:return: Optional[ManagedClusterStorageProfile]
"""
Expand Down Expand Up @@ -1040,6 +1076,76 @@ def get_dns_zone_resource_id(self) -> Union[str, None]:
# this parameter does not need validation
return dns_zone_resource_id

def _get_enable_keda(self, enable_validation: bool = False) -> bool:
"""Internal function to obtain the value of enable_keda.
This function supports the option of enable_validation. When enabled, if both enable_keda and disable_keda are
specified, raise a MutuallyExclusiveArgumentError.
:return: bool
"""
# Read the original value passed by the command.
enable_keda = self.raw_param.get("enable_keda")

# In create mode, try to read the property value corresponding to the parameter from the `mc` object.
if self.decorator_mode == DecoratorMode.CREATE:
if (
self.mc and
self.mc.workload_auto_scaler_profile and
self.mc.workload_auto_scaler_profile.keda
):
enable_keda = self.mc.workload_auto_scaler_profile.keda.enabled

# This parameter does not need dynamic completion.
if enable_validation:
if enable_keda and self._get_disable_keda(enable_validation=False):
raise MutuallyExclusiveArgumentError(
"Cannot specify --enable-keda and --disable-keda at the same time."
)

return enable_keda

def get_enable_keda(self) -> bool:
"""Obtain the value of enable_keda.
This function will verify the parameter by default. If both enable_keda and disable_keda are specified, raise a
MutuallyExclusiveArgumentError.
:return: bool
"""
return self._get_enable_keda(enable_validation=True)

def _get_disable_keda(self, enable_validation: bool = False) -> bool:
"""Internal function to obtain the value of disable_keda.
This function supports the option of enable_validation. When enabled, if both enable_keda and disable_keda are
specified, raise a MutuallyExclusiveArgumentError.
:return: bool
"""
# Read the original value passed by the command.
disable_keda = self.raw_param.get("disable_keda")

# This option is not supported in create mode, hence we do not read the property value from the `mc` object.
# This parameter does not need dynamic completion.
if enable_validation:
if disable_keda and self._get_enable_keda(enable_validation=False):
raise MutuallyExclusiveArgumentError(
"Cannot specify --enable-keda and --disable-keda at the same time."
)

return disable_keda

def get_disable_keda(self) -> bool:
"""Obtain the value of disable_keda.
This function will verify the parameter by default. If both enable_keda and disable_keda are specified, raise a
MutuallyExclusiveArgumentError.
:return: bool
"""
return self._get_disable_keda(enable_validation=True)


class AKSPreviewManagedClusterCreateDecorator(AKSManagedClusterCreateDecorator):
def __init__(
Expand Down Expand Up @@ -1282,6 +1388,8 @@ def set_up_storage_profile(self, mc: ManagedCluster) -> ManagedCluster:
:return: the ManagedCluster object
"""
self._ensure_mc(mc)

mc.storage_profile = self.context.get_storage_profile()

return mc
Expand All @@ -1291,6 +1399,8 @@ def set_up_ingress_web_app_routing(self, mc: ManagedCluster) -> ManagedCluster:
:return: the ManagedCluster object
"""
self._ensure_mc(mc)

addons = self.context.get_enable_addons()
if "web_application_routing" in addons:
if mc.ingress_profile is None:
Expand All @@ -1302,6 +1412,20 @@ def set_up_ingress_web_app_routing(self, mc: ManagedCluster) -> ManagedCluster:
)
return mc

def set_up_workload_auto_scaler_profile(self, mc: ManagedCluster) -> ManagedCluster:
"""Set up workload auto-scaler profile for the ManagedCluster object.
:return: the ManagedCluster object
"""
self._ensure_mc(mc)

if self.context.get_enable_keda():
if mc.workload_auto_scaler_profile is None:
mc.workload_auto_scaler_profile = self.models.ManagedClusterWorkloadAutoScalerProfile()
mc.workload_auto_scaler_profile.keda = self.models.ManagedClusterWorkloadAutoScalerProfileKeda(enabled=True)

return mc

def construct_mc_profile_preview(self, bypass_restore_defaults: bool = False) -> ManagedCluster:
"""The overall controller used to construct the default ManagedCluster profile.
Expand Down Expand Up @@ -1336,6 +1460,8 @@ def construct_mc_profile_preview(self, bypass_restore_defaults: bool = False) ->
mc = self.set_up_storage_profile(mc)
# set up ingress web app routing profile
mc = self.set_up_ingress_web_app_routing(mc)
# set up workload auto scaler profile
mc = self.set_up_workload_auto_scaler_profile(mc)

# DO NOT MOVE: keep this at the bottom, restore defaults
mc = self._restore_defaults_in_mc(mc)
Expand Down Expand Up @@ -1407,66 +1533,15 @@ def check_raw_parameters(self):
reconcilePrompt = 'no argument specified to update would you like to reconcile to current settings?'
if not prompt_y_n(reconcilePrompt, default="n"):
# Note: Uncomment the followings to automatically generate the error message.
# option_names = [
# '"{}"'.format(format_parameter_name_to_option_name(x))
# for x in self.context.raw_param.keys()
# if x not in excluded_keys
# ]
# error_msg = "Please specify one or more of {}.".format(
# " or ".join(option_names)
# )
# raise RequiredArgumentMissingError(error_msg)
raise RequiredArgumentMissingError(
'Please specify "--enable-cluster-autoscaler" or '
'"--disable-cluster-autoscaler" or '
'"--update-cluster-autoscaler" or '
'"--cluster-autoscaler-profile" or '
'"--enable-pod-security-policy" or '
'"--disable-pod-security-policy" or '
'"--api-server-authorized-ip-ranges" or '
'"--attach-acr" or '
'"--detach-acr" or '
'"--uptime-sla" or '
'"--no-uptime-sla" or '
'"--load-balancer-managed-outbound-ip-count" or '
'"--load-balancer-outbound-ips" or '
'"--load-balancer-outbound-ip-prefixes" or '
'"--nat-gateway-managed-outbound-ip-count" or '
'"--nat-gateway-idle-timeout" or '
'"--enable-aad" or '
'"--aad-tenant-id" or '
'"--aad-admin-group-object-ids" or '
'"--enable-ahub" or '
'"--disable-ahub" or '
'"--enable-managed-identity" or '
'"--enable-pod-identity" or '
'"--disable-pod-identity" or '
'"--auto-upgrade-channel" or '
'"--enable-secret-rotation" or '
'"--disable-secret-rotation" or '
'"--rotation-poll-interval" or '
'"--tags" or '
'"--windows-admin-password" or '
'"--enable-azure-rbac" or '
'"--disable-azure-rbac" or '
'"--enable-local-accounts" or '
'"--disable-local-accounts" or '
'"--enable-public-fqdn" or '
'"--disable-public-fqdn"'
'"--enble-windows-gmsa" or '
'"--nodepool-labels" or '
'"--enable-oidc-issuer" or '
'"--http-proxy-config" or '
'"--enable-disk-driver" or '
'"--disable-disk-driver" or '
'"--enable-file-driver" or '
'"--disable-file-driver" or '
'"--enable-snapshot-controller" or '
'"--disable-snapshot-controller" or '
'"--enable-azure-keyvault-kms" or '
'"--enable-workload-identity" or '
'"--disable-workload-identity".'
option_names = [
'"{}"'.format(format_parameter_name_to_option_name(x))
for x in self.context.raw_param.keys()
if x not in excluded_keys
]
error_msg = "Please specify one or more of {}.".format(
" or ".join(option_names)
)
raise RequiredArgumentMissingError(error_msg)

def update_load_balancer_profile(self, mc: ManagedCluster) -> ManagedCluster:
"""Update load balancer profile for the ManagedCluster object.
Expand Down Expand Up @@ -1624,6 +1699,25 @@ def update_storage_profile(self, mc: ManagedCluster) -> ManagedCluster:

return mc

def update_workload_auto_scaler_profile(self, mc: ManagedCluster) -> ManagedCluster:
"""Update workload auto-scaler profile for the ManagedCluster object.
:return: the ManagedCluster object
"""
self._ensure_mc(mc)

if self.context.get_enable_keda():
if mc.workload_auto_scaler_profile is None:
mc.workload_auto_scaler_profile = self.models.ManagedClusterWorkloadAutoScalerProfile()
mc.workload_auto_scaler_profile.keda = self.models.ManagedClusterWorkloadAutoScalerProfileKeda(enabled=True)

if self.context.get_disable_keda():
if mc.workload_auto_scaler_profile is None:
mc.workload_auto_scaler_profile = self.models.ManagedClusterWorkloadAutoScalerProfile()
mc.workload_auto_scaler_profile.keda = self.models.ManagedClusterWorkloadAutoScalerProfileKeda(enabled=False)

return mc

def update_mc_profile_preview(self) -> ManagedCluster:
"""The overall controller used to update the preview ManagedCluster profile.
Expand Down Expand Up @@ -1653,5 +1747,7 @@ def update_mc_profile_preview(self) -> ManagedCluster:
mc = self.update_azure_keyvault_kms(mc)
# update stroage profile
mc = self.update_storage_profile(mc)
# update workload auto scaler profile
mc = self.update_workload_auto_scaler_profile(mc)

return mc
Loading

0 comments on commit fc460d0

Please sign in to comment.