in src/azure-cli/azure/cli/command_modules/appservice/custom.py [0:0]
def create_webapp(cmd, resource_group_name, name, plan, runtime=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, sitecontainers_app=None,
container_registry_password=None, container_registry_user=None,
container_registry_url=None, container_image_name=None,
multicontainer_config_type=None, multicontainer_config_file=None, tags=None,
using_webapp_up=False, language=None, assign_identities=None,
role='Contributor', scope=None, vnet=None, subnet=None, https_only=False,
public_network_access=None, acr_use_identity=False, acr_identity=None, basic_auth=""):
from azure.mgmt.web.models import Site
from azure.core.exceptions import ResourceNotFoundError as _ResourceNotFoundError
SiteConfig, SkuDescription, NameValuePair = cmd.get_models(
'SiteConfig', 'SkuDescription', 'NameValuePair')
if deployment_source_url and deployment_local_git:
raise MutuallyExclusiveArgumentError('usage error: --deployment-source-url <url> | --deployment-local-git')
if deployment_container_image_name and container_image_name:
raise MutuallyExclusiveArgumentError('Cannot use both --deployment-container-image-name'
' and --container-image-name')
if container_registry_url and not container_image_name:
raise ArgumentUsageError('Please specify both --container-registry-url and --container-image-name')
if container_registry_url:
container_registry_url = parse_container_registry_url(container_registry_url)
else:
container_registry_url = parse_docker_image_name(deployment_container_image_name)
if container_image_name:
container_image_name = container_image_name if not container_registry_url else "{}/{}".format(
urlparse(container_registry_url).hostname,
container_image_name[1:] if container_image_name.startswith('/') else container_image_name)
if deployment_container_image_name:
container_image_name = deployment_container_image_name
client = web_client_factory(cmd.cli_ctx)
plan_info = None
if is_valid_resource_id(plan):
parse_result = parse_resource_id(plan)
plan_info = client.app_service_plans.get(parse_result['resource_group'], parse_result['name'])
else:
try:
plan_info = client.app_service_plans.get(name=plan, resource_group_name=resource_group_name)
except _ResourceNotFoundError:
plan_info = None
if not plan_info:
plans = list(client.app_service_plans.list(detailed=True))
for user_plan in plans:
if user_plan.name.lower() == plan.lower():
if plan_info:
raise InvalidArgumentValueError("There are multiple plans with name {}.".format(plan),
"Try using the plan resource ID instead.")
parse_result = parse_resource_id(user_plan.id)
plan_info = client.app_service_plans.get(parse_result['resource_group'], parse_result['name'])
if not plan_info:
raise ResourceNotFoundError("The plan '{}' doesn't exist.".format(plan))
is_linux = plan_info.reserved
helper = _StackRuntimeHelper(cmd, linux=is_linux, windows=not is_linux)
location = plan_info.location
# 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 ValidationError(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)
if app_details is None:
raise ResourceNotFoundError("Unable to retrieve details of the existing app '{}'. Please check that "
"the app is a part of the current subscription. If "
"creating a new app, app names must be globally unique. Please try a more "
"unique name".format(name))
current_rg = app_details.resource_group
if resource_group_name is not None and (resource_group_name.lower() != current_rg.lower()):
raise ValidationError("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=[])
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
if subnet or vnet:
subnet_info = _get_subnet_info(cmd=cmd,
resource_group_name=resource_group_name,
subnet=subnet,
vnet=vnet)
_validate_vnet_integration_location(cmd=cmd, webapp_location=plan_info.location,
subnet_resource_group=subnet_info["resource_group_name"],
vnet_name=subnet_info["vnet_name"],
vnet_sub_id=subnet_info["subnet_subscription_id"])
_vnet_delegation_check(cmd, subnet_subscription_id=subnet_info["subnet_subscription_id"],
vnet_resource_group=subnet_info["resource_group_name"],
vnet_name=subnet_info["vnet_name"],
subnet_name=subnet_info["subnet_name"])
subnet_resource_id = subnet_info["subnet_resource_id"]
vnet_route_all_enabled = True
else:
subnet_resource_id = None
vnet_route_all_enabled = None
if using_webapp_up:
https_only = using_webapp_up
if acr_use_identity:
site_config.acr_use_managed_identity_creds = acr_use_identity
webapp_def = Site(location=location, site_config=site_config, server_farm_id=plan_info.id, tags=tags,
https_only=https_only, virtual_network_subnet_id=subnet_resource_id,
public_network_access=public_network_access, vnet_route_all_enabled=vnet_route_all_enabled)
if runtime:
runtime = _StackRuntimeHelper.remove_delimiters(runtime)
current_stack = None
if is_linux:
if not validate_container_app_create_options(runtime, container_image_name,
multicontainer_config_type, multicontainer_config_file,
sitecontainers_app):
if deployment_container_image_name:
raise ArgumentUsageError('Please specify both --multicontainer-config-type TYPE '
'and --multicontainer-config-file FILE, '
'and only specify one out of --runtime, '
'--deployment-container-image-name, --multicontainer-config-type '
'or --sitecontainers_app')
raise ArgumentUsageError('Please specify both --multicontainer-config-type TYPE '
'and --multicontainer-config-file FILE, '
'and only specify one out of --runtime, '
'--container-image-name, --multicontainer-config-type '
'or --sitecontainers_app')
if startup_file:
site_config.app_command_line = startup_file
if sitecontainers_app:
site_config.linux_fx_version = 'SITECONTAINERS'
elif runtime:
match = helper.resolve(runtime, is_linux)
if not match:
raise ValidationError("Linux Runtime '{}' is not supported."
"Run 'az webapp list-runtimes --os-type linux' to cross check".format(runtime))
helper.get_site_config_setter(match, linux=is_linux)(cmd=cmd, stack=match, site_config=site_config)
elif container_image_name:
site_config.linux_fx_version = _format_fx_version(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 container_image_name:
site_config.windows_fx_version = _format_fx_version(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=container_registry_user))
site_config.app_settings.append(NameValuePair(name="DOCKER_REGISTRY_SERVER_PASSWORD",
value=container_registry_password))
site_config.app_settings.append(NameValuePair(name="DOCKER_REGISTRY_SERVER_URL",
value=container_registry_url))
elif runtime: # windows webapp with runtime specified
if any([startup_file, deployment_container_image_name, container_image_name, multicontainer_config_file,
multicontainer_config_type]):
raise ArgumentUsageError("usage error: --startup-file or --deployment-container-image-name or "
"--container-image-name or "
"--multicontainer-config-type and --multicontainer-config-file is "
"only appliable on linux webapp")
match = helper.resolve(runtime, linux=is_linux)
if not match:
raise ValidationError("Windows runtime '{}' is not supported."
"Run 'az webapp list-runtimes --os-type windows' to cross check".format(runtime))
helper.get_site_config_setter(match, linux=is_linux)(cmd=cmd, stack=match, site_config=site_config)
# TODO: Ask Calvin the purpose of this - seems like unneeded set of calls
# 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 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 container_image_name:
logger.info("Updating container settings")
update_container_settings(cmd, resource_group_name, name, container_registry_url,
container_image_name, container_registry_user,
container_registry_password=container_registry_password)
if assign_identities is not None:
identity = assign_identity(cmd, resource_group_name, name, assign_identities,
role, None, scope)
webapp.identity = identity
if acr_identity:
update_site_configs(cmd, resource_group_name, name, acr_identity=acr_identity)
_enable_basic_auth(cmd, name, None, resource_group_name, basic_auth.lower())
return webapp