Skip to content

[AKS] az aks create/update: Add new parameters --enable-gateway-api and --disable-gateway-api to manage Gateway API installation#33238

Open
meecethereese wants to merge 11 commits intoAzure:devfrom
meecethereese:maufe/mga-ga-cli
Open

[AKS] az aks create/update: Add new parameters --enable-gateway-api and --disable-gateway-api to manage Gateway API installation#33238
meecethereese wants to merge 11 commits intoAzure:devfrom
meecethereese:maufe/mga-ga-cli

Conversation

@meecethereese
Copy link
Copy Markdown

Related command
az aks create
az aks update

Description
Promote the Managed Gateway API feature from the aks-preview extension to the GA Azure CLI.

Adds two new mutually-exclusive flags to az aks create (enable only) and az aks update (enable and disable):

  • --enable-gateway-api: install the managed Kubernetes Gateway API on the cluster (sets
    ingressProfile.gatewayApi.installation to Standard).
  • --disable-gateway-api: uninstall it (sets the value to Disabled).

The feature requires a gateway implementation, such as Azure Service Mesh (Istio), to be enabled on the cluster. This change
ports the implementation from Azure/azure-cli-extensions#9077 and
bumps azure-mgmt-containerservice to ~=41.1.0 so the GA SDK exposes ManagedClusterIngressProfileGatewayConfiguration (see changelog here).

Testing Guide

# Create a cluster with Istio + managed Gateway API
az aks create -g $RG -n $CLUSTER \                                                            
    --enable-azure-service-mesh \      
    --enable-gateway-api

# Enable on an existing Istio-enabled cluster
az aks update -g $RG -n $CLUSTER --enable-gateway-api

# Disable
az aks update -g $RG -n $CLUSTER --disable-gateway-api

History Notes
[AKS] az aks create: Add --enable-gateway-api to install the managed Kubernetes Gateway
API.
[AKS] az aks update: Add --enable-gateway-api and --disable-gateway-api to manage
installation of the managed Kubernetes Gateway API.


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

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

azure-client-tools-bot-prd Bot commented Apr 21, 2026

❌AzureCLI-FullTest
️✔️acr
️✔️latest
️✔️3.12
️✔️3.13
❌acs
❌latest
❌3.12
Type Test Case Error Message Line
Failed test_aks_create_with_gateway_api_and_azureservicemesh self = <azure.cli.testsdk.base.ExecutionResult object at 0x7f2165b2bb60>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7f2168596930>
command = 'group create --location centraluseuap --name clitestjcqqm3bzig --tag product=azurecli cause=automation test date=2026-04-23T14:21:51Z test=test_aks_create_with_gateway_api_and_azureservicemesh module=acs'
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 = CLIError("Please run 'az login' to setup account."), 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 CLIError 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:
src/azure-cli-testsdk/azure/cli/testsdk/scenario_tests/decorators.py:40: in preparer_wrapper
    fn(test_class_instance, **kwargs)
src/azure-cli-testsdk/azure/cli/testsdk/scenario_tests/preparers.py:39: in preparer_wrapper
    parameter_update = self.create_resource(
src/azure-cli-testsdk/azure/cli/testsdk/preparers.py:99: in create_resource
    self.live_only_execute(self.cli_ctx, template.format(self.location, name))
src/azure-cli-testsdk/azure/cli/testsdk/preparers.py:39: in live_only_execute
    return self.raw_execute(cli_ctx, command, expect_failure)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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/resource/custom.py:1641: in create_resource_group
    rcf = resource_client_factory(cmd.cli_ctx)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/resource/client_factory.py:10: in resource_client_factory
    return get_mgmt_service_client(cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/client_factory.py:83: in get_mgmt_service_client
    client, 
 = get_mgmt_service_client(cli_ctx, client_type, subscription_id=subscription_id,
src/azure-cli-core/azure/cli/core/commands/client_factory.py:234: in get_mgmt_service_client
    credential, subscription_id, 
 = profile.get_login_credentials(
src/azure-cli-core/azure/cli/core/profile.py:342: in get_login_credentials
    account = self.get_subscription(subscription_id)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 
 
 
 
 
 
 
 
 
 
 
 
                           

self = <azure.cli.core._profile.Profile object at 0x7f21652cb530>
subscription = None

    def get_subscription(self, subscription=None):  # take id or name
        subscriptions = self.load_cached_subscriptions()
        if not subscriptions:
>           raise CLIError(_AZ_LOGIN_MESSAGE)
E           knack.util.CLIError: Please run 'az login' to setup account.

src/azure-cli-core/azure/cli/core/_profile.py:603: CLIError
azure/cli/command_modules/acs/tests/latest/test_aks_commands.py:15054
Failed test_aks_managed_gateway_requires_service_mesh self = <azure.cli.testsdk.base.ExecutionResult object at 0x7f21658ece00>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7f2167ccc860>
command = 'group create --location centraluseuap --name clitestmldjtepwbw --tag product=azurecli cause=automation test date=2026-04-23T14:22:19Z test=test_aks_managed_gateway_requires_service_mesh module=acs'
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 = CLIError("Please run 'az login' to setup account."), 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 CLIError 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:
src/azure-cli-testsdk/azure/cli/testsdk/scenario_tests/decorators.py:40: in preparer_wrapper
    fn(test_class_instance, **kwargs)
src/azure-cli-testsdk/azure/cli/testsdk/scenario_tests/preparers.py:39: in preparer_wrapper
    parameter_update = self.create_resource(
src/azure-cli-testsdk/azure/cli/testsdk/preparers.py:99: in create_resource
    self.live_only_execute(self.cli_ctx, template.format(self.location, name))
src/azure-cli-testsdk/azure/cli/testsdk/preparers.py:39: in live_only_execute
    return self.raw_execute(cli_ctx, command, expect_failure)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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/resource/custom.py:1641: in create_resource_group
    rcf = resource_client_factory(cmd.cli_ctx)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/resource/client_factory.py:10: in resource_client_factory
    return get_mgmt_service_client(cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/client_factory.py:83: in get_mgmt_service_client
    client, 
 = get_mgmt_service_client(cli_ctx, client_type, subscription_id=subscription_id,
src/azure-cli-core/azure/cli/core/commands/client_factory.py:234: in get_mgmt_service_client
    credential, subscription_id, 
 = profile.get_login_credentials(
src/azure-cli-core/azure/cli/core/profile.py:342: in get_login_credentials
    account = self.get_subscription(subscription_id)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 
 
 
 
 
 
 
 
 
 
 
 
                           

self = <azure.cli.core._profile.Profile object at 0x7f2165311af0>
subscription = None

    def get_subscription(self, subscription=None):  # take id or name
        subscriptions = self.load_cached_subscriptions()
        if not subscriptions:
>           raise CLIError(_AZ_LOGIN_MESSAGE)
E           knack.util.CLIError: Please run 'az login' to setup account.

src/azure-cli-core/azure/cli/core/_profile.py:603: CLIError
azure/cli/command_modules/acs/tests/latest/test_aks_commands.py:15126
❌3.13
Type Test Case Error Message Line
Failed test_aks_create_with_gateway_api_and_azureservicemesh self = <azure.cli.testsdk.base.ExecutionResult object at 0x7fa282158830>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7fa284a9fd90>
command = 'group create --location centraluseuap --name clitestdixom2nvun --tag product=azurecli cause=automation test date=2026-04-23T14:21:41Z test=test_aks_create_with_gateway_api_and_azureservicemesh module=acs'
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 = CLIError("Please run 'az login' to setup account."), 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 CLIError 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:
src/azure-cli-testsdk/azure/cli/testsdk/scenario_tests/decorators.py:40: in preparer_wrapper
    fn(test_class_instance, **kwargs)
src/azure-cli-testsdk/azure/cli/testsdk/scenario_tests/preparers.py:39: in preparer_wrapper
    parameter_update = self.create_resource(
src/azure-cli-testsdk/azure/cli/testsdk/preparers.py:99: in create_resource
    self.live_only_execute(self.cli_ctx, template.format(self.location, name))
src/azure-cli-testsdk/azure/cli/testsdk/preparers.py:39: in live_only_execute
    return self.raw_execute(cli_ctx, command, expect_failure)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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/resource/custom.py:1641: in create_resource_group
    rcf = resource_client_factory(cmd.cli_ctx)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/resource/client_factory.py:10: in resource_client_factory
    return get_mgmt_service_client(cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/client_factory.py:83: in get_mgmt_service_client
    client, 
 = get_mgmt_service_client(cli_ctx, client_type, subscription_id=subscription_id,
src/azure-cli-core/azure/cli/core/commands/client_factory.py:234: in get_mgmt_service_client
    credential, subscription_id, 
 = profile.get_login_credentials(
src/azure-cli-core/azure/cli/core/profile.py:342: in get_login_credentials
    account = self.get_subscription(subscription_id)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 
 
 
 
 
 
 
 
 
 
 
 
                           

self = <azure.cli.core._profile.Profile object at 0x7fa2821597f0>
subscription = None

    def get_subscription(self, subscription=None):  # take id or name
        subscriptions = self.load_cached_subscriptions()
        if not subscriptions:
>           raise CLIError(_AZ_LOGIN_MESSAGE)
E           knack.util.CLIError: Please run 'az login' to setup account.

src/azure-cli-core/azure/cli/core/_profile.py:603: CLIError
azure/cli/command_modules/acs/tests/latest/test_aks_commands.py:15054
Failed test_aks_managed_gateway_requires_service_mesh self = <azure.cli.testsdk.base.ExecutionResult object at 0x7fa282158830>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7fa284a9f390>
command = 'group create --location centraluseuap --name clitestspnjjegapt --tag product=azurecli cause=automation test date=2026-04-23T14:22:03Z test=test_aks_managed_gateway_requires_service_mesh module=acs'
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 = CLIError("Please run 'az login' to setup account."), 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 CLIError 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:
src/azure-cli-testsdk/azure/cli/testsdk/scenario_tests/decorators.py:40: in preparer_wrapper
    fn(test_class_instance, **kwargs)
src/azure-cli-testsdk/azure/cli/testsdk/scenario_tests/preparers.py:39: in preparer_wrapper
    parameter_update = self.create_resource(
src/azure-cli-testsdk/azure/cli/testsdk/preparers.py:99: in create_resource
    self.live_only_execute(self.cli_ctx, template.format(self.location, name))
src/azure-cli-testsdk/azure/cli/testsdk/preparers.py:39: in live_only_execute
    return self.raw_execute(cli_ctx, command, expect_failure)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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/resource/custom.py:1641: in create_resource_group
    rcf = resource_client_factory(cmd.cli_ctx)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/resource/client_factory.py:10: in resource_client_factory
    return get_mgmt_service_client(cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/client_factory.py:83: in get_mgmt_service_client
    client, 
 = get_mgmt_service_client(cli_ctx, client_type, subscription_id=subscription_id,
src/azure-cli-core/azure/cli/core/commands/client_factory.py:234: in get_mgmt_service_client
    credential, subscription_id, 
 = profile.get_login_credentials(
src/azure-cli-core/azure/cli/core/profile.py:342: in get_login_credentials
    account = self.get_subscription(subscription_id)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 
 
 
 
 
 
 
 
 
 
 
 
                           

self = <azure.cli.core._profile.Profile object at 0x7fa28c8a9160>
subscription = None

    def get_subscription(self, subscription=None):  # take id or name
        subscriptions = self.load_cached_subscriptions()
        if not subscriptions:
>           raise CLIError(_AZ_LOGIN_MESSAGE)
E           knack.util.CLIError: Please run 'az login' to setup account.

src/azure-cli-core/azure/cli/core/_profile.py:603: CLIError
azure/cli/command_modules/acs/tests/latest/test_aks_commands.py:15126
️✔️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 @meecethereese,
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 Apr 21, 2026

⚠️AzureCLI-BreakingChangeTest
⚠️acs
rule cmd_name rule_message suggest_message
⚠️ 1006 - ParaAdd aks create cmd aks create added parameter enable_gateway_api
⚠️ 1006 - ParaAdd aks update cmd aks update added parameter disable_gateway_api
⚠️ 1006 - ParaAdd aks update cmd aks update added parameter enable_gateway_api

@yonzhan
Copy link
Copy Markdown
Collaborator

yonzhan commented Apr 21, 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>

@meecethereese meecethereese changed the title [AKS] az aks create/update: Add new parameters --enable-gateway-api and --disable-gateway-api to manage Gateway API installation [AKS] az aks create/update: Add new parameters --enable-gateway-api and --disable-gateway-api to manage Gateway API installation Apr 21, 2026
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 promotes the managed Kubernetes Gateway API installation controls from aks-preview into Azure CLI GA by adding new flags to az aks create/az aks update and wiring them to ingressProfile.gatewayApi.installation via the mgmt-containerservice SDK.

Changes:

  • Add --enable-gateway-api (create/update) and --disable-gateway-api (update) flags and plumb them into managed cluster ingress profile updates.
  • Introduce constants for Gateway API installation state and add unit/live scenario coverage for the new behavior.
  • Bump azure-mgmt-containerservice in setup.py to expose the GA SDK model needed for gateway API configuration.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/azure-cli/setup.py Bumps azure-mgmt-containerservice SDK range used by the CLI package metadata.
src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py Adds context getters and create/update decorator logic to set ingress_profile.gateway_api.installation.
src/azure-cli/azure/cli/command_modules/acs/custom.py Adds new keyword parameters to aks_create/aks_update entry points.
src/azure-cli/azure/cli/command_modules/acs/_params.py Registers the new CLI arguments for aks create and aks update.
src/azure-cli/azure/cli/command_modules/acs/_help.py Documents the new flags and adds examples.
src/azure-cli/azure/cli/command_modules/acs/_consts.py Adds constants for Gateway API installation enum strings.
src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_managed_cluster_decorator.py Adds unit tests for the new context getters and decorator update/create methods.
src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py Adds live scenario tests for enabling/disabling managed Gateway API and for the provider prerequisite.

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

Comment on lines +15075 to +15115
# Test successful creation with Gateway API and Azure Service Mesh addon
create_cmd = (
"aks create --resource-group={resource_group} --name={name} "
"--enable-azure-service-mesh "
"--enable-gateway-api "
"--ssh-key-value={ssh_key_value} -o json "
)
self.cmd(
create_cmd,
checks=[
self.check("provisioningState", "Succeeded"),
self.check("serviceMeshProfile.mode", "Istio"),
self.check("ingressProfile.gatewayApi.installation", "Standard"),
],
)

# Test disabling Gateway API
update_cmd = (
"aks update --resource-group={resource_group} --name={name} "
"--disable-gateway-api "
)
self.cmd(
update_cmd,
checks=[
self.check("provisioningState", "Succeeded"),
self.check("ingressProfile.gatewayApi.installation", "Disabled"),
],
)

# Test re-enabling Gateway API
update_cmd = (
"aks update --resource-group={resource_group} --name={name} "
"--enable-gateway-api "
)
self.cmd(
update_cmd,
checks=[
self.check("provisioningState", "Succeeded"),
self.check("ingressProfile.gatewayApi.installation", "Standard"),
],
)
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

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

test_aks_create_with_gateway_api_and_azureservicemesh creates a cluster but never deletes it. This will leak live-test resources (and can cause subsequent test failures/cost). Please add cleanup at the end (ideally aks delete ... --yes --no-wait like other tests in this file).

Suggested change
# Test successful creation with Gateway API and Azure Service Mesh addon
create_cmd = (
"aks create --resource-group={resource_group} --name={name} "
"--enable-azure-service-mesh "
"--enable-gateway-api "
"--ssh-key-value={ssh_key_value} -o json "
)
self.cmd(
create_cmd,
checks=[
self.check("provisioningState", "Succeeded"),
self.check("serviceMeshProfile.mode", "Istio"),
self.check("ingressProfile.gatewayApi.installation", "Standard"),
],
)
# Test disabling Gateway API
update_cmd = (
"aks update --resource-group={resource_group} --name={name} "
"--disable-gateway-api "
)
self.cmd(
update_cmd,
checks=[
self.check("provisioningState", "Succeeded"),
self.check("ingressProfile.gatewayApi.installation", "Disabled"),
],
)
# Test re-enabling Gateway API
update_cmd = (
"aks update --resource-group={resource_group} --name={name} "
"--enable-gateway-api "
)
self.cmd(
update_cmd,
checks=[
self.check("provisioningState", "Succeeded"),
self.check("ingressProfile.gatewayApi.installation", "Standard"),
],
)
try:
# Test successful creation with Gateway API and Azure Service Mesh addon
create_cmd = (
"aks create --resource-group={resource_group} --name={name} "
"--enable-azure-service-mesh "
"--enable-gateway-api "
"--ssh-key-value={ssh_key_value} -o json "
)
self.cmd(
create_cmd,
checks=[
self.check("provisioningState", "Succeeded"),
self.check("serviceMeshProfile.mode", "Istio"),
self.check("ingressProfile.gatewayApi.installation", "Standard"),
],
)
# Test disabling Gateway API
update_cmd = (
"aks update --resource-group={resource_group} --name={name} "
"--disable-gateway-api "
)
self.cmd(
update_cmd,
checks=[
self.check("provisioningState", "Succeeded"),
self.check("ingressProfile.gatewayApi.installation", "Disabled"),
],
)
# Test re-enabling Gateway API
update_cmd = (
"aks update --resource-group={resource_group} --name={name} "
"--enable-gateway-api "
)
self.cmd(
update_cmd,
checks=[
self.check("provisioningState", "Succeeded"),
self.check("ingressProfile.gatewayApi.installation", "Standard"),
],
)
finally:
self.cmd(
"aks delete --resource-group={resource_group} --name={name} --yes --no-wait"
)

Copilot uses AI. Check for mistakes.
Comment thread src/azure-cli/setup.py
Comment on lines +82 to 83
'azure-mgmt-containerservice~=41.1.0',
'azure-mgmt-cosmosdb==9.9.0',
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

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

setup.py bumps azure-mgmt-containerservice to ~=41.1.0, but the platform-specific requirement pins still reference azure-mgmt-containerservice==41.0.0 (requirements.py3.{Linux,Darwin,windows}.txt). This can lead to release builds/installers using the older SDK and missing ManagedClusterIngressProfileGatewayConfiguration. Please update the pinned versions in those requirements files as well (or document why setup.py alone is sufficient).

Copilot uses AI. Check for mistakes.
c.argument(
"enable_gateway_api",
action="store_true",
help="Enable managed installation of Gateway API CRDs from the standard release channel."
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

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

The help text for enable_gateway_api here doesn't mention the documented prerequisite (a managed Gateway API ingress provider such as Azure Service Mesh/Istio). In _help.py the same flag states this requirement. Please align the argparse help with the command help so users see the prerequisite consistently (including in -h output).

Suggested change
help="Enable managed installation of Gateway API CRDs from the standard release channel."
help=(
"Enable managed installation of Gateway API CRDs from the standard release channel. "
"Requires a managed Gateway API ingress provider such as Azure Service Mesh/Istio."
)

Copilot uses AI. Check for mistakes.
Comment on lines +884 to +889
help="Enable managed installation of Gateway API CRDs from the standard release channel."
)
c.argument(
"disable_gateway_api",
action="store_true",
help="Disable managed installation of Gateway API CRDs."
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

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

Same as aks create: the argparse help for --enable-gateway-api/--disable-gateway-api doesn't reflect the prerequisite described in _help.py (requires a managed Gateway API ingress provider). Please update these help strings to match the public help/documentation so az aks update -h is accurate.

Suggested change
help="Enable managed installation of Gateway API CRDs from the standard release channel."
)
c.argument(
"disable_gateway_api",
action="store_true",
help="Disable managed installation of Gateway API CRDs."
help=(
"Enable managed installation of Gateway API CRDs from the standard release channel. "
"Requires a managed Gateway API ingress provider."
)
)
c.argument(
"disable_gateway_api",
action="store_true",
help=(
"Disable managed installation of Gateway API CRDs. "
"Requires a managed Gateway API ingress provider."
)

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

It makes sense to add it for enable but not for disable

Comment on lines +7381 to +7392
def set_up_ingress_profile_gateway_api(self, mc: ManagedCluster) -> ManagedCluster:
self._ensure_mc(mc)
if self.context.get_enable_gateway_api():
if mc.ingress_profile is None:
mc.ingress_profile = self.models.ManagedClusterIngressProfile()
if mc.ingress_profile.gateway_api is None:
mc.ingress_profile.gateway_api = (
self.models.ManagedClusterIngressProfileGatewayConfiguration(
installation=CONST_MANAGED_GATEWAY_INSTALLATION_STANDARD
)
)
return mc
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

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

--enable-gateway-api is documented as requiring an ingress provider (e.g., Azure Service Mesh/Istio), but this create-path setup unconditionally sets ingress_profile.gateway_api when the flag is present and does not validate the prerequisite. This means users may get a late RP-side failure or end up with an invalid configuration depending on RP behavior. Consider adding an explicit validation here (or in the context getter) that checks the relevant provider flags (e.g., enable_azure_service_mesh / other managed providers) and raises a clear CLI error before sending the PUT.

Copilot uses AI. Check for mistakes.
Comment on lines +9045 to +9068
def update_ingress_profile_gateway_api(self, mc: ManagedCluster) -> ManagedCluster:
"""Update gateway api installation in the ingress profile for the ManagedCluster object.

:return: the ManagedCluster object
"""
self._ensure_mc(mc)
enable_gateway_api = self.context.get_enable_gateway_api()
disable_gateway_api = self.context.get_disable_gateway_api()
if enable_gateway_api and disable_gateway_api:
raise MutuallyExclusiveArgumentError(
"Cannot specify --enable-gateway-api and --disable-gateway-api at the same time."
)
if enable_gateway_api or disable_gateway_api:
if mc.ingress_profile is None:
mc.ingress_profile = self.models.ManagedClusterIngressProfile() # pylint: disable=no-member
if mc.ingress_profile.gateway_api is None:
mc.ingress_profile.gateway_api = (
self.models.ManagedClusterIngressProfileGatewayConfiguration() # pylint: disable=no-member
)
if enable_gateway_api:
mc.ingress_profile.gateway_api.installation = CONST_MANAGED_GATEWAY_INSTALLATION_STANDARD
elif disable_gateway_api:
mc.ingress_profile.gateway_api.installation = CONST_MANAGED_GATEWAY_INSTALLATION_DISABLED
return mc
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

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

This update-path method sets/clears gateway_api.installation but does not validate the documented prerequisite that a managed Gateway API ingress provider is enabled on the cluster. Please add a precondition check (e.g., when enabling, verify service_mesh_profile.mode != Disabled or other supported providers are enabled) and raise a clear RequiredArgumentMissingError/InvalidArgumentValueError, instead of relying on an RP-side failure.

Copilot uses AI. Check for mistakes.
@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

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.

Could you remove these unrelated changes from the updates to feature support?

@AKSCustomResourceGroupPreparer(
random_name_length=17, name_prefix="clitest", location="centraluseuap"
)
def test_aks_create_with_gateway_api_and_azureservicemesh(
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.

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.

Please commit recording files to pass built-in CI checks.

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 live test failed with error

E azure.cli.core.azclierror.BadRequestError: (PreviewFeatureNotRegistered) Preview feature Microsoft.ContainerService/ManagedGatewayAPIPreview not registered.
E Code: PreviewFeatureNotRegistered
E Message: Preview feature Microsoft.ContainerService/ManagedGatewayAPIPreview not registered.

https://dev.azure.com/msazure/CloudNativeCompute/CloudNativeCompute%20Team/_build/results?buildId=161520143&view=logs&j=b162b355-d59d-5864-ce0f-0a70f12dd28b&t=dc59ccd1-231f-538b-777f-33a592c7ca57&l=4020

  1. Remove the feature flag validation for features published to the stable API.
  2. For now, you can test it with a subscription where the feature is registered to confirm it works as intended.

Please also resolve merge conflict.
@meecethereese

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants