in src/appservice-kube/azext_appservice_kube/custom.py [0:0]
def create_webapp(cmd, resource_group_name, name, plan=None, runtime=None, custom_location=None, startup_file=None, # pylint: disable=too-many-statements,too-many-branches
deployment_container_image_name=None, deployment_source_url=None, deployment_source_branch='master',
deployment_local_git=None, docker_registry_server_password=None, docker_registry_server_user=None,
multicontainer_config_type=None, multicontainer_config_file=None, tags=None,
using_webapp_up=False, language=None, assign_identities=None, role='Contributor', scope=None,
min_worker_count=None, max_worker_count=None):
SiteConfig, SkuDescription, Site, NameValuePair, AppServicePlan = cmd.get_models(
'SiteConfig', 'SkuDescription', 'Site', 'NameValuePair', "AppServicePlan")
if deployment_source_url and deployment_local_git:
raise CLIError('usage error: --deployment-source-url <url> | --deployment-local-git')
custom_location = _get_custom_location_id(cmd, custom_location, resource_group_name)
if not plan and not custom_location:
raise RequiredArgumentMissingError("Either Plan or Custom Location must be specified")
# This is to keep the existing appsettings for a newly created webapp on existing webapp name.
name_validation = get_site_availability(cmd, name)
if not name_validation.name_available:
if name_validation.reason == 'Invalid':
raise CLIError(name_validation.message)
logger.warning("Webapp '%s' already exists. The command will use the existing app's settings.", name)
app_details = get_app_details(cmd, name, resource_group_name)
if app_details is None:
raise CLIError("Unable to retrieve details of the existing app '{}'. Please check that "
"the app is a part of the current subscription".format(name))
current_rg = app_details.resource_group
if resource_group_name is not None and (resource_group_name.lower() != current_rg.lower()):
raise CLIError("The webapp '{}' exists in resource group '{}' and does not "
"match the value entered '{}'. Please re-run command with the "
"correct parameters.".format(name, current_rg, resource_group_name))
existing_app_settings = _generic_site_operation(cmd.cli_ctx, resource_group_name,
name, 'list_application_settings')
settings = []
for k, v in existing_app_settings.properties.items():
settings.append(NameValuePair(name=k, value=v))
site_config = SiteConfig(app_settings=settings)
else:
site_config = SiteConfig(app_settings=[])
_should_create_new_plan = _should_create_new_appservice_plan_for_k8se(cmd,
name, custom_location,
plan, resource_group_name)
if _should_create_new_plan:
plan = generate_default_app_service_plan_name(name)
logger.warning("Plan not specified. Creating Plan '%s' with sku '%s'", plan, KUBE_DEFAULT_SKU)
create_app_service_plan(cmd=cmd, resource_group_name=resource_group_name,
name=plan, is_linux=True, hyper_v=False, custom_location=custom_location,
per_site_scaling=True, number_of_workers=1)
if custom_location and plan:
if not _validate_asp_and_custom_location_kube_envs_match(cmd, resource_group_name, custom_location, plan):
raise ValidationError("Custom location's kube environment and App Service Plan's "
"kube environment don't match")
elif custom_location and not plan:
app_details = get_app_details(cmd, name, resource_group_name)
if app_details is not None:
plan = app_details.server_farm_id
docker_registry_server_url = parse_docker_image_name(deployment_container_image_name)
client = web_client_factory(cmd.cli_ctx)
if is_valid_resource_id(plan):
parse_result = parse_resource_id(plan)
plan_info = AppServicePlan.from_dict(AppServiceClient.show(cmd=cmd, name=parse_result['name'],
resource_group_name=parse_result["resource_group"]))
else:
plan_info = AppServicePlan.from_dict(AppServiceClient.show(cmd=cmd,
name=plan, resource_group_name=resource_group_name))
if not plan_info:
raise CLIError("The plan '{}' doesn't exist in the resource group '{}".format(plan, resource_group_name))
if custom_location:
_validate_asp_sku(app_service_environment=None, custom_location=custom_location, sku=plan_info.sku.name)
is_linux = plan_info.reserved
location = plan_info.location
if isinstance(plan_info.sku, SkuDescription) and plan_info.sku.name.upper() not in ['F1', 'FREE', 'SHARED', 'D1',
'B1', 'B2', 'B3', 'BASIC']:
site_config.always_on = True
webapp_def = Site(location=location, site_config=site_config, server_farm_id=plan_info.id, tags=tags,
https_only=using_webapp_up)
is_kube = _is_webapp_kube(custom_location, plan_info, SkuDescription)
if is_kube:
if deployment_container_image_name:
webapp_def.kind = KUBE_CONTAINER_APP_KIND
else:
webapp_def.kind = KUBE_APP_KIND
# if Custom Location provided, use that for Extended Location Envelope. Otherwise, get Custom Location from ASP
if custom_location:
webapp_def.enable_additional_properties_sending()
custom_location_id = _get_custom_location_id_from_custom_location(cmd, custom_location, resource_group_name)
if custom_location_id:
extended_loc = {'name': custom_location_id, 'type': 'CustomLocation'}
webapp_def.additional_properties["extendedLocation"] = extended_loc
else:
extended_loc = plan_info.additional_properties["extendedLocation"]
webapp_def.additional_properties["extendedLocation"] = extended_loc
if is_kube:
if min_worker_count is not None:
site_config.number_of_workers = min_worker_count
if max_worker_count is not None:
site_config.app_settings.append(NameValuePair(name='K8SE_APP_MAX_INSTANCE_COUNT', value=max_worker_count))
if deployment_container_image_name:
site_config.app_settings.append(NameValuePair(name='DOCKER_REGISTRY_SERVER_URL',
value=docker_registry_server_url))
if docker_registry_server_user is not None and docker_registry_server_password is not None:
site_config.app_settings.append(NameValuePair(name='DOCKER_REGISTRY_SERVER_USERNAME',
value=docker_registry_server_user))
site_config.app_settings.append(NameValuePair(name='DOCKER_REGISTRY_SERVER_PASSWORD',
value=docker_registry_server_password))
helper = _StackRuntimeHelper(cmd, linux=bool(is_linux or is_kube), windows=not bool(is_linux or is_kube))
if is_kube:
helper = _AppOnArcStackRuntimeHelper(cmd, linux=bool(is_linux or is_kube), windows=not bool(is_linux or is_kube))
if runtime:
runtime = helper.remove_delimiters(runtime)
current_stack = None
if is_linux or is_kube:
if not validate_container_app_create_options(runtime, deployment_container_image_name,
multicontainer_config_type, multicontainer_config_file):
raise CLIError("usage error: --runtime | --deployment-container-image-name |"
" --multicontainer-config-type TYPE --multicontainer-config-file FILE")
if startup_file:
site_config.app_command_line = startup_file
if runtime:
site_config.linux_fx_version = runtime
match = helper.resolve(runtime, linux=True)
if not match:
raise CLIError("Linux Runtime '{}' is not supported."
"Please invoke 'list-runtimes --kube' to cross check".format(runtime))
helper.get_site_config_setter(match, linux=True)(cmd=cmd, stack=match, site_config=site_config)
elif deployment_container_image_name:
site_config.linux_fx_version = _format_fx_version(deployment_container_image_name)
if name_validation.name_available:
site_config.app_settings.append(NameValuePair(name="WEBSITES_ENABLE_APP_SERVICE_STORAGE",
value="false"))
elif multicontainer_config_type and multicontainer_config_file:
encoded_config_file = _get_linux_multicontainer_encoded_config_from_file(multicontainer_config_file)
site_config.linux_fx_version = _format_fx_version(encoded_config_file, multicontainer_config_type)
elif plan_info.is_xenon: # windows container webapp
if deployment_container_image_name:
site_config.windows_fx_version = _format_fx_version(deployment_container_image_name)
# set the needed app settings for container image validation
if name_validation.name_available:
site_config.app_settings.append(NameValuePair(name="DOCKER_REGISTRY_SERVER_USERNAME",
value=docker_registry_server_user))
site_config.app_settings.append(NameValuePair(name="DOCKER_REGISTRY_SERVER_PASSWORD",
value=docker_registry_server_password))
site_config.app_settings.append(NameValuePair(name="DOCKER_REGISTRY_SERVER_URL",
value=docker_registry_server_url))
elif runtime: # windows webapp with runtime specified
if any([startup_file, deployment_container_image_name, multicontainer_config_file, multicontainer_config_type]):
raise CLIError("usage error: --startup-file or --deployment-container-image-name or "
"--multicontainer-config-type and --multicontainer-config-file is "
"only appliable on linux webapp")
match = helper.resolve(runtime, linux=False)
if not match:
raise CLIError("Windows runtime '{}' is not supported. "
"Please invoke 'az webapp list-runtimes' to cross check".format(runtime))
helper.get_site_config_setter(match, linux=is_linux)(cmd=cmd, stack=match, site_config=site_config)
# portal uses the current_stack propety in metadata to display stack for windows apps
current_stack = get_current_stack_from_runtime(runtime)
else: # windows webapp without runtime specified
if name_validation.name_available: # If creating new webapp
node_default_version = helper.get_default_version("node", is_linux, get_windows_config_version=True)
site_config.app_settings.append(NameValuePair(name="WEBSITE_NODE_DEFAULT_VERSION",
value=node_default_version))
if site_config.app_settings:
for setting in site_config.app_settings:
logger.info('Will set appsetting %s', setting)
if using_webapp_up: # when the routine is invoked as a help method for webapp up
if name_validation.name_available:
logger.info("will set appsetting for enabling build")
site_config.app_settings.append(NameValuePair(name="SCM_DO_BUILD_DURING_DEPLOYMENT", value=True))
if language is not None and language.lower() == 'dotnetcore':
if name_validation.name_available:
site_config.app_settings.append(NameValuePair(name='ANCM_ADDITIONAL_ERROR_PAGE_LINK',
value='https://{}.scm.azurewebsites.net/detectors'
.format(name)))
poller = client.web_apps.begin_create_or_update(resource_group_name, name, webapp_def)
webapp = LongRunningOperation(cmd.cli_ctx)(poller)
if deployment_container_image_name:
update_container_settings(cmd, resource_group_name, name, docker_registry_server_url,
deployment_container_image_name, docker_registry_server_user,
container_registry_password=docker_registry_server_password)
if is_kube:
return webapp
if current_stack:
_update_webapp_current_stack_property_if_needed(cmd, resource_group_name, name, current_stack)
# Ensure SCC operations follow right after the 'create', no precedent appsetting update commands
_set_remote_or_local_git(cmd, webapp, resource_group_name, name, deployment_source_url,
deployment_source_branch, deployment_local_git)
_fill_ftp_publishing_url(cmd, webapp, resource_group_name, name)
if assign_identities is not None:
identity = assign_identity(cmd, resource_group_name, name, assign_identities,
role, None, scope)
webapp.identity = identity
return webapp