import { WebSiteManagementClient , WebSiteManagementMappers , WebSiteManagementModels as SiteModels , WebSiteManagementModels } from '@azure/arm-appservice' ; import { Progress } from 'vscode' ; import { CustomLocation , IAppServiceWizardContext , ParsedSite , WebsiteOS } from 'vscode-azureappservice' ; import { AzureWizardExecuteStep , LocationListStep , parseError } from 'vscode-azureextensionui' ; import { contentConnectionStringKey , contentShareKey , extensionVersionKey , ProjectLanguage , runFromPackageKey , webProvider } from '../../constants' ; import { ext } from '../../extensionVariables' ; import { azureWebJobsStorageKey } from '../../funcConfig/local.settings' ; import { FuncVersion , getMajorVersion } from '../../FuncVersion' ; import { localize } from '../../localize' ; import { getStorageConnectionString } from '../../utils/azure' ; import { createWebSiteClient } from '../../utils/azureClients' ; import { getRandomHexString } from '../../utils/fs' ; import { nonNullProp } from '../../utils/nonNull' ; import { enableFileLogging } from '../logstream/enableFileLogging' ; import { FullFunctionAppStack , IFunctionAppWizardContext } from './IFunctionAppWizardContext' ; import { showSiteCreated } from './showSiteCreated' ; import { FunctionAppRuntimeSettings } from './stacks/models/FunctionAppStackModel' ; export class FunctionAppCreateStep extends AzureWizardExecuteStep < IFunctionAppWizardContext > { public priority : number = 140 ; public async execute ( context , progress ) { const os = nonNullProp ( context , 'newSiteOS' ) ; const stack = nonNullProp ( context , 'newSiteStack' ) ; context . telemetry . properties . newSiteOS = os ; context . telemetry . properties . newSiteStack = stack . stack . value ; context . telemetry . properties . newSiteMajorVersion = stack . majorVersion . value ; context . telemetry . properties . newSiteMinorVersion = stack . minorVersion . value ; context . telemetry . properties . planSkuTier = context . plan ?. sku ?. tier ; const message = localize ( 'creatingNewApp' , 'Creating new function app "{0}"...' , context . newSiteName ) ; ext . outputChannel . appendLog ( message ) ; progress . report ( { message } ) ; const siteName = nonNullProp ( context , 'newSiteName' ) ; const rgName = nonNullProp ( nonNullProp ( context , 'resourceGroup' ) , 'name' ) ; const client = await createWebSiteClient ( context ) ; context . site = await client . webApps . createOrUpdate ( rgName , siteName , await this . getNewSite ( context , stack ) ) ; const site = new ParsedSite ( context . site , context ) ; if ( ! site . isLinux ) { try { await enableFileLogging ( context , site ) ; } catch ( error ) { context . telemetry . properties . fileLoggingError = parseError ( error ) . message ; } } showSiteCreated ( site , context ) ; } public shouldExecute ( context ) { return ! context . site ; } private async getNewSite ( context , stack ) { const location = await LocationListStep . getLocation ( context , webProvider ) ; const site = { name : context . newSiteName , kind : getSiteKind ( context ) , location : nonNullProp ( location , 'name' ) , serverFarmId : context . plan ?. id , clientAffinityEnabled : false , siteConfig : await this . getNewSiteConfig ( context , stack ) , reserved : context . newSiteOS === WebsiteOS . linux } ; if ( context . customLocation ) { this . addCustomLocationProperties ( site , context . customLocation ) ; } return site ; } /**
     * Has a few temporary workarounds so that the sdk allows some newer properties on the plan
     */ private addCustomLocationProperties ( site , customLocation ) { nonNullProp ( site , 'siteConfig' ) . alwaysOn = true ; WebSiteManagementMappers . Site . type . modelProperties ! . extendedLocation = { serializedName : 'extendedLocation' , type : { name : "Composite" , modelProperties : { name : { serializedName : "name" , type : { name : "String" } } , type : { serializedName : "type" , type : { name : "String" } } } } } ; ( < any > site ) . extendedLocation = { name : customLocation . id , type : 'customLocation' } ; } private async getNewSiteConfig ( context , stack ) { const stackSettings = nonNullProp ( stack . minorVersion . stackSettings , context . newSiteOS === WebsiteOS . linux ? 'linuxRuntimeSettings' : 'windowsRuntimeSettings' ) ; if ( context . newSiteOS === 'windows' && context . version === FuncVersion . v4 ) { stackSettings . siteConfigPropertiesDictionary . netFrameworkVersion = 'v6.0' ; } const newSiteConfig = stackSettings . siteConfigPropertiesDictionary ; const storageConnectionString = ( await getStorageConnectionString ( context ) ) . connectionString ; const appSettings = [ { name : azureWebJobsStorageKey , value : storageConnectionString } , { name : extensionVersionKey , value : '~' + getMajorVersion ( context . version ) } , ... Object . entries ( stackSettings . appSettingsDictionary ) . map ( ( [ name , value ] ) => { return { name , value } ; } ) ] ; if ( context . version === FuncVersion . v1 ) { appSettings . push ( { name : 'AzureWebJobsDashboard' , value : storageConnectionString } ) ; } const isElasticPremium = context . plan ?. sku ?. family ?. toLowerCase ( ) === 'ep' ; const isConsumption = context . plan ?. sku ?. family ?. toLowerCase ( ) === 'y' ; if ( isConsumption || isElasticPremium ) { appSettings . push ( { name : contentConnectionStringKey , value : storageConnectionString } ) ; appSettings . push ( { name : contentShareKey , value : getNewFileShareName ( nonNullProp ( context , 'newSiteName' ) ) } ) ; } if ( context . newSiteOS === WebsiteOS . windows && ! ( context . language === ProjectLanguage . CSharpScript && context . version === FuncVersion . v1 ) ) { appSettings . push ( { name : runFromPackageKey , value : '1' } ) ; } if ( context . appInsightsComponent ) { appSettings . push ( { name : 'APPINSIGHTS_INSTRUMENTATIONKEY' , value : context . appInsightsComponent . instrumentationKey } ) ; } newSiteConfig . appSettings = appSettings ; return newSiteConfig ; } } function getNewFileShareName ( siteName ) { const randomLetters = 6 ; const maxFileShareNameLength = 63 ; return siteName . toLowerCase ( ) . substr ( 0 , maxFileShareNameLength - randomLetters ) + getRandomHexString ( randomLetters ) ; } function getSiteKind ( context ) { let kind = context . newSiteKind ; if ( context . newSiteOS === 'linux' ) { kind += ',linux' ; } if ( context . customLocation ) { kind += ',kubernetes' ; } return kind ; }