diff --git a/src/network-manager/HISTORY.rst b/src/network-manager/HISTORY.rst index 19a5f1fe80b..bd8cf39fda5 100644 --- a/src/network-manager/HISTORY.rst +++ b/src/network-manager/HISTORY.rst @@ -2,6 +2,11 @@ Release History =============== +3.1.0 ++++++ +* `az network manager routing-config rule-collection rule create/update`: Support comma-separated IP addresses in `--next-hop-address` for ECMP scenarios when `--next-hop-type` is `VirtualAppliance` +* Upgrade routing rule commands API version to 2025-07-01 + 3.0.1 +++++ * Add NG of type Subnet support for routing config diff --git a/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_create.py b/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_create.py index fbc29e95b21..ffc32a18159 100644 --- a/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_create.py +++ b/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_create.py @@ -20,12 +20,15 @@ class Create(AAZCommand): :example: Create an routing rule. az network manager routing-config rule-collection rule create --config-name TestNetworkManagerConfig --manager-name TestNetworkManager --collection-name TestNetworkManagerCollection --name TestNetworkManagerRule --resource-group "rg1" --destination {"destination_address":"10.0.0.0/16","type":"AddressPrefix"} --next-hop {"next_hop_type":"VirtualNetworkGateway"} + + :example: Create an routing rule with ECMP next hop (comma-separated IP addresses). + az network manager routing-config rule-collection rule create --config-name TestNetworkManagerConfig --manager-name TestNetworkManager --collection-name TestNetworkManagerCollection --name TestNetworkManagerRule --resource-group "rg1" --destination {"destination_address":"10.0.0.0/16","type":"AddressPrefix"} --next-hop {next_hop_type:VirtualAppliance,next_hop_address:'10.1.0.4,10.1.0.5,10.1.0.6'} """ _aaz_info = { - "version": "2024-05-01", + "version": "2025-07-01", "resources": [ - ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkmanagers/{}/routingconfigurations/{}/rulecollections/{}/rules/{}", "2024-05-01"], + ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkmanagers/{}/routingconfigurations/{}/rulecollections/{}/rules/{}", "2025-07-01"], ] } @@ -116,7 +119,7 @@ def _build_arguments_schema(cls, *args, **kwargs): next_hop = cls._args_schema.next_hop next_hop.next_hop_address = AAZStrArg( options=["next-hop-address"], - help="Next hop address. Only relevant if the next hop type is VirtualAppliance.", + help="Next hop address. Only relevant if the next hop type is VirtualAppliance. Supports comma-separated IP addresses for ECMP scenarios (e.g., '10.1.0.4,10.1.0.5,10.1.0.6').", ) next_hop.next_hop_type = AAZStrArg( options=["next-hop-type"], @@ -203,7 +206,7 @@ def url_parameters(self): def query_parameters(self): parameters = { **self.serialize_query_param( - "api-version", "2024-05-01", + "api-version", "2025-07-01", required=True, ), } diff --git a/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_delete.py b/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_delete.py index a348a31dac2..34385acaf00 100644 --- a/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_delete.py +++ b/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_delete.py @@ -24,9 +24,9 @@ class Delete(AAZCommand): """ _aaz_info = { - "version": "2024-05-01", + "version": "2025-07-01", "resources": [ - ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkmanagers/{}/routingconfigurations/{}/rulecollections/{}/rules/{}", "2024-05-01"], + ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkmanagers/{}/routingconfigurations/{}/rulecollections/{}/rules/{}", "2025-07-01"], ] } @@ -193,7 +193,7 @@ def query_parameters(self): "force", self.ctx.args.force, ), **self.serialize_query_param( - "api-version", "2024-05-01", + "api-version", "2025-07-01", required=True, ), } diff --git a/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_list.py b/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_list.py index e5cb1040c86..48d854caf89 100644 --- a/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_list.py +++ b/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_list.py @@ -23,9 +23,9 @@ class List(AAZCommand): """ _aaz_info = { - "version": "2024-05-01", + "version": "2025-07-01", "resources": [ - ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkmanagers/{}/routingconfigurations/{}/rulecollections/{}/rules", "2024-05-01"], + ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkmanagers/{}/routingconfigurations/{}/rulecollections/{}/rules", "2025-07-01"], ] } @@ -167,7 +167,7 @@ def query_parameters(self): "$top", self.ctx.args.top, ), **self.serialize_query_param( - "api-version", "2024-05-01", + "api-version", "2025-07-01", required=True, ), } diff --git a/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_show.py b/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_show.py index 49c540a516f..29323fd1aac 100644 --- a/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_show.py +++ b/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_show.py @@ -23,9 +23,9 @@ class Show(AAZCommand): """ _aaz_info = { - "version": "2024-05-01", + "version": "2025-07-01", "resources": [ - ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkmanagers/{}/routingconfigurations/{}/rulecollections/{}/rules/{}", "2024-05-01"], + ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkmanagers/{}/routingconfigurations/{}/rulecollections/{}/rules/{}", "2025-07-01"], ] } @@ -163,7 +163,7 @@ def url_parameters(self): def query_parameters(self): parameters = { **self.serialize_query_param( - "api-version", "2024-05-01", + "api-version", "2025-07-01", required=True, ), } diff --git a/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_update.py b/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_update.py index 4b6459ca54f..1326c531d8e 100644 --- a/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_update.py +++ b/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_update.py @@ -23,9 +23,9 @@ class Update(AAZCommand): """ _aaz_info = { - "version": "2024-05-01", + "version": "2025-07-01", "resources": [ - ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkmanagers/{}/routingconfigurations/{}/rulecollections/{}/rules/{}", "2024-05-01"], + ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkmanagers/{}/routingconfigurations/{}/rulecollections/{}/rules/{}", "2025-07-01"], ] } @@ -121,7 +121,7 @@ def _build_arguments_schema(cls, *args, **kwargs): next_hop = cls._args_schema.next_hop next_hop.next_hop_address = AAZStrArg( options=["next-hop-address"], - help="Next hop address. Only relevant if the next hop type is VirtualAppliance.", + help="Next hop address. Only relevant if the next hop type is VirtualAppliance. Supports comma-separated IP addresses for ECMP scenarios (e.g., '10.1.0.4,10.1.0.5,10.1.0.6').", nullable=True, ) next_hop.next_hop_type = AAZStrArg( @@ -221,7 +221,7 @@ def url_parameters(self): def query_parameters(self): parameters = { **self.serialize_query_param( - "api-version", "2024-05-01", + "api-version", "2025-07-01", required=True, ), } @@ -316,7 +316,7 @@ def url_parameters(self): def query_parameters(self): parameters = { **self.serialize_query_param( - "api-version", "2024-05-01", + "api-version", "2025-07-01", required=True, ), } diff --git a/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_wait.py b/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_wait.py index a761e010fba..79a9d43f309 100644 --- a/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_wait.py +++ b/src/network-manager/azext_network_manager/aaz/latest/network/manager/routing_config/rule_collection/rule/_wait.py @@ -20,7 +20,7 @@ class Wait(AAZWaitCommand): _aaz_info = { "resources": [ - ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkmanagers/{}/routingconfigurations/{}/rulecollections/{}/rules/{}", "2024-05-01"], + ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkmanagers/{}/routingconfigurations/{}/rulecollections/{}/rules/{}", "2025-07-01"], ] } @@ -158,7 +158,7 @@ def url_parameters(self): def query_parameters(self): parameters = { **self.serialize_query_param( - "api-version", "2024-05-01", + "api-version", "2025-07-01", required=True, ), } diff --git a/src/network-manager/azext_network_manager/tests/latest/recordings/test_network_manager_routing_rule_ecmp.yaml b/src/network-manager/azext_network_manager/tests/latest/recordings/test_network_manager_routing_rule_ecmp.yaml new file mode 100644 index 00000000000..79cc5978dd1 --- /dev/null +++ b/src/network-manager/azext_network_manager/tests/latest/recordings/test_network_manager_routing_rule_ecmp.yaml @@ -0,0 +1,280 @@ +interactions: +- request: + body: '{"location": "eastus2", "properties": {"description": "My Test Network + Manager", "networkManagerScopeAccesses": ["Routing"], "networkManagerScopes": + {"subscriptions": ["/subscriptions/00000000-0000-0000-0000-000000000000"]}}}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - network manager create + Connection: + - keep-alive + Content-Length: + - '225' + Content-Type: + - application/json + ParameterSetName: + - --name --description --scope-accesses --network-manager-scopes -l --resource-group + User-Agent: + - AZURECLI/2.85.0 azsdk-python-core/1.38.0 Python/3.12.10 (Windows-11-10.0.26200-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test_network_manager_routing_rule_ecmp000001/providers/Microsoft.Network/networkManagers/TestNetworkManager?api-version=2023-09-01 + response: + body: + string: '{"name":"TestNetworkManager","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test_network_manager_routing_rule_ecmp000001/providers/Microsoft.Network/networkManagers/TestNetworkManager","location":"eastus2","type":"Microsoft.Network/networkManagers","tags":{},"etag":"","properties":{"description":"My + Test Network Manager","networkManagerScopes":{"managementGroups":[],"subscriptions":["/subscriptions/00000000-0000-0000-0000-000000000000"],"crossTenantScopes":[]},"provisioningState":"Succeeded","networkManagerScopeAccesses":["Routing"],"resourceGuid":"a8bf2696-7617-41e7-a5f2-693fbd3e3b17"},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-04-08T02:21:18.1409519Z","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-04-08T02:21:18.1409519Z"}}' + headers: + cache-control: + - no-cache + content-length: + - '844' + content-type: + - application/json; charset=utf-8 + date: + - Wed, 08 Apr 2026 02:21:19 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=ed94de55-1f87-4278-9651-525e7ba467d6,objectId=4c73e7a5-a580-4613-82cf-af0b98695e15/eastus2/22942e4f-9044-40bd-9d15-46ae63697a8b + x-ms-ratelimit-remaining-subscription-global-writes: + - '2999' + x-ms-ratelimit-remaining-subscription-writes: + - '199' + x-msedge-ref: + - 'Ref A: 2C18D44B94714B5B99A06153ABE0294A Ref B: SG2AA1040518031 Ref C: 2026-04-08T02:21:17Z' + status: + code: 200 + message: OK +- request: + body: '{}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - network manager group create + Connection: + - keep-alive + Content-Length: + - '2' + Content-Type: + - application/json + ParameterSetName: + - --name --network-manager-name -g + User-Agent: + - AZURECLI/2.85.0 azsdk-python-core/1.38.0 Python/3.12.10 (Windows-11-10.0.26200-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test_network_manager_routing_rule_ecmp000001/providers/Microsoft.Network/networkManagers/TestNetworkManager/networkGroups/TestNetworkManagerGroup?api-version=2024-07-01 + response: + body: + string: '{"name":"TestNetworkManagerGroup","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test_network_manager_routing_rule_ecmp000001/providers/Microsoft.Network/networkManagers/TestNetworkManager/networkGroups/TestNetworkManagerGroup","type":"Microsoft.Network/networkManagers/networkGroups","etag":"","properties":{"description":"","provisioningState":"Succeeded","memberType":"VirtualNetwork","resourceGuid":"d0c58b6b-717b-4e55-8f42-259196d59743"},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-04-08T02:21:20.2741520Z","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-04-08T02:21:20.2741520Z"}}' + headers: + cache-control: + - no-cache + content-length: + - '693' + content-type: + - application/json; charset=utf-8 + date: + - Wed, 08 Apr 2026 02:21:20 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=ed94de55-1f87-4278-9651-525e7ba467d6,objectId=4c73e7a5-a580-4613-82cf-af0b98695e15/eastus2/a8875b75-33a6-4768-af9c-23382d0a6aa1 + x-ms-ratelimit-remaining-subscription-global-writes: + - '2999' + x-ms-ratelimit-remaining-subscription-writes: + - '199' + x-msedge-ref: + - 'Ref A: 248CB048043F41C485E273B5BA5DA733 Ref B: SG2AA1040517060 Ref C: 2026-04-08T02:21:20Z' + status: + code: 200 + message: OK +- request: + body: '{}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - network manager routing-config create + Connection: + - keep-alive + Content-Length: + - '2' + Content-Type: + - application/json + ParameterSetName: + - --name --manager-name --resource-group + User-Agent: + - AZURECLI/2.85.0 azsdk-python-core/1.38.0 Python/3.12.10 (Windows-11-10.0.26200-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test_network_manager_routing_rule_ecmp000001/providers/Microsoft.Network/networkManagers/TestNetworkManager/routingConfigurations/routing-config-000002?api-version=2024-05-01 + response: + body: + string: '{"name":"routing-config-000002","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test_network_manager_routing_rule_ecmp000001/providers/Microsoft.Network/networkManagers/TestNetworkManager/routingConfigurations/routing-config-000002","type":"Microsoft.Network/networkManagers/routingConfigurations","etag":"","properties":{"description":"","provisioningState":"Succeeded","resourceGuid":"2d52f104-deec-42ff-8970-14a7e9c812cf","routeTableUsageMode":"ManagedOnly"},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-04-08T02:21:21.5905686Z","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-04-08T02:21:21.5905686Z"}}' + headers: + cache-control: + - no-cache + content-length: + - '711' + content-type: + - application/json; charset=utf-8 + date: + - Wed, 08 Apr 2026 02:21:22 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=ed94de55-1f87-4278-9651-525e7ba467d6,objectId=4c73e7a5-a580-4613-82cf-af0b98695e15/eastus2/5d11be8a-3f7b-4e62-9f53-02e805639379 + x-ms-ratelimit-remaining-subscription-global-writes: + - '2999' + x-ms-ratelimit-remaining-subscription-writes: + - '199' + x-msedge-ref: + - 'Ref A: 7E480109E3424BEFA0AE6AE0EE97A95F Ref B: SG2AA1040515023 Ref C: 2026-04-08T02:21:21Z' + status: + code: 200 + message: OK +- request: + body: '{"properties": {"appliesTo": [{"networkGroupId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test_network_manager_routing_rule_ecmp000001/providers/Microsoft.Network/networkManagers/TestNetworkManager/networkGroups/TestNetworkManagerGroup"}], + "disableBgpRoutePropagation": "True"}}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - network manager routing-config rule-collection create + Connection: + - keep-alive + Content-Length: + - '305' + Content-Type: + - application/json + ParameterSetName: + - --config-name --manager-name --name --resource-group --applies-to --disable-bgp-route + User-Agent: + - AZURECLI/2.85.0 azsdk-python-core/1.38.0 Python/3.12.10 (Windows-11-10.0.26200-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test_network_manager_routing_rule_ecmp000001/providers/Microsoft.Network/networkManagers/TestNetworkManager/routingConfigurations/routing-config-000002/ruleCollections/rule-collection-000003?api-version=2024-05-01 + response: + body: + string: '{"name":"rule-collection-000003","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test_network_manager_routing_rule_ecmp000001/providers/Microsoft.Network/networkManagers/TestNetworkManager/routingConfigurations/routing-config-000002/ruleCollections/rule-collection-000003","type":"Microsoft.Network/networkManagers/routingConfigurations/ruleCollections","etag":"","properties":{"description":"","provisioningState":"Succeeded","resourceGuid":"36dfc4e2-68ee-4dac-88ce-48a6ce469889","appliesTo":[{"networkGroupId":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test_network_manager_routing_rule_ecmp000001/providers/Microsoft.Network/networkManagers/TestNetworkManager/networkGroups/TestNetworkManagerGroup"}],"disableBgpRoutePropagation":"True","localRouteSetting":"NotSpecified","peeringRoutePropagationRules":[]},"systemData":{"createdBy":"test@example.com","createdByType":"User","createdAt":"2026-04-08T02:21:22.9673008Z","lastModifiedBy":"test@example.com","lastModifiedByType":"User","lastModifiedAt":"2026-04-08T02:21:22.9673008Z"}}' + headers: + cache-control: + - no-cache + content-length: + - '1084' + content-type: + - application/json; charset=utf-8 + date: + - Wed, 08 Apr 2026 02:21:23 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=ed94de55-1f87-4278-9651-525e7ba467d6,objectId=4c73e7a5-a580-4613-82cf-af0b98695e15/eastus2/fc65d709-34cc-4a9a-a353-8b986080d29f + x-ms-ratelimit-remaining-subscription-global-writes: + - '2999' + x-ms-ratelimit-remaining-subscription-writes: + - '199' + x-msedge-ref: + - 'Ref A: FFD0B9474DBA4E938055A6728354DF4C Ref B: SG2AA1040515062 Ref C: 2026-04-08T02:21:22Z' + status: + code: 200 + message: OK +- request: + body: '{"properties": {"destination": {"destinationAddress": "10.0.0.0/16", "type": + "AddressPrefix"}, "nextHop": {"nextHopAddress": "10.1.0.4,10.1.0.5,10.1.0.6", + "nextHopType": "VirtualAppliance"}}}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - network manager routing-config rule-collection rule create + Connection: + - keep-alive + Content-Length: + - '191' + Content-Type: + - application/json + ParameterSetName: + - --config-name --manager-name --collection-name --name --resource-group --destination + --next-hop + User-Agent: + - AZURECLI/2.85.0 azsdk-python-core/1.38.0 Python/3.12.10 (Windows-11-10.0.26200-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test_network_manager_routing_rule_ecmp000001/providers/Microsoft.Network/networkManagers/TestNetworkManager/routingConfigurations/routing-config-000002/ruleCollections/rule-collection-000003/rules/rule-000004?api-version=2025-07-01 + response: + body: + string: '{"error":{"message":"Attempting to use a feature 88939486-3f56-4b35-bd43-5d6b34df022f + which is not currently available.","code":"BadRequest"}}' + headers: + cache-control: + - no-cache + content-length: + - '142' + content-type: + - application/json; charset=utf-8 + date: + - Wed, 08 Apr 2026 02:21:23 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=ed94de55-1f87-4278-9651-525e7ba467d6,objectId=4c73e7a5-a580-4613-82cf-af0b98695e15/eastus2/dc06911d-3600-45dd-8d2b-e0e24db91ba0 + x-ms-ratelimit-remaining-subscription-global-writes: + - '2999' + x-ms-ratelimit-remaining-subscription-writes: + - '199' + x-msedge-ref: + - 'Ref A: 6C4E517489354EB29A0F69926C4B0653 Ref B: SG2AA1040520034 Ref C: 2026-04-08T02:21:24Z' + status: + code: 400 + message: Bad Request +version: 1 diff --git a/src/network-manager/azext_network_manager/tests/latest/test_network_scenario.py b/src/network-manager/azext_network_manager/tests/latest/test_network_scenario.py index f8c8b2756f6..4bc7cf2541e 100644 --- a/src/network-manager/azext_network_manager/tests/latest/test_network_scenario.py +++ b/src/network-manager/azext_network_manager/tests/latest/test_network_scenario.py @@ -653,6 +653,76 @@ def test_network_manager_routing_config_crud(self, resource_group): self.cmd('network manager delete --resource-group {rg} --name {manager_name} --force --yes') + @serial_test() + @AllowLargeResponse() + @ResourceGroupPreparer(name_prefix='test_network_manager_routing_rule_ecmp', location='eastus2') + def test_network_manager_routing_rule_ecmp(self, resource_group): + self.kwargs.update({ + 'manager_name': 'TestNetworkManager', + "group_name": 'TestNetworkManagerGroup', + 'sub': '/subscriptions/{}'.format(self.get_subscription_id()), + "routing_config": self.create_random_name("routing-config-", 20), + "rule_collection": self.create_random_name("rule-collection-", 20), + "rule_name": self.create_random_name("rule-", 10), + "ecmp_addresses": "10.1.0.4,10.1.0.5,10.1.0.6" + }) + + self.cmd('network manager create --name {manager_name} --description "My Test Network Manager" ' + '--scope-accesses "Routing" ' + '--network-manager-scopes ' + 'subscriptions={sub} ' + '-l eastus2 ' + '--resource-group {rg}') + + manager_group = self.cmd('network manager group create --name {group_name} --network-manager-name {manager_name} -g {rg}').get_output_in_json() + + self.kwargs.update({ + 'manager_id': manager_group['id'] + }) + + self.cmd('az network manager routing-config create --name {routing_config} --manager-name {manager_name} --resource-group {rg}', + self.check('name', '{routing_config}')) + + self.cmd('az network manager routing-config rule-collection create --config-name {routing_config} --manager-name {manager_name} --name {rule_collection} --resource-group {rg} --applies-to [{{"network_group_id":"{manager_id}"}}] --disable-bgp-route true', + self.check('name', '{rule_collection}')) + + # Create a routing rule with ECMP next hop (comma-separated IP addresses) + self.cmd('az network manager routing-config rule-collection rule create --config-name {routing_config} --manager-name {manager_name} --collection-name {rule_collection} --name {rule_name} --resource-group {rg} --destination {{"destination_address":"10.0.0.0/16","type":"AddressPrefix"}} --next-hop {{"next_hop_type":"VirtualAppliance","next_hop_address":"\'{ecmp_addresses}\'"}}', + checks=[ + self.check('name', '{rule_name}'), + self.check('nextHop.nextHopType', 'VirtualAppliance'), + self.check('nextHop.nextHopAddress', '{ecmp_addresses}') + ]) + + # Verify show preserves comma-separated addresses + self.cmd('az network manager routing-config rule-collection rule show --config-name {routing_config} --manager-name {manager_name} --collection-name {rule_collection} --name {rule_name} --resource-group {rg}', + checks=[ + self.check('name', '{rule_name}'), + self.check('nextHop.nextHopType', 'VirtualAppliance'), + self.check('nextHop.nextHopAddress', '{ecmp_addresses}') + ]) + + # Verify list preserves comma-separated addresses + self.cmd('az network manager routing-config rule-collection rule list --config-name {routing_config} --manager-name {manager_name} --collection-name {rule_collection} --resource-group {rg}', + checks=[ + self.check('length(@)', 1), + self.check('[0].nextHop.nextHopType', 'VirtualAppliance'), + self.check('[0].nextHop.nextHopAddress', '{ecmp_addresses}') + ]) + + # Update the rule and verify ECMP addresses are preserved + self.cmd('az network manager routing-config rule-collection rule update --config-name {routing_config} --manager-name {manager_name} --collection-name {rule_collection} --name {rule_name} --resource-group {rg} --description "ecmp test"', + checks=[ + self.check('description', 'ecmp test'), + self.check('nextHop.nextHopAddress', '{ecmp_addresses}') + ]) + + self.cmd('az network manager routing-config rule-collection rule delete --config-name {routing_config} --manager-name {manager_name} --collection-name {rule_collection} --name {rule_name} --resource-group {rg} -y') + self.cmd('az network manager routing-config rule-collection delete --config-name {routing_config} --manager-name {manager_name} --name {rule_collection} --resource-group {rg} -y') + self.cmd('az network manager routing-config delete --name {routing_config} --manager-name {manager_name} --resource-group {rg} -y') + + self.cmd('network manager delete --resource-group {rg} --name {manager_name} --force --yes') + @serial_test() @AllowLargeResponse() @ResourceGroupPreparer(name_prefix='test_network_manager_static_cidr_crud', location='eastus2') diff --git a/src/network-manager/setup.py b/src/network-manager/setup.py index e92608563af..918994c0992 100644 --- a/src/network-manager/setup.py +++ b/src/network-manager/setup.py @@ -11,7 +11,7 @@ # HISTORY.rst entry. # Fixed post commit issue in routing -VERSION = '3.0.1' +VERSION = '3.1.0' # The full list of classifiers is available at # https://pypi.python.org/pypi?%3Aaction=list_classifiers