Skip to content

Commit a907094

Browse files
authored
[AKS] Add Etags in AKS CLI (#30309)
1 parent 5169006 commit a907094

File tree

8 files changed

+322
-15
lines changed

8 files changed

+322
-15
lines changed

src/azure-cli/azure/cli/command_modules/acs/_help.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,12 @@
554554
type: string
555555
short-summary: Restriction level on the managed node resource group.
556556
long-summary: The restriction level of permissions allowed on the cluster's managed node resource group, supported values are Unrestricted, and ReadOnly (recommended ReadOnly).
557+
- name: --if-match
558+
type: string
559+
short-summary: The value provided will be compared to the ETag of the managed cluster, if it matches the operation will proceed. If it does not match, the request will be rejected to prevent accidental overwrites. This must not be specified when creating a new cluster.
560+
- name: --if-none-match
561+
type: string
562+
short-summary: Set to '*' to allow a new cluster to be created, but to prevent updating an existing cluster. Other values will be ignored.
557563
558564
examples:
559565
- name: Create a Kubernetes cluster with an existing SSH public key.
@@ -976,7 +982,12 @@
976982
type: string
977983
short-summary: Restriction level on the managed node resource group.
978984
long-summary: The restriction level of permissions allowed on the cluster's managed node resource group, supported values are Unrestricted, and ReadOnly (recommended ReadOnly).
979-
985+
- name: --if-match
986+
type: string
987+
short-summary: The value provided will be compared to the ETag of the managed cluster, if it matches the operation will proceed. If it does not match, the request will be rejected to prevent accidental overwrites. This must not be specified when creating a new cluster.
988+
- name: --if-none-match
989+
type: string
990+
short-summary: Set to '*' to allow a new cluster to be created, but to prevent updating an existing cluster. Other values will be ignored.
980991
examples:
981992
- name: Reconcile the cluster back to its current state.
982993
text: az aks update -g MyResourceGroup -n MyManagedCluster
@@ -1624,6 +1635,12 @@
16241635
- name: --enable-vtpm
16251636
type: bool
16261637
short-summary: Enable vTPM on agent node pool. Must use VMSS agent pool type.
1638+
- name: --if-match
1639+
type: string
1640+
short-summary: The value provided will be compared to the ETag of the agentpool, if it matches the operation will proceed. If it does not match, the request will be rejected to prevent accidental overwrites. This must not be specified when creating a new agentpool.
1641+
- name: --if-none-match
1642+
type: string
1643+
short-summary: Set to '*' to allow a new agentpool to be created, but to prevent updating an existing agentpool. Other values will be ignored.
16271644
16281645
examples:
16291646
- name: Create a nodepool in an existing AKS cluster with ephemeral os enabled.
@@ -1647,6 +1664,13 @@
16471664
helps['aks nodepool delete'] = """
16481665
type: command
16491666
short-summary: Delete the agent pool in the managed Kubernetes cluster.
1667+
parameters:
1668+
- name: --if-match
1669+
type: string
1670+
short-summary: The value provided will be compared to the ETag of the node pool, if it matches the operation will proceed. If it does not match, the request will be rejected to prevent accidental overwrites. This must not be specified when creating a new agentpool.
1671+
examples:
1672+
- name: Delete an agent pool with ignore-pod-disruption-budget
1673+
text: az aks nodepool delete --resource-group MyResourceGroup --cluster-name MyManagedCluster --name nodepool1 --if-match etag
16501674
"""
16511675

16521676
helps['aks nodepool get-upgrades'] = """
@@ -1748,6 +1772,12 @@
17481772
- name: --disable-vtpm
17491773
type: bool
17501774
short-summary: Disable vTPM on an existing Trusted Launch enabled agent node pool.
1775+
- name: --if-match
1776+
type: string
1777+
short-summary: The value provided will be compared to the ETag of the node pool, if it matches the operation will proceed. If it does not match, the request will be rejected to prevent accidental overwrites. This must not be specified when creating a new agentpool.
1778+
- name: --if-none-match
1779+
type: string
1780+
short-summary: Set to '*' to allow a new node pool to be created, but to prevent updating an existing node pool. Other values will be ignored.
17511781
examples:
17521782
- name: Reconcile the nodepool back to its current state.
17531783
text: az aks nodepool update -g MyResourceGroup -n nodepool1 --cluster-name MyManagedCluster
@@ -1784,6 +1814,12 @@
17841814
- name: --aks-custom-headers
17851815
type: string
17861816
short-summary: Comma-separated key-value pairs to specify custom headers.
1817+
- name: --if-match
1818+
type: string
1819+
short-summary: The value provided will be compared to the ETag of the node pool, if it matches the operation will proceed. If it does not match, the request will be rejected to prevent accidental overwrites. This must not be specified when creating a new agentpool. For upgrade node image version requests this will be ignored.
1820+
- name: --if-none-match
1821+
type: string
1822+
short-summary: Set to '*' to allow a new node pool to be created, but to prevent updating an existing node pool. Other values will be ignored.
17871823
"""
17881824

17891825
helps['aks nodepool stop'] = """
@@ -1952,6 +1988,12 @@
19521988
- name: --tier
19531989
type: string
19541990
short-summary: Specify SKU tier for managed clusters. '--tier standard' enables a standard managed cluster service with a financially backed SLA. '--tier free' does not have a financially backed SLA. '--tier premium' is required for '--k8s-support-plan AKSLongTermSupport'.
1991+
- name: --if-match
1992+
type: string
1993+
short-summary: The value provided will be compared to the ETag of the managed cluster, if it matches the operation will proceed. If it does not match, the request will be rejected to prevent accidental overwrites. This must not be specified when creating a new cluster.
1994+
- name: --if-none-match
1995+
type: string
1996+
short-summary: Set to '*' to allow a new cluster to be created, but to prevent updating an existing cluster. Other values will be ignored.
19551997
19561998
examples:
19571999
- name: Upgrade a managed Kubernetes cluster to a newer version. (autogenerated)

src/azure-cli/azure/cli/command_modules/acs/_params.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,8 @@ def load_arguments(self, _):
476476
c.argument('enable_acns', action='store_true')
477477
c.argument('disable_acns_observability', action='store_true')
478478
c.argument('disable_acns_security', action='store_true')
479+
c.argument("if_match")
480+
c.argument("if_none_match")
479481

480482
with self.argument_context('aks update') as c:
481483
# managed cluster paramerters
@@ -629,6 +631,8 @@ def load_arguments(self, _):
629631
c.argument('yes', options_list=['--yes', '-y'], help='Do not prompt for confirmation.', action='store_true')
630632
c.argument('enable_cost_analysis', action='store_true')
631633
c.argument('disable_cost_analysis', action='store_true')
634+
c.argument("if_match")
635+
c.argument("if_none_match")
632636

633637
with self.argument_context('aks disable-addons', resource_type=ResourceType.MGMT_CONTAINERSERVICE, operation_group='managed_clusters') as c:
634638
c.argument('addons', options_list=['--addons', '-a'])
@@ -782,6 +786,8 @@ def load_arguments(self, _):
782786
help='space-separated tags: key[=value] [key[=value] ...].')
783787
c.argument('enable_vtpm', action='store_true')
784788
c.argument('enable_secure_boot', action='store_true')
789+
c.argument("if_match")
790+
c.argument("if_none_match")
785791

786792
with self.argument_context('aks nodepool update', resource_type=ResourceType.MGMT_CONTAINERSERVICE, operation_group='agent_pools') as c:
787793
c.argument('enable_cluster_autoscaler', options_list=[
@@ -809,6 +815,8 @@ def load_arguments(self, _):
809815
c.argument('disable_vtpm', action='store_true')
810816
c.argument('enable_secure_boot', action='store_true')
811817
c.argument('disable_secure_boot', action='store_true')
818+
c.argument("if_match")
819+
c.argument("if_none_match")
812820

813821
with self.argument_context('aks nodepool upgrade') as c:
814822
c.argument('max_surge', validator=validate_max_surge)
@@ -930,6 +938,9 @@ def load_arguments(self, _):
930938
c.argument('dns_zone_resource_ids', options_list=['--ids'], required=True)
931939
c.argument('attach_zones')
932940

941+
with self.argument_context('aks nodepool delete') as c:
942+
c.argument("if_match")
943+
933944
with self.argument_context("aks nodepool delete-machines") as c:
934945
c.argument(
935946
"machine_names",

src/azure-cli/azure/cli/command_modules/acs/agentpool_decorator.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
MutuallyExclusiveArgumentError,
3939
RequiredArgumentMissingError,
4040
)
41+
from azure.cli.core.cloud import get_active_cloud
4142
from azure.cli.core.commands import AzCliCommand
4243
from azure.cli.core.profiles import ResourceType
4344
from azure.cli.core.util import get_file_json, sdk_no_wait
@@ -1504,6 +1505,20 @@ def get_disable_windows_outbound_nat(self) -> bool:
15041505
"""
15051506
return self._get_disable_windows_outbound_nat()
15061507

1508+
def get_if_match(self) -> str:
1509+
"""Obtain the value of if_match.
1510+
1511+
:return: string
1512+
"""
1513+
return self.raw_param.get("if_match")
1514+
1515+
def get_if_none_match(self) -> str:
1516+
"""Obtain the value of if_none_match.
1517+
1518+
:return: string
1519+
"""
1520+
return self.raw_param.get("if_none_match")
1521+
15071522

15081523
class AKSAgentPoolAddDecorator:
15091524
def __init__(
@@ -1916,6 +1931,18 @@ def add_agentpool(self, agentpool: AgentPool) -> AgentPool:
19161931
"""
19171932
self._ensure_agentpool(agentpool)
19181933

1934+
active_cloud = get_active_cloud(self.cmd.cli_ctx)
1935+
if active_cloud.profile != "latest":
1936+
return sdk_no_wait(
1937+
self.context.get_no_wait(),
1938+
self.client.begin_create_or_update,
1939+
self.context.get_resource_group_name(),
1940+
self.context.get_cluster_name(),
1941+
self.context._get_nodepool_name(enable_validation=False),
1942+
agentpool,
1943+
headers=self.context.get_aks_custom_headers(),
1944+
)
1945+
19191946
return sdk_no_wait(
19201947
self.context.get_no_wait(),
19211948
self.client.begin_create_or_update,
@@ -1924,6 +1951,8 @@ def add_agentpool(self, agentpool: AgentPool) -> AgentPool:
19241951
# validated in "init_agentpool", skip to avoid duplicate api calls
19251952
self.context._get_nodepool_name(enable_validation=False),
19261953
agentpool,
1954+
if_match=self.context.get_if_match(),
1955+
if_none_match=self.context.get_if_none_match(),
19271956
headers=self.context.get_aks_custom_headers(),
19281957
)
19291958

@@ -2221,12 +2250,26 @@ def update_agentpool(self, agentpool: AgentPool) -> AgentPool:
22212250
"""
22222251
self._ensure_agentpool(agentpool)
22232252

2253+
active_cloud = get_active_cloud(self.cmd.cli_ctx)
2254+
if active_cloud.profile != "latest":
2255+
return sdk_no_wait(
2256+
self.context.get_no_wait(),
2257+
self.client.begin_create_or_update,
2258+
self.context.get_resource_group_name(),
2259+
self.context.get_cluster_name(),
2260+
self.context.get_nodepool_name(),
2261+
agentpool,
2262+
headers=self.context.get_aks_custom_headers(),
2263+
)
2264+
22242265
return sdk_no_wait(
22252266
self.context.get_no_wait(),
22262267
self.client.begin_create_or_update,
22272268
self.context.get_resource_group_name(),
22282269
self.context.get_cluster_name(),
22292270
self.context.get_nodepool_name(),
22302271
agentpool,
2272+
if_match=self.context.get_if_match(),
2273+
if_none_match=self.context.get_if_none_match(),
22312274
headers=self.context.get_aks_custom_headers(),
22322275
)

src/azure-cli/azure/cli/command_modules/acs/custom.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
ValidationError,
9393
RequiredArgumentMissingError,
9494
)
95+
from azure.cli.core.cloud import get_active_cloud
9596
from azure.cli.core.commands import LongRunningOperation
9697
from azure.cli.core.commands.client_factory import get_subscription_id
9798
from azure.cli.core.profiles import ResourceType
@@ -641,6 +642,8 @@ def aks_create(
641642
no_wait=False,
642643
aks_custom_headers=None,
643644
node_public_ip_tags=None,
645+
if_match=None,
646+
if_none_match=None,
644647
# metrics profile
645648
enable_cost_analysis=False,
646649
# trusted launch
@@ -802,6 +805,8 @@ def aks_update(
802805
yes=False,
803806
no_wait=False,
804807
aks_custom_headers=None,
808+
if_match=None,
809+
if_none_match=None,
805810
# metrics profile
806811
enable_cost_analysis=False,
807812
disable_cost_analysis=False,
@@ -840,7 +845,9 @@ def aks_upgrade(cmd,
840845
upgrade_override_until=None,
841846
tier=None,
842847
k8s_support_plan=None,
843-
yes=False):
848+
yes=False,
849+
if_match=None,
850+
if_none_match=None):
844851
msg = 'Kubernetes may be unavailable during cluster upgrades.\n Are you sure you want to perform this operation?'
845852
if not yes and not prompt_y_n(msg, default="n"):
846853
return None
@@ -933,7 +940,11 @@ def aks_upgrade(cmd,
933940
# null out the SP profile because otherwise validation complains
934941
instance.service_principal_profile = None
935942

936-
return sdk_no_wait(no_wait, client.begin_create_or_update, resource_group_name, name, instance)
943+
active_cloud = get_active_cloud(cmd.cli_ctx)
944+
if active_cloud.profile != "latest":
945+
return sdk_no_wait(no_wait, client.begin_create_or_update, resource_group_name, name, instance)
946+
947+
return sdk_no_wait(no_wait, client.begin_create_or_update, resource_group_name, name, instance, if_match=if_match, if_none_match=if_none_match)
937948

938949

939950
def _update_upgrade_settings(cmd, instance,
@@ -2391,6 +2402,9 @@ def aks_agentpool_add(
23912402
# trusted launch
23922403
enable_vtpm=False,
23932404
enable_secure_boot=False,
2405+
# etag headers
2406+
if_match=None,
2407+
if_none_match=None,
23942408
):
23952409
# DO NOT MOVE: get all the original parameters and save them as a dictionary
23962410
raw_parameters = locals()
@@ -2446,6 +2460,9 @@ def aks_agentpool_update(
24462460
disable_vtpm=False,
24472461
enable_secure_boot=False,
24482462
disable_secure_boot=False,
2463+
# etag headers
2464+
if_match=None,
2465+
if_none_match=None,
24492466
):
24502467
# DO NOT MOVE: get all the original parameters and save them as a dictionary
24512468
raw_parameters = locals()
@@ -2484,7 +2501,9 @@ def aks_agentpool_upgrade(cmd, client, resource_group_name, cluster_name,
24842501
snapshot_id=None,
24852502
no_wait=False,
24862503
aks_custom_headers=None,
2487-
yes=False):
2504+
yes=False,
2505+
if_match=None,
2506+
if_none_match=None):
24882507
AgentPoolUpgradeSettings = cmd.get_models(
24892508
"AgentPoolUpgradeSettings",
24902509
resource_type=ResourceType.MGMT_CONTAINERSERVICE,
@@ -2571,6 +2590,8 @@ def aks_agentpool_upgrade(cmd, client, resource_group_name, cluster_name,
25712590
nodepool_name,
25722591
instance,
25732592
headers=aks_custom_headers,
2593+
if_match=if_match,
2594+
if_none_match=if_none_match,
25742595
)
25752596

25762597

@@ -2644,7 +2665,8 @@ def aks_agentpool_stop(cmd, # pylint: disable=unused-argument
26442665

26452666
def aks_agentpool_delete(cmd, client, resource_group_name, cluster_name,
26462667
nodepool_name,
2647-
no_wait=False):
2668+
no_wait=False,
2669+
if_match=None):
26482670
agentpool_exists = False
26492671
instances = client.list(resource_group_name, cluster_name)
26502672
for agentpool_profile in instances:
@@ -2656,7 +2678,11 @@ def aks_agentpool_delete(cmd, client, resource_group_name, cluster_name,
26562678
raise CLIError("Node pool {} doesnt exist, "
26572679
"use 'aks nodepool list' to get current node pool list".format(nodepool_name))
26582680

2659-
return sdk_no_wait(no_wait, client.begin_delete, resource_group_name, cluster_name, nodepool_name)
2681+
active_cloud = get_active_cloud(cmd.cli_ctx)
2682+
if active_cloud.profile != "latest":
2683+
return sdk_no_wait(no_wait, client.begin_delete, resource_group_name, cluster_name, nodepool_name)
2684+
2685+
return sdk_no_wait(no_wait, client.begin_delete, resource_group_name, cluster_name, nodepool_name, if_match=if_match)
26602686

26612687

26622688
def aks_agentpool_operation_abort(cmd,

0 commit comments

Comments
 (0)