Skip to content

{AKS} az aks: add --outbound-type-sku for managed NAT Gateway V2 GA - #34017

Open
Christine DOSSA (christine33-creator) wants to merge 8 commits into
Azure:devfrom
christine33-creator:cdossa/natgwv2-ga-cli-sku
Open

{AKS} az aks: add --outbound-type-sku for managed NAT Gateway V2 GA#34017
Christine DOSSA (christine33-creator) wants to merge 8 commits into
Azure:devfrom
christine33-creator:cdossa/natgwv2-ga-cli-sku

Conversation

@christine33-creator

@christine33-creator Christine DOSSA (christine33-creator) commented Sep 2, 2026

Copy link
Copy Markdown

🤖 PR Validation — ⚠️ Review suggested

Breaking Changes Tests
⚠️ None ️✔️ 130/130
⚠️AzureCLI-BreakingChangeTest
⚠️acs
rule cmd_name rule_message suggest_message
⚠️ 1006 - ParaAdd aks create cmd aks create added parameter nat_gateway_managed_outbound_ipv6_count
⚠️ 1006 - ParaAdd aks create cmd aks create added parameter nat_gateway_outbound_ip_ids
⚠️ 1006 - ParaAdd aks create cmd aks create added parameter nat_gateway_outbound_ip_prefix_ids
⚠️ 1006 - ParaAdd aks create cmd aks create added parameter nat_gateway_sku
⚠️ 1006 - ParaAdd aks update cmd aks update added parameter nat_gateway_managed_outbound_ipv6_count
⚠️ 1006 - ParaAdd aks update cmd aks update added parameter nat_gateway_outbound_ip_ids
⚠️ 1006 - ParaAdd aks update cmd aks update added parameter nat_gateway_outbound_ip_prefix_ids
⚠️ 1006 - ParaAdd aks update cmd aks update added parameter nat_gateway_sku

Summary

Ports the NAT Gateway V2 GA surface to core az aks, now that the 2026-06-01 API SDK (azure-mgmt-containerservice 41.6.0) is vendored (#34011). Mirrors the aks-preview extension PR Azure/azure-cli-extensions#10264 and follows the AKS NAT Gateway V2 GA API proposal.

What

az aks create / az aks update:

  • --outbound-type-sku {Standard,StandardV2} — select the managed NAT gateway SKU with --outbound-type managedNATGateway (the GA shape of NAT Gateway V2).
  • --nat-gateway-managed-outbound-ipv6-count — dual-stack IPv6 outbound IPs (StandardV2 only).
  • --nat-gateway-outbound-ips / --nat-gateway-outbound-ip-prefixes — bring-your-own public IPs / prefixes (StandardV2 only).

Validation: create requires an explicit --outbound-type managedNATGateway; update verifies the cluster's existing outbound type before applying the SKU / V2 params.

Testing

  • Unit tests (builder, validators, decorator) pass; new cases added to test_natgateway.py and test_validators.py.
  • azdev style acs: pylint + flake8 pass.
  • End-to-end validator behavior verified against a local build with SDK 41.6.0.
  • Recorded scenario test test_aks_create_and_update_with_managed_nat_gateway_v2 is scaffolded but not yet recorded — needs an azdev test ... --live run against a StandardV2-capable region. This is why the PR is a draft.

History Notes

Added an entry under AKS in src/azure-cli/HISTORY.rst.

Ports the aks-preview NAT Gateway V2 GA surface (extension PR Azure#10264) into core az aks now that the 2026-06-01 SDK (azure-mgmt-containerservice 41.6.0) is vendored.

az aks create / az aks update: add --outbound-type-sku (Standard|StandardV2) to select the managed NAT gateway SKU with --outbound-type managedNATGateway (the GA shape of NAT Gateway V2), plus the StandardV2-only --nat-gateway-managed-outbound-ipv6-count, --nat-gateway-outbound-ips and --nat-gateway-outbound-ip-prefixes. Create requires an explicit --outbound-type managedNATGateway; update verifies the cluster's existing outbound type before applying. Adds builder + validator unit tests.
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@microsoft-github-policy-service microsoft-github-policy-service Bot added the customer-reported Issues that are reported by GitHub users external to the Azure organization. label Sep 2, 2026
@microsoft-github-policy-service

Copy link
Copy Markdown
Contributor

Thank you for your contribution Christine DOSSA (@christine33-creator)! We will review the pull request and get back to you soon.

@a0x1ab

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).

…rameter_test_coverage; mark StandardV2 scenario test live-only
@a0x1ab

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).

@a0x1ab

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).

@christine33-creator
Christine DOSSA (christine33-creator) marked this pull request as ready for review September 3, 2026 20:08
Copilot AI lite review requested due to automatic review settings September 3, 2026 20:08
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The current validation/help/model-guarding has correctness and usability gaps (SKU enforcement for V2-only params, missing help entries, and potential None-model call paths) that should be fixed before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds GA CLI surface area for AKS managed NAT Gateway V2 by introducing a managed NAT gateway SKU selector and V2-only outbound configuration parameters, wiring them through argument parsing, validation, model-building, and decorator update logic in the acs command module.

Changes:

  • Add --outbound-type-sku {Standard,StandardV2} plus StandardV2-only parameters (--nat-gateway-managed-outbound-ipv6-count, --nat-gateway-outbound-ips, --nat-gateway-outbound-ip-prefixes) to az aks create/update.
  • Implement validators and NAT gateway profile building/updating to carry the new SKU and V2 properties.
  • Add/extend unit tests and scaffold a live-only scenario test; update HISTORY and linter exclusions.
File summaries
File Description
src/azure-cli/HISTORY.rst Release note entry for the new NAT gateway V2 GA CLI surface.
src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_validators.py New unit tests covering outbound-type-sku and V2 parameter validators.
src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_natgateway.py New unit tests for NAT gateway profile construction/update with SKU and V2 fields.
src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py Live-only scenario test scaffold for create/update with managed NAT gateway V2.
src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py Plumbs new args into network profile setup/update; adds model accessors and update-time validation.
src/azure-cli/azure/cli/command_modules/acs/linter_exclusions.yml Suppresses linter “missing parameter test coverage” for the new parameters (draft-oriented).
src/azure-cli/azure/cli/command_modules/acs/custom.py Extends aks_create/aks_update signatures to accept new parameters.
src/azure-cli/azure/cli/command_modules/acs/_validators.py Adds range checks and create/update validation for SKU and V2-only params.
src/azure-cli/azure/cli/command_modules/acs/_params.py Registers new CLI arguments, enums, and validators for create/update.
src/azure-cli/azure/cli/command_modules/acs/_natgateway.py Extends NAT gateway profile building to set SKU, IPv6 count, and BYO outbound IPs/prefixes.
src/azure-cli/azure/cli/command_modules/acs/_help.py Adds help text for --outbound-type-sku (but missing help entries for the other new flags).
src/azure-cli/azure/cli/command_modules/acs/_consts.py Adds constants for managed NAT gateway SKUs.
Review details

Suppressed comments (3)

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

  • The new NAT Gateway V2 parameters (--nat-gateway-managed-outbound-ipv6-count, --nat-gateway-outbound-ips, --nat-gateway-outbound-ip-prefixes) are not documented in the az aks update help section here, so users won’t discover them via az aks update -h.
  - name: --outbound-type-sku
    type: string
    short-summary: SKU of the managed NAT Gateway (Standard or StandardV2).
    long-summary: Only valid with --outbound-type managedNATGateway. Migrate an existing Standard (V1) cluster to StandardV2 by passing StandardV2. StandardV2 adds zone resiliency, IPv6 support, and higher bandwidth. Downgrade from StandardV2 to Standard is not supported.

src/azure-cli/azure/cli/command_modules/acs/linter_exclusions.yml:160

  • These new parameters are excluded from missing_parameter_test_coverage, which will suppress CLI linter coverage checks for the new surface area. Before merging out of draft, consider recording a scenario test for these flags and then removing these exclusions so the linter can enforce coverage going forward.
      nat_gateway_sku:
          rule_exclusions:
          - missing_parameter_test_coverage
      nat_gateway_managed_outbound_ipv6_count:
          rule_exclusions:
          - missing_parameter_test_coverage
      nat_gateway_outbound_ip_ids:
          rule_exclusions:
          - missing_parameter_test_coverage
      nat_gateway_outbound_ip_prefix_ids:
          rule_exclusions:
          - missing_parameter_test_coverage

src/azure-cli/azure/cli/command_modules/acs/_natgateway.py:113

  • ManagedClusterNATGatewayProfileOutboundIpPrefixes is populated with None for backward compatibility when the SDK model isn’t available, but this block unconditionally calls it. If the selected SDK/profile doesn’t include this type, this will fail with a NoneType is not callable error; raise a clearer error instead.
    if outbound_ip_prefix_ids is not None:
        ManagedClusterNATGatewayProfileOutboundIpPrefixes = models.ManagedClusterNATGatewayProfileOutboundIpPrefixes
        prefix_id_list = [x.strip() for x in outbound_ip_prefix_ids.split(',') if x.strip()]
        profile.outbound_ip_prefixes = ManagedClusterNATGatewayProfileOutboundIpPrefixes(
            public_ip_prefixes=prefix_id_list
        )
  • Files reviewed: 12/12 changed files
  • Comments generated: 5
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/azure-cli/azure/cli/command_modules/acs/_natgateway.py Outdated
Comment thread src/azure-cli/azure/cli/command_modules/acs/_validators.py
Comment thread src/azure-cli/azure/cli/command_modules/acs/_validators.py Outdated
Comment thread src/azure-cli/azure/cli/command_modules/acs/_help.py
Comment on lines +13 to +24
nat_gateway_sku:
rule_exclusions:
- missing_parameter_test_coverage
nat_gateway_managed_outbound_ipv6_count:
rule_exclusions:
- missing_parameter_test_coverage
nat_gateway_outbound_ip_ids:
rule_exclusions:
- missing_parameter_test_coverage
nat_gateway_outbound_ip_prefix_ids:
rule_exclusions:
- missing_parameter_test_coverage
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@a0x1ab

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

Code review

Found 3 issues:

  1. On update, omitting --outbound-type-sku preserves an existing Standard NAT gateway SKU while accepting V2-only options. The validator rejects only an explicitly supplied Standard, so the command can send an invalid Standard profile with V2 fields.

def validate_nat_gateway_v2_params_for_update(namespace):
"""Validate StandardV2-only NAT gateway params on update.
Unlike create, --outbound-type may be omitted when the cluster is already managed NAT gateway;
only an explicit non-managed-NAT-gateway outbound type or the Standard SKU is rejected here.
"""
v2_params = [
getattr(namespace, 'nat_gateway_managed_outbound_ipv6_count', None),
getattr(namespace, 'nat_gateway_outbound_ip_ids', None),
getattr(namespace, 'nat_gateway_outbound_ip_prefix_ids', None),
]
if not any(p is not None for p in v2_params):
return
if (namespace.outbound_type is not None and namespace.outbound_type != 'managedNATGateway') or \
getattr(namespace, 'nat_gateway_sku', None) == 'Standard':
raise InvalidArgumentValueError(
"--nat-gateway-managed-outbound-ipv6-count, --nat-gateway-outbound-ips and "
"--nat-gateway-outbound-ip-prefixes are only valid with --outbound-type managedNATGateway "
"and --outbound-type-sku StandardV2."

  1. --nat-gateway-managed-outbound-ipv6-count accepts 0, but the service contract requires a value from 1 through 16. The zero value passes client validation and then fails server-side.

def validate_nat_gateway_managed_outbound_ipv6_count(namespace):
"""validate NAT gateway profile managed outbound IPv6 count (StandardV2, dual-stack only)"""
ipv6_count = namespace.nat_gateway_managed_outbound_ipv6_count
if ipv6_count is not None:
if ipv6_count < 0 or ipv6_count > 16:
raise InvalidArgumentValueError(
"--nat-gateway-managed-outbound-ipv6-count must be in the range [0,16]"
)

  1. Creating a NAT gateway profile with only an IPv6 count leaves the IPv4 count unset. SDK 41.6 no longer materializes the documented IPv4 default of 1, so this path serializes no IPv4 count instead of preserving the required default.

if managed_outbound_ip_count is not None or managed_outbound_ipv6_count is not None:
ManagedClusterManagedOutboundIPProfile = models.ManagedClusterManagedOutboundIPProfile
if not profile.managed_outbound_ip_profile:
profile.managed_outbound_ip_profile = ManagedClusterManagedOutboundIPProfile()
if managed_outbound_ip_count is not None:
profile.managed_outbound_ip_profile.count = managed_outbound_ip_count
if managed_outbound_ipv6_count is not None:
profile.managed_outbound_ip_profile.count_ipv6 = managed_outbound_ipv6_count
if idle_timeout:

@a0x1ab

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).

…unt range [1,16], and preserve IPv4 default of 1
@christine33-creator

Copy link
Copy Markdown
Author

Code review

Found 3 issues:

  1. On update, omitting --outbound-type-sku preserves an existing Standard NAT gateway SKU while accepting V2-only options. The validator rejects only an explicitly supplied Standard, so the command can send an invalid Standard profile with V2 fields.

def validate_nat_gateway_v2_params_for_update(namespace):
"""Validate StandardV2-only NAT gateway params on update.
Unlike create, --outbound-type may be omitted when the cluster is already managed NAT gateway;
only an explicit non-managed-NAT-gateway outbound type or the Standard SKU is rejected here.
"""
v2_params = [
getattr(namespace, 'nat_gateway_managed_outbound_ipv6_count', None),
getattr(namespace, 'nat_gateway_outbound_ip_ids', None),
getattr(namespace, 'nat_gateway_outbound_ip_prefix_ids', None),
]
if not any(p is not None for p in v2_params):
return
if (namespace.outbound_type is not None and namespace.outbound_type != 'managedNATGateway') or \
getattr(namespace, 'nat_gateway_sku', None) == 'Standard':
raise InvalidArgumentValueError(
"--nat-gateway-managed-outbound-ipv6-count, --nat-gateway-outbound-ips and "
"--nat-gateway-outbound-ip-prefixes are only valid with --outbound-type managedNATGateway "
"and --outbound-type-sku StandardV2."

  1. --nat-gateway-managed-outbound-ipv6-count accepts 0, but the service contract requires a value from 1 through 16. The zero value passes client validation and then fails server-side.

def validate_nat_gateway_managed_outbound_ipv6_count(namespace):
"""validate NAT gateway profile managed outbound IPv6 count (StandardV2, dual-stack only)"""
ipv6_count = namespace.nat_gateway_managed_outbound_ipv6_count
if ipv6_count is not None:
if ipv6_count < 0 or ipv6_count > 16:
raise InvalidArgumentValueError(
"--nat-gateway-managed-outbound-ipv6-count must be in the range [0,16]"
)

  1. Creating a NAT gateway profile with only an IPv6 count leaves the IPv4 count unset. SDK 41.6 no longer materializes the documented IPv4 default of 1, so this path serializes no IPv4 count instead of preserving the required default.

if managed_outbound_ip_count is not None or managed_outbound_ipv6_count is not None:
ManagedClusterManagedOutboundIPProfile = models.ManagedClusterManagedOutboundIPProfile
if not profile.managed_outbound_ip_profile:
profile.managed_outbound_ip_profile = ManagedClusterManagedOutboundIPProfile()
if managed_outbound_ip_count is not None:
profile.managed_outbound_ip_profile.count = managed_outbound_ip_count
if managed_outbound_ipv6_count is not None:
profile.managed_outbound_ip_profile.count_ipv6 = managed_outbound_ipv6_count
if idle_timeout:

1: Fixed. validate_nat_gateway_v2_params_for_update now requires an explicit --outbound-type-sku StandardV2 whenever any V2-only param is set — it rejects both an omitted sku and Standard (previously only Standard). Create intentionally keeps the sku-less path, since there the converter defaults to StandardV2 where the region supports it

  1. Fixed. validate_nat_gateway_managed_outbound_ipv6_count now enforces [1,16], so 0 is rejected client-side
  2. Fixed. In configure_nat_gateway_profile, when only an IPv6 count is supplied we now set the IPv4 count to default of 1. It's guarded (elif profile.managed_outbound_ip_profile.count is None) so an existing IPv4 count is never overwritten on update.

@a0x1ab

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).

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 customer-reported Issues that are reported by GitHub users external to the Azure organization.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants