Skip to content

Commit

Permalink
aks-preview: feature support for apiserver vnet integration (#4787)
Browse files Browse the repository at this point in the history
  • Loading branch information
levimm authored May 12, 2022
1 parent c8dedfa commit 4358498
Show file tree
Hide file tree
Showing 11 changed files with 1,382 additions and 4 deletions.
6 changes: 4 additions & 2 deletions src/aks-preview/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ To release a new version, please select a new version number (usually plus 1 to

Pending
+++++++
* Update to use 2022-04-02-preview api version.

0.5.67 (NOT RELEASED)

0.5.67
+++++++++++++++++++++
* Add support for csi drivers extensibility.
* Update to use 2022-04-02-preview api version.
* Add support for apiserver vnet integration.

0.5.66
++++++
Expand Down
12 changes: 12 additions & 0 deletions src/aks-preview/azext_aks_preview/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,12 @@
- name: --attach-acr
type: string
short-summary: Grant the 'acrpull' role assignment to the ACR specified by name or resource ID.
- name: --enable-apiserver-vnet-integration
type: bool
short-summary: Enable integration of user vnet with control plane apiserver pods.
- name: --apiserver-subnet-id
type: string
short-summary: The ID of a subnet in an existing VNet into which to assign control plane apiserver pods(requires --enable-apiserver-vnet-integration)
- name: --enable-private-cluster
type: string
short-summary: Enable private cluster.
Expand Down Expand Up @@ -737,6 +743,12 @@
- name: --azure-keyvault-kms-key-id
type: string
short-summary: Identifier of Azure Key Vault key.
- name: --enable-apiserver-vnet-integration
type: bool
short-summary: Enable integration of user vnet with control plane apiserver pods.
- name: --apiserver-subnet-id
type: string
short-summary: The ID of a subnet in an existing VNet into which to assign control plane apiserver pods(requires --enable-apiserver-vnet-integration)
examples:
- name: Reconcile the cluster back to its current state.
text: az aks update -g MyResourceGroup -n MyManagedCluster
Expand Down
5 changes: 5 additions & 0 deletions src/aks-preview/azext_aks_preview/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
validate_acr,
validate_addon,
validate_addons,
validate_apiserver_subnet_id,
validate_assign_identity,
validate_assign_kubelet_identity,
validate_azure_keyvault_kms_key_id,
Expand Down Expand Up @@ -293,6 +294,8 @@ def load_arguments(self, _):
c.argument('message_of_the_day')
c.argument('gpu_instance_profile', arg_type=get_enum_type(gpu_instance_profiles))
c.argument('workload_runtime', arg_type=get_enum_type(workload_runtimes), default=CONST_WORKLOAD_RUNTIME_OCI_CONTAINER)
c.argument('enable_apiserver_vnet_integration', action='store_true', is_preview=True)
c.argument('apiserver_subnet_id', validator=validate_apiserver_subnet_id, is_preview=True)

with self.argument_context('aks update') as c:
# managed cluster paramerters
Expand Down Expand Up @@ -365,6 +368,8 @@ def load_arguments(self, _):
c.argument('enable_oidc_issuer', action='store_true', is_preview=True)
c.argument('enable_azure_keyvault_kms', action='store_true', is_preview=True)
c.argument('azure_keyvault_kms_key_id', validator=validate_azure_keyvault_kms_key_id, is_preview=True)
c.argument('enable_apiserver_vnet_integration', action='store_true', is_preview=True)
c.argument('apiserver_subnet_id', validator=validate_apiserver_subnet_id, is_preview=True)

with self.argument_context('aks scale') as c:
c.argument('nodepool_name',
Expand Down
4 changes: 4 additions & 0 deletions src/aks-preview/azext_aks_preview/_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ def validate_pod_subnet_id(namespace):
_validate_subnet_id(namespace.pod_subnet_id, "--pod-subnet-id")


def validate_apiserver_subnet_id(namespace):
_validate_subnet_id(namespace.apiserver_subnet_id, "--apiserver-subnet-id")


def _validate_subnet_id(subnet_id, name):
if subnet_id is None or subnet_id == '':
return
Expand Down
6 changes: 5 additions & 1 deletion src/aks-preview/azext_aks_preview/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,8 @@ def aks_create(cmd,
message_of_the_day=None,
enable_azure_keyvault_kms=False,
azure_keyvault_kms_key_id=None,
enable_apiserver_vnet_integration=False,
apiserver_subnet_id=None,
yes=False):
# DO NOT MOVE: get all the original parameters and save them as a dictionary
raw_parameters = locals()
Expand Down Expand Up @@ -890,7 +892,9 @@ def aks_update(cmd, # pylint: disable=too-many-statements,too-many-branches,
enable_oidc_issuer=False,
http_proxy_config=None,
enable_azure_keyvault_kms=False,
azure_keyvault_kms_key_id=None):
azure_keyvault_kms_key_id=None,
enable_apiserver_vnet_integration=False,
apiserver_subnet_id=None):
# DO NOT MOVE: get all the original parameters and save them as a dictionary
raw_parameters = locals()

Expand Down
138 changes: 138 additions & 0 deletions src/aks-preview/azext_aks_preview/decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
ManagedClusterStorageProfileDiskCSIDriver = TypeVar('ManagedClusterStorageProfileDiskCSIDriver')
ManagedClusterStorageProfileFileCSIDriver = TypeVar('ManagedClusterStorageProfileFileCSIDriver')
ManagedClusterStorageProfileSnapshotController = TypeVar('ManagedClusterStorageProfileSnapshotController')
ManagedClusterAPIServerAccessProfile = TypeVar('ManagedClusterAPIServerAccessProfile')
Snapshot = TypeVar("Snapshot")
ManagedClusterSnapshot = TypeVar("ManagedClusterSnapshot")
AzureKeyVaultKms = TypeVar('AzureKeyVaultKms')
Expand Down Expand Up @@ -166,6 +167,11 @@ def __init__(self, cmd: AzCommandsLoader, resource_type: ResourceType):
resource_type=self.resource_type,
operation_group="managed_clusters",
)
self.ManagedClusterAPIServerAccessProfile = self.__cmd.get_models(
"ManagedClusterAPIServerAccessProfile",
resource_type=self.resource_type,
operation_group="managed_clusters",
)
# holder for nat gateway related models
self.__nat_gateway_models = None
# holder for pod identity related models
Expand Down Expand Up @@ -1964,6 +1970,110 @@ def get_cluster_uaidentity_object_id(self) -> str:
cluster_identity_resource_id = assigned_identity
return self.get_identity_by_msi_client(cluster_identity_resource_id).principal_id

def _get_enable_apiserver_vnet_integration(self, enable_validation: bool = False) -> bool:
"""Internal function to obtain the value of enable_apiserver_vnet_integration.
This function supports the option of enable_validation. When enable_apiserver_vnet_integration is specified,
For CREATE: if enable-private-cluster is not used, raise an RequiredArgumentMissingError;
For UPDATE: if apiserver-subnet-id is not used, raise an RequiredArgumentMissingError;
:return: bool
"""
# read the original value passed by the command
enable_apiserver_vnet_integration = self.raw_param.get("enable_apiserver_vnet_integration")
# 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.api_server_access_profile and
self.mc.api_server_access_profile.enable_vnet_integration is not None
):
enable_apiserver_vnet_integration = self.mc.api_server_access_profile.enable_vnet_integration

# this parameter does not need dynamic completion
# validation
if enable_validation:
if self.decorator_mode == DecoratorMode.CREATE:
if enable_apiserver_vnet_integration:
# remove this validation after we support public cluster
if not self._get_enable_private_cluster(enable_validation=False):
raise RequiredArgumentMissingError(
"--apiserver-vnet-integration is only supported for private cluster right now. "
"Please use it together with --enable-private-cluster"
)
if self.decorator_mode == DecoratorMode.UPDATE:
if enable_apiserver_vnet_integration:
if self._get_apiserver_subnet_id(enable_validation=False) is None:
raise RequiredArgumentMissingError(
"--apiserver-subnet-id is required for update with --apiserver-vnet-integration."
)

return enable_apiserver_vnet_integration

def get_enable_apiserver_vnet_integration(self) -> bool:
"""Obtain the value of enable_apiserver_vnet_integration.
This function will verify the parameter by default. When enable_apiserver_vnet_integration is specified,
For CREATE: if enable-private-cluster is not used, raise an RequiredArgumentMissingError;
For UPDATE: if apiserver-subnet-id is not used, raise an RequiredArgumentMissingError
:return: bool
"""
return self._get_enable_apiserver_vnet_integration(enable_validation=True)

def _get_apiserver_subnet_id(self, enable_validation: bool = False) -> Union[str, None]:
"""Internal function to obtain the value of apiserver_subnet_id.
This function supports the option of enable_validation. When apiserver_subnet_id is specified,
if enable_apiserver_vnet_integration is not used, raise an RequiredArgumentMissingError;
For CREATE: if vnet_subnet_id is not used, raise an RequiredArgumentMissingError;
:return: bool
"""
# read the original value passed by the command
apiserver_subnet_id = self.raw_param.get("apiserver_subnet_id")
# 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.api_server_access_profile and
self.mc.api_server_access_profile.subnet_id is not None
):
apiserver_subnet_id = self.mc.api_server_access_profile.subnet_id

# this parameter does not need dynamic completion
# validation
if enable_validation:
if self.decorator_mode == DecoratorMode.CREATE:
vnet_subnet_id = self.get_vnet_subnet_id()
if apiserver_subnet_id and vnet_subnet_id is None:
raise RequiredArgumentMissingError(
'"--apiserver-subnet-id" requires "--vnet-subnet-id".')

enable_apiserver_vnet_integration = self._get_enable_apiserver_vnet_integration(
enable_validation=False)
if (
apiserver_subnet_id and
(
enable_apiserver_vnet_integration is None or
enable_apiserver_vnet_integration is False
)
):
raise RequiredArgumentMissingError(
'"--apiserver-subnet-id" requires "--enable-apiserver-vnet-integration".')

return apiserver_subnet_id

def get_apiserver_subnet_id(self) -> Union[str, None]:
"""Obtain the value of apiserver_subnet_id.
This function will verify the parameter by default. When apiserver_subnet_id is specified,
if enable_apiserver_vnet_integration is not specified, raise an RequiredArgumentMissingError;
:return: bool
"""
return self._get_apiserver_subnet_id(enable_validation=True)


class AKSPreviewCreateDecorator(AKSCreateDecorator):
# pylint: disable=super-init-not-called
Expand Down Expand Up @@ -2346,6 +2456,19 @@ def set_up_azure_keyvault_kms(self, mc: ManagedCluster) -> ManagedCluster:

return mc

def set_up_api_server_access_profile(self, mc: ManagedCluster) -> ManagedCluster:
"""Set up apiserverAccessProfile enableVnetIntegration and subnetId for the ManagedCluster object.
:return: the ManagedCluster object
"""
mc = super().set_up_api_server_access_profile(mc)
if self.context.get_enable_apiserver_vnet_integration():
mc.api_server_access_profile.enable_vnet_integration = True
if self.context.get_apiserver_subnet_id():
mc.api_server_access_profile.subnet_id = self.context.get_apiserver_subnet_id()

return mc

def construct_mc_preview_profile(self) -> ManagedCluster:
"""The overall controller used to construct the preview ManagedCluster profile.
Expand Down Expand Up @@ -2752,6 +2875,21 @@ def update_identity_profile(self, mc: ManagedCluster) -> ManagedCluster:
mc.identity_profile = identity_profile
return mc

def update_api_server_access_profile(self, mc: ManagedCluster) -> ManagedCluster:
"""Update apiServerAccessProfile vnet integration related property for the ManagedCluster object.
:return: the ManagedCluster object
"""
mc = super().update_api_server_access_profile(mc)
if self.context.get_enable_apiserver_vnet_integration():
if mc.api_server_access_profile is None:
mc.api_server_access_profile = self.models.ManagedClusterAPIServerAccessProfile()
mc.api_server_access_profile.enable_vnet_integration = True
if self.context.get_apiserver_subnet_id():
mc.api_server_access_profile.subnet_id = self.context.get_apiserver_subnet_id()

return mc

def patch_mc(self, mc: ManagedCluster) -> ManagedCluster:
"""Helper function to patch the ManagedCluster object.
Expand Down
Loading

0 comments on commit 4358498

Please sign in to comment.