Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ def load_arguments(self, _):
help='get regions which support hosting web apps on Windows Container workers')
c.argument('linux_workers_enabled', action='store_true',
help='get regions which support hosting web apps on Linux workers')
c.argument('managed_instance_enabled', action='store_true', is_preview=True,
help='get regions which support hosting web apps on Managed Instance workers')
c.argument('sku', arg_type=sku_arg_type)

with self.argument_context('appservice plan') as c:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
# flake8: noqa

from .__cmd_group import *
from ._list_locations import *
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
#
# Code generated by aaz-dev-tools
# --------------------------------------------------------------------------------------------

# pylint: skip-file
# flake8: noqa

from azure.cli.core.aaz import *


class ListLocations(AAZCommand):
"""List regions where a plan sku is available
"""

_aaz_info = {
"version": "2025-03-01",
"resources": [
["mgmt-plane", "/subscriptions/{}/providers/microsoft.web/georegions", "2025-03-01"],
]
}

AZ_SUPPORT_PAGINATION = True

def _handler(self, command_args):
super()._handler(command_args)
return self.build_paging(self._execute_operations, self._output)

_args_schema = None

@classmethod
def _build_arguments_schema(cls, *args, **kwargs):
if cls._args_schema is not None:
return cls._args_schema
cls._args_schema = super()._build_arguments_schema(*args, **kwargs)

# define Arg Group ""

_args_schema = cls._args_schema
_args_schema.custom_mode_workers_enabled = AAZBoolArg(
options=["--custom-mode-workers-enabled"],
help="Specify <code>true</code> if you want to filter to only regions that support App Service Plans with <code>IsCustomMode</code> set to <code>true</code>.",
)
_args_schema.linux_dynamic_workers_enabled = AAZBoolArg(
options=["--linux-dynamic-workers-enabled"],
help="Specify <code>true</code> if you want to filter to only regions that support Linux Consumption Workers.",
Comment thread
joslinmicrosoft marked this conversation as resolved.
Outdated
Comment thread
joslinmicrosoft marked this conversation as resolved.
Outdated
)
_args_schema.linux_workers_enabled = AAZBoolArg(
options=["--linux-workers-enabled"],
help="Get regions which support hosting web apps on Linux workers.",
)
_args_schema.sku = AAZStrArg(
options=["--sku"],
help="Name of SKU used to filter the regions.",
enum={"Basic": "Basic", "Dynamic": "Dynamic", "ElasticIsolated": "ElasticIsolated", "ElasticPremium": "ElasticPremium", "FlexConsumption": "FlexConsumption", "Free": "Free", "Isolated": "Isolated", "IsolatedV2": "IsolatedV2", "Premium": "Premium", "PremiumContainer": "PremiumContainer", "PremiumV2": "PremiumV2", "PremiumV3": "PremiumV3", "Shared": "Shared", "Standard": "Standard"},
)
_args_schema.hyperv_workers_enabled = AAZBoolArg(
options=["--hyperv-workers-enabled"],
help="Get regions which support hosting web apps on Windows Container workers.",
)
return cls._args_schema

def _execute_operations(self):
self.pre_operations()
self.ListGeoRegions(ctx=self.ctx)()
self.post_operations()

@register_callback
def pre_operations(self):
pass

@register_callback
def post_operations(self):
pass

def _output(self, *args, **kwargs):
result = self.deserialize_output(self.ctx.vars.instance.value, client_flatten=True)
next_link = self.deserialize_output(self.ctx.vars.instance.next_link)
return result, next_link

class ListGeoRegions(AAZHttpOperation):
CLIENT_TYPE = "MgmtClient"

def __call__(self, *args, **kwargs):
request = self.make_request()
session = self.client.send_request(request=request, stream=False, **kwargs)
if session.http_response.status_code in [200]:
return self.on_200(session)

return self.on_error(session.http_response)

@property
def url(self):
return self.client.format_url(
"/subscriptions/{subscriptionId}/providers/Microsoft.Web/geoRegions",
**self.url_parameters
)

@property
def method(self):
return "GET"

@property
def error_format(self):
return "ODataV4Format"

@property
def url_parameters(self):
parameters = {
**self.serialize_url_param(
"subscriptionId", self.ctx.subscription_id,
required=True,
),
}
return parameters

@property
def query_parameters(self):
parameters = {
**self.serialize_query_param(
"customModeWorkersEnabled", self.ctx.args.custom_mode_workers_enabled,
),
**self.serialize_query_param(
"linuxDynamicWorkersEnabled", self.ctx.args.linux_dynamic_workers_enabled,
),
**self.serialize_query_param(
"linuxWorkersEnabled", self.ctx.args.linux_workers_enabled,
),
**self.serialize_query_param(
"sku", self.ctx.args.sku,
),
**self.serialize_query_param(
"xenonWorkersEnabled", self.ctx.args.hyperv_workers_enabled,
),
**self.serialize_query_param(
"api-version", "2025-03-01",
required=True,
),
}
return parameters

@property
def header_parameters(self):
parameters = {
**self.serialize_header_param(
"Accept", "application/json",
),
}
return parameters

def on_200(self, session):
data = self.deserialize_http_content(session)
self.ctx.set_var(
"instance",
data,
schema_builder=self._build_schema_on_200
)

_schema_on_200 = None

@classmethod
def _build_schema_on_200(cls):
if cls._schema_on_200 is not None:
return cls._schema_on_200

cls._schema_on_200 = AAZObjectType()

_schema_on_200 = cls._schema_on_200
_schema_on_200.next_link = AAZStrType(
serialized_name="nextLink",
flags={"read_only": True},
)
_schema_on_200.value = AAZListType(
flags={"required": True},
)

value = cls._schema_on_200.value
value.Element = AAZObjectType()

_element = cls._schema_on_200.value.Element
_element.id = AAZStrType(
flags={"read_only": True},
)
_element.kind = AAZStrType()
_element.name = AAZStrType(
flags={"read_only": True},
)
_element.properties = AAZObjectType(
flags={"client_flatten": True},
)
_element.type = AAZStrType(
flags={"read_only": True},
)

properties = cls._schema_on_200.value.Element.properties
properties.description = AAZStrType(
flags={"read_only": True},
)
properties.display_name = AAZStrType(
serialized_name="displayName",
flags={"read_only": True},
)
properties.org_domain = AAZStrType(
serialized_name="orgDomain",
flags={"read_only": True},
)

return cls._schema_on_200


class _ListLocationsHelper:
"""Helper class for ListLocations"""


__all__ = ["ListLocations"]
33 changes: 27 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 @@ -74,7 +74,8 @@
get_resource_if_exists, repo_url_to_name, get_token,
app_service_plan_exists, is_centauri_functionapp, is_flex_functionapp,
_remove_list_duplicates, get_raw_functionapp,
register_app_provider)
register_app_provider,
is_sku_tier_enabled_for_managed_instance)
from ._create_util import (zip_contents_from_dir, get_runtime_version_details, create_resource_group, get_app_details,
check_resource_group_exists, set_location, get_site_availability,
get_regional_site_availability, get_profile_username,
Expand All @@ -100,6 +101,7 @@
from .aaz.latest.relay.hyco.authorization_rule import List as HycoAuthoList, Create as HycoAuthoCreate
from .aaz.latest.relay.hyco.authorization_rule.keys import List as HycoAuthoKeysList
from .aaz.latest.relay.namespace import List as NamespaceList
from .aaz.latest.appservice import ListLocations as AppServiceListLocations
from .aaz.latest.appservice.plan import (Show as AppServicePlanShow, Create as AppServicePlanCreate,
Update as AppServicePlanUpdate)
from .aaz.latest.appservice.plan.managed_instance import (ShowRdpPassword
Expand Down Expand Up @@ -8125,13 +8127,18 @@ def list_flexconsumption_zone_redundant_locations(cmd):
return [{'name': x.name.lower().replace(' ', '')} for x in regions]


def list_locations(cmd, sku, linux_workers_enabled=None, hyperv_workers_enabled=None):
def list_locations(cmd, sku, linux_workers_enabled=None, hyperv_workers_enabled=None, managed_instance_enabled=None):
web_client = web_client_factory(cmd.cli_ctx)
full_sku = get_sku_tier(sku)
# Temporary fix due to regression in this specific API with 2021-03-01, should be removed with the next SDK update
web_client_geo_regions = web_client.list_geo_regions(sku=full_sku,
linux_workers_enabled=linux_workers_enabled,
xenon_workers_enabled=hyperv_workers_enabled)

if managed_instance_enabled:
# managed_instance_enabled needs to be specially handled due to requiring version 2025-03-01
# and due to additional validation needed for SKU
web_client_geo_regions = _list_managed_instance_locations(cmd, full_sku)
else:
web_client_geo_regions = web_client.list_geo_regions(sku=full_sku,
linux_workers_enabled=linux_workers_enabled,
xenon_workers_enabled=hyperv_workers_enabled)

providers_client = providers_client_factory(cmd.cli_ctx)
providers_client_locations_list = getattr(providers_client.get('Microsoft.Web'), 'resource_types', [])
Expand All @@ -8143,6 +8150,20 @@ def list_locations(cmd, sku, linux_workers_enabled=None, hyperv_workers_enabled=
return [geo_region for geo_region in web_client_geo_regions if geo_region.name in providers_client_locations_list]


def _list_managed_instance_locations(cmd, sku_tier):
from types import SimpleNamespace

if not is_sku_tier_enabled_for_managed_instance(sku_tier):
return []

list_locations_cmd = AppServiceListLocations(cli_ctx=cmd.cli_ctx)
locations = list_locations_cmd(command_args={
'custom_mode_workers_enabled': True
Comment thread
joslinmicrosoft marked this conversation as resolved.
})

return [SimpleNamespace(**location) for location in locations]


def _check_zip_deployment_status(cmd, rg_name, name, deployment_status_url, slot, timeout=None):
import requests
from azure.cli.core.util import should_disable_connection_verify
Expand Down
6 changes: 6 additions & 0 deletions src/azure-cli/azure/cli/command_modules/appservice/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ def get_sku_name(tier):
return get_sku_tier(name=tier)


def is_sku_tier_enabled_for_managed_instance(sku_tier):
sku_tier = sku_tier.upper()
enabled_skus = ['PREMIUMV4', 'PREMIUMMV4']
return sku_tier in enabled_skus


# resource is client.web_apps for webapps, client.app_service_plans for ASPs, etc.
def get_resource_if_exists(resource, **kwargs):
from azure.core.exceptions import ResourceNotFoundError as R
Expand Down
Loading