text: # --------------------------------------------------------------------------------------------
  # Copyright (c) Microsoft Corporation. All rights reserved.
  # Licensed under the MIT License. See License.txt in the project root for license information.
  # --------------------------------------------------------------------------------------------
  
  from binascii import hexlify
  from os import urandom
  
  from knack.log import get_logger
  
  from msrestazure.tools import is_valid_resource_id, parse_resource_id
  
  from azure.cli.core.commands import LongRunningOperation
  from azure.cli.core.azclierror import InvalidArgumentValueError, MutuallyExclusiveArgumentError
  
  from azure.cli.command_modules.appservice.utils import (_list_app)
  from azure.cli.command_modules.appservice._client_factory import web_client_factory
  from azure.cli.command_modules.appservice.custom import (
      _format_fx_version,
      _get_extension_version_functionapp,
      get_app_insights_key,
      parse_docker_image_name,
      list_consumption_locations,
      is_plan_elastic_premium,
      _validate_and_get_connection_string,
      update_container_settings_functionapp,
      try_create_application_insights,
      _set_remote_or_local_git, show_app,
      create_app_service_plan)
  
  from ._constants import (DEFAULT_LOGICAPP_FUNCTION_VERSION,
                           DEFAULT_LOGICAPP_RUNTIME,
                           DEFAULT_LOGICAPP_RUNTIME_VERSION,
                           FUNCTIONS_VERSION_TO_SUPPORTED_RUNTIME_VERSIONS,
                           FUNCTIONS_VERSION_TO_DEFAULT_RUNTIME_VERSION,
                           DOTNET_RUNTIME_VERSION_TO_DOTNET_LINUX_FX_VERSION)
  
  logger = get_logger(__name__)
  
  
  def create_logicapp(cmd, resource_group_name, name, storage_account, plan=None,
                      os_type=None, consumption_plan_location=None,
                      app_insights=None, app_insights_key=None, disable_app_insights=None,
                      deployment_source_url=None, deployment_source_branch='master', deployment_local_git=None,
                      docker_registry_server_password=None, docker_registry_server_user=None,
                      deployment_container_image_name=None, tags=None):
      # pylint: disable=too-many-statements, too-many-branches, too-many-locals
      functions_version = DEFAULT_LOGICAPP_FUNCTION_VERSION
      runtime = None
      runtime_version = None
  
      if consumption_plan_location or not deployment_container_image_name:
          runtime = DEFAULT_LOGICAPP_RUNTIME
          runtime_version = DEFAULT_LOGICAPP_RUNTIME_VERSION
  
      if deployment_source_url and deployment_local_git:
          raise MutuallyExclusiveArgumentError('usage error: --deployment-source-url <url> | --deployment-local-git')
  
      if consumption_plan_location and plan:
          raise MutuallyExclusiveArgumentError("Consumption Plan and Plan cannot be used together")
  
      SiteConfig, Site, NameValuePair = cmd.get_models('SiteConfig', 'Site', 'NameValuePair')
  
      docker_registry_server_url = parse_docker_image_name(
          deployment_container_image_name)
  
      site_config = SiteConfig(app_settings=[])
      logicapp_def = Site(location=None, site_config=site_config, tags=tags)
      client = web_client_factory(cmd.cli_ctx)
      plan_info = None
      if runtime is not None:
          runtime = runtime.lower()
  
      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 InvalidArgumentValueError(
                  "Location is invalid. Use: az logicapp list-consumption-locations")
          logicapp_def.location = consumption_plan_location
          logicapp_def.kind = 'functionapp,workflowapp'
          # if os_type is None, the os type is windows
          is_linux = os_type and os_type.lower() == 'linux'
  
      else:
          if not plan:  # no plan passed in, so create a WS1 ASP
              plan_name = "{}_app_service_plan".format(name)
              create_app_service_plan(cmd, resource_group_name, plan_name, False, False, sku='WS1')
              logger.warning("Created App Service Plan %s in resource group %s", plan_name, resource_group_name)
              plan_info = client.app_service_plans.get(resource_group_name, plan_name)
          else:  # 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)
  
          is_linux = plan_info.reserved
          logicapp_def.server_farm_id = plan_info.id
          logicapp_def.location = plan_info.location
  
      if runtime:
          site_config.app_settings.append(NameValuePair(
              name='FUNCTIONS_WORKER_RUNTIME', value=runtime))
  
      con_string = _validate_and_get_connection_string(cmd.cli_ctx, resource_group_name, storage_account)
  
      if is_linux:
          logicapp_def.kind = 'functionapp,workflowapp,linux'
          logicapp_def.reserved = True
          is_consumption = consumption_plan_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 deployment_container_image_name:
                  logicapp_def.kind = 'functionapp,workflowapp,linux,container'
                  site_config.app_settings.append(NameValuePair(name='DOCKER_CUSTOM_IMAGE_NAME',
                                                                value=deployment_container_image_name))
                  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(
                      deployment_container_image_name)
              else:
                  site_config.app_settings.append(NameValuePair(name='WEBSITES_ENABLE_APP_SERVICE_STORAGE',
                                                                value='true'))
                  if runtime not in FUNCTIONS_VERSION_TO_SUPPORTED_RUNTIME_VERSIONS[functions_version]:
                      raise InvalidArgumentValueError(
                          "An appropriate linux image for runtime:'{}', "
                          "functions_version: '{}' was not found".format(runtime, functions_version))
          if deployment_container_image_name is None:
              site_config.linux_fx_version = _get_linux_fx_functionapp(
                  functions_version, runtime, runtime_version)
      else:
          logicapp_def.kind = 'functionapp,workflowapp'
  
      # adding appsetting to site to make it a workflow
      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))
      site_config.app_settings.append(NameValuePair(name='AzureWebJobsDashboard', value=con_string))
      site_config.app_settings.append(NameValuePair(
          name='AzureFunctionsJobHost__extensionBundle__id', value="Microsoft.Azure.Functions.ExtensionBundle.Workflows"))
      site_config.app_settings.append(NameValuePair(
          name='AzureFunctionsJobHost__extensionBundle__version', value="[1.*, 2.0.0)"))
      site_config.app_settings.append(
          NameValuePair(name='APP_KIND', value="workflowApp"))
  
      # If plan is not consumption or elastic premium or workflow standard, we need to set always on
      if (consumption_plan_location is None and
              not is_plan_elastic_premium(cmd, plan_info) and
              not is_plan_workflow_standard(cmd, plan_info) and not is_plan_ASEV3(cmd, plan_info)):
          site_config.always_on = True
  
      # If plan is elastic premium or windows consumption, we need these app settings
      is_windows_consumption = consumption_plan_location is not None and not is_linux
      if is_plan_elastic_premium(cmd, plan_info) or is_windows_consumption:
          site_config.app_settings.append(NameValuePair(name='WEBSITE_CONTENTAZUREFILECONNECTIONSTRING',
                                                        value=con_string))
          site_config.app_settings.append(NameValuePair(
              name='WEBSITE_CONTENTSHARE', value=name.lower()))
  
      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:
          instrumentation_key = get_app_insights_key(
              cmd.cli_ctx, resource_group_name, app_insights)
          site_config.app_settings.append(NameValuePair(name='APPINSIGHTS_INSTRUMENTATIONKEY',
                                                        value=instrumentation_key))
      elif not disable_app_insights:
          create_app_insights = True
  
      poller = client.web_apps.begin_create_or_update(
          resource_group_name, name, logicapp_def)
      logicapp = LongRunningOperation(cmd.cli_ctx)(poller)
  
      if consumption_plan_location and is_linux:
          logger.warning("Your Linux logic 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, logicapp, resource_group_name, name, deployment_source_url,
                                   deployment_source_branch, deployment_local_git)
  
      if create_app_insights:
          try:
              try_create_application_insights(cmd, logicapp)
          except Exception:  # pylint: disable=broad-except
              logger.warning('Error while trying to create and configure an Application Insights for the Logic App. '
                             'Please use the Azure Portal to create and configure the Application Insights, if needed.')
  
      if deployment_container_image_name:
          update_container_settings_functionapp(cmd, resource_group_name, name, docker_registry_server_url,
                                                deployment_container_image_name, docker_registry_server_user,
                                                docker_registry_server_password)
  
      return logicapp
  
  
  def is_plan_workflow_standard(cmd, plan_info):
      SkuDescription, AppServicePlan = cmd.get_models('SkuDescription', 'AppServicePlan')
      if isinstance(plan_info, AppServicePlan):
          if isinstance(plan_info.sku, SkuDescription):
              return plan_info.sku.tier == 'WorkflowStandard'
      return False
  
  
  def is_plan_ASEV3(cmd, plan_info):
      SkuDescription, AppServicePlan = cmd.get_models('SkuDescription', 'AppServicePlan')
      if isinstance(plan_info, AppServicePlan):
          if isinstance(plan_info.sku, SkuDescription):
              return plan_info.sku.tier == 'IsolatedV2'
      return False
  
  
  def list_logicapp(cmd, resource_group_name=None):
      return list(filter(lambda x: x.kind is not None and "workflow" in x.kind.lower(),
                         _list_app(cmd.cli_ctx, resource_group_name)))
  
  
  def _get_linux_fx_functionapp(functions_version, runtime, runtime_version):
      if runtime_version is None:
          runtime_version = FUNCTIONS_VERSION_TO_DEFAULT_RUNTIME_VERSION[functions_version][runtime]
      if runtime == 'dotnet':
          runtime_version = DOTNET_RUNTIME_VERSION_TO_DOTNET_LINUX_FX_VERSION[runtime_version]
      else:
          runtime = runtime.upper()
      return '{}|{}'.format(runtime, runtime_version)
  
  
  def _get_java_version_functionapp(functions_version, runtime_version):
      if runtime_version is None:
          runtime_version = FUNCTIONS_VERSION_TO_DEFAULT_RUNTIME_VERSION[functions_version]['java']
      if runtime_version == '8':
          return '1.8'
      return runtime_version
  
  
  def show_logicapp(cmd, resource_group_name, name):
      return show_app(cmd, resource_group_name=resource_group_name, name=name)
  