Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e20cf35
draft
xmzhao0822 Apr 24, 2025
5bcf136
tested add namespace
xmzhao0822 Apr 25, 2025
77f787c
add namespace update code
xmzhao0822 Apr 25, 2025
6872269
tested ns update
xmzhao0822 Apr 25, 2025
2bf6d67
fix validate resource quota logic
xmzhao0822 Apr 25, 2025
c8ebaa2
add no wait
xmzhao0822 Apr 25, 2025
a748a3b
add ut and e2e for add and update
xmzhao0822 Apr 25, 2025
2854cac
ran test e2e for namespace add and update and passed
xmzhao0822 Apr 26, 2025
86690ec
add show
xmzhao0822 Apr 29, 2025
7962a92
add namespace list
xmzhao0822 Apr 29, 2025
8e16d6c
add managed namespace delete
xmzhao0822 Apr 29, 2025
de08a72
update delete in custom.py
xmzhao0822 Apr 30, 2025
eb65fd9
add namespace list format
xmzhao0822 Apr 30, 2025
eb66745
add namespace get-credential
xmzhao0822 Apr 30, 2025
c5277d3
update e2e and tested passed
xmzhao0822 Apr 30, 2025
7bad223
solve linter issue
xmzhao0822 Apr 30, 2025
64d7ff0
update ingress and egress flag name and update get credential without…
xmzhao0822 May 2, 2025
57847f2
fix typo in help
xmzhao0822 May 2, 2025
57468b4
Merge remote-tracking branch 'origin/main' into xmzhao/namespace-ops
xmzhao0822 May 21, 2025
d27d176
update the code with latest model and sdk
xmzhao0822 May 21, 2025
307df88
change str to none as default in TestValidateManagedNamespace
xmzhao0822 May 21, 2025
a9281d3
resolve comments
xmzhao0822 May 22, 2025
3ceff36
remove --name from help add and update
xmzhao0822 May 22, 2025
fe4987b
resolve conflict
xmzhao0822 May 27, 2025
fb80ca8
update history
xmzhao0822 May 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/aks-preview/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ To release a new version, please select a new version number (usually plus 1 to
Pending
+++++++

18.0.0b4
+++++++
* Add managed namespace commands `az aks namespace add/update/show/list/delete/get-credentials`

18.0.0b3
+++++++
* Add basic lb sku migration support `az aks update --load-balancer-sku standard`
Expand Down
4 changes: 4 additions & 0 deletions src/aks-preview/azext_aks_preview/_client_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ def cf_agent_pools(cli_ctx, *_):
return get_container_service_client(cli_ctx).agent_pools


def cf_managed_namespaces(cli_ctx, *_):
return get_container_service_client(cli_ctx).managed_namespaces


def cf_machines(cli_ctx, *_):
return get_container_service_client(cli_ctx).machines

Expand Down
10 changes: 10 additions & 0 deletions src/aks-preview/azext_aks_preview/_consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,16 @@
CONST_IMDS_RESTRICTION_ENABLED = "None"
CONST_IMDS_RESTRICTION_DISABLED = "IMDS"

# Managed Namespace
CONST_NAMESPACE_ADOPTION_POLICY_NEVER = "Never"
CONST_NAMESPACE_ADOPTION_POLICY_IFIDENTICAL = "IfIdentical"
CONST_NAMESPACE_ADOPTION_POLICY_ALWAYS = "Always"
CONST_NAMESPACE_NETWORK_POLICY_RULE_DENYALL = "DenyAll"
CONST_NAMESPACE_NETWORK_POLICY_RULE_ALLOWALL = "AllowAll"
CONST_NAMESPACE_NETWORK_POLICY_RULE_ALLOWSAMENAMESPACE = "AllowSameNamespace"
CONST_NAMESPACE_DELETE_POLICY_KEEP = "Keep"
CONST_NAMESPACE_DELETE_POLICY_DELETE = "Delete"

# GPU Driver Type Consts
CONST_GPU_DRIVER_TYPE_CUDA = "CUDA"
CONST_GPU_DRIVER_TYPE_GRID = "GRID"
Expand Down
25 changes: 25 additions & 0 deletions src/aks-preview/azext_aks_preview/_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,31 @@ def parser(entry):
return parser(result)


def aks_namespace_list_table_format(results):
"""Format an managed namespace list for display with "-o table"."""
return [_aks_namespace_list_table_format(r) for r in results]


def _aks_namespace_list_table_format(result):
parsed = compile_jmes("""{
name: name,
tags: to_string(tags),
provisioningState: to_string(properties.provisioningState),
labels: to_string(properties.labels),
annotations: to_string(properties.annotations),
cpuRequest: to_string(properties.defaultResourceQuota.cpuRequest),
cpuLimit: to_string(properties.defaultResourceQuota.cpuLimit),
memoryRequest: to_string(properties.defaultResourceQuota.memoryRequest),
memoryLimit: to_string(properties.defaultResourceQuota.memoryLimit),
ingress: to_string(properties.defaultNetworkPolicy.ingress),
egress: to_string(properties.defaultNetworkPolicy.egress),
adoptionPolicy: to_string(properties.adoptionPolicy),
deletePolicy: to_string(properties.deletePolicy)
}""")
# use ordered dicts so headers are predictable
return parsed.search(result, Options(dict_cls=OrderedDict))


def aks_agentpool_show_table_format(result):
"""Format an agent pool as summary results for display with "-o table"."""
return [_aks_agentpool_table_format(result)]
Expand Down
143 changes: 143 additions & 0 deletions src/aks-preview/azext_aks_preview/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -1673,6 +1673,149 @@
}
"""

helps['aks namespace'] = """
type: group
short-summary: Commands to manage namespace in managed Kubernetes cluster.
"""

helps['aks namespace add'] = """
type: command
short-summary: Add namespace to the managed Kubernetes cluster.
parameters:
- name: --cluster-name
type: string
short-summary: Name of the managed cluster.
- name: --tags
type: string
short-summary: The tags of the managed namespace.
- name: --labels
type: string
short-summary: Labels for the managed namespace.
- name: --annotations
type: string
short-summary: Annotations for the managed namespace.
- name: --cpu-request
type: string
short-summary: CPU request of the namespace.
- name: --cpu-limit
type: string
short-summary: CPU limit of the namespace.
- name: --memory-request
type: string
short-summary: Memory request of the namespace.
- name: --memory-limit
type: string
short-summary: Memory limit of the namespace.
- name: --ingress-policy
type: string
short-summary: Ingress policy for the network. The default value is AllowSameNamespace.
- name: --egress-policy
type: string
short-summary: Egress policy for the network. The default value is AllowAll.
- name: --adoption-policy
type: string
short-summary: Action if Kubernetes namespace with same name already exists. The default value is Never.
- name: --delete-policy
type: string
short-summary: Delete options of a namespace. The default value is Keep.
- name: --aks-custom-headers
type: string
short-summary: Send custom headers. When specified, format should be Key1=Value1,Key2=Value2.
- name: --no-wait
type: bool
short-summary: Do not wait for the long-running operation to finish.
examples:
- name: Create a namespace in an existing AKS cluster.
text: az aks namespace add -g MyResourceGroup --cluster-name MyClusterName --name NamespaceName --cpu-request 500m --cpu-limit 800m --memory-request 1Gi --memory-limit 2Gi --aks-custom-headers AKSHTTPCustomFeatures=Microsoft.ContainerService/ManagedNamespacePreview
- name: Create a namespace in an existing AKS cluster with labels, annotations and tags
text: az aks namespace add -g MyResourceGroup --cluster-name MyClusterName --name NamespaceName --labels a=b p=q --annotations a=b p=q --tags a=b p=q --cpu-request 500m --cpu-limit 800m --memory-request 1Gi --memory-limit 2Gi --aks-custom-headers AKSHTTPCustomFeatures=Microsoft.ContainerService/ManagedNamespacePreview
"""

helps['aks namespace update'] = """
type: command
short-summary: Update namespace on the managed Kubernetes cluster.
parameters:
- name: --cluster-name
type: string
short-summary: Name of the managed cluster.
- name: --tags
type: string
short-summary: The tags of the managed namespace.
- name: --labels
type: string
short-summary: Labels for the managed namespace.
- name: --annotations
type: string
short-summary: Annotations for the managed namespace.
- name: --cpu-request
type: string
short-summary: CPU request of the namespace.
- name: --cpu-limit
type: string
short-summary: CPU limit of the namespace.
- name: --memory-request
type: string
short-summary: Memory request of the namespace.
- name: --memory-limit
type: string
short-summary: Memory limit of the namespace.
- name: --ingress-policy
type: string
short-summary: Ingress policy rule for the network.
- name: --egress-policy
type: string
short-summary: Egress policy rule for the network.
- name: --adoption-policy
type: string
short-summary: Action if Kubernetes namespace with same name already exists.
- name: --delete-policy
type: string
short-summary: Delete options of a namespace
- name: --aks-custom-headers
type: string
short-summary: Send custom headers. When specified, format should be Key1=Value1,Key2=Value2
- name: --no-wait
type: bool
short-summary: Do not wait for the long-running operation to finish
examples:
- name: update namespace in an existing AKS cluster.
text: az aks namespace update -g MyResourceGroup --cluster-name MyClusterName --name NamespaceName --labels a=b p=q --annotations a=b p=q --tags a=b p=q --cpu-request 600m --cpu-limit 800m --memory-request 2Gi --memory-limit 3Gi --adoption-policy Always --aks-custom-headers AKSHTTPCustomFeatures=Microsoft.ContainerService/ManagedNamespacePreview
"""

helps['aks namespace show'] = """
type: command
short-summary: show the details of a managed namespace in managed Kubernetes cluster.
"""

helps['aks namespace list'] = """
type: command
short-summary: List managed namespaces in managed Kubernetes cluster.
"""

helps['aks namespace delete'] = """
type: command
short-summary: Delete a managed namespace in managed Kubernetes cluster.
"""

helps['aks namespace get-credentials'] = """
type: command
short-summary: Get access credentials for a managed namespace.
parameters:
- name: --file -f
type: string
short-summary: Kubernetes configuration file to update. Use "-" to print YAML to stdout instead.
- name: --overwrite-existing
type: bool
short-summary: Overwrite any existing cluster entry with the same name.
- name: --output -o
type: string
long-summary: Credentials are always in YAML format, so this argument is effectively ignored.
examples:
- name: Get access credentials for a managed namespace. (autogenerated)
text: az aks namespace get-credentials --resource-group MyResourceGroup --cluster-name MyManagedCluster --name ManagedNamespaceName
crafted: true
"""

helps['aks nodepool'] = """
type: group
short-summary: Commands to manage node pools in managed Kubernetes cluster.
Expand Down
74 changes: 74 additions & 0 deletions src/aks-preview/azext_aks_preview/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@
CONST_ABSOLUTEMONTHLY_MAINTENANCE_SCHEDULE,
CONST_AZURE_KEYVAULT_NETWORK_ACCESS_PRIVATE,
CONST_AZURE_KEYVAULT_NETWORK_ACCESS_PUBLIC,
CONST_NAMESPACE_ADOPTION_POLICY_NEVER,
CONST_NAMESPACE_ADOPTION_POLICY_IFIDENTICAL,
CONST_NAMESPACE_ADOPTION_POLICY_ALWAYS,
CONST_NAMESPACE_NETWORK_POLICY_RULE_DENYALL,
CONST_NAMESPACE_NETWORK_POLICY_RULE_ALLOWALL,
CONST_NAMESPACE_NETWORK_POLICY_RULE_ALLOWSAMENAMESPACE,
CONST_NAMESPACE_DELETE_POLICY_KEEP,
CONST_NAMESPACE_DELETE_POLICY_DELETE,
CONST_CREDENTIAL_FORMAT_AZURE,
CONST_CREDENTIAL_FORMAT_EXEC,
CONST_DAILY_MAINTENANCE_SCHEDULE,
Expand Down Expand Up @@ -139,6 +147,8 @@

from azext_aks_preview._validators import (
validate_acr,
validate_namespace_name,
validate_resource_quota,
validate_addon,
validate_addons,
validate_agent_pool_name,
Expand Down Expand Up @@ -329,6 +339,24 @@
CONST_NRG_LOCKDOWN_RESTRICTION_LEVEL_UNRESTRICTED,
]

# consts for managed namespace
network_policy_rule = [
CONST_NAMESPACE_NETWORK_POLICY_RULE_DENYALL,
CONST_NAMESPACE_NETWORK_POLICY_RULE_ALLOWALL,
CONST_NAMESPACE_NETWORK_POLICY_RULE_ALLOWSAMENAMESPACE,
]

adoption_policy = [
CONST_NAMESPACE_ADOPTION_POLICY_NEVER,
CONST_NAMESPACE_ADOPTION_POLICY_IFIDENTICAL,
CONST_NAMESPACE_ADOPTION_POLICY_ALWAYS,
]

delete_policy = [
CONST_NAMESPACE_DELETE_POLICY_KEEP,
CONST_NAMESPACE_DELETE_POLICY_DELETE,
]

# consts for maintenance configuration
schedule_types = [
CONST_DAILY_MAINTENANCE_SCHEDULE,
Expand Down Expand Up @@ -1434,6 +1462,52 @@ def load_arguments(self, _):
validator=validate_nodepool_name,
)

# managed namespace
with self.argument_context("aks namespace") as c:
c.argument("cluster_name", help="The cluster name.")
c.argument(
"name",
validator=validate_namespace_name,
help="The managed namespace name.",
)

for scope in [
"aks namespace add",
"aks namespace update",
]:
with self.argument_context(scope) as c:
c.argument("tags", tags_type, help="The tags to set to the managed namespace")
c.argument("labels", nargs="*", help="Labels set to the managed namespace")
c.argument(
"annotations",
nargs="*",
help="Annotations set to the managed namespace",
)
c.argument("cpu_request", validator=validate_resource_quota)
c.argument("cpu_limit", validator=validate_resource_quota)
c.argument("memory_request", validator=validate_resource_quota)
c.argument("memory_limit", validator=validate_resource_quota)
c.argument("ingress_policy", arg_type=get_enum_type(network_policy_rule))
c.argument("egress_policy", arg_type=get_enum_type(network_policy_rule))
c.argument("adoption_policy", arg_type=get_enum_type(adoption_policy))
c.argument("delete_policy", arg_type=get_enum_type(delete_policy))
c.argument("aks_custom_headers")
c.argument("no_wait", help="Do not wait for the long-running operation to finish")

with self.argument_context("aks namespace get-credentials") as c:
c.argument(
"context_name",
options_list=["--context"],
help="If specified, overwrite the default context name.",
)
c.argument(
"path",
options_list=["--file", "-f"],
type=file_type,
completer=FilesCompleter(),
default=os.path.join(os.path.expanduser("~"), ".kube", "config"),
)

with self.argument_context("aks nodepool") as c:
c.argument("cluster_name", help="The cluster name.")
c.argument(
Expand Down
38 changes: 38 additions & 0 deletions src/aks-preview/azext_aks_preview/_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,44 @@ def validate_ip_ranges(namespace):
pass


def validate_namespace_name(namespace):
_validate_namespace_name(namespace.name)


def _validate_namespace_name(name):
"""
Validates a Kubernetes namespace name.
Raises ValueError if the name is invalid.
"""
if name != "":
if len(name) < 1 or len(name) > 63:
raise ValueError("Namespace name must be between 1 and 63 characters.")
pattern = r'^[a-z0-9]([-a-z0-9]*[a-z0-9])?$'
if not re.match(pattern, name):
raise ValueError(
f"Invalid namespace '{name}'. Must consist of lower case alphanumeric characters or '-', "
"and must start and end with an alphanumeric character."
)


def validate_resource_quota(namespace):
if namespace.cpu_request is not None:
if not namespace.cpu_request.endswith("m"):
raise ValueError("--cpu-request must be specified in millicores, like 200m")
if namespace.cpu_limit is not None:
if not namespace.cpu_limit.endswith("m"):
raise ValueError("--cpu-limit must be specified in millicores, like 200m")
pattern = r"^\d+(Ki|Mi|Gi|Ti|Pi|Ei)$"
if namespace.memory_request is not None:
if not re.match(pattern, namespace.memory_request):
raise ValueError("--memory-request must be specified in the power-of-two equivalents form:"
"Ei, Pi, Ti, Gi, Mi, Ki.")
if namespace.memory_limit is not None:
if not re.match(pattern, namespace.memory_limit):
raise ValueError("--memory-limit must be specified in the power-of-two equivalents form:"
"Ei, Pi, Ti, Gi, Mi, Ki.")


def _validate_nodepool_name(nodepool_name):
"""Validates a nodepool name to be at most 12 characters, alphanumeric only."""
if nodepool_name != "":
Expand Down
Loading
Loading