diff --git a/src/aks-preview/azext_aks_preview/_help.py b/src/aks-preview/azext_aks_preview/_help.py index 0588cc1c269..da70b764632 100644 --- a/src/aks-preview/azext_aks_preview/_help.py +++ b/src/aks-preview/azext_aks_preview/_help.py @@ -641,6 +641,9 @@ - name: --vm-sizes type: string short-summary: Comma-separated list of sizes. Must use VirtualMachines agent pool type. + - name: --encoded-custom-configuration + type: string + short-summary: Path to JSON file containing custom configuration for the cluster. examples: - name: Create a Kubernetes cluster with an existing SSH public key. text: az aks create -g MyResourceGroup -n MyManagedCluster --ssh-key-value /path/to/publickey diff --git a/src/aks-preview/azext_aks_preview/_params.py b/src/aks-preview/azext_aks_preview/_params.py index c6f1ed9efae..8a654a477af 100644 --- a/src/aks-preview/azext_aks_preview/_params.py +++ b/src/aks-preview/azext_aks_preview/_params.py @@ -967,6 +967,7 @@ def load_arguments(self, _): # virtual machines c.argument("vm_sizes", is_preview=True) c.argument("enable_imds_restriction", action="store_true", is_preview=True) + c.argument("encoded_custom_configuration", is_preview=True) with self.argument_context("aks update") as c: # managed cluster paramerters diff --git a/src/aks-preview/azext_aks_preview/custom.py b/src/aks-preview/azext_aks_preview/custom.py index eafe732c511..eafef46a62e 100644 --- a/src/aks-preview/azext_aks_preview/custom.py +++ b/src/aks-preview/azext_aks_preview/custom.py @@ -544,6 +544,8 @@ def aks_create( vm_sizes=None, # IMDS restriction enable_imds_restriction=False, + # Encoded Custom Configuration + encoded_custom_configuration=None, ): # DO NOT MOVE: get all the original parameters and save them as a dictionary raw_parameters = locals() diff --git a/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py b/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py index 86d6031cc31..f08ba413097 100644 --- a/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py +++ b/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py @@ -7,6 +7,7 @@ import copy import datetime import os +import base64 from types import SimpleNamespace from typing import Any, Dict, List, Optional, Tuple, TypeVar, Union @@ -2805,6 +2806,24 @@ def get_disable_imds_restriction(self) -> bool: """ return self.raw_param.get("disable_imds_restriction") + def get_encoded_custom_configuration(self) -> bytes: + """Obtain the value of encoded_custom_configuration and encode it to base64. + + :return: str + """ + encoded_custom_configuration_file_path = self.raw_param.get("encoded_custom_configuration") + logger.debug("Custom configuration file path: ", encoded_custom_configuration_file_path) + if encoded_custom_configuration_file_path: + if not os.path.isfile(encoded_custom_configuration_file_path): + raise InvalidArgumentValueError( + f"{encoded_custom_configuration_file_path} is not valid file, or not accessable." + ) + with open(encoded_custom_configuration_file_path, "rb") as file: + file_content = file.read() + encoded_custom_configuration = base64.b64encode(file_content).decode("utf-8") + + logger.debug("Encoded custom configuration file content: ", encoded_custom_configuration) + return encoded_custom_configuration # pylint: disable=too-many-public-methods class AKSPreviewManagedClusterCreateDecorator(AKSManagedClusterCreateDecorator): @@ -3535,6 +3554,19 @@ def set_up_imds_restriction(self, mc: ManagedCluster) -> ManagedCluster: mc.network_profile.pod_link_local_access = CONST_IMDS_RESTRICTION_ENABLED return mc + def set_up_encoded_custom_configuration(self, mc: ManagedCluster) -> ManagedCluster: + """Set up custom configuration for the ManagedCluster object. + + :return: the ManagedCluster object + """ + self._ensure_mc(mc) + + encoded_custom_configuration = self.context.get_encoded_custom_configuration() + if encoded_custom_configuration: + mc.encoded_custom_configuration = encoded_custom_configuration + + return mc + # pylint: disable=unused-argument def construct_mc_profile_preview(self, bypass_restore_defaults: bool = False) -> ManagedCluster: """The overall controller used to construct the default ManagedCluster profile. @@ -3597,6 +3629,8 @@ def construct_mc_profile_preview(self, bypass_restore_defaults: bool = False) -> mc = self.set_up_static_egress_gateway(mc) # set up imds restriction(a property in network profile) mc = self.set_up_imds_restriction(mc) + # set up encoded custom configuration + mc = self.set_up_encoded_custom_configuration(mc) # validate the azure cli core version self.verify_cli_core_version() diff --git a/src/aks-preview/azext_aks_preview/vendored_sdks/azure_mgmt_preview_aks/v2025_01_02_preview/models/_models_py3.py b/src/aks-preview/azext_aks_preview/vendored_sdks/azure_mgmt_preview_aks/v2025_01_02_preview/models/_models_py3.py index 91613ec20c6..dc8e2467758 100644 --- a/src/aks-preview/azext_aks_preview/vendored_sdks/azure_mgmt_preview_aks/v2025_01_02_preview/models/_models_py3.py +++ b/src/aks-preview/azext_aks_preview/vendored_sdks/azure_mgmt_preview_aks/v2025_01_02_preview/models/_models_py3.py @@ -4165,6 +4165,8 @@ class ManagedCluster(TrackedResource): ~azure.mgmt.containerservice.v2025_01_02_preview.models.ManagedClusterBootstrapProfile :ivar status: Contains read-only information about the Managed Cluster. :vartype status: ~azure.mgmt.containerservice.v2025_01_02_preview.models.ManagedClusterStatus + :ivar encoded_custom_configuration: Encoded custom configuration. + :vartype encoded_custom_configuration: str """ _validation = { @@ -4266,6 +4268,10 @@ class ManagedCluster(TrackedResource): }, "bootstrap_profile": {"key": "properties.bootstrapProfile", "type": "ManagedClusterBootstrapProfile"}, "status": {"key": "properties.status", "type": "ManagedClusterStatus"}, + "encoded_custom_configuration": { + "key": "properties.encodedCustomConfiguration", + "type": "str", + }, } def __init__( # pylint: disable=too-many-locals @@ -4318,6 +4324,7 @@ def __init__( # pylint: disable=too-many-locals node_provisioning_profile: Optional["_models.ManagedClusterNodeProvisioningProfile"] = None, bootstrap_profile: Optional["_models.ManagedClusterBootstrapProfile"] = None, status: Optional["_models.ManagedClusterStatus"] = None, + encoded_custom_configuration: Optional[str] = None, **kwargs: Any ) -> None: """ @@ -4472,6 +4479,8 @@ def __init__( # pylint: disable=too-many-locals ~azure.mgmt.containerservice.v2025_01_02_preview.models.ManagedClusterBootstrapProfile :keyword status: Contains read-only information about the Managed Cluster. :paramtype status: ~azure.mgmt.containerservice.v2025_01_02_preview.models.ManagedClusterStatus + :keyword encoded_custom_configuration: Encoded custom configuration. + :paramtype encoded_custom_configuration: str """ super().__init__(tags=tags, location=location, **kwargs) self.e_tag: Optional[str] = None @@ -4528,6 +4537,7 @@ def __init__( # pylint: disable=too-many-locals self.node_provisioning_profile = node_provisioning_profile self.bootstrap_profile = bootstrap_profile self.status = status + self.encoded_custom_configuration = encoded_custom_configuration class ManagedClusterAADProfile(_serialization.Model): diff --git a/src/aks-preview/linter_exclusions.yml b/src/aks-preview/linter_exclusions.yml index 6beb62be69d..f32738deb26 100644 --- a/src/aks-preview/linter_exclusions.yml +++ b/src/aks-preview/linter_exclusions.yml @@ -93,6 +93,9 @@ aks create: disable_acns_observability: rule_exclusions: - option_length_too_long + encoded_custom_configuration: + rule_exclusions: + - option_length_too_long aks update: parameters: enable_pod_identity_with_kubenet: