diff --git a/src/azure-cli/azure/cli/command_modules/appservice/_validators.py b/src/azure-cli/azure/cli/command_modules/appservice/_validators.py index 10a6fc8417a..33bd2ec9add 100644 --- a/src/azure-cli/azure/cli/command_modules/appservice/_validators.py +++ b/src/azure-cli/azure/cli/command_modules/appservice/_validators.py @@ -91,7 +91,7 @@ def validate_ase_create(cmd, namespace): def _validate_asp_sku(sku, app_service_environment, zone_redundant): - supported_skus = ['PREMIUMV2', 'PREMIUMV3', 'PREMIUMMV3', 'PREMIUM0V3', 'PREMIUMV4', 'PREMIUMMV4', 'ISOLATEDV2', 'ISOLATEDMV2'] # pylint: disable=line-too-long + supported_skus = ['PREMIUMV2', 'PREMIUMV3', 'PREMIUMMV3', 'PREMIUM0V3', 'PREMIUMV4', 'PREMIUMMV4', 'ISOLATEDV2', 'ISOLATEDMV2', 'ELASTICPREMIUM'] # pylint: disable=line-too-long if zone_redundant and get_sku_tier(sku).upper() not in supported_skus: raise ValidationError("Zone redundancy cannot be enabled for sku {}".format(sku)) # Isolated SKU is supported only for ASE diff --git a/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/recordings/test_functionapp_create_elastic_premium_ep2_zone_redundant_plan.yaml b/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/recordings/test_functionapp_create_elastic_premium_ep2_zone_redundant_plan.yaml new file mode 100644 index 00000000000..678e4a4a325 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/recordings/test_functionapp_create_elastic_premium_ep2_zone_redundant_plan.yaml @@ -0,0 +1,111 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - functionapp plan create + Connection: + - keep-alive + ParameterSetName: + - -g -n --sku --zone-redundant + User-Agent: + - AZURECLI/2.78.0 azsdk-python-core/1.35.0 Python/3.11.9 (Windows-10-10.0.22631-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001?api-version=2024-11-01 + response: + body: + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001","name":"clitest.rg000001","type":"Microsoft.Resources/resourceGroups","location":"francecentral","tags":{"product":"azurecli","cause":"automation","test":"test_functionapp_create_elastic_premium_ep2_zone_redundant_plan","date":"2025-11-07T05:25:22Z","module":"appservice"},"properties":{"provisioningState":"Succeeded"}}' + headers: + cache-control: + - no-cache + content-length: + - '412' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 07 Nov 2025 05:25:28 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 6312A332DBA64578A8A493DDB458D25A Ref B: MWH011020809052 Ref C: 2025-11-07T05:25:28Z' + status: + code: 200 + message: OK +- request: + body: '{"location": "francecentral", "sku": {"name": "EP2", "tier": "ElasticPremium", + "capacity": 3}, "properties": {"perSiteScaling": false, "isXenon": false, "zoneRedundant": + true}}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - functionapp plan create + Connection: + - keep-alive + Content-Length: + - '176' + Content-Type: + - application/json + ParameterSetName: + - -g -n --sku --zone-redundant + User-Agent: + - AZURECLI/2.78.0 azsdk-python-core/1.35.0 Python/3.11.9 (Windows-10-10.0.22631-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Web/serverfarms/epplan000002?api-version=2024-11-01 + response: + body: + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Web/serverfarms/epplan000002","name":"epplan000002","type":"Microsoft.Web/serverfarms","kind":"elastic","location":"francecentral","properties":{"serverFarmId":22750,"name":"epplan000002","sku":{"name":"EP2","tier":"ElasticPremium","size":"EP2","family":"EP","capacity":3},"workerSize":"D2","workerSizeId":4,"workerTierName":null,"numberOfWorkers":3,"currentWorkerSize":"D2","currentWorkerSizeId":4,"currentNumberOfWorkers":3,"status":"Ready","webSpace":"clitest.rg000001-FranceCentralwebspace","subscription":"2819c8c8-a774-4ac9-bf91-8bb8f1f47ece","adminSiteName":null,"hostingEnvironment":null,"hostingEnvironmentProfile":null,"maximumNumberOfWorkers":0,"planName":"VirtualDedicatedPlan","adminRuntimeSiteName":null,"computeMode":"Dedicated","siteMode":null,"geoRegion":"France + Central","perSiteScaling":false,"elasticScaleEnabled":true,"maximumElasticWorkerCount":3,"numberOfSites":0,"hostingEnvironmentId":null,"isSpot":false,"spotExpirationTime":null,"freeOfferExpirationTime":null,"tags":null,"kind":"elastic","resourceGroup":"clitest.rg000001","reserved":false,"isXenon":false,"hyperV":false,"mdmId":"waws-prod-par-053_22750","targetWorkerCount":0,"targetWorkerSizeId":0,"targetWorkerSku":null,"provisioningState":"Succeeded","webSiteId":null,"existingServerFarmIds":null,"kubeEnvironmentProfile":null,"zoneRedundant":true,"maximumNumberOfZones":3,"currentNumberOfZonesUtilized":3,"migrateToVMSS":null,"vnetConnectionsUsed":null,"vnetConnectionsMax":null,"createdTime":"2025-11-07T05:25:33.54","asyncScalingEnabled":false,"isCustomMode":null,"powerState":null,"eligibleLogCategories":null},"sku":{"name":"EP2","tier":"ElasticPremium","size":"EP2","family":"EP","capacity":3}}' + headers: + cache-control: + - no-cache + content-length: + - '1793' + content-type: + - application/json + date: + - Fri, 07 Nov 2025 05:25:36 GMT + etag: + - '"1DC4FA6F13ACBC0"' + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-aspnet-version: + - 4.0.30319 + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=bd30bf6a-f200-4cfd-bcd6-a339b0d9dbe8/northcentralus/867ac0da-eace-4898-b1c0-55ac836f5539 + x-ms-ratelimit-remaining-subscription-global-writes: + - '11999' + x-ms-ratelimit-remaining-subscription-writes: + - '799' + x-msedge-ref: + - 'Ref A: E3FEE3C150B84FD7B5E544AA0AD3E400 Ref B: CO6AA3150217033 Ref C: 2025-11-07T05:25:29Z' + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +version: 1 diff --git a/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/recordings/test_functionapp_create_elastic_premium_ep3_zone_redundant_plan.yaml b/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/recordings/test_functionapp_create_elastic_premium_ep3_zone_redundant_plan.yaml new file mode 100644 index 00000000000..8b170722e45 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/recordings/test_functionapp_create_elastic_premium_ep3_zone_redundant_plan.yaml @@ -0,0 +1,111 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - functionapp plan create + Connection: + - keep-alive + ParameterSetName: + - -g -n --sku --zone-redundant + User-Agent: + - AZURECLI/2.78.0 azsdk-python-core/1.35.0 Python/3.11.9 (Windows-10-10.0.22631-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001?api-version=2024-11-01 + response: + body: + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001","name":"clitest.rg000001","type":"Microsoft.Resources/resourceGroups","location":"francecentral","tags":{"product":"azurecli","cause":"automation","test":"test_functionapp_create_elastic_premium_ep3_zone_redundant_plan","date":"2025-10-24T20:43:41Z","module":"appservice"},"properties":{"provisioningState":"Succeeded"}}' + headers: + cache-control: + - no-cache + content-length: + - '412' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 24 Oct 2025 20:43:45 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: 75EA64BC39954670B6E4213DF8A4B8BF Ref B: MWH011020808042 Ref C: 2025-10-24T20:43:45Z' + status: + code: 200 + message: OK +- request: + body: '{"location": "francecentral", "sku": {"name": "EP3", "tier": "ElasticPremium", + "capacity": 3}, "properties": {"perSiteScaling": false, "isXenon": false, "zoneRedundant": + true}}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - functionapp plan create + Connection: + - keep-alive + Content-Length: + - '176' + Content-Type: + - application/json + ParameterSetName: + - -g -n --sku --zone-redundant + User-Agent: + - AZURECLI/2.78.0 azsdk-python-core/1.35.0 Python/3.11.9 (Windows-10-10.0.22631-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Web/serverfarms/epplan000002?api-version=2024-11-01 + response: + body: + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Web/serverfarms/epplan000002","name":"epplan000002","type":"Microsoft.Web/serverfarms","kind":"elastic","location":"francecentral","properties":{"serverFarmId":72567,"name":"epplan000002","sku":{"name":"EP3","tier":"ElasticPremium","size":"EP3","family":"EP","capacity":3},"workerSize":"D3","workerSizeId":5,"workerTierName":null,"numberOfWorkers":3,"currentWorkerSize":"D3","currentWorkerSizeId":5,"currentNumberOfWorkers":3,"status":"Ready","webSpace":"clitest.rg000001-FranceCentralwebspace","subscription":"2819c8c8-a774-4ac9-bf91-8bb8f1f47ece","adminSiteName":null,"hostingEnvironment":null,"hostingEnvironmentProfile":null,"maximumNumberOfWorkers":0,"planName":"VirtualDedicatedPlan","adminRuntimeSiteName":null,"computeMode":"Dedicated","siteMode":null,"geoRegion":"France + Central","perSiteScaling":false,"elasticScaleEnabled":true,"maximumElasticWorkerCount":3,"numberOfSites":0,"hostingEnvironmentId":null,"isSpot":false,"spotExpirationTime":null,"freeOfferExpirationTime":null,"tags":null,"kind":"elastic","resourceGroup":"clitest.rg000001","reserved":false,"isXenon":false,"hyperV":false,"mdmId":"waws-prod-par-021_72567","targetWorkerCount":0,"targetWorkerSizeId":0,"targetWorkerSku":null,"provisioningState":"Succeeded","webSiteId":null,"existingServerFarmIds":null,"kubeEnvironmentProfile":null,"zoneRedundant":true,"maximumNumberOfZones":3,"currentNumberOfZonesUtilized":3,"migrateToVMSS":null,"vnetConnectionsUsed":null,"vnetConnectionsMax":null,"createdTime":"2025-10-24T20:43:50.82","asyncScalingEnabled":false,"isCustomMode":null,"powerState":null,"eligibleLogCategories":null},"sku":{"name":"EP3","tier":"ElasticPremium","size":"EP3","family":"EP","capacity":3}}' + headers: + cache-control: + - no-cache + content-length: + - '1793' + content-type: + - application/json + date: + - Fri, 24 Oct 2025 20:43:53 GMT + etag: + - '"1DC4526E7F8784B"' + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-aspnet-version: + - 4.0.30319 + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=bd30bf6a-f200-4cfd-bcd6-a339b0d9dbe8/westus2/47bc07cb-b0fb-45fc-b9f3-93b192a568f5 + x-ms-ratelimit-remaining-subscription-global-writes: + - '12000' + x-ms-ratelimit-remaining-subscription-writes: + - '800' + x-msedge-ref: + - 'Ref A: 26FA6A5BCD50434D9E2BCE1F4B0FD909 Ref B: CO6AA3150220039 Ref C: 2025-10-24T20:43:45Z' + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +version: 1 diff --git a/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/recordings/test_functionapp_create_elastic_premium_zone_redundant_plan.yaml b/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/recordings/test_functionapp_create_elastic_premium_zone_redundant_plan.yaml new file mode 100644 index 00000000000..d2dc8f76753 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/recordings/test_functionapp_create_elastic_premium_zone_redundant_plan.yaml @@ -0,0 +1,111 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - functionapp plan create + Connection: + - keep-alive + ParameterSetName: + - -g -n --sku --zone-redundant + User-Agent: + - AZURECLI/2.78.0 azsdk-python-core/1.35.0 Python/3.11.9 (Windows-10-10.0.22631-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001?api-version=2024-11-01 + response: + body: + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001","name":"clitest.rg000001","type":"Microsoft.Resources/resourceGroups","location":"francecentral","tags":{"product":"azurecli","cause":"automation","test":"test_functionapp_create_elastic_premium_zone_redundant_plan","date":"2025-10-24T19:29:44Z","module":"appservice"},"properties":{"provisioningState":"Succeeded"}}' + headers: + cache-control: + - no-cache + content-length: + - '408' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 24 Oct 2025 19:29:52 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-global-reads: + - '16499' + x-msedge-ref: + - 'Ref A: E84614F2A52F47DB9F22CF1806B3120A Ref B: MWH011020809040 Ref C: 2025-10-24T19:29:51Z' + status: + code: 200 + message: OK +- request: + body: '{"location": "francecentral", "sku": {"name": "EP1", "tier": "ElasticPremium", + "capacity": 3}, "properties": {"perSiteScaling": false, "isXenon": false, "zoneRedundant": + true}}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - functionapp plan create + Connection: + - keep-alive + Content-Length: + - '176' + Content-Type: + - application/json + ParameterSetName: + - -g -n --sku --zone-redundant + User-Agent: + - AZURECLI/2.78.0 azsdk-python-core/1.35.0 Python/3.11.9 (Windows-10-10.0.22631-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Web/serverfarms/epplan000002?api-version=2024-11-01 + response: + body: + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Web/serverfarms/epplan000002","name":"epplan000002","type":"Microsoft.Web/serverfarms","kind":"elastic","location":"francecentral","properties":{"serverFarmId":49329,"name":"epplan000002","sku":{"name":"EP1","tier":"ElasticPremium","size":"EP1","family":"EP","capacity":3},"workerSize":"D1","workerSizeId":3,"workerTierName":null,"numberOfWorkers":3,"currentWorkerSize":"D1","currentWorkerSizeId":3,"currentNumberOfWorkers":3,"status":"Ready","webSpace":"clitest.rg000001-FranceCentralwebspace","subscription":"2819c8c8-a774-4ac9-bf91-8bb8f1f47ece","adminSiteName":null,"hostingEnvironment":null,"hostingEnvironmentProfile":null,"maximumNumberOfWorkers":0,"planName":"VirtualDedicatedPlan","adminRuntimeSiteName":null,"computeMode":"Dedicated","siteMode":null,"geoRegion":"France + Central","perSiteScaling":false,"elasticScaleEnabled":true,"maximumElasticWorkerCount":3,"numberOfSites":0,"hostingEnvironmentId":null,"isSpot":false,"spotExpirationTime":null,"freeOfferExpirationTime":null,"tags":null,"kind":"elastic","resourceGroup":"clitest.rg000001","reserved":false,"isXenon":false,"hyperV":false,"mdmId":"waws-prod-par-029_49329","targetWorkerCount":0,"targetWorkerSizeId":0,"targetWorkerSku":null,"provisioningState":"Succeeded","webSiteId":null,"existingServerFarmIds":null,"kubeEnvironmentProfile":null,"zoneRedundant":true,"maximumNumberOfZones":3,"currentNumberOfZonesUtilized":3,"migrateToVMSS":null,"vnetConnectionsUsed":null,"vnetConnectionsMax":null,"createdTime":"2025-10-24T19:29:57.7633333","asyncScalingEnabled":false,"isCustomMode":null,"powerState":null,"eligibleLogCategories":null},"sku":{"name":"EP1","tier":"ElasticPremium","size":"EP1","family":"EP","capacity":3}}' + headers: + cache-control: + - no-cache + content-length: + - '1798' + content-type: + - application/json + date: + - Fri, 24 Oct 2025 19:30:00 GMT + etag: + - '"1DC451C95C3A4E0"' + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-aspnet-version: + - 4.0.30319 + x-cache: + - CONFIG_NOCACHE + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47,objectId=bd30bf6a-f200-4cfd-bcd6-a339b0d9dbe8/westus2/412c828c-939b-41d5-b009-3825e4a158db + x-ms-ratelimit-remaining-subscription-global-writes: + - '12000' + x-ms-ratelimit-remaining-subscription-writes: + - '800' + x-msedge-ref: + - 'Ref A: 8D5BEF42718E4279B082054561E55B1B Ref B: MWH011020806060 Ref C: 2025-10-24T19:29:52Z' + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +version: 1 diff --git a/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/test_functionapp_commands.py b/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/test_functionapp_commands.py index c3b6231b375..22cb6736376 100644 --- a/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/test_functionapp_commands.py +++ b/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/test_functionapp_commands.py @@ -3402,6 +3402,30 @@ def test_functionapp_elastic_premium_restricted_public_network_access_storage_mu with self.assertRaises(ValidationError): self.cmd('functionapp create -g {} -n {} -s {} -p {} --functions-version 4 --vnet {} --subnet {} --configure-networking-later'.format(resource_group, functionapp_name, storage_account, ep_plan_name, vnet_name, subnet_name)) + @ResourceGroupPreparer(location=WINDOWS_ASP_LOCATION_FUNCTIONAPP) + def test_functionapp_create_elastic_premium_zone_redundant_plan(self, resource_group): + ep_plan_name = self.create_random_name('epplan', 24) + + self.cmd('functionapp plan create -g {} -n {} --sku EP1 --zone-redundant'.format(resource_group, ep_plan_name)).assert_with_checks([ + JMESPathCheck('zoneRedundant', True) + ]) + + @ResourceGroupPreparer(location=WINDOWS_ASP_LOCATION_FUNCTIONAPP) + def test_functionapp_create_elastic_premium_ep2_zone_redundant_plan(self, resource_group): + ep_plan_name = self.create_random_name('epplan', 24) + + self.cmd('functionapp plan create -g {} -n {} --sku EP2 --zone-redundant'.format(resource_group, ep_plan_name)).assert_with_checks([ + JMESPathCheck('zoneRedundant', True) + ]) + + @ResourceGroupPreparer(location=WINDOWS_ASP_LOCATION_FUNCTIONAPP) + def test_functionapp_create_elastic_premium_ep3_zone_redundant_plan(self, resource_group): + ep_plan_name = self.create_random_name('epplan', 24) + + self.cmd('functionapp plan create -g {} -n {} --sku EP3 --zone-redundant'.format(resource_group, ep_plan_name)).assert_with_checks([ + JMESPathCheck('zoneRedundant', True) + ]) + @live_only() @ResourceGroupPreparer(location=WINDOWS_ASP_LOCATION_FUNCTIONAPP) def test_functionapp_elastic_premium_restricted_public_network_access_storage_vnet(self, resource_group):