Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions src/azure-cli/azure/cli/command_modules/appservice/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,18 @@
type: command
short-summary: Create an app service plan.
examples:
- name: Create a basic app service plan.
- name: Create a Linux app service plan (defaults to P0V3 when --sku is not specified).
text: >
az appservice plan create -g MyResourceGroup -n MyPlan --is-linux
- name: Create a Windows app service plan (defaults to B1 when --sku is not specified).
text: >
az appservice plan create -g MyResourceGroup -n MyPlan
- name: Create a standard app service plan with four Linux workers.
- name: Create a Windows app service plan with a specific SKU.
text: >
az appservice plan create -g MyResourceGroup -n MyPlan --sku B1
- name: Create a Linux app service plan with four Linux workers.
text: >
az appservice plan create -g MyResourceGroup -n MyPlan --is-linux --number-of-workers 4 --sku S1
az appservice plan create -g MyResourceGroup -n MyPlan --is-linux --number-of-workers 4 --sku P0V3
- name: Create a Windows container app service plan.
text: >
az appservice plan create -g MyResourceGroup -n MyPlan --hyper-v --sku P1V3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,15 @@ def _validate_asp_sku(sku, app_service_environment, zone_redundant):

def validate_asp_create(namespace):
validate_tags(namespace)
if namespace.sku is None:
Comment thread
Shi1810 marked this conversation as resolved.
if namespace.is_linux:
namespace.sku = 'P0V3'
logger.warning("No --sku specified. Using default: P0V3 (Premium V3 Extra Small). "
"See all options: az appservice plan create --help. "
"For current pricing, visit: "
"https://azure.microsoft.com/pricing/details/app-service/")
else:
namespace.sku = 'B1'
sku = _normalize_sku(namespace.sku)
_validate_asp_sku(sku, namespace.app_service_environment, namespace.zone_redundant)
if namespace.is_linux and namespace.hyper_v:
Expand Down
18 changes: 12 additions & 6 deletions src/azure-cli/azure/cli/command_modules/appservice/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -2174,7 +2174,7 @@ def update_webapp(cmd, instance, client_affinity_enabled=None, https_only=None,
args = ["--minimum-elastic-instance-count", "--prewarmed-instance-count"]
plan = get_app_service_plan_from_webapp(cmd, instance)
sku = _normalize_sku(plan.sku.name)
if get_sku_tier(sku) not in ["PREMIUMV2", "PREMIUMV3"]:
if get_sku_tier(sku) not in ["PREMIUMV2", "PREMIUM0V3", "PREMIUMV3"]:
raise ValidationError("{} are only supported for elastic premium V2/V3 SKUs".format(str(args)))
if not plan.elastic_scale_enabled:
raise ValidationError("Elastic scale is not enabled on the App Service Plan. Please update the plan ")
Expand Down Expand Up @@ -4212,11 +4212,14 @@ def is_async_response(poller, timeout_seconds=30):


def create_app_service_plan(cmd, resource_group_name, name, is_linux, hyper_v, per_site_scaling=False,
app_service_environment=None, sku='B1', number_of_workers=None, location=None,
app_service_environment=None, sku=None, number_of_workers=None, location=None,
tags=None, no_wait=False, zone_redundant=False, async_scaling_enabled=None,
is_managed_instance=None, mi_system_assigned=None, mi_user_assigned=None,
default_identity=None, rdp_enabled=None, vnet=None, subnet=None,
registry_adapters=None, install_scripts=None, storage_mounts=None):
if sku is None:
sku = 'P0V3' if is_linux else 'B1'

HostingEnvironmentProfile, SkuDescription, AppServicePlan = cmd.get_models(
'HostingEnvironmentProfile', 'SkuDescription', 'AppServicePlan')

Expand Down Expand Up @@ -4260,10 +4263,13 @@ def create_app_service_plan(cmd, resource_group_name, name, is_linux, hyper_v, p

if sku.upper() in ['WS1', 'WS2', 'WS3']:
existing_plan = get_resource_if_exists(client.app_service_plans,
resource_group_name=resource_group_name, name=name)
resource_group_name=resource_group_name,
name=name)
if existing_plan and existing_plan.sku.tier != "WorkflowStandard":
raise ValidationError("Plan {} in resource group {} already exists and "
"cannot be updated to a logic app SKU (WS1, WS2, or WS3)")
raise ValidationError(
"Plan '{}' in resource group '{}' already exists and "
"cannot be updated to a logic app SKU (WS1, WS2, or WS3)"
.format(name, resource_group_name))
plan_def.type = "elastic"

if zone_redundant:
Expand Down Expand Up @@ -4397,7 +4403,7 @@ def update_app_service_plan(cmd, instance, sku=None, number_of_workers=None, ela
if elastic_scale is not None or max_elastic_worker_count is not None:
if sku is None:
sku = instance.sku.name
if get_sku_tier(sku) not in ["PREMIUMV2", "PREMIUMV3", "WorkflowStandard"]:
if get_sku_tier(sku) not in ["PREMIUMV2", "PREMIUM0V3", "PREMIUMV3", "WorkflowStandard"]:
raise ValidationError("--number-of-workers and --elastic-scale can only "
"be used on premium V2/V3 or workflow SKUs. "
"Use command help to see all available SKUs.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -644,5 +644,32 @@ def __init__(self, status_code):
self.status_code = status_code


class TestCreateAppServicePlanDefaults(unittest.TestCase):
"""Tests for create_app_service_plan default SKU behavior"""

@mock.patch('azure.cli.command_modules.appservice.custom.web_client_factory')
@mock.patch('azure.cli.command_modules.appservice.custom._get_location_from_resource_group', return_value='eastus')
def test_default_sku_is_p0v3_when_not_specified(self, mock_location, mock_client_factory):
from azure.cli.command_modules.appservice.custom import create_app_service_plan
mock_cmd = mock.MagicMock()
mock_cmd.get_models.return_value = (mock.MagicMock(), mock.MagicMock(), mock.MagicMock())
mock_cmd.cli_ctx = mock.MagicMock()
mock_client = mock.MagicMock()
mock_client_factory.return_value = mock_client

# Call without sku parameter — should default to P0V3
try:
create_app_service_plan(mock_cmd, 'rg', 'plan', is_linux=True, hyper_v=False)
except Exception:
pass # We don't care about downstream errors, just checking the SKU

# Verify SkuDescription was called with P0V3 tier/name
sku_description_cls = mock_cmd.get_models.return_value[1]
sku_description_cls.assert_called()
call_kwargs = sku_description_cls.call_args
# The sku name should be normalized P0V3
self.assertIn('P0V3', str(call_kwargs))


if __name__ == '__main__':
unittest.main()
Loading