Skip to content

[AKS] Preserve existing ACNS settings during partial updates#33049

Open
nddq wants to merge 1 commit intoAzure:devfrom
nddq:fix/acns-update-preserve-existing-state-v2
Open

[AKS] Preserve existing ACNS settings during partial updates#33049
nddq wants to merge 1 commit intoAzure:devfrom
nddq:fix/acns-update-preserve-existing-state-v2

Conversation

@nddq
Copy link
Copy Markdown
Member

@nddq nddq commented Mar 25, 2026

Currently update_network_profile_advanced_networking creates a new AdvancedNetworking object on every update call, replacing the existing one wholesale. When a user updates only a single ACNS sub-property (e.g. --acns-advanced-networkpolicies L7), existing sub-properties like observability, security, and transit encryption are discarded because they weren't re-specified.

This PR changes the update path to modify the existing AdvancedNetworking object in-place, only overwriting fields the user explicitly provided.

  • Decorator: Mutate mc.network_profile.advanced_networking in-place instead of constructing a fresh object and replacing it
  • Unit tests: Add test_update_network_profile_advanced_networking_preserves_existing_state covering partial updates to network policies, observability, and disable flows
  • Live test: Add test_aks_update_acns_preserves_existing_settings — creates a cluster with ACNS, updates only network policies, then updates only transit encryption, verifying all existing settings survive each step

Testing

Unit tests:

python -m pytest src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_managed_cluster_decorator.py -k "test_update_network_profile_advanced_networking" -xvs
# 4 passed

Live test:

python -m pytest src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py -k "test_aks_update_acns_preserves_existing_settings" -xvs
# 1 passed in 864.37s

Copilot AI review requested due to automatic review settings March 25, 2026 21:27
@azure-client-tools-bot-prd
Copy link
Copy Markdown

azure-client-tools-bot-prd bot commented Mar 25, 2026

❌AzureCLI-FullTest
️✔️acr
️✔️latest
️✔️3.12
️✔️3.13
❌acs
❌latest
❌3.12
Type Test Case Error Message Line
Failed test_aks_update_acns_preserves_existing_settings self = <azure.cli.testsdk.base.ExecutionResult object at 0x7f4254522570>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7f425786b770>
command = 'aks update --resource-group=clitest000001 --name=cliakstest000001 --acns-transit-encryption-type WireGuard '
expect_failure = False

    def in_process_execute(self, cli_ctx, command, expect_failure=False):
        from io import StringIO
        from vcr.errors import CannotOverwriteExistingCassetteException
    
        if command.startswith('az '):
            command = command[3:]
    
        stdout_buf = StringIO()
        logging_buf = StringIO()
        try:
            # issue: stderr cannot be redirect in this form, as a result some failure information
            # is lost when command fails.
>           self.exit_code = cli_ctx.invoke(shlex.split(command), out_file=stdout_buf) or 0
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

src/azure-cli-testsdk/azure/cli/testsdk/base.py:303: 
                                        
env/lib/python3.12/site-packages/knack/cli.py:245: in invoke
    exit_code = self.exception_handler(ex)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/init.py:157: in exception_handler
    return handle_exception(ex)
           ^^^^^^^^^^^^^^^^^^^^
                                        

ex = ResourceExistsError("(OperationNotAllowed) Operation is not allowed because there's an in progress PutExtensionAddonHa...finish before starting a new operation. You can also use 'az aks operation-abort ...' to abort the ongoing operation.")
args = (), kwargs = {}

    def handle_main_exception(ex, *args, **kwargs):  # pylint: disable=unused-argument
        if isinstance(ex, CannotOverwriteExistingCassetteException):
            # This exception usually caused by a no match HTTP request. This is a product error
            # that is caused by change of SDK invocation.
            raise ex
    
>       raise CliExecutionError(ex)
E       azure.cli.testsdk.exceptions.CliExecutionError: The CLI throws exception ResourceExistsError during execution and fails the command.

src/azure-cli-testsdk/azure/cli/testsdk/patches.py:35: CliExecutionError

During handling of the above exception, another exception occurred:

self = <azure.cli.command_modules.acs.tests.latest.test_aks_commands.AzureKubernetesServiceScenarioTest testMethod=test_aks_update_acns_preserves_existing_settings>
resource_group = 'clitest000001', resource_group_location = 'westcentralus'

    @AllowLargeResponse()
    @AKSCustomResourceGroupPreparer(
        random_name_length=17,
        name_prefix="clitest",
        location="westcentralus",
    )
    def test_aks_update_acns_preserves_existing_settings(
        self, resource_group, resource_group_location
    ):
        self.test_resources_count = 0
        aks_name = self.create_random_name("cliakstest", 16)
        self.kwargs.update(
            {
                "resource_group": resource_group,
                "name": aks_name,
                "ssh_key_value": self.generate_ssh_keys(),
                "location": resource_group_location,
            }
        )
    
        # Create cluster with ACNS enabled (gets observability + security by default)
        create_cmd = (
            "aks create --resource-group={resource_group} --name={name} --location={location} "
            "--ssh-key-value={ssh_key_value} --node-count=1 --tier standard "
            "--network-plugin azure --network-dataplane=cilium --network-plugin-mode overlay "
            "--enable-acns "
        )
        self.cmd(
            create_cmd,
            checks=[
                self.check("provisioningState", "Succeeded"),
                self.check("networkProfile.advancedNetworking.enabled", True),
                self.check("networkProfile.advancedNetworking.observability.enabled", True),
                self.check("networkProfile.advancedNetworking.security.enabled", True),
            ],
        )
    
        # Update only network policies - existing observability and security.enabled should be preserved
        update_cmd = (
            "aks update --resource-group={resource_group} --name={name} "
            "--enable-acns --acns-advanced-networkpolicies L7 "
        )
        self.cmd(
            update_cmd,
            checks=[
                self.check("provisioningState", "Succeeded"),
                self.check("networkProfile.advancedNetworking.enabled", True),
                self.check("networkProfile.advancedNetworking.observability.enabled", True),
                self.check("networkProfile.advancedNetworking.security.enabled", True),
                self.check("networkProfile.advancedNetworking.security.advancedNetworkPolicies", "L7"),
            ],
        )
    
        # Update only transit encryption - existing observability, security, and network policies should be preserved
        update_cmd_2 = (
            "aks update --resource-group={resource_group} --name={name} "
            "--acns-transit-encryption-type WireGuard "
        )
>       self.cmd(
            update_cmd_2,
            checks=[
                self.check("provisioningState", "Succeeded"),
                self.check("networkProfile.advancedNetworking.enabled", True),
                self.check("networkProfile.advancedNetworking.observability.enabled", True),
                self.check("networkProfile.advancedNetworking.security.enabled", True),
                self.check("networkProfile.advancedNetworking.security.advancedNetworkPolicies", "L7"),
                self.check("networkProfile.advancedNetworking.security.transitEncryption.type", "WireGuard"),
            ],
        )

src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py:13718: 
 
                                       
src/azure-cli-testsdk/azure/cli/testsdk/base.py:177: in cmd
    return execute(self.cli_ctx, command, expect_failure=expect_failure).assert_with_checks(checks)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-testsdk/azure/cli/testsdk/base.py:252: in init
    self.in_process_execute(cli_ctx, command, expect_failure=expect_failure)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:315: in in_process_execute
    raise ex.exception
env/lib/python3.12/site-packages/knack/cli.py:233: in invoke
    cmd_result = self.invocation.execute(args)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/init.py:677: in execute
    raise ex
src/azure-cli-core/azure/cli/core/commands/init.py:820: in run_jobs_serially
    results.append(self.run_job(expanded_arg, cmd_copy))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/init.py:789: in run_job
    result = cmd_copy(params)
             ^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/init.py:335: in call
    return self.handler(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/command_operation.py:120: in handler
    return op(**command_args)
           ^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/acs/custom.py:1250: in aks_update
    return aks_update_decorator.update_mc(mc)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py:10319: in update_mc
    return self.put_mc(mc)
           ^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py:10301: in put_mc
    cluster = sdk_no_wait(
src/azure-cli-core/azure/cli/core/util.py:794: in sdk_no_wait
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/tracing/decorator.py:119: in wrapper_use_tracer
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/mgmt/containerservice/operations/operations.py:3600: in begin_create_or_update
    raw_result = self.create_or_update_initial(
env/lib/python3.12/site-packages/azure/mgmt/containerservice/operations/operations.py:3434: in create_or_update_initial
    map_error(status_code=response.status_code, response=response, error_map=error_map)
 
 
 
 
 
 
 
 
                               _ 

status_code = 409
response = HttpResponse: 409 Conflict, Content-Type: application/json
error_map = {304: <class 'azure.core.exceptions.ResourceNotModifiedError'>, 401: <class 'azure.core.exceptions.ClientAuthenticatio..., 404: <class 'azure.core.exceptions.ResourceNotFoundError'>, 409: <class 'azure.core.exceptions.ResourceExistsError'>}

    def map_error(
        status_code: int,
        response: _HttpResponseCommonAPI,
        error_map: Mapping[int, Type[HttpResponseError]],
    ) -> None:
        if not error_map:
            return
        error_type = error_map.get(status_code)
        if not error_type:
            return
        error = error_type(response=response)
>       raise error
E       azure.core.exceptions.ResourceExistsError: (OperationNotAllowed) Operation is not allowed because there's an in progress PutExtensionAddonHandler.PUT operation (operation ID: aff3bc5e-7e90-4746-a026-0bba7ee5922a) on the managed cluster started on UTC 2026-03-30T08:05:33Z. Please wait for it to finish before starting a new operation. You can also use 'az aks operation-abort ...' to abort the ongoing operation.
E       Code: OperationNotAllowed
E       Message: Operation is not allowed because there's an in progress PutExtensionAddonHandler.PUT operation (operation ID: aff3bc5e-7e90-4746-a026-0bba7ee5922a) on the managed cluster started on UTC 2026-03-30T08:05:33Z. Please wait for it to finish before starting a new operation. You can also use 'az aks operation-abort ...' to abort the ongoing operation.

env/lib/python3.12/site-packages/azure/core/exceptions.py:163: ResourceExistsError
azure/cli/command_modules/acs/tests/latest/test_aks_commands.py:13659
❌3.13
Type Test Case Error Message Line
Failed test_aks_update_acns_preserves_existing_settings self = <azure.cli.testsdk.base.ExecutionResult object at 0x7f82b71ece10>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7f82bade5450>
command = 'aks update --resource-group=clitest000001 --name=cliakstest000001 --acns-transit-encryption-type WireGuard '
expect_failure = False

    def in_process_execute(self, cli_ctx, command, expect_failure=False):
        from io import StringIO
        from vcr.errors import CannotOverwriteExistingCassetteException
    
        if command.startswith('az '):
            command = command[3:]
    
        stdout_buf = StringIO()
        logging_buf = StringIO()
        try:
            # issue: stderr cannot be redirect in this form, as a result some failure information
            # is lost when command fails.
>           self.exit_code = cli_ctx.invoke(shlex.split(command), out_file=stdout_buf) or 0
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

src/azure-cli-testsdk/azure/cli/testsdk/base.py:303: 
                                        
env/lib/python3.13/site-packages/knack/cli.py:245: in invoke
    exit_code = self.exception_handler(ex)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/init.py:157: in exception_handler
    return handle_exception(ex)
           ^^^^^^^^^^^^^^^^^^^^
                                        

ex = ResourceExistsError("(OperationNotAllowed) Operation is not allowed because there's an in progress PutExtensionAddonHa...finish before starting a new operation. You can also use 'az aks operation-abort ...' to abort the ongoing operation.")
args = (), kwargs = {}

    def handle_main_exception(ex, *args, **kwargs):  # pylint: disable=unused-argument
        if isinstance(ex, CannotOverwriteExistingCassetteException):
            # This exception usually caused by a no match HTTP request. This is a product error
            # that is caused by change of SDK invocation.
            raise ex
    
>       raise CliExecutionError(ex)
E       azure.cli.testsdk.exceptions.CliExecutionError: The CLI throws exception ResourceExistsError during execution and fails the command.

src/azure-cli-testsdk/azure/cli/testsdk/patches.py:35: CliExecutionError

During handling of the above exception, another exception occurred:

self = <azure.cli.command_modules.acs.tests.latest.test_aks_commands.AzureKubernetesServiceScenarioTest testMethod=test_aks_update_acns_preserves_existing_settings>
resource_group = 'clitest000001', resource_group_location = 'westcentralus'

    @AllowLargeResponse()
    @AKSCustomResourceGroupPreparer(
        random_name_length=17,
        name_prefix="clitest",
        location="westcentralus",
    )
    def test_aks_update_acns_preserves_existing_settings(
        self, resource_group, resource_group_location
    ):
        self.test_resources_count = 0
        aks_name = self.create_random_name("cliakstest", 16)
        self.kwargs.update(
            {
                "resource_group": resource_group,
                "name": aks_name,
                "ssh_key_value": self.generate_ssh_keys(),
                "location": resource_group_location,
            }
        )
    
        # Create cluster with ACNS enabled (gets observability + security by default)
        create_cmd = (
            "aks create --resource-group={resource_group} --name={name} --location={location} "
            "--ssh-key-value={ssh_key_value} --node-count=1 --tier standard "
            "--network-plugin azure --network-dataplane=cilium --network-plugin-mode overlay "
            "--enable-acns "
        )
        self.cmd(
            create_cmd,
            checks=[
                self.check("provisioningState", "Succeeded"),
                self.check("networkProfile.advancedNetworking.enabled", True),
                self.check("networkProfile.advancedNetworking.observability.enabled", True),
                self.check("networkProfile.advancedNetworking.security.enabled", True),
            ],
        )
    
        # Update only network policies - existing observability and security.enabled should be preserved
        update_cmd = (
            "aks update --resource-group={resource_group} --name={name} "
            "--enable-acns --acns-advanced-networkpolicies L7 "
        )
        self.cmd(
            update_cmd,
            checks=[
                self.check("provisioningState", "Succeeded"),
                self.check("networkProfile.advancedNetworking.enabled", True),
                self.check("networkProfile.advancedNetworking.observability.enabled", True),
                self.check("networkProfile.advancedNetworking.security.enabled", True),
                self.check("networkProfile.advancedNetworking.security.advancedNetworkPolicies", "L7"),
            ],
        )
    
        # Update only transit encryption - existing observability, security, and network policies should be preserved
        update_cmd_2 = (
            "aks update --resource-group={resource_group} --name={name} "
            "--acns-transit-encryption-type WireGuard "
        )
>       self.cmd(
            update_cmd_2,
            checks=[
                self.check("provisioningState", "Succeeded"),
                self.check("networkProfile.advancedNetworking.enabled", True),
                self.check("networkProfile.advancedNetworking.observability.enabled", True),
                self.check("networkProfile.advancedNetworking.security.enabled", True),
                self.check("networkProfile.advancedNetworking.security.advancedNetworkPolicies", "L7"),
                self.check("networkProfile.advancedNetworking.security.transitEncryption.type", "WireGuard"),
            ],
        )

src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py:13718: 
 
                                       
src/azure-cli-testsdk/azure/cli/testsdk/base.py:177: in cmd
    return execute(self.cli_ctx, command, expect_failure=expect_failure).assert_with_checks(checks)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-testsdk/azure/cli/testsdk/base.py:252: in init
    self.in_process_execute(cli_ctx, command, expect_failure=expect_failure)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:315: in in_process_execute
    raise ex.exception
env/lib/python3.13/site-packages/knack/cli.py:233: in invoke
    cmd_result = self.invocation.execute(args)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/init.py:677: in execute
    raise ex
src/azure-cli-core/azure/cli/core/commands/init.py:820: in run_jobs_serially
    results.append(self.run_job(expanded_arg, cmd_copy))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/init.py:789: in run_job
    result = cmd_copy(params)
             ^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/init.py:335: in call
    return self.handler(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/command_operation.py:120: in handler
    return op(**command_args)
           ^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/acs/custom.py:1250: in aks_update
    return aks_update_decorator.update_mc(mc)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py:10319: in update_mc
    return self.put_mc(mc)
           ^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py:10301: in put_mc
    cluster = sdk_no_wait(
src/azure-cli-core/azure/cli/core/util.py:794: in sdk_no_wait
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/tracing/decorator.py:119: in wrapper_use_tracer
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/mgmt/containerservice/operations/operations.py:3600: in begin_create_or_update
    raw_result = self.create_or_update_initial(
env/lib/python3.13/site-packages/azure/mgmt/containerservice/operations/operations.py:3434: in create_or_update_initial
    map_error(status_code=response.status_code, response=response, error_map=error_map)
 
 
 
 
 
 
 
 
                               _ 

status_code = 409
response = HttpResponse: 409 Conflict, Content-Type: application/json
error_map = {304: <class 'azure.core.exceptions.ResourceNotModifiedError'>, 401: <class 'azure.core.exceptions.ClientAuthenticatio..., 404: <class 'azure.core.exceptions.ResourceNotFoundError'>, 409: <class 'azure.core.exceptions.ResourceExistsError'>}

    def map_error(
        status_code: int,
        response: _HttpResponseCommonAPI,
        error_map: Mapping[int, Type[HttpResponseError]],
    ) -> None:
        if not error_map:
            return
        error_type = error_map.get(status_code)
        if not error_type:
            return
        error = error_type(response=response)
>       raise error
E       azure.core.exceptions.ResourceExistsError: (OperationNotAllowed) Operation is not allowed because there's an in progress PutExtensionAddonHandler.PUT operation (operation ID: aff3bc5e-7e90-4746-a026-0bba7ee5922a) on the managed cluster started on UTC 2026-03-30T08:05:33Z. Please wait for it to finish before starting a new operation. You can also use 'az aks operation-abort ...' to abort the ongoing operation.
E       Code: OperationNotAllowed
E       Message: Operation is not allowed because there's an in progress PutExtensionAddonHandler.PUT operation (operation ID: aff3bc5e-7e90-4746-a026-0bba7ee5922a) on the managed cluster started on UTC 2026-03-30T08:05:33Z. Please wait for it to finish before starting a new operation. You can also use 'az aks operation-abort ...' to abort the ongoing operation.

env/lib/python3.13/site-packages/azure/core/exceptions.py:163: ResourceExistsError
azure/cli/command_modules/acs/tests/latest/test_aks_commands.py:13659
️✔️advisor
️✔️latest
️✔️3.12
️✔️3.13
️✔️ams
️✔️latest
️✔️3.12
️✔️3.13
️✔️apim
️✔️latest
️✔️3.12
️✔️3.13
️✔️appconfig
️✔️latest
️✔️3.12
️✔️3.13
️✔️appservice
️✔️latest
️✔️3.12
️✔️3.13
️✔️aro
️✔️latest
️✔️3.12
️✔️3.13
️✔️backup
️✔️latest
️✔️3.12
️✔️3.13
️✔️batch
️✔️latest
️✔️3.12
️✔️3.13
️✔️batchai
️✔️latest
️✔️3.12
️✔️3.13
️✔️billing
️✔️latest
️✔️3.12
️✔️3.13
️✔️botservice
️✔️latest
️✔️3.12
️✔️3.13
️✔️cdn
️✔️latest
️✔️3.12
️✔️3.13
️✔️cloud
️✔️latest
️✔️3.12
️✔️3.13
️✔️cognitiveservices
️✔️latest
️✔️3.12
️✔️3.13
️✔️compute_recommender
️✔️latest
️✔️3.12
️✔️3.13
️✔️computefleet
️✔️latest
️✔️3.12
️✔️3.13
️✔️config
️✔️latest
️✔️3.12
️✔️3.13
️✔️configure
️✔️latest
️✔️3.12
️✔️3.13
️✔️consumption
️✔️latest
️✔️3.12
️✔️3.13
️✔️container
️✔️latest
️✔️3.12
️✔️3.13
️✔️containerapp
️✔️latest
️✔️3.12
️✔️3.13
️✔️core
️✔️latest
️✔️3.12
️✔️3.13
️✔️cosmosdb
️✔️latest
️✔️3.12
️✔️3.13
️✔️databoxedge
️✔️latest
️✔️3.12
️✔️3.13
️✔️dls
️✔️latest
️✔️3.12
️✔️3.13
️✔️dms
️✔️latest
️✔️3.12
️✔️3.13
️✔️eventgrid
️✔️latest
️✔️3.12
️✔️3.13
️✔️eventhubs
️✔️latest
️✔️3.12
️✔️3.13
️✔️feedback
️✔️latest
️✔️3.12
️✔️3.13
️✔️find
️✔️latest
️✔️3.12
️✔️3.13
️✔️hdinsight
️✔️latest
️✔️3.12
️✔️3.13
️✔️identity
️✔️latest
️✔️3.12
️✔️3.13
️✔️iot
️✔️latest
️✔️3.12
️✔️3.13
️✔️keyvault
️✔️latest
️✔️3.12
️✔️3.13
️✔️lab
️✔️latest
️✔️3.12
️✔️3.13
️✔️managedservices
️✔️latest
️✔️3.12
️✔️3.13
️✔️maps
️✔️latest
️✔️3.12
️✔️3.13
️✔️marketplaceordering
️✔️latest
️✔️3.12
️✔️3.13
️✔️monitor
️✔️latest
️✔️3.12
️✔️3.13
️✔️mysql
️✔️latest
️✔️3.12
️✔️3.13
️✔️netappfiles
️✔️latest
️✔️3.12
️✔️3.13
️✔️network
️✔️latest
️✔️3.12
️✔️3.13
️✔️policyinsights
️✔️latest
️✔️3.12
️✔️3.13
️✔️postgresql
️✔️latest
️✔️3.12
️✔️3.13
️✔️privatedns
️✔️latest
️✔️3.12
️✔️3.13
️✔️profile
️✔️latest
️✔️3.12
️✔️3.13
️✔️rdbms
️✔️latest
️✔️3.12
️✔️3.13
️✔️redis
️✔️latest
️✔️3.12
️✔️3.13
️✔️relay
️✔️latest
️✔️3.12
️✔️3.13
️✔️resource
️✔️latest
️✔️3.12
️✔️3.13
️✔️role
️✔️latest
️✔️3.12
️✔️3.13
️✔️search
️✔️latest
️✔️3.12
️✔️3.13
️✔️security
️✔️latest
️✔️3.12
️✔️3.13
️✔️servicebus
️✔️latest
️✔️3.12
️✔️3.13
️✔️serviceconnector
️✔️latest
️✔️3.12
️✔️3.13
️✔️servicefabric
️✔️latest
️✔️3.12
️✔️3.13
️✔️signalr
️✔️latest
️✔️3.12
️✔️3.13
️✔️sql
️✔️latest
️✔️3.12
️✔️3.13
️✔️sqlvm
️✔️latest
️✔️3.12
️✔️3.13
️✔️storage
️✔️latest
️✔️3.12
️✔️3.13
️✔️synapse
️✔️latest
️✔️3.12
️✔️3.13
️✔️telemetry
️✔️latest
️✔️3.12
️✔️3.13
️✔️util
️✔️latest
️✔️3.12
️✔️3.13
️✔️vm
️✔️latest
️✔️3.12
️✔️3.13

@azure-client-tools-bot-prd
Copy link
Copy Markdown

Hi @nddq,
Since the current milestone time is less than 7 days, this pr will be reviewed in the next milestone.

@azure-client-tools-bot-prd
Copy link
Copy Markdown

azure-client-tools-bot-prd bot commented Mar 25, 2026

️✔️AzureCLI-BreakingChangeTest
️✔️Non Breaking Changes

@yonzhan
Copy link
Copy Markdown
Collaborator

yonzhan commented Mar 25, 2026

Thank you for your contribution! We will review the pull request and get back to you soon.

@github-actions
Copy link
Copy Markdown

The git hooks are available for azure-cli and azure-cli-extensions repos. They could help you run required checks before creating the PR.

Please sync the latest code with latest dev branch (for azure-cli) or main branch (for azure-cli-extensions).
After that please run the following commands to enable git hooks:

pip install azdev --upgrade
azdev setup -c <your azure-cli repo path> -r <your azure-cli-extensions repo path>

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses an AKS update-path issue where partial ACNS updates could unintentionally drop existing advancedNetworking sub-settings by replacing the entire AdvancedNetworking object, instead of updating only user-specified fields.

Changes:

  • Update decorator logic to mutate mc.network_profile.advanced_networking in-place and only overwrite explicitly provided ACNS fields.
  • Add/extend unit tests to validate partial updates preserve existing ACNS state.
  • Add a live test that performs sequential partial updates (network policies, then transit encryption) and verifies settings persist.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py Switches ACNS update logic from “replace object” to “mutate existing object” for partial updates.
src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_managed_cluster_decorator.py Adds unit coverage for preserving existing ACNS sub-properties across partial updates.
src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py Adds a live test ensuring sequential partial ACNS updates preserve previously-set values.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@nddq nddq force-pushed the fix/acns-update-preserve-existing-state-v2 branch from 22be663 to 37d1788 Compare March 25, 2026 22:58
@FumingZhang
Copy link
Copy Markdown
Member

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

Copy link
Copy Markdown
Member

@FumingZhang FumingZhang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update the PR title or description to meet the required history note format so the CI check can pass.

User-Agent:
- AZURECLI/2.84.0 azsdk-python-core/1.38.3 Python/3.12.3 (Linux-6.17.0-1008-azure-x86_64-with-glibc2.39)
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.ContainerService/managedClusters/cliakstest000001?api-version=2025-10-02-preview
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The recording file is outdated—the API version used is 2025-10-02-preview, but it should be a stable API version, which is now 2026-01-01. Please generate a new recording file.

name_prefix="clitest",
location="westcentralus",
)
def test_aks_update_acns_preserves_existing_settings(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Queued live test to validate the change.

  • test_aks_update_acns_preserves_existing_settings

You might consider running the test with other related existing test cases to make sure the change doesn't cause any regression.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-queued live test

User-Agent:
- AZURECLI/2.84.0 azsdk-python-core/1.38.3 Python/3.12.3 (Linux-6.17.0-1008-azure-x86_64-with-glibc2.39)
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.ContainerService/managedClusters/cliakstest000001?api-version=2025-10-02-preview
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The recording file is outdated—the API version used is 2025-10-02-preview, but it should be a stable API version, which is now 2026-01-01. Please generate a new recording file.

@nddq nddq force-pushed the fix/acns-update-preserve-existing-state-v2 branch 2 times, most recently from fdb827a to e8ddb8e Compare March 26, 2026 02:31
@FumingZhang
Copy link
Copy Markdown
Member

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@FumingZhang
Copy link
Copy Markdown
Member

There's a merge conflict in your PR; please resolve it first. Also, the code cutoff for the upcoming official azure-cli release (03/31/2026 06:00 UTC) is approaching. Make sure both CI and live tests pass to meet the minimum requirements for the PR to be accepted and merged. @nddq

@nddq nddq force-pushed the fix/acns-update-preserve-existing-state-v2 branch from e8ddb8e to 9ca3063 Compare March 30, 2026 05:46
@FumingZhang
Copy link
Copy Markdown
Member

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@nddq nddq changed the title fix(aks): preserve existing ACNS settings during partial updates [AKS] Fix: preserve existing ACNS settings during partial updates Mar 30, 2026
The update_network_profile_advanced_networking method was creating a
new AdvancedNetworking object on every update, discarding existing
sub-properties (observability, security, transit encryption) that the
user didn't explicitly specify. This changes the method to modify the
existing object in-place, only overwriting fields the user provided.
When disabling ACNS, sub-features are explicitly set to disabled to
ensure a consistent payload.

Signed-off-by: Quang Nguyen <nguyenquang@microsoft.com>
@nddq nddq force-pushed the fix/acns-update-preserve-existing-state-v2 branch from 9ca3063 to f80b386 Compare March 30, 2026 09:12
@FumingZhang
Copy link
Copy Markdown
Member

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@FumingZhang
Copy link
Copy Markdown
Member

Re-queued live test

@FumingZhang FumingZhang changed the title [AKS] Fix: preserve existing ACNS settings during partial updates [AKS] Preserve existing ACNS settings during partial updates Mar 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

act-observability-squad AKS az aks/acs/openshift Auto-Assign Auto assign by bot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants