in src/azure-cli/azure/cli/command_modules/appservice/custom.py [0:0]
def create_functionapp(cmd, resource_group_name, name, storage_account, plan=None,
os_type=None, functions_version=None, runtime=None, runtime_version=None,
consumption_plan_location=None, app_insights=None, app_insights_key=None,
disable_app_insights=None, deployment_source_url=None,
deployment_source_branch=None, deployment_local_git=None,
registry_server=None, registry_password=None, registry_username=None,
image=None, tags=None, assign_identities=None,
role='Contributor', scope=None, vnet=None, subnet=None, https_only=False,
environment=None, min_replicas=None, max_replicas=None, workspace=None,
enable_dapr=False, dapr_app_id=None, dapr_app_port=None, dapr_http_max_request_size=None,
dapr_http_read_buffer_size=None, dapr_log_level=None, dapr_enable_api_logging=False,
workload_profile_name=None, cpu=None, memory=None,
always_ready_instances=None, maximum_instance_count=None, instance_memory=None,
flexconsumption_location=None, deployment_storage_name=None,
deployment_storage_container_name=None, deployment_storage_auth_type=None,
deployment_storage_auth_value=None, zone_redundant=False, configure_networking_later=None):
# pylint: disable=too-many-statements, too-many-branches
if functions_version is None and flexconsumption_location is None:
logger.warning("No functions version specified so defaulting to 4.")
functions_version = '4'
enable_dapr = enable_dapr == "true"
if deployment_source_url and deployment_local_git:
raise MutuallyExclusiveArgumentError('usage error: --deployment-source-url <url> | --deployment-local-git')
if any([cpu, memory, workload_profile_name]) and environment is None:
raise RequiredArgumentMissingError("usage error: parameters --cpu, -memory, --workload-profile-name "
"must be used with parameter --environment, please provide the "
"name of the container app environment using --environment.")
if environment is None and not is_exactly_one_true(plan, consumption_plan_location, flexconsumption_location):
raise MutuallyExclusiveArgumentError("usage error: You must specify one of these parameter "
"--plan NAME_OR_ID | --consumption-plan-location LOCATION |"
" --flexconsumption-location LOCATION")
if ((min_replicas is not None or max_replicas is not None) and environment is None):
raise RequiredArgumentMissingError("usage error: parameters --min-replicas and --max-replicas must be "
"used with parameter --environment, please provide the name "
"of the container app environment using --environment.")
if any([enable_dapr, dapr_app_id, dapr_app_port, dapr_http_max_request_size, dapr_http_read_buffer_size,
dapr_log_level, dapr_enable_api_logging]) and environment is None:
raise RequiredArgumentMissingError("usage error: parameters --enable-dapr, --dapr-app-id, "
"--dapr-app-port, --dapr-http-max-request-size, "
"--dapr-http-read-buffer-size, --dapr-log-level and "
"dapr-enable-api-logging must be used with parameter --environment,"
"please provide the name of the container app environment using "
"--environment.")
if any([dapr_app_id, dapr_app_port, dapr_http_max_request_size, dapr_http_read_buffer_size,
dapr_log_level, dapr_enable_api_logging]) and not enable_dapr:
raise ArgumentUsageError("usage error: parameters --dapr-app-id, "
"--dapr-app-port, --dapr-http-max-request-size, "
"--dapr-http-read-buffer-size, --dapr-log-level and "
"dapr-enable-api-logging must be used with parameter --enable-dapr true.")
from azure.mgmt.web.models import Site
SiteConfig, NameValuePair, DaprConfig, ResourceConfig = cmd.get_models('SiteConfig', 'NameValuePair',
'DaprConfig', 'ResourceConfig')
if flexconsumption_location is None:
if zone_redundant:
raise ArgumentUsageError(
'--zone-redundant is only valid for the Flex Consumption plan. '
'Please try again without the --zone-redundant parameter.')
if flexconsumption_location is not None:
if image is not None:
raise ArgumentUsageError(
'--image is not a valid input for Azure Functions on the Flex Consumption plan. '
'Please try again without the --image parameter.')
if deployment_local_git is not None:
raise ArgumentUsageError(
'--deployment-local-git is not a valid input for Azure Functions on the Flex Consumption plan. '
'Please try again without the --deployment-local-git parameter.')
if deployment_source_url is not None:
raise ArgumentUsageError(
'--deployment-source-url is not a valid input for Azure Functions on the Flex Consumption plan. '
'Please try again without the --deployment-source-url parameter.')
if deployment_source_branch is not None:
raise ArgumentUsageError(
'--deployment-source-branch is not a valid input for Azure Functions on the Flex Consumption plan. '
'Please try again without the --deployment-source-branch parameter.')
if os_type and os_type.lower() != LINUX_OS_NAME:
raise ArgumentUsageError(
'--os-type windows is not a valid input for Azure Functions on the Flex Consumption plan. '
'Please try again without the --os-type parameter or set --os-type to be linux.'
)
flexconsumption_location = _normalize_flex_location(flexconsumption_location)
if (any([always_ready_instances, maximum_instance_count, instance_memory, deployment_storage_name,
deployment_storage_container_name, deployment_storage_auth_type, deployment_storage_auth_value]) and
flexconsumption_location is None):
raise RequiredArgumentMissingError("usage error: parameters --always-ready-instances, "
"--maximum-instance-count, --instance-memory, "
"--deployment-storage-name, --deployment-storage-container-name, "
"--deployment-storage-auth-type and --deployment-storage-auth-value "
"must be used with parameter --flexconsumption-location, please "
"provide the name of the flex plan location using "
"--flexconsumption-location.")
if flexconsumption_location is None:
deployment_source_branch = deployment_source_branch or 'master'
disable_app_insights = disable_app_insights == "true"
site_config = SiteConfig(app_settings=[])
client = web_client_factory(cmd.cli_ctx)
if vnet or subnet:
if plan:
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:
plan_info = client.app_service_plans.get(resource_group_name, plan)
webapp_location = plan_info.location
elif flexconsumption_location:
webapp_location = flexconsumption_location
register_app_provider(cmd)
else:
webapp_location = consumption_plan_location
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=webapp_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_service_delegation=FLEX_SUBNET_DELEGATION if flexconsumption_location else None)
subnet_resource_id = subnet_info["subnet_resource_id"]
vnet_route_all_enabled = True
site_config.vnet_route_all_enabled = True
else:
subnet_resource_id = None
vnet_route_all_enabled = None
functionapp_def = Site(location=None, site_config=site_config, tags=tags,
virtual_network_subnet_id=subnet_resource_id, https_only=https_only,
vnet_route_all_enabled=vnet_route_all_enabled)
plan_info = None
if runtime is not None:
runtime = runtime.lower()
is_storage_container_created = False
is_user_assigned_identity_created = False
if consumption_plan_location:
locations = list_consumption_locations(cmd)
location = next((loc for loc in locations if loc['name'].lower() == consumption_plan_location.lower()), None)
if location is None:
raise ValidationError("Location is invalid. Use: az functionapp list-consumption-locations")
functionapp_def.location = consumption_plan_location
functionapp_def.kind = 'functionapp'
# if os_type is None, the os type is windows
is_linux = bool(os_type and os_type.lower() == LINUX_OS_NAME)
elif plan: # apps with SKU based plan
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:
plan_info = client.app_service_plans.get(resource_group_name, plan)
if not plan_info:
raise ResourceNotFoundError("The plan '{}' doesn't exist".format(plan))
location = plan_info.location
is_linux = bool(plan_info.reserved)
functionapp_def.server_farm_id = plan
functionapp_def.location = location
elif flexconsumption_location:
locations = list_flexconsumption_locations(cmd)
location = next((loc for loc in locations if loc['name'].lower() == flexconsumption_location.lower()), None)
if location is None:
raise ValidationError("Location is invalid. Use: az functionapp list-flexconsumption-locations")
is_linux = True
if environment is not None:
if consumption_plan_location is not None:
raise ArgumentUsageError(
'--consumption-plan-location is not a valid input for Azure Functions on Azure Container App '
'environments. Please try again without the --consumption-plan-location parameter.')
if plan is not None:
raise ArgumentUsageError(
'--plan is not a valid input for Azure Functions on Azure Container App environments. '
'Please try again without the --plan parameter.')
if os_type is not None:
raise ArgumentUsageError(
'--os-type is not a valid input for Azure Functions on Azure Container App environments. '
'Please try again without the --os-type parameter.')
is_linux = True
if image is None:
image = DEFAULT_CENTAURI_IMAGE
if registry_server:
docker_registry_server_url = registry_server
else:
docker_registry_server_url = parse_docker_image_name(image, environment)
if is_linux and not runtime and (consumption_plan_location or not image):
raise ArgumentUsageError(
"usage error: --runtime RUNTIME required for linux functions apps without custom image.")
if runtime is None and runtime_version is not None:
raise ArgumentUsageError('Must specify --runtime to use --runtime-version')
if flexconsumption_location:
runtime_helper = _FlexFunctionAppStackRuntimeHelper(cmd, flexconsumption_location, runtime, runtime_version)
matched_runtime = runtime_helper.resolve(runtime, runtime_version)
else:
runtime_helper = _FunctionAppStackRuntimeHelper(cmd, linux=is_linux, windows=not is_linux)
matched_runtime = runtime_helper.resolve("dotnet" if not runtime else runtime,
runtime_version, functions_version, is_linux)
SiteConfigPropertiesDictionary = cmd.get_models('SiteConfigPropertiesDictionary')
site_config_dict = matched_runtime.site_config_dict if not flexconsumption_location \
else SiteConfigPropertiesDictionary()
app_settings_dict = matched_runtime.app_settings_dict if not flexconsumption_location else {}
if is_storage_account_network_restricted(cmd.cli_ctx, resource_group_name, storage_account):
if consumption_plan_location is not None:
raise ValidationError('The Consumption plan does not support storage accounts with network restrictions. '
'If you wish to use virtual networks, please create your app on a different hosting '
'plan.')
if not vnet and not configure_networking_later:
raise ValidationError('The storage account you selected "{}" has networking restrictions. No virtual '
'networking was configured so your app will not start. Please try again with '
'virtual networking integration by adding the --vnet and --subnet flags. If '
'you wish to do this at a later time, use the --configure-networking-later '
'flag instead.'.format(storage_account))
if vnet and configure_networking_later:
raise ValidationError('The --vnet and --configure-networking-later flags are mutually exclusive.')
functionapp_def.vnet_content_share_enabled = True
con_string = _validate_and_get_connection_string(cmd.cli_ctx, resource_group_name, storage_account)
if environment is not None:
if docker_registry_server_url is not None:
site_config.app_settings.append(
NameValuePair(name='DOCKER_REGISTRY_SERVER_URL', value=docker_registry_server_url)
)
if (not registry_username and not registry_password and
docker_registry_server_url and '.azurecr.io' in str(docker_registry_server_url)):
logger.warning('No credential was provided to access Azure Container Registry. Trying to look up...')
parsed = urlparse(docker_registry_server_url)
registry_name = (parsed.netloc if parsed.scheme else parsed.path).split('.')[0]
try:
registry_username, registry_password = _get_acr_cred(cmd.cli_ctx, registry_name)
except Exception as ex: # pylint: disable=broad-except
logger.warning("Retrieving credentials failed with an exception:'%s'", ex) # consider throw if needed
if registry_username is not None:
site_config.app_settings.append(
NameValuePair(name='DOCKER_REGISTRY_SERVER_USERNAME', value=registry_username)
)
if registry_password is not None:
site_config.app_settings.append(
NameValuePair(name='DOCKER_REGISTRY_SERVER_PASSWORD', value=registry_password)
)
app_settings_dict = {}
matched_runtime.app_insights = True
elif is_linux:
functionapp_def.kind = 'functionapp,linux'
functionapp_def.reserved = True
is_consumption = consumption_plan_location is not None or flexconsumption_location is not None
if not is_consumption:
site_config.app_settings.append(NameValuePair(name='MACHINEKEY_DecryptionKey',
value=str(hexlify(urandom(32)).decode()).upper()))
if image:
functionapp_def.kind = 'functionapp,linux,container'
site_config.app_settings.append(NameValuePair(name='DOCKER_CUSTOM_IMAGE_NAME',
value=image))
site_config.app_settings.append(NameValuePair(name='FUNCTION_APP_EDIT_MODE', value='readOnly'))
site_config.app_settings.append(NameValuePair(name='WEBSITES_ENABLE_APP_SERVICE_STORAGE',
value='false'))
site_config.linux_fx_version = _format_fx_version(image)
# clear all runtime specific configs and settings
site_config_dict.use32_bit_worker_process = False
app_settings_dict = {}
# ensure that app insights is created if not disabled
matched_runtime.app_insights = True
else:
site_config.app_settings.append(NameValuePair(name='WEBSITES_ENABLE_APP_SERVICE_STORAGE',
value='true'))
else:
functionapp_def.kind = 'functionapp'
if site_config_dict.additional_properties:
for prop, value in site_config_dict.additional_properties.items():
snake_case_prop = _convert_camel_to_snake_case(prop)
setattr(site_config, snake_case_prop, value)
# set site configs
for prop, value in site_config_dict.as_dict().items():
snake_case_prop = _convert_camel_to_snake_case(prop)
setattr(site_config, snake_case_prop, value)
if environment is not None:
functionapp_def.kind = 'functionapp,linux,container,azurecontainerapps'
functionapp_def.reserved = None
functionapp_def.name = name
functionapp_def.https_only = None
functionapp_def.scm_site_also_stopped = None
functionapp_def.hyper_v = None
functionapp_def.is_xenon = None
functionapp_def.type = 'Microsoft.Web/sites'
# validate cpu and memory parameters.
_validate_cpu_momory_functionapp(cpu, memory)
if workload_profile_name is not None:
functionapp_def.workload_profile_name = workload_profile_name
if cpu is not None and memory is not None:
functionapp_def.resource_config = ResourceConfig()
functionapp_def.resource_config.cpu = cpu
functionapp_def.resource_config.memory = memory
site_config.net_framework_version = None
site_config.java_version = None
site_config.use32_bit_worker_process = None
site_config.power_shell_version = None
site_config.linux_fx_version = _format_fx_version(image)
site_config.http20_enabled = None
site_config.local_my_sql_enabled = None
if min_replicas is not None:
site_config.minimum_elastic_instance_count = min_replicas
if max_replicas is not None:
site_config.function_app_scale_limit = max_replicas
if enable_dapr:
logger.warning("Please note while using Dapr Extension for Azure Functions, app port is "
"mandatory when using Dapr triggers and should be empty when using only Dapr bindings.")
dapr_enable_api_logging = dapr_enable_api_logging == "true"
dapr_config = DaprConfig()
dapr_config.enabled = True
dapr_config.app_id = dapr_app_id
dapr_config.app_port = dapr_app_port
dapr_config.http_max_request_size = dapr_http_max_request_size or 4
dapr_config.http_read_buffer_size = dapr_http_read_buffer_size or 4
dapr_config.log_level = dapr_log_level
dapr_config.enable_api_logging = dapr_enable_api_logging
functionapp_def.dapr_config = dapr_config
managed_environment = get_managed_environment(cmd, resource_group_name, environment)
location = managed_environment.location
functionapp_def.location = location
functionapp_def.managed_environment_id = managed_environment.id
# adding app settings
for app_setting, value in app_settings_dict.items():
site_config.app_settings.append(NameValuePair(name=app_setting, value=value))
if flexconsumption_location is None:
site_config.app_settings.append(NameValuePair(name='FUNCTIONS_EXTENSION_VERSION',
value=_get_extension_version_functionapp(functions_version)))
site_config.app_settings.append(NameValuePair(name='AzureWebJobsStorage', value=con_string))
# If plan is not flex, consumption or elastic premium, we need to set always on
if (flexconsumption_location is None and consumption_plan_location is None and plan_info is not None and
not is_plan_elastic_premium(cmd, plan_info)):
site_config.always_on = True
# If plan is elastic premium or consumption, we need these app settings
if (plan_info is not None and is_plan_elastic_premium(cmd, plan_info)) or consumption_plan_location is not None:
site_config.app_settings.append(NameValuePair(name='WEBSITE_CONTENTAZUREFILECONNECTIONSTRING',
value=con_string))
content_share_name = _get_content_share_name(name)
site_config.app_settings.append(NameValuePair(name='WEBSITE_CONTENTSHARE', value=content_share_name))
if is_storage_account_network_restricted(cmd.cli_ctx, resource_group_name, storage_account):
create_file_share(cmd.cli_ctx, resource_group_name, storage_account, content_share_name)
create_app_insights = False
if app_insights_key is not None:
site_config.app_settings.append(NameValuePair(name='APPINSIGHTS_INSTRUMENTATIONKEY',
value=app_insights_key))
elif app_insights is not None:
app_insights_conn_string = get_app_insights_connection_string(cmd.cli_ctx, resource_group_name, app_insights)
site_config.app_settings.append(NameValuePair(name='APPLICATIONINSIGHTS_CONNECTION_STRING',
value=app_insights_conn_string))
elif flexconsumption_location is None and (disable_app_insights or not matched_runtime.app_insights):
# set up dashboard if no app insights
site_config.app_settings.append(NameValuePair(name='AzureWebJobsDashboard', value=con_string))
elif not disable_app_insights and matched_runtime.app_insights:
create_app_insights = True
if flexconsumption_location is not None:
if zone_redundant:
zone_redundant_locations = list_flexconsumption_zone_redundant_locations(cmd)
zone_redundant_location = next((loc for loc in zone_redundant_locations
if loc['name'].lower() == flexconsumption_location.lower()), None)
if zone_redundant_location is None:
raise ValidationError("The specified location '{0}' "
"doesn't support zone redundancy in Flex Consumption. "
"Use: az functionapp list-flexconsumption-locations --zone-redundant "
"for the list of locations that support zone redundancy."
.format(flexconsumption_location))
site_config.net_framework_version = None
functionapp_def.reserved = None
functionapp_def.is_xenon = None
try:
plan_name = generatePlanName(resource_group_name)
plan_info = create_flex_app_service_plan(
cmd, resource_group_name, plan_name, flexconsumption_location, zone_redundant)
functionapp_def.server_farm_id = plan_info.id
functionapp_def.location = flexconsumption_location
if not deployment_storage_name:
deployment_storage_name = storage_account
deployment_storage = _validate_and_get_deployment_storage(cmd.cli_ctx, resource_group_name,
deployment_storage_name)
deployment_storage_container = _get_or_create_deployment_storage_container(
cmd, resource_group_name, name, deployment_storage_name, deployment_storage_container_name)
if deployment_storage_container_name is None:
is_storage_container_created = True
deployment_storage_container_name = deployment_storage_container.name
endpoints = deployment_storage.primary_endpoints
deployment_config_storage_value = getattr(endpoints, 'blob') + deployment_storage_container_name
deployment_storage_auth_type = deployment_storage_auth_type or 'StorageAccountConnectionString'
if deployment_storage_auth_value and deployment_storage_auth_type == 'SystemAssignedIdentity':
raise ArgumentUsageError(
'--deployment-storage-auth-value is only a valid input when '
'--deployment-storage-auth-type is set to UserAssignedIdentity or StorageAccountConnectionString. '
'Please try again with --deployment-storage-auth-type set to UserAssignedIdentity or '
'StorageAccountConnectionString.'
)
function_app_config = {}
deployment_storage_auth_config = {
"type": deployment_storage_auth_type
}
function_app_config["deployment"] = {
"storage": {
"type": "blobContainer",
"value": deployment_config_storage_value,
"authentication": deployment_storage_auth_config
}
}
if deployment_storage_auth_type == 'UserAssignedIdentity':
deployment_storage_user_assigned_identity = _get_or_create_user_assigned_identity(
cmd,
resource_group_name,
name,
deployment_storage_auth_value,
flexconsumption_location)
if deployment_storage_auth_value is None:
is_user_assigned_identity_created = True
deployment_storage_auth_value = deployment_storage_user_assigned_identity.id
deployment_storage_auth_config["userAssignedIdentityResourceId"] = deployment_storage_auth_value
elif deployment_storage_auth_type == 'StorageAccountConnectionString':
deployment_storage_conn_string = _get_storage_connection_string(cmd.cli_ctx, deployment_storage)
conn_string_app_setting = deployment_storage_auth_value or 'DEPLOYMENT_STORAGE_CONNECTION_STRING'
site_config.app_settings.append(NameValuePair(name=conn_string_app_setting,
value=deployment_storage_conn_string))
deployment_storage_auth_value = conn_string_app_setting
deployment_storage_auth_config["storageAccountConnectionStringName"] = deployment_storage_auth_value
flex_sku = matched_runtime.sku
runtime = flex_sku['functionAppConfigProperties']['runtime']['name']
version = flex_sku['functionAppConfigProperties']['runtime']['version']
runtime_config = {
"name": runtime,
"version": version
}
function_app_config["runtime"] = runtime_config
always_ready_dict = _parse_key_value_pairs(always_ready_instances)
always_ready_config = []
for key, value in always_ready_dict.items():
always_ready_config.append(
{
"name": key,
"instanceCount": max(0, validate_and_convert_to_int(key, value))
}
)
default_instance_memory = [x for x in flex_sku['instanceMemoryMB'] if x['isDefault'] is True][0]
function_app_config["scaleAndConcurrency"] = {
"maximumInstanceCount": maximum_instance_count or flex_sku['maximumInstanceCount']['defaultValue'],
"instanceMemoryMB": instance_memory or default_instance_memory['size'],
"alwaysReady": always_ready_config
}
functionapp_def.enable_additional_properties_sending()
existing_properties = functionapp_def.serialize()["properties"]
functionapp_def.additional_properties["properties"] = existing_properties
functionapp_def.additional_properties["properties"]["functionAppConfig"] = function_app_config
functionapp_def.additional_properties["properties"]["sku"] = "FlexConsumption"
poller = client.web_apps.begin_create_or_update(resource_group_name, name, functionapp_def,
api_version='2023-12-01')
functionapp = LongRunningOperation(cmd.cli_ctx)(poller)
except Exception as ex: # pylint: disable=broad-except
client.app_service_plans.delete(resource_group_name, plan_name)
if is_storage_container_created:
delete_storage_container(cmd, resource_group_name, deployment_storage_name,
deployment_storage_container_name)
if is_user_assigned_identity_created:
delete_user_assigned_identity(cmd, resource_group_name, deployment_storage_user_assigned_identity.name)
raise ex
else:
poller = client.web_apps.begin_create_or_update(resource_group_name, name, functionapp_def)
functionapp = LongRunningOperation(cmd.cli_ctx)(poller)
if environment is not None:
functionapp = client.web_apps.get(resource_group_name, name)
if consumption_plan_location and is_linux:
logger.warning("Your Linux function app '%s', that uses a consumption plan has been successfully "
"created but is not active until content is published using "
"Azure Portal or the Functions Core Tools.", name)
else:
_set_remote_or_local_git(cmd, functionapp, resource_group_name, name, deployment_source_url,
deployment_source_branch, deployment_local_git)
if create_app_insights:
try:
try_create_workspace_based_application_insights(cmd, functionapp, workspace)
if should_enable_distributed_tracing(consumption_plan_location,
flexconsumption_location,
matched_runtime,
image):
update_app_settings(cmd, functionapp.resource_group, functionapp.name,
["APPLICATIONINSIGHTS_ENABLE_AGENT=true"])
except Exception: # pylint: disable=broad-except
logger.warning('Error while trying to create and configure an Application Insights for the Function App. '
'Please use the Azure Portal to create and configure the Application Insights, if needed.')
if flexconsumption_location is None:
update_app_settings(cmd, functionapp.resource_group, functionapp.name,
['AzureWebJobsDashboard={}'.format(con_string)])
if image and environment is None:
update_container_settings_functionapp(cmd, resource_group_name, name, docker_registry_server_url,
image, registry_username,
registry_password)
if flexconsumption_location is not None:
if deployment_storage_auth_type == 'UserAssignedIdentity':
assign_identity(cmd, resource_group_name, name, [deployment_storage_auth_value])
if not _has_deployment_storage_role_assignment_on_resource(
cmd.cli_ctx,
deployment_storage,
deployment_storage_user_assigned_identity.principal_id):
_assign_deployment_storage_managed_identity_role(
cmd.cli_ctx,
deployment_storage,
deployment_storage_user_assigned_identity.principal_id)
else:
logger.warning("User assigned identity '%s' already has the role assignment on "
"the storage account '%s'",
deployment_storage_user_assigned_identity.principal_id, deployment_storage_name)
elif deployment_storage_auth_type == 'SystemAssignedIdentity':
assign_identity(cmd, resource_group_name, name, ['[system]'], 'Storage Blob Data Contributor',
None, deployment_storage.id)
if assign_identities is not None:
identity = assign_identity(cmd, resource_group_name, name, assign_identities,
role, None, scope)
functionapp.identity = identity
if flexconsumption_location is not None:
return get_raw_functionapp(cmd.cli_ctx, resource_group_name, name)
return functionapp