Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,9 @@
- name: --node-taints
type: string
short-summary: The node taints for the node pool. You can't change the node taints through CLI after the node pool is created.
- name: --labels
type: string
short-summary: The node labels for the node pool. You can't change the node labels through CLI after the node pool is created. See https://aka.ms/node-labels for syntax of labels.
"""

helps['aks nodepool delete'] = """
Expand Down
4 changes: 3 additions & 1 deletion src/azure-cli/azure/cli/command_modules/acs/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
validate_list_of_integers, validate_ssh_key, validate_connector_name, validate_max_pods, validate_nodes_count,
validate_nodepool_name, validate_vm_set_type, validate_load_balancer_sku, validate_load_balancer_outbound_ips,
validate_load_balancer_outbound_ip_prefixes, validate_taints, validate_ip_ranges, validate_acr, validate_nodepool_tags,
validate_load_balancer_outbound_ports, validate_load_balancer_idle_timeout, validate_vnet_subnet_id)
validate_load_balancer_outbound_ports, validate_load_balancer_idle_timeout, validate_vnet_subnet_id, validate_nodepool_labels)

aci_connector_os_type = ['Windows', 'Linux', 'Both']

Expand Down Expand Up @@ -200,6 +200,7 @@ def load_arguments(self, _):
c.argument('attach_acr', acr_arg_type)
c.argument('enable_private_cluster', action='store_true')
c.argument('nodepool_tags', nargs='*', validator=validate_nodepool_tags, help='space-separated tags: key[=value] [key[=value] ...]. Use "" to clear existing tags.')
c.argument('nodepool_labels', nargs='*', validator=validate_nodepool_labels, help='space-separated labels: key[=value] [key[=value] ...]. You can not change the node labels through CLI after creation. See https://aka.ms/node-labels for syntax of labels.')

with self.argument_context('aks update') as c:
c.argument('attach_acr', acr_arg_type, validator=validate_acr)
Expand Down Expand Up @@ -288,6 +289,7 @@ def load_arguments(self, _):
c.argument('enable_cluster_autoscaler', options_list=["--enable-cluster-autoscaler", "-e"], action='store_true')
c.argument('node_taints', type=str, validator=validate_taints)
c.argument('tags', tags_type)
c.argument('labels', nargs='*', validator=validate_nodepool_labels)

for scope in ['aks nodepool show', 'aks nodepool delete', 'aks nodepool scale', 'aks nodepool upgrade', 'aks nodepool update']:
with self.argument_context(scope) as c:
Expand Down
72 changes: 72 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,75 @@ def validate_vnet_subnet_id(namespace):
from msrestazure.tools import is_valid_resource_id
if not is_valid_resource_id(namespace.vnet_subnet_id):
raise CLIError("--vnet-subnet-id is not a valid Azure resource ID.")


def validate_nodepool_labels(namespace):
"""Validates that provided node labels is a valid format"""

if hasattr(namespace, 'nodepool_labels'):
labels = namespace.nodepool_labels
else:
labels = namespace.labels

if labels is None:
return

if isinstance(labels, list):
labels_dict = {}
for item in labels:
labels_dict.update(validate_label(item))
after_validation_labels = labels_dict
else:
after_validation_labels = validate_label(labels)

if hasattr(namespace, 'nodepool_labels'):
namespace.nodepool_labels = after_validation_labels
else:
namespace.labels = after_validation_labels


def validate_label(label):
"""Validates that provided label is a valid format"""
prefix_regex = re.compile(r"^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
name_regex = re.compile(r"^([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$")
value_regex = re.compile(r"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$")

if label == "":
return {}
kv = label.split('=')
if len(kv) != 2:
raise CLIError("Invalid label: %s. Label definition must be of format name=value." % label)
name_parts = kv[0].split('/')
if len(name_parts) == 1:
name = name_parts[0]
elif len(name_parts) == 2:
prefix = name_parts[0]
if not prefix or len(prefix) > 253:
raise CLIError("Invalid label: %s. Label prefix can't be empty or more than 253 chars." % label)
if not prefix_regex.match(prefix):
raise CLIError("Invalid label: %s. Prefix part a DNS-1123 label must consist of lower case alphanumeric "
"characters or '-', and must start and end with an alphanumeric character" % label)
name = name_parts[1]
else:
raise CLIError("Invalid label: %s. A qualified name must consist of alphanumeric characters, '-', '_' "
"or '.', and must start and end with an alphanumeric character (e.g. 'MyName', or "
"'my.name', or '123-abc') with an optional DNS subdomain prefix and '/' "
"(e.g. 'example.com/MyName')" % label)

# validate label name
if not name or len(name) > 63:
raise CLIError("Invalid label: %s. Label name can't be empty or more than 63 chars." % label)
if not name_regex.match(name):
raise CLIError("Invalid label: %s. A qualified name must consist of alphanumeric characters, '-', '_' "
"or '.', and must start and end with an alphanumeric character (e.g. 'MyName', or "
"'my.name', or '123-abc') with an optional DNS subdomain prefix and '/' (e.g. "
"'example.com/MyName')" % label)

# validate label value
if len(kv[1]) > 63:
raise CLIError("Invalid label: %s. Label must be more than 63 chars." % label)
if not value_regex.match(kv[1]):
raise CLIError("Invalid label: %s. A valid label must be an empty string or consist of alphanumeric "
"characters, '-', '_' or '.', and must start and end with an alphanumeric character" % label)

return {kv[0]: kv[1]}
4 changes: 4 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -1647,6 +1647,7 @@ def aks_create(cmd, client, resource_group_name, name, ssh_key_value, # pylint:
node_count=3,
nodepool_name="nodepool1",
nodepool_tags=None,
nodepool_labels=None,
service_principal=None, client_secret=None,
no_ssh_key=False,
disable_rbac=None,
Expand Down Expand Up @@ -1701,6 +1702,7 @@ def aks_create(cmd, client, resource_group_name, name, ssh_key_value, # pylint:
agent_pool_profile = ManagedClusterAgentPoolProfile(
name=_trim_nodepoolname(nodepool_name), # Must be 12 chars or less before ACS RP adds to it
tags=nodepool_tags,
node_labels=nodepool_labels,
count=int(node_count),
vm_size=node_vm_size,
os_type="Linux",
Expand Down Expand Up @@ -2717,6 +2719,7 @@ def aks_agentpool_add(cmd, client, resource_group_name, cluster_name, nodepool_n
enable_cluster_autoscaler=False,
node_taints=None,
tags=None,
labels=None,
no_wait=False):
instances = client.list(resource_group_name, cluster_name)
for agentpool_profile in instances:
Expand All @@ -2742,6 +2745,7 @@ def aks_agentpool_add(cmd, client, resource_group_name, cluster_name, nodepool_n
agent_pool = AgentPool(
name=nodepool_name,
tags=tags,
node_labels=labels,
count=int(node_count),
vm_size=node_vm_size,
os_type=os_type,
Expand Down
Loading