Skip to content

Commit ce1414e

Browse files
authored
{AKS} create managed namespace commands (#8689)
1 parent 274e67f commit ce1414e

File tree

15 files changed

+3057
-1
lines changed

15 files changed

+3057
-1
lines changed

src/aks-preview/HISTORY.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ To release a new version, please select a new version number (usually plus 1 to
1212
Pending
1313
+++++++
1414

15+
18.0.0b4
16+
+++++++
17+
* Add managed namespace commands `az aks namespace add/update/show/list/delete/get-credentials`
18+
1519
18.0.0b3
1620
+++++++
1721
* Add basic lb sku migration support `az aks update --load-balancer-sku standard`

src/aks-preview/azext_aks_preview/_client_factory.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ def cf_agent_pools(cli_ctx, *_):
3535
return get_container_service_client(cli_ctx).agent_pools
3636

3737

38+
def cf_managed_namespaces(cli_ctx, *_):
39+
return get_container_service_client(cli_ctx).managed_namespaces
40+
41+
3842
def cf_machines(cli_ctx, *_):
3943
return get_container_service_client(cli_ctx).machines
4044

src/aks-preview/azext_aks_preview/_consts.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,16 @@
341341
CONST_IMDS_RESTRICTION_ENABLED = "None"
342342
CONST_IMDS_RESTRICTION_DISABLED = "IMDS"
343343

344+
# Managed Namespace
345+
CONST_NAMESPACE_ADOPTION_POLICY_NEVER = "Never"
346+
CONST_NAMESPACE_ADOPTION_POLICY_IFIDENTICAL = "IfIdentical"
347+
CONST_NAMESPACE_ADOPTION_POLICY_ALWAYS = "Always"
348+
CONST_NAMESPACE_NETWORK_POLICY_RULE_DENYALL = "DenyAll"
349+
CONST_NAMESPACE_NETWORK_POLICY_RULE_ALLOWALL = "AllowAll"
350+
CONST_NAMESPACE_NETWORK_POLICY_RULE_ALLOWSAMENAMESPACE = "AllowSameNamespace"
351+
CONST_NAMESPACE_DELETE_POLICY_KEEP = "Keep"
352+
CONST_NAMESPACE_DELETE_POLICY_DELETE = "Delete"
353+
344354
# GPU Driver Type Consts
345355
CONST_GPU_DRIVER_TYPE_CUDA = "CUDA"
346356
CONST_GPU_DRIVER_TYPE_GRID = "GRID"

src/aks-preview/azext_aks_preview/_format.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,31 @@ def parser(entry):
8787
return parser(result)
8888

8989

90+
def aks_namespace_list_table_format(results):
91+
"""Format an managed namespace list for display with "-o table"."""
92+
return [_aks_namespace_list_table_format(r) for r in results]
93+
94+
95+
def _aks_namespace_list_table_format(result):
96+
parsed = compile_jmes("""{
97+
name: name,
98+
tags: to_string(tags),
99+
provisioningState: to_string(properties.provisioningState),
100+
labels: to_string(properties.labels),
101+
annotations: to_string(properties.annotations),
102+
cpuRequest: to_string(properties.defaultResourceQuota.cpuRequest),
103+
cpuLimit: to_string(properties.defaultResourceQuota.cpuLimit),
104+
memoryRequest: to_string(properties.defaultResourceQuota.memoryRequest),
105+
memoryLimit: to_string(properties.defaultResourceQuota.memoryLimit),
106+
ingress: to_string(properties.defaultNetworkPolicy.ingress),
107+
egress: to_string(properties.defaultNetworkPolicy.egress),
108+
adoptionPolicy: to_string(properties.adoptionPolicy),
109+
deletePolicy: to_string(properties.deletePolicy)
110+
}""")
111+
# use ordered dicts so headers are predictable
112+
return parsed.search(result, Options(dict_cls=OrderedDict))
113+
114+
90115
def aks_agentpool_show_table_format(result):
91116
"""Format an agent pool as summary results for display with "-o table"."""
92117
return [_aks_agentpool_table_format(result)]

src/aks-preview/azext_aks_preview/_help.py

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,6 +1673,149 @@
16731673
}
16741674
"""
16751675

1676+
helps['aks namespace'] = """
1677+
type: group
1678+
short-summary: Commands to manage namespace in managed Kubernetes cluster.
1679+
"""
1680+
1681+
helps['aks namespace add'] = """
1682+
type: command
1683+
short-summary: Add namespace to the managed Kubernetes cluster.
1684+
parameters:
1685+
- name: --cluster-name
1686+
type: string
1687+
short-summary: Name of the managed cluster.
1688+
- name: --tags
1689+
type: string
1690+
short-summary: The tags of the managed namespace.
1691+
- name: --labels
1692+
type: string
1693+
short-summary: Labels for the managed namespace.
1694+
- name: --annotations
1695+
type: string
1696+
short-summary: Annotations for the managed namespace.
1697+
- name: --cpu-request
1698+
type: string
1699+
short-summary: CPU request of the namespace.
1700+
- name: --cpu-limit
1701+
type: string
1702+
short-summary: CPU limit of the namespace.
1703+
- name: --memory-request
1704+
type: string
1705+
short-summary: Memory request of the namespace.
1706+
- name: --memory-limit
1707+
type: string
1708+
short-summary: Memory limit of the namespace.
1709+
- name: --ingress-policy
1710+
type: string
1711+
short-summary: Ingress policy for the network. The default value is AllowSameNamespace.
1712+
- name: --egress-policy
1713+
type: string
1714+
short-summary: Egress policy for the network. The default value is AllowAll.
1715+
- name: --adoption-policy
1716+
type: string
1717+
short-summary: Action if Kubernetes namespace with same name already exists. The default value is Never.
1718+
- name: --delete-policy
1719+
type: string
1720+
short-summary: Delete options of a namespace. The default value is Keep.
1721+
- name: --aks-custom-headers
1722+
type: string
1723+
short-summary: Send custom headers. When specified, format should be Key1=Value1,Key2=Value2.
1724+
- name: --no-wait
1725+
type: bool
1726+
short-summary: Do not wait for the long-running operation to finish.
1727+
examples:
1728+
- name: Create a namespace in an existing AKS cluster.
1729+
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
1730+
- name: Create a namespace in an existing AKS cluster with labels, annotations and tags
1731+
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
1732+
"""
1733+
1734+
helps['aks namespace update'] = """
1735+
type: command
1736+
short-summary: Update namespace on the managed Kubernetes cluster.
1737+
parameters:
1738+
- name: --cluster-name
1739+
type: string
1740+
short-summary: Name of the managed cluster.
1741+
- name: --tags
1742+
type: string
1743+
short-summary: The tags of the managed namespace.
1744+
- name: --labels
1745+
type: string
1746+
short-summary: Labels for the managed namespace.
1747+
- name: --annotations
1748+
type: string
1749+
short-summary: Annotations for the managed namespace.
1750+
- name: --cpu-request
1751+
type: string
1752+
short-summary: CPU request of the namespace.
1753+
- name: --cpu-limit
1754+
type: string
1755+
short-summary: CPU limit of the namespace.
1756+
- name: --memory-request
1757+
type: string
1758+
short-summary: Memory request of the namespace.
1759+
- name: --memory-limit
1760+
type: string
1761+
short-summary: Memory limit of the namespace.
1762+
- name: --ingress-policy
1763+
type: string
1764+
short-summary: Ingress policy rule for the network.
1765+
- name: --egress-policy
1766+
type: string
1767+
short-summary: Egress policy rule for the network.
1768+
- name: --adoption-policy
1769+
type: string
1770+
short-summary: Action if Kubernetes namespace with same name already exists.
1771+
- name: --delete-policy
1772+
type: string
1773+
short-summary: Delete options of a namespace
1774+
- name: --aks-custom-headers
1775+
type: string
1776+
short-summary: Send custom headers. When specified, format should be Key1=Value1,Key2=Value2
1777+
- name: --no-wait
1778+
type: bool
1779+
short-summary: Do not wait for the long-running operation to finish
1780+
examples:
1781+
- name: update namespace in an existing AKS cluster.
1782+
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
1783+
"""
1784+
1785+
helps['aks namespace show'] = """
1786+
type: command
1787+
short-summary: show the details of a managed namespace in managed Kubernetes cluster.
1788+
"""
1789+
1790+
helps['aks namespace list'] = """
1791+
type: command
1792+
short-summary: List managed namespaces in managed Kubernetes cluster.
1793+
"""
1794+
1795+
helps['aks namespace delete'] = """
1796+
type: command
1797+
short-summary: Delete a managed namespace in managed Kubernetes cluster.
1798+
"""
1799+
1800+
helps['aks namespace get-credentials'] = """
1801+
type: command
1802+
short-summary: Get access credentials for a managed namespace.
1803+
parameters:
1804+
- name: --file -f
1805+
type: string
1806+
short-summary: Kubernetes configuration file to update. Use "-" to print YAML to stdout instead.
1807+
- name: --overwrite-existing
1808+
type: bool
1809+
short-summary: Overwrite any existing cluster entry with the same name.
1810+
- name: --output -o
1811+
type: string
1812+
long-summary: Credentials are always in YAML format, so this argument is effectively ignored.
1813+
examples:
1814+
- name: Get access credentials for a managed namespace. (autogenerated)
1815+
text: az aks namespace get-credentials --resource-group MyResourceGroup --cluster-name MyManagedCluster --name ManagedNamespaceName
1816+
crafted: true
1817+
"""
1818+
16761819
helps['aks nodepool'] = """
16771820
type: group
16781821
short-summary: Commands to manage node pools in managed Kubernetes cluster.

src/aks-preview/azext_aks_preview/_params.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@
4343
CONST_ABSOLUTEMONTHLY_MAINTENANCE_SCHEDULE,
4444
CONST_AZURE_KEYVAULT_NETWORK_ACCESS_PRIVATE,
4545
CONST_AZURE_KEYVAULT_NETWORK_ACCESS_PUBLIC,
46+
CONST_NAMESPACE_ADOPTION_POLICY_NEVER,
47+
CONST_NAMESPACE_ADOPTION_POLICY_IFIDENTICAL,
48+
CONST_NAMESPACE_ADOPTION_POLICY_ALWAYS,
49+
CONST_NAMESPACE_NETWORK_POLICY_RULE_DENYALL,
50+
CONST_NAMESPACE_NETWORK_POLICY_RULE_ALLOWALL,
51+
CONST_NAMESPACE_NETWORK_POLICY_RULE_ALLOWSAMENAMESPACE,
52+
CONST_NAMESPACE_DELETE_POLICY_KEEP,
53+
CONST_NAMESPACE_DELETE_POLICY_DELETE,
4654
CONST_CREDENTIAL_FORMAT_AZURE,
4755
CONST_CREDENTIAL_FORMAT_EXEC,
4856
CONST_DAILY_MAINTENANCE_SCHEDULE,
@@ -139,6 +147,8 @@
139147

140148
from azext_aks_preview._validators import (
141149
validate_acr,
150+
validate_namespace_name,
151+
validate_resource_quota,
142152
validate_addon,
143153
validate_addons,
144154
validate_agent_pool_name,
@@ -329,6 +339,24 @@
329339
CONST_NRG_LOCKDOWN_RESTRICTION_LEVEL_UNRESTRICTED,
330340
]
331341

342+
# consts for managed namespace
343+
network_policy_rule = [
344+
CONST_NAMESPACE_NETWORK_POLICY_RULE_DENYALL,
345+
CONST_NAMESPACE_NETWORK_POLICY_RULE_ALLOWALL,
346+
CONST_NAMESPACE_NETWORK_POLICY_RULE_ALLOWSAMENAMESPACE,
347+
]
348+
349+
adoption_policy = [
350+
CONST_NAMESPACE_ADOPTION_POLICY_NEVER,
351+
CONST_NAMESPACE_ADOPTION_POLICY_IFIDENTICAL,
352+
CONST_NAMESPACE_ADOPTION_POLICY_ALWAYS,
353+
]
354+
355+
delete_policy = [
356+
CONST_NAMESPACE_DELETE_POLICY_KEEP,
357+
CONST_NAMESPACE_DELETE_POLICY_DELETE,
358+
]
359+
332360
# consts for maintenance configuration
333361
schedule_types = [
334362
CONST_DAILY_MAINTENANCE_SCHEDULE,
@@ -1434,6 +1462,52 @@ def load_arguments(self, _):
14341462
validator=validate_nodepool_name,
14351463
)
14361464

1465+
# managed namespace
1466+
with self.argument_context("aks namespace") as c:
1467+
c.argument("cluster_name", help="The cluster name.")
1468+
c.argument(
1469+
"name",
1470+
validator=validate_namespace_name,
1471+
help="The managed namespace name.",
1472+
)
1473+
1474+
for scope in [
1475+
"aks namespace add",
1476+
"aks namespace update",
1477+
]:
1478+
with self.argument_context(scope) as c:
1479+
c.argument("tags", tags_type, help="The tags to set to the managed namespace")
1480+
c.argument("labels", nargs="*", help="Labels set to the managed namespace")
1481+
c.argument(
1482+
"annotations",
1483+
nargs="*",
1484+
help="Annotations set to the managed namespace",
1485+
)
1486+
c.argument("cpu_request", validator=validate_resource_quota)
1487+
c.argument("cpu_limit", validator=validate_resource_quota)
1488+
c.argument("memory_request", validator=validate_resource_quota)
1489+
c.argument("memory_limit", validator=validate_resource_quota)
1490+
c.argument("ingress_policy", arg_type=get_enum_type(network_policy_rule))
1491+
c.argument("egress_policy", arg_type=get_enum_type(network_policy_rule))
1492+
c.argument("adoption_policy", arg_type=get_enum_type(adoption_policy))
1493+
c.argument("delete_policy", arg_type=get_enum_type(delete_policy))
1494+
c.argument("aks_custom_headers")
1495+
c.argument("no_wait", help="Do not wait for the long-running operation to finish")
1496+
1497+
with self.argument_context("aks namespace get-credentials") as c:
1498+
c.argument(
1499+
"context_name",
1500+
options_list=["--context"],
1501+
help="If specified, overwrite the default context name.",
1502+
)
1503+
c.argument(
1504+
"path",
1505+
options_list=["--file", "-f"],
1506+
type=file_type,
1507+
completer=FilesCompleter(),
1508+
default=os.path.join(os.path.expanduser("~"), ".kube", "config"),
1509+
)
1510+
14371511
with self.argument_context("aks nodepool") as c:
14381512
c.argument("cluster_name", help="The cluster name.")
14391513
c.argument(

src/aks-preview/azext_aks_preview/_validators.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,44 @@ def validate_ip_ranges(namespace):
166166
pass
167167

168168

169+
def validate_namespace_name(namespace):
170+
_validate_namespace_name(namespace.name)
171+
172+
173+
def _validate_namespace_name(name):
174+
"""
175+
Validates a Kubernetes namespace name.
176+
Raises ValueError if the name is invalid.
177+
"""
178+
if name != "":
179+
if len(name) < 1 or len(name) > 63:
180+
raise ValueError("Namespace name must be between 1 and 63 characters.")
181+
pattern = r'^[a-z0-9]([-a-z0-9]*[a-z0-9])?$'
182+
if not re.match(pattern, name):
183+
raise ValueError(
184+
f"Invalid namespace '{name}'. Must consist of lower case alphanumeric characters or '-', "
185+
"and must start and end with an alphanumeric character."
186+
)
187+
188+
189+
def validate_resource_quota(namespace):
190+
if namespace.cpu_request is not None:
191+
if not namespace.cpu_request.endswith("m"):
192+
raise ValueError("--cpu-request must be specified in millicores, like 200m")
193+
if namespace.cpu_limit is not None:
194+
if not namespace.cpu_limit.endswith("m"):
195+
raise ValueError("--cpu-limit must be specified in millicores, like 200m")
196+
pattern = r"^\d+(Ki|Mi|Gi|Ti|Pi|Ei)$"
197+
if namespace.memory_request is not None:
198+
if not re.match(pattern, namespace.memory_request):
199+
raise ValueError("--memory-request must be specified in the power-of-two equivalents form:"
200+
"Ei, Pi, Ti, Gi, Mi, Ki.")
201+
if namespace.memory_limit is not None:
202+
if not re.match(pattern, namespace.memory_limit):
203+
raise ValueError("--memory-limit must be specified in the power-of-two equivalents form:"
204+
"Ei, Pi, Ti, Gi, Mi, Ki.")
205+
206+
169207
def _validate_nodepool_name(nodepool_name):
170208
"""Validates a nodepool name to be at most 12 characters, alphanumeric only."""
171209
if nodepool_name != "":

0 commit comments

Comments
 (0)