import { WebSiteManagementClient , WebSiteManagementModels } from '@azure/arm-appservice' ; import { WorkspaceFolder } from 'vscode' ; import { AppInsightsCreateStep , AppInsightsListStep , AppKind , AppServicePlanCreateStep , CustomLocationListStep , IAppServiceWizardContext , ParsedSite , SiteNameStep , WebsiteOS } from 'vscode-azureappservice' ; import { AzExtTreeItem , AzureWizard , AzureWizardExecuteStep , AzureWizardPromptStep , IActionContext , ICreateChildImplContext , INewStorageAccountDefaults , LocationListStep , parseError , ResourceGroupCreateStep , ResourceGroupListStep , StorageAccountCreateStep , StorageAccountKind , StorageAccountListStep , StorageAccountPerformance , StorageAccountReplication , SubscriptionTreeItemBase , VerifyProvidersStep } from 'vscode-azureextensionui' ; import { FunctionAppCreateStep } from '../commands/createFunctionApp/FunctionAppCreateStep' ; import { FunctionAppHostingPlanStep , setConsumptionPlanProperties } from '../commands/createFunctionApp/FunctionAppHostingPlanStep' ; import { IFunctionAppWizardContext } from '../commands/createFunctionApp/IFunctionAppWizardContext' ; import { FunctionAppStackStep } from '../commands/createFunctionApp/stacks/FunctionAppStackStep' ; import { funcVersionSetting , projectLanguageSetting , webProvider } from '../constants' ; import { tryGetLocalFuncVersion } from '../funcCoreTools/tryGetLocalFuncVersion' ; import { FuncVersion , latestGAVersion , tryParseFuncVersion } from '../FuncVersion' ; import { localize } from "../localize" ; import { createWebSiteClient } from '../utils/azureClients' ; import { nonNullProp } from '../utils/nonNull' ; import { getRootFunctionsWorkerRuntime , getWorkspaceSetting , getWorkspaceSettingFromAnyFolder } from '../vsCodeConfig/settings' ; import { ProductionSlotTreeItem } from './ProductionSlotTreeItem' ; import { isProjectCV , isRemoteProjectCV } from './projectContextValues' ; export interface ICreateFunctionAppContext extends ICreateChildImplContext { newResourceGroupName ? : string ; workspaceFolder ? : WorkspaceFolder ; } export class SubscriptionTreeItem extends SubscriptionTreeItemBase { public readonly childTypeLabel : string = localize ( 'FunctionApp' , 'Function App in Azure' ) ; public supportsAdvancedCreation : boolean = true ; private _nextLink : string | undefined ; public hasMoreChildrenImpl ( ) { return ! ! this . _nextLink ; } public async loadMoreChildrenImpl ( clearCache , context ) { if ( clearCache ) { this . _nextLink = undefined ; } const client = await createWebSiteClient ( [ context , this ] ) ; let webAppCollection ; try { webAppCollection = this . _nextLink ? await client . webApps . listNext ( this . _nextLink ) : await client . webApps . list ( ) ; } catch ( error ) { if ( parseError ( error ) . errorType . toLowerCase ( ) === 'notfound' ) { return [ ] ; } else { throw error ; } } this . _nextLink = webAppCollection . nextLink ; return await this . createTreeItemsWithErrorHandling ( webAppCollection , 'azFuncInvalidFunctionApp' , ( site ) => { const parsedSite = new ParsedSite ( site , this . subscription ) ; if ( parsedSite . isFunctionApp ) { return new ProductionSlotTreeItem ( this , parsedSite ) ; } return undefined ; } , ( site ) => { return site . name ; } ) ; } public async createChildImpl ( context ) { const version = await getDefaultFuncVersion ( context ) ; context . telemetry . properties . projectRuntime = version ; const language = context . workspaceFolder ? getWorkspaceSetting ( projectLanguageSetting , context . workspaceFolder ) : getWorkspaceSettingFromAnyFolder ( projectLanguageSetting ) ; context . telemetry . properties . projectLanguage = language ; const wizardContext = Object . assign ( context , this . subscription , { newSiteKind : AppKind . functionapp , resourceGroupDeferLocationStep : true , version , language } ) ; const promptSteps = [ ] ; const executeSteps = [ ] ; promptSteps . push ( new SiteNameStep ( ) ) ; promptSteps . push ( new FunctionAppStackStep ( ) ) ; const storageAccountCreateOptions = { kind : StorageAccountKind . Storage , performance : StorageAccountPerformance . Standard , replication : StorageAccountReplication . LRS } ; if ( version === FuncVersion . v1 ) { wizardContext . newSiteOS = WebsiteOS . windows ; } if ( ! context . advancedCreation ) { LocationListStep . addStep ( wizardContext , promptSteps ) ; wizardContext . useConsumptionPlan = true ; wizardContext . stackFilter = getRootFunctionsWorkerRuntime ( language ) ; executeSteps . push ( new ResourceGroupCreateStep ( ) ) ; executeSteps . push ( new AppServicePlanCreateStep ( ) ) ; executeSteps . push ( new StorageAccountCreateStep ( storageAccountCreateOptions ) ) ; executeSteps . push ( new AppInsightsCreateStep ( ) ) ; } else { promptSteps . push ( new ResourceGroupListStep ( ) ) ; CustomLocationListStep . addStep ( wizardContext , promptSteps ) ; promptSteps . push ( new FunctionAppHostingPlanStep ( ) ) ; promptSteps . push ( new StorageAccountListStep ( storageAccountCreateOptions , { kind : [ StorageAccountKind . BlobStorage ] , performance : [ StorageAccountPerformance . Premium ] , replication : [ StorageAccountReplication . ZRS ] , learnMoreLink : 'https://aka.ms/Cfqnrc' } ) ) ; promptSteps . push ( new AppInsightsListStep ( ) ) ; } const storageProvider = 'Microsoft.Storage' ; LocationListStep . addProviderForFiltering ( wizardContext , storageProvider , 'storageAccounts' ) ; executeSteps . push ( new VerifyProvidersStep ( [ webProvider , storageProvider , 'Microsoft.Insights' ] ) ) ; executeSteps . push ( new FunctionAppCreateStep ( ) ) ; const title = localize ( 'functionAppCreatingTitle' , 'Create new Function App in Azure' ) ; const wizard = new AzureWizard ( wizardContext , { promptSteps , executeSteps , title } ) ; await wizard . prompt ( ) ; context . showCreatingTreeItem ( nonNullProp ( wizardContext , 'newSiteName' ) ) ; if ( ! context . advancedCreation ) { const newName = await wizardContext . relatedNameTask ; if ( ! newName ) { throw new Error ( localize ( 'noUniqueName' , 'Failed to generate unique name for resources. Use advanced creation to manually enter resource names.' ) ) ; } wizardContext . newResourceGroupName = context . newResourceGroupName || newName ; setConsumptionPlanProperties ( wizardContext ) ; wizardContext . newStorageAccountName = newName ; wizardContext . newAppInsightsName = newName ; } await wizard . execute ( ) ; return new ProductionSlotTreeItem ( this , new ParsedSite ( nonNullProp ( wizardContext , 'site' ) , this . subscription ) ) ; } public isAncestorOfImpl ( contextValue ) { return ! isProjectCV ( contextValue ) || isRemoteProjectCV ( contextValue ) ; } } async function getDefaultFuncVersion ( context ) { const settingValue = context . workspaceFolder ? getWorkspaceSetting ( funcVersionSetting , context . workspaceFolder ) : getWorkspaceSettingFromAnyFolder ( funcVersionSetting ) ; let version = tryParseFuncVersion ( settingValue ) ; context . telemetry . properties . runtimeSource = 'VSCodeSetting' ; if ( version === undefined ) { version = await tryGetLocalFuncVersion ( context , undefined ) ; context . telemetry . properties . runtimeSource = 'LocalFuncCli' ; } if ( version === undefined ) { version = latestGAVersion ; context . telemetry . properties . runtimeSource = 'Backup' ; } return version ; }