Skip to content

{Compute} az vmss: Migrate command group to aaz-based implementation#32857

Open
william051200 wants to merge 20 commits intoAzure:devfrom
william051200:vmss-migration
Open

{Compute} az vmss: Migrate command group to aaz-based implementation#32857
william051200 wants to merge 20 commits intoAzure:devfrom
william051200:vmss-migration

Conversation

@william051200
Copy link
Member

Related command

az vmss create
az vmss show
az vmss update
az vmss wait

Description

Migration from mgmt.compute to aaz-based

Testing Guide

History Notes


This checklist is used to make sure that common guidelines for a pull request are followed.

Copilot AI review requested due to automatic review settings February 26, 2026 00:02
@azure-client-tools-bot-prd
Copy link

azure-client-tools-bot-prd bot commented Feb 26, 2026

❌AzureCLI-FullTest
️✔️acr
️✔️latest
️✔️3.12
️✔️3.13
️✔️acs
️✔️latest
️✔️3.12
️✔️3.13
️✔️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
Type Test Case Error Message Line
Failed test_private_endpoint_connection_durable_task_scheduler self = <azure.cli.testsdk.base.ExecutionResult object at 0x7fe8ee6c3110>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7fe8ee2011c0>
command = 'network private-endpoint create --resource-group cli_test_durable_task_pec000002 --name cli000005 --vnet-name cli0000.../Microsoft.DurableTask/schedulers/cli000007 --location centraluseuap --group-ids scheduler --connection-name cli000006'
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:141: in exception_handler
    return handle_exception(ex)
           ^^^^^^^^^^^^^^^^^^^^
src/azure-cli-testsdk/azure/cli/testsdk/patches.py:33: in handle_main_exception
    raise ex
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:682: in execute
    raise ex
src/azure-cli-core/azure/cli/core/commands/init.py:812: in run_jobs_serially
    results.append(self.run_job(expanded_arg, cmd_copy))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/init.py:792: in run_job
    result = LongRunningOperation(cmd_copy.cli_ctx, 'Starting {}'.format(cmd_copy.name))(result)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/init.py:1150: in call
    result = poller.result()
             ^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/aaz/poller.py:105: in result
    self.wait(timeout)
env/lib/python3.12/site-packages/azure/core/tracing/decorator.py:119: in wrapper_use_tracer
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/aaz/poller.py:127: in wait
    raise self.exception
src/azure-cli-core/azure/cli/core/aaz/poller.py:80: in start
    for polling_method in self.polling_generator:
                          ^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/private_endpoint/__cmds.py:1296: in execute_operations
    yield self.PrivateEndpointsCreateOrUpdate(ctx=self.ctx)()
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/private_endpoint/__cmds.py:1316: in call
    session = self.client.send_request(request=request, stream=False, **kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/aaz/client.py:108: in send_request
    session = self.pipeline.run(request, stream=stream, **kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:242: in run
    return first_node.send(pipeline_request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/mgmt/core/policies/base.py:95: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/policies/redirect.py:205: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/policies/retry.py:545: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/aaz/http_policy.py:112: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:130: in send
    self.sender.send(request.http_request, **request.context.options),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/transport/requests_basic.py:375: in send
    response = self.session.request(  # type: ignore
env/lib/python3.12/site-packages/requests/sessions.py:589: in request
    resp = self.send(prep, **send_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/requests/sessions.py:703: in send
    r = adapter.send(request, **kwargs)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/requests/adapters.py:667: in send
    resp = conn.urlopen(
env/lib/python3.12/site-packages/urllib3/connectionpool.py:787: in urlopen
    response = self.make_request(
env/lib/python3.12/site-packages/urllib3/connectionpool.py:534: in make_request
    response = conn.getresponse()
               ^^^^^^^^^^^^^^^^^^
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       

self = <VCRRequestsHTTPSConnection/mnt/vss/work/1/s/src/azure-cli/azure/cli/command_modules/network/tests/latest/recordings/test_private_endpoint_connection_durable_task_scheduler.yaml(host='management.azure.com', port=443) at 0x7fe8ee8c0dd0>
 = False, kwargs = {}

    def getresponse(self, =False, **kwargs):
        """Retrieve the response"""
        # Check to see if the cassette has a response for this request. If so,
        # then return it
        if self.cassette.can_play_response_for(self.vcr_request):
            log.info(f"Playing response for {self.vcr_request} from cassette")
            response = self.cassette.play_response(self.vcr_request)
            return VCRHTTPResponse(response)
        else:
            if self.cassette.write_protected and self.cassette.filter_request(self.vcr_request):
>               raise CannotOverwriteExistingCassetteException(
                    cassette=self.cassette,
                    failed_request=self.vcr_request,
                )
E               vcr.errors.CannotOverwriteExistingCassetteException: Can't overwrite existing cassette ('/mnt/vss/work/1/s/src/azure-cli/azure/cli/command_modules/network/tests/latest/recordings/test_private_endpoint_connection_durable_task_scheduler.yaml') in your current record mode ('once').
E               No match for the request (<Request (PUT) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_durable_task_pec000002/providers/Microsoft.Network/privateEndpoints/cli000005?api-version=2025-05-01>)&nbsp;was&nbsp;found.
E               Found 1 similar requests with 1 different matcher(s) :
E               
E               1 - (<Request (PUT) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_durable_task_pec000002/providers/Microsoft.Network/privateEndpoints/cli000005?api-version=2022-01-01>).
E               Matchers succeeded : ['method', 'scheme', 'host', 'port', 'path']
E               Matchers failed :
E               custom_request_query_matcher - assertion failure :
E               None

env/lib/python3.12/site-packages/vcr/stubs/init.py:277: CannotOverwriteExistingCassetteException

During handling of the above exception, another exception occurred:

self = <azure.cli.command_modules.network.tests.latest.test_private_endpoint_commands.NetworkPrivateLinkDurableTaskScenarioTest testMethod=test_private_endpoint_connection_durable_task_scheduler>
resource_group = 'cli_test_durable_task_pec000001'
resource_group_2 = 'cli_test_durable_task_pec000002'

    @AllowLargeResponse()
    @ResourceGroupPreparer(name_prefix='cli_test_durable_task_pec', location='centraluseuap')
    @ResourceGroupPreparer(name_prefix='cli_test_durable_task_pec', parameter_name='resource_group_2', location='centraluseuap')
    def test_private_endpoint_connection_durable_task_scheduler(self, resource_group, resource_group_2):
        self.kwargs.update({
            'resource_group_net': resource_group_2,
            'vnet_name': self.create_random_name(prefix='cli', length=20),
            'subnet_name': self.create_random_name(prefix='cli', length=20),
            'private_endpoint_name': self.create_random_name(prefix='cli', length=20),
            'connection_name': self.create_random_name(prefix='cli', length=20),
            'scheduler_name': self.create_random_name(prefix='cli', length=20),
            'location': 'centraluseuap',
            'approval_description': 'You are approved!',
            'rejection_description': 'You are rejected!',
            'rg': resource_group,
            'sub': self.get_subscription_id(),
            'body': '{\"location\": \"centraluseuap\", \"properties\": {\"ipAllowlist\": [], \"publicNetworkAccess\": \"Disabled\", \"sku\": {\"name\": \"Consumption\"}}}',
        })
    
        self.cmd('network vnet create --resource-group {resource_group_net} --location {location} --name {vnet_name} --address-prefix 10.0.0.0/16')
        self.cmd('network vnet subnet create --resource-group {resource_group_net} --vnet-name {vnet_name} --name {subnet_name} --address-prefixes 10.0.0.0/24')
        self.cmd('network vnet subnet update --resource-group {resource_group_net} --vnet-name {vnet_name} --name {subnet_name} --disable-private-endpoint-network-policies true')
    
        self.cmd(
            'rest --method "PUT" '
            '--url "https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}'
            '/providers/Microsoft.DurableTask/schedulers/{scheduler_name}?api-version=2026-02-01" '
            '--body "{body}"')
    
        scope = self.cmd(
            'rest --method "GET" '
            '--url "https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}'
            '/providers/Microsoft.DurableTask/schedulers/{scheduler_name}?api-version=2026-02-01"',
            checks=[
                self.check('name', self.kwargs['scheduler_name']),
                self.check('properties.provisioningState', 'Succeeded'),
                self.check('properties.publicNetworkAccess', 'Disabled')
            ]).get_output_in_json()['id']
    
        self.kwargs.update({
            'scope': scope,
        })
    
        # Create private endpoint
>       self.cmd(
            'network private-endpoint create --resource-group {resource_group_net} --name {private_endpoint_name} '
            '--vnet-name {vnet_name} --subnet {subnet_name} --private-connection-resource-id {scope} '
            '--location {location} --group-ids scheduler --connection-name {connection_name}')

src/azure-cli/azure/cli/command_modules/network/tests/latest/test_private_endpoint_commands.py:5534: 
 
 
 
 
 
 
 
                                 
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)
                                       _ 

self = <azure.cli.testsdk.base.ExecutionResult object at 0x7fe8ee6c3110>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7fe8ee2011c0>
command = 'network private-endpoint create --resource-group cli_test_durable_task_pec000002 --name cli000005 --vnet-name cli0000.../Microsoft.DurableTask/schedulers/cli000007 --location centraluseuap --group-ids scheduler --connection-name cli000006'
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
            self.output = stdout_buf.getvalue()
            self.applog = logging_buf.getvalue()
    
        except CannotOverwriteExistingCassetteException as ex:
>           raise AssertionError(ex)
E           AssertionError: Can't overwrite existing cassette ('/mnt/vss/_work/1/s/src/azure-cli/azure/cli/command_modules/network/tests/latest/recordings/test_private_endpoint_connection_durable_task_scheduler.yaml') in your current record mode ('once').
E           No match for the request (<Request (PUT) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_durable_task_pec000002/providers/Microsoft.Network/privateEndpoints/cli000005?api-version=2025-05-01>)&nbsp;was&nbsp;found.
E           Found 1 similar requests with 1 different matcher(s) :
E           
E           1 - (<Request (PUT) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_durable_task_pec000002/providers/Microsoft.Network/privateEndpoints/cli000005?api-version=2022-01-01>).
E           Matchers succeeded : ['method', 'scheme', 'host', 'port', 'path']
E           Matchers failed :
E           _custom_request_query_matcher - assertion failure :
E           None

src/azure-cli-testsdk/azure/cli/testsdk/base.py:308: AssertionError
src/azure-cli/azure/cli/command_modules/network/tests/latest/test_private_endpoint_commands.py:5489
❌3.13
Type Test Case Error Message Line
Failed test_private_endpoint_connection_durable_task_scheduler self = <azure.cli.testsdk.base.ExecutionResult object at 0x7f249d067020>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7f249d491f90>
command = 'network private-endpoint create --resource-group cli_test_durable_task_pec000002 --name cli000005 --vnet-name cli0000.../Microsoft.DurableTask/schedulers/cli000007 --location centraluseuap --group-ids scheduler --connection-name cli000006'
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:141: in exception_handler
    return handle_exception(ex)
           ^^^^^^^^^^^^^^^^^^^^
src/azure-cli-testsdk/azure/cli/testsdk/patches.py:33: in handle_main_exception
    raise ex
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:682: in execute
    raise ex
src/azure-cli-core/azure/cli/core/commands/init.py:812: in run_jobs_serially
    results.append(self.run_job(expanded_arg, cmd_copy))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/init.py:792: in run_job
    result = LongRunningOperation(cmd_copy.cli_ctx, 'Starting {}'.format(cmd_copy.name))(result)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/init.py:1150: in call
    result = poller.result()
             ^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/aaz/poller.py:105: in result
    self.wait(timeout)
env/lib/python3.13/site-packages/azure/core/tracing/decorator.py:119: in wrapper_use_tracer
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/aaz/poller.py:127: in wait
    raise self.exception
src/azure-cli-core/azure/cli/core/aaz/poller.py:80: in start
    for polling_method in self.polling_generator:
                          ^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/private_endpoint/__cmds.py:1804: in execute_operations
    yield self.PrivateEndpointsCreateOrUpdate(ctx=self.ctx)()
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/private_endpoint/__cmds.py:1824: in call
    session = self.client.send_request(request=request, stream=False, **kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/aaz/client.py:108: in send_request
    session = self.pipeline.run(request, stream=stream, **kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:242: in run
    return first_node.send(pipeline_request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/mgmt/core/policies/base.py:95: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/policies/redirect.py:205: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/policies/retry.py:545: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/aaz/http_policy.py:112: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:130: in send
    self.sender.send(request.http_request, **request.context.options),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/transport/requests_basic.py:375: in send
    response = self.session.request(  # type: ignore
env/lib/python3.13/site-packages/requests/sessions.py:589: in request
    resp = self.send(prep, **send_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/requests/sessions.py:703: in send
    r = adapter.send(request, **kwargs)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/requests/adapters.py:667: in send
    resp = conn.urlopen(
env/lib/python3.13/site-packages/urllib3/connectionpool.py:787: in urlopen
    response = self.make_request(
env/lib/python3.13/site-packages/urllib3/connectionpool.py:534: in make_request
    response = conn.getresponse()
               ^^^^^^^^^^^^^^^^^^
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       

self = <VCRRequestsHTTPSConnection/mnt/vss/work/1/s/src/azure-cli/azure/cli/command_modules/network/tests/latest/recordings/test_private_endpoint_connection_durable_task_scheduler.yaml(host='management.azure.com', port=443) at 0x7f2496be2dd0>
 = False, kwargs = {}

    def getresponse(self, =False, **kwargs):
        """Retrieve the response"""
        # Check to see if the cassette has a response for this request. If so,
        # then return it
        if self.cassette.can_play_response_for(self.vcr_request):
            log.info(f"Playing response for {self.vcr_request} from cassette")
            response = self.cassette.play_response(self.vcr_request)
            return VCRHTTPResponse(response)
        else:
            if self.cassette.write_protected and self.cassette.filter_request(self.vcr_request):
>               raise CannotOverwriteExistingCassetteException(
                    cassette=self.cassette,
                    failed_request=self.vcr_request,
                )
E               vcr.errors.CannotOverwriteExistingCassetteException: Can't overwrite existing cassette ('/mnt/vss/work/1/s/src/azure-cli/azure/cli/command_modules/network/tests/latest/recordings/test_private_endpoint_connection_durable_task_scheduler.yaml') in your current record mode ('once').
E               No match for the request (<Request (PUT) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_durable_task_pec000002/providers/Microsoft.Network/privateEndpoints/cli000005?api-version=2025-05-01>)&nbsp;was&nbsp;found.
E               Found 1 similar requests with 1 different matcher(s) :
E               
E               1 - (<Request (PUT) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_durable_task_pec000002/providers/Microsoft.Network/privateEndpoints/cli000005?api-version=2022-01-01>).
E               Matchers succeeded : ['method', 'scheme', 'host', 'port', 'path']
E               Matchers failed :
E               custom_request_query_matcher - assertion failure :
E               None

env/lib/python3.13/site-packages/vcr/stubs/init.py:277: CannotOverwriteExistingCassetteException

During handling of the above exception, another exception occurred:

self = <azure.cli.command_modules.network.tests.latest.test_private_endpoint_commands.NetworkPrivateLinkDurableTaskScenarioTest testMethod=test_private_endpoint_connection_durable_task_scheduler>
resource_group = 'cli_test_durable_task_pec000001'
resource_group_2 = 'cli_test_durable_task_pec000002'

    @AllowLargeResponse()
    @ResourceGroupPreparer(name_prefix='cli_test_durable_task_pec', location='centraluseuap')
    @ResourceGroupPreparer(name_prefix='cli_test_durable_task_pec', parameter_name='resource_group_2', location='centraluseuap')
    def test_private_endpoint_connection_durable_task_scheduler(self, resource_group, resource_group_2):
        self.kwargs.update({
            'resource_group_net': resource_group_2,
            'vnet_name': self.create_random_name(prefix='cli', length=20),
            'subnet_name': self.create_random_name(prefix='cli', length=20),
            'private_endpoint_name': self.create_random_name(prefix='cli', length=20),
            'connection_name': self.create_random_name(prefix='cli', length=20),
            'scheduler_name': self.create_random_name(prefix='cli', length=20),
            'location': 'centraluseuap',
            'approval_description': 'You are approved!',
            'rejection_description': 'You are rejected!',
            'rg': resource_group,
            'sub': self.get_subscription_id(),
            'body': '{\"location\": \"centraluseuap\", \"properties\": {\"ipAllowlist\": [], \"publicNetworkAccess\": \"Disabled\", \"sku\": {\"name\": \"Consumption\"}}}',
        })
    
        self.cmd('network vnet create --resource-group {resource_group_net} --location {location} --name {vnet_name} --address-prefix 10.0.0.0/16')
        self.cmd('network vnet subnet create --resource-group {resource_group_net} --vnet-name {vnet_name} --name {subnet_name} --address-prefixes 10.0.0.0/24')
        self.cmd('network vnet subnet update --resource-group {resource_group_net} --vnet-name {vnet_name} --name {subnet_name} --disable-private-endpoint-network-policies true')
    
        self.cmd(
            'rest --method "PUT" '
            '--url "https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}'
            '/providers/Microsoft.DurableTask/schedulers/{scheduler_name}?api-version=2026-02-01" '
            '--body "{body}"')
    
        scope = self.cmd(
            'rest --method "GET" '
            '--url "https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}'
            '/providers/Microsoft.DurableTask/schedulers/{scheduler_name}?api-version=2026-02-01"',
            checks=[
                self.check('name', self.kwargs['scheduler_name']),
                self.check('properties.provisioningState', 'Succeeded'),
                self.check('properties.publicNetworkAccess', 'Disabled')
            ]).get_output_in_json()['id']
    
        self.kwargs.update({
            'scope': scope,
        })
    
        # Create private endpoint
>       self.cmd(
            'network private-endpoint create --resource-group {resource_group_net} --name {private_endpoint_name} '
            '--vnet-name {vnet_name} --subnet {subnet_name} --private-connection-resource-id {scope} '
            '--location {location} --group-ids scheduler --connection-name {connection_name}')

src/azure-cli/azure/cli/command_modules/network/tests/latest/test_private_endpoint_commands.py:5534: 
 
 
 
 
 
 
 
                                 
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)
                                       _ 

self = <azure.cli.testsdk.base.ExecutionResult object at 0x7f249d067020>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7f249d491f90>
command = 'network private-endpoint create --resource-group cli_test_durable_task_pec000002 --name cli000005 --vnet-name cli0000.../Microsoft.DurableTask/schedulers/cli000007 --location centraluseuap --group-ids scheduler --connection-name cli000006'
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
            self.output = stdout_buf.getvalue()
            self.applog = logging_buf.getvalue()
    
        except CannotOverwriteExistingCassetteException as ex:
>           raise AssertionError(ex)
E           AssertionError: Can't overwrite existing cassette ('/mnt/vss/_work/1/s/src/azure-cli/azure/cli/command_modules/network/tests/latest/recordings/test_private_endpoint_connection_durable_task_scheduler.yaml') in your current record mode ('once').
E           No match for the request (<Request (PUT) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_durable_task_pec000002/providers/Microsoft.Network/privateEndpoints/cli000005?api-version=2025-05-01>)&nbsp;was&nbsp;found.
E           Found 1 similar requests with 1 different matcher(s) :
E           
E           1 - (<Request (PUT) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_durable_task_pec000002/providers/Microsoft.Network/privateEndpoints/cli000005?api-version=2022-01-01>).
E           Matchers succeeded : ['method', 'scheme', 'host', 'port', 'path']
E           Matchers failed :
E           _custom_request_query_matcher - assertion failure :
E           None

src/azure-cli-testsdk/azure/cli/testsdk/base.py:308: AssertionError
src/azure-cli/azure/cli/command_modules/network/tests/latest/test_private_endpoint_commands.py:5489
️✔️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

azure-client-tools-bot-prd bot commented Feb 26, 2026

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

@yonzhan
Copy link
Collaborator

yonzhan commented Feb 26, 2026

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

@github-actions
Copy link

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
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 migrates the az vmss command group core commands (create, show, update, wait) from SDK-based implementation to AAZ-based implementation, following Azure CLI's ongoing effort to standardize on AAZ for compute resources.

Changes:

  • Migrated vmss show, vmss update, and vmss wait command registrations from SDK-based to AAZ-based implementation
  • Updated create_vmss function to use AAZ-based get_vmss_by_aaz instead of SDK-based get_vmss
  • Modified Guest Attestation Extension installation logic to work with AAZ dictionary responses (camelCase keys)

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/azure-cli/azure/cli/command_modules/vm/commands.py Moved vmss create/show/update/wait command registrations from SDK operation group to AAZ-based command group without operation_group
src/azure-cli/azure/cli/command_modules/vm/custom.py Updated create_vmss to use get_vmss_by_aaz and modified extension installation code to handle AAZ dictionary responses

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

Comment on lines +4131 to +4158
vmss = get_vmss_by_aaz(cmd, resource_group_name, vmss_name)
vmss['virtualMachineProfile']['storageProfile']['imageReference'] = None
os_type = vmss.get('virtualMachineProfile', {}).get('storageProfile', {}).get('osDisk', {}).get('osType')
if os_type == 'Linux':
publisher = 'Microsoft.Azure.Security.LinuxAttestation'
if vmss.virtual_machine_profile.storage_profile.os_disk.os_type == 'Windows':
elif os_type == 'Windows':
publisher = 'Microsoft.Azure.Security.WindowsAttestation'
version = _normalize_extension_version(cmd.cli_ctx, publisher, 'GuestAttestation', None, vmss.location)
ext = VirtualMachineScaleSetExtension(name='GuestAttestation',
publisher=publisher,
type_properties_type='GuestAttestation',
protected_settings=None,
type_handler_version=version,
settings=None,
auto_upgrade_minor_version=True,
provision_after_extensions=None,
enable_automatic_upgrade=not disable_integrity_monitoring_autoupgrade)
if not vmss.virtual_machine_profile.extension_profile:
vmss.virtual_machine_profile.extension_profile = VirtualMachineScaleSetExtensionProfile(extensions=[])
vmss.virtual_machine_profile.extension_profile.extensions.append(ext)
else:
publisher = ''
version = _normalize_extension_version(cmd.cli_ctx, publisher, 'GuestAttestation',
None, vmss.get('location'))
ext = {
'name': 'GuestAttestation',
'auto_upgrade_minor_version': True,
'enable_automatic_upgrade': not disable_integrity_monitoring_autoupgrade,
'publisher': publisher,
'type_handler_version': version,
'type': 'GuestAttestation'
}
if not vmss.get('virtualMachineProfile', {}).get('extensionProfile'):
vmss['virtualMachineProfile']['extensionProfile'] = {'extensions': []}
vmss['virtualMachineProfile']['extensionProfile']['extensions'].append(ext)
try:
LongRunningOperation(cmd.cli_ctx)(client.virtual_machine_scale_sets.begin_create_or_update(
resource_group_name, vmss_name, vmss))
from .operations.vmss import VMSSCreate
vmss['resource_group'] = resource_group_name
vmss['vm_scale_set_name'] = vmss_name
_create_vmss = VMSSCreate(cli_ctx=cmd.cli_ctx)(command_args=vmss)
LongRunningOperation(cmd.cli_ctx)(_create_vmss)
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

The VMSS object retrieved from get_vmss_by_aaz returns camelCase keys (e.g., 'virtualMachineProfile'), but AAZ Create/Update commands expect snake_case argument names. Before passing the vmss dictionary to VMSSCreate, you must convert it using the convert_show_result_to_snake_case function.

Compare this to the update_vmss function (lines 4587-4593) which correctly performs this conversion:

from .operations.vmss import convert_show_result_to_snake_case
vmss = vmss_convert_show_result_to_snake_case(vmss)

Without this conversion, the AAZ command will fail to properly map the dictionary keys to its argument schema, potentially causing the operation to fail or produce incorrect results.

Copilot uses AI. Check for mistakes.
@william051200
Copy link
Member Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

if (is_trusted_launch or is_confidential_vm) and enable_integrity_monitoring:
client = _compute_client_factory(cmd.cli_ctx)
vmss = client.virtual_machine_scale_sets.get(resource_group_name, vmss_name)
vmss.virtual_machine_profile.storage_profile.image_reference = None
Copy link
Contributor

Choose a reason for hiding this comment

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

May I ask where the logic for this line is implemented?

Copy link
Member Author

Choose a reason for hiding this comment

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

It is at line 4138
vmss['virtualMachineProfile']['storageProfile']['imageReference'] = None

Comment on lines +4148 to +4155
ext = {
'name': 'GuestAttestation',
'autoUpgradeMinorVersion': True,
'enableAutomaticUpgrade': not disable_integrity_monitoring_autoupgrade,
'publisher': publisher,
'typeHandlerVersion': version,
'type': 'GuestAttestation'
}
Copy link
Contributor

Choose a reason for hiding this comment

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

please add the properties back whose values are None.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Auto-Assign Auto assign by bot Compute az vm/vmss/image/disk/snapshot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants