Skip to content

Commit

Permalink
Merge pull request Azure#80 from haroonf/managedenvcheck
Browse files Browse the repository at this point in the history
Check location of managed environment before attempting to create
  • Loading branch information
StrawnSC committed May 2, 2022
2 parents 724249a + a1ce4dd commit 4fc7267
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 5 deletions.
78 changes: 74 additions & 4 deletions src/containerapp/azext_containerapp/_up_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
create_service_principal_for_rbac,
repo_url_to_name,
get_container_app_if_exists,
trigger_workflow
trigger_workflow,
_ensure_location_allowed
)

from ._constants import MAXIMUM_SECRET_LENGTH
Expand All @@ -62,6 +63,8 @@ def __init__(self, cmd, name: str, location: str, exists: bool = None):
self.cmd = cmd
self.name = name
self.location = _get_default_containerapps_location(cmd, location)
if self.location.lower() == "northcentralusstage":
self.location = "eastus"
self.exists = exists

self.check_exists()
Expand Down Expand Up @@ -151,7 +154,7 @@ def __init__(
rg = parse_resource_id(name)["resource_group"]
if resource_group.name != rg:
self.resource_group = ResourceGroup(cmd, rg, location)
self.location = _get_default_containerapps_location(cmd, location)
self.location = location
self.logs_key = logs_key
self.logs_customer_id = logs_customer_id

Expand All @@ -164,7 +167,7 @@ def set_name(self, name_or_rid):
self.resource_group = ResourceGroup(
self.cmd,
rg,
_get_default_containerapps_location(self.cmd, self.location),
self.location,
)
else:
self.name = name_or_rid
Expand All @@ -188,6 +191,7 @@ def create_if_needed(self, app_name):
) # TODO use .info()

def create(self):
self.location = validate_environment_location(self.cmd, self.location)
env = create_managed_environment(
self.cmd,
self.name,
Expand Down Expand Up @@ -291,7 +295,7 @@ def create_acr(self):
url = self.registry_server
registry_name = url[: url.rindex(".azurecr.io")]
registry_def = create_new_acr(
self.cmd, registry_name, registry_rg.name, self.env.location
self.cmd, registry_name, registry_rg.name, self.env.location if self.env.location.lower() != "northcentralusstage" else "eastus"
)
self.registry_server = registry_def.login_server

Expand Down Expand Up @@ -782,3 +786,69 @@ def find_existing_acr(cmd, app: "ContainerApp"):
app.should_create_acr = False
return acr.name, parse_resource_id(acr.id)["resource_group"]
return None, None


def validate_environment_location(cmd, location):
MAX_ENV_PER_LOCATION = 2
env_list = list_managed_environments(cmd)

locations = [l["location"] for l in env_list]
locations = list(set(locations)) # remove duplicates

location_count = {}
for loc in locations:
location_count[loc] = len([e for e in env_list if e["location"] == loc])

disallowed_locations = []
for _, value in enumerate(location_count):
if location_count[value] > MAX_ENV_PER_LOCATION - 1:
disallowed_locations.append(value)

res_locations = list_environment_locations(cmd)
res_locations = [l for l in res_locations if l not in disallowed_locations]

allowed_locs = ", ".join(res_locations)

if location:
try:
_ensure_location_allowed(cmd, location, "Microsoft.App", "managedEnvironments")
except Exception: # pylint: disable=broad-except
raise ValidationError("You cannot create a Containerapp environment in location {}. List of eligible locations: {}.".format(location, allowed_locs))

if len(res_locations) > 0:
if not location:
logger.warning("Creating environment on location {}.".format(res_locations[0]))
return res_locations[0]
if location in disallowed_locations:
raise ValidationError("You have more than {} environments in location {}. List of eligible locations: {}.".format(MAX_ENV_PER_LOCATION, location, allowed_locs))
return location
else:
raise ValidationError("You cannot create any more environments. Environments are limited to {} per location in a subscription. Please specify an existing environment using --environment.".format(MAX_ENV_PER_LOCATION))


def list_environment_locations(cmd):
from ._utils import providers_client_factory
providers_client = providers_client_factory(cmd.cli_ctx, get_subscription_id(cmd.cli_ctx))
resource_types = getattr(providers_client.get("Microsoft.App"), 'resource_types', [])
res_locations = []
for res in resource_types:
if res and getattr(res, 'resource_type', "") == "managedEnvironments":
res_locations = getattr(res, 'locations', [])

res_locations = [res_loc.lower().replace(" ", "").replace("(", "").replace(")", "") for res_loc in res_locations if res_loc.strip()]

return res_locations


def check_env_name_on_rg(cmd, managed_env, resource_group_name, location):
if location:
_ensure_location_allowed(cmd, location, "Microsoft.App", "managedEnvironments")
if managed_env and resource_group_name and location:
env_def = None
try:
env_def = ManagedEnvironmentClient.show(cmd, resource_group_name, parse_resource_id(managed_env)["name"])
except:
pass
if env_def:
if location != env_def["location"]:
raise ValidationError("Environment {} already exists in resource group {} on location {}, cannot change location of existing environment to {}.".format(parse_resource_id(managed_env)["name"], resource_group_name, env_def["location"], location))
4 changes: 3 additions & 1 deletion src/containerapp/azext_containerapp/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -2015,12 +2015,14 @@ def containerapp_up(cmd,
service_principal_tenant_id=None):
from ._up_utils import (_validate_up_args, _reformat_image, _get_dockerfile_content, _get_ingress_and_target_port,
ResourceGroup, ContainerAppEnvironment, ContainerApp, _get_registry_from_app,
_get_registry_details, _create_github_action, _set_up_defaults, up_output, AzureContainerRegistry)
_get_registry_details, _create_github_action, _set_up_defaults, up_output, AzureContainerRegistry,
check_env_name_on_rg)
HELLOWORLD = "mcr.microsoft.com/azuredocs/containerapps-helloworld"
dockerfile = "Dockerfile" # for now the dockerfile name must be "Dockerfile" (until GH actions API is updated)

_validate_up_args(source, image, repo, registry_server)
validate_container_app_name(name)
check_env_name_on_rg(cmd, managed_env, resource_group_name, location)

image = _reformat_image(source, repo, image)
token = None if not repo else get_github_access_token(cmd, ["admin:repo_hook", "repo", "workflow"], token)
Expand Down

0 comments on commit 4fc7267

Please sign in to comment.