import type { WebSiteManagementClient , WebSiteManagementModels as Models } from '@azure/arm-appservice' ; import type { HttpOperationResponse , ServiceClient } from '@azure/ms-rest-js' ; import { createGenericClient , IActionContext , ISubscriptionContext , parseError } from 'vscode-azureextensionui' ; import { AppKind } from './createAppService/AppKind' ; import { AppSettingsClientProvider , IAppSettingsClient } from './IAppSettingsClient' ; import { deleteFunctionSlot , getFunctionSlot , listFunctionsSlot } from './slotFunctionOperations' ; import { tryGetAppServicePlan , tryGetWebApp , tryGetWebAppSlot } from './tryGetSiteResource' ; import { createWebSiteClient } from './utils/azureClients' ; import { nonNullProp , nonNullValue } from './utils/nonNull' ; export class ParsedSite implements AppSettingsClientProvider { public readonly id : string ; public readonly isSlot : boolean ; /**
     * The main site name (does not include the slot name)
     */ public readonly siteName : string ; public readonly slotName ? : string ; /**
     * Combination of the site name and slot name (if applicable), separated by a hyphen
     */ public readonly fullName : string ; public readonly resourceGroup : string ; public readonly location : string ; public readonly serverFarmId : string ; public readonly kind : string ; public readonly initialState ? : string ; public readonly isFunctionApp : boolean ; public readonly isWorkflowApp : boolean ; public readonly isKubernetesApp : boolean ; public readonly isLinux : boolean ; public readonly planResourceGroup : string ; public readonly planName : string ; public readonly defaultHostName : string ; public readonly defaultHostUrl : string ; public readonly kuduHostName : string | undefined ; public readonly kuduUrl : string | undefined ; public readonly gitUrl : string | undefined ; public readonly subscription : ISubscriptionContext ; public readonly rawSite : Models . Site ; constructor ( site , subscription ) { this . rawSite = site ; let matches = nonNullProp ( site , 'serverFarmId' ) . match ( /\/subscriptions\/(.*)\/resourceGroups\/(.*)\/providers\/Microsoft.Web\/serverfarms\/(.*)/ ) ; matches = nonNullValue ( matches , 'Invalid serverFarmId.' ) ; this . id = nonNullProp ( site , 'id' ) ; [ this . siteName , this . slotName ] = nonNullProp ( site , 'name' ) . split ( '/' ) ; this . isSlot = ! ! this . slotName ; this . fullName = this . siteName + ( this . slotName ? `-${ this . slotName }` : '' ) ; this . resourceGroup = nonNullProp ( site , 'resourceGroup' ) ; this . location = site . location ; this . serverFarmId = nonNullProp ( site , 'serverFarmId' ) ; this . kind = nonNullProp ( site , 'kind' ) ; this . initialState = site . state ; const kind = ( site . kind || '' ) . toLowerCase ( ) ; this . isFunctionApp = kind . includes ( AppKind . functionapp ) ; this . isWorkflowApp = kind . includes ( AppKind . workflowapp ) ; this . isKubernetesApp = kind . includes ( 'kubernetes' ) ; this . isLinux = kind . includes ( 'linux' ) ; this . planResourceGroup = matches [ 2 ] ; this . planName = matches [ 3 ] ; this . defaultHostName = nonNullProp ( site , 'defaultHostName' ) ; this . defaultHostUrl = `https://${ this . defaultHostName }` ; const kuduRepositoryUrl = nonNullProp ( site , 'hostNameSslStates' ) . find ( h => ! ! h . hostType && h . hostType . toLowerCase ( ) === 'repository' ) ; if ( kuduRepositoryUrl ) { this . kuduHostName = kuduRepositoryUrl . name ; this . kuduUrl = `https://${ this . kuduHostName }` ; this . gitUrl = `${ this . kuduHostName }:443/${ site . repositorySiteName }.git` ; } this . subscription = subscription ; } public async createClient ( context ) { let client = context . _parsedSiteClients ?. [ this . id ] ; if ( ! client ) { const internalClient = await createWebSiteClient ( [ context , this . subscription ] ) ; const internalGenericClient = await createGenericClient ( context , this . subscription ) ; client = new SiteClient ( internalClient , internalGenericClient , this ) ; context . _parsedSiteClients ||= { } ; context . _parsedSiteClients [ this . id ] = client ; } return client ; } } /**
 * Wrapper of a WebSiteManagementClient for use with a specific Site
 * Reduces the number of arguments needed for every call and automatically ensures the 'slot' method is called when appropriate
 */ export class SiteClient implements IAppSettingsClient { private _client : WebSiteManagementClient ; private _genericClient : ServiceClient ; private _site : ParsedSite ; private _cachedSku : string | undefined ; constructor ( internalClient , internalGenericClient , site ) { this . _client = internalClient ; this . _genericClient = internalGenericClient ; this . _site = site ; } public get fullName ( ) : string { return this . _site . fullName ; } public get isLinux ( ) : boolean { return this . _site . isLinux ; } public async getIsConsumption ( context ) { if ( this . _site . isFunctionApp ) { const sku = await this . getCachedSku ( context ) ; return ! ! sku && sku . toLowerCase ( ) === 'dynamic' ; } else { return false ; } } public async stop ( ) { this . _site . slotName ? await this . _client . webApps . stopSlot ( this . _site . resourceGroup , this . _site . siteName , this . _site . slotName ) : await this . _client . webApps . stop ( this . _site . resourceGroup , this . _site . siteName ) ; } public async start ( ) { this . _site . slotName ? await this . _client . webApps . startSlot ( this . _site . resourceGroup , this . _site . siteName , this . _site . slotName ) : await this . _client . webApps . start ( this . _site . resourceGroup , this . _site . siteName ) ; } public async getSite ( ) { return ( this . _site . slotName ? await tryGetWebAppSlot ( this . _client , this . _site . resourceGroup , this . _site . siteName , this . _site . slotName ) : await tryGetWebApp ( this . _client , this . _site . resourceGroup , this . _site . siteName ) ) ; } public async getState ( ) { return ( await this . getSite ( ) ) ?. state ; } public async getWebAppPublishCredential ( ) { return this . _site . slotName ? await this . _client . webApps . listPublishingCredentialsSlot ( this . _site . resourceGroup , this . _site . siteName , this . _site . slotName ) : await this . _client . webApps . listPublishingCredentials ( this . _site . resourceGroup , this . _site . siteName ) ; } public async getSiteConfig ( ) { return this . _site . slotName ? await this . _client . webApps . getConfigurationSlot ( this . _site . resourceGroup , this . _site . siteName , this . _site . slotName ) : await this . _client . webApps . getConfiguration ( this . _site . resourceGroup , this . _site . siteName ) ; } public async updateConfiguration ( config ) { return this . _site . slotName ? await this . _client . webApps . updateConfigurationSlot ( this . _site . resourceGroup , this . _site . siteName , config , this . _site . slotName ) : await this . _client . webApps . updateConfiguration ( this . _site . resourceGroup , this . _site . siteName , config ) ; } public async getLogsConfig ( ) { return this . _site . slotName ? await this . _client . webApps . getDiagnosticLogsConfigurationSlot ( this . _site . resourceGroup , this . _site . siteName , this . _site . slotName ) : await this . _client . webApps . getDiagnosticLogsConfiguration ( this . _site . resourceGroup , this . _site . siteName ) ; } public async updateLogsConfig ( config ) { return this . _site . slotName ? await this . _client . webApps . updateDiagnosticLogsConfigSlot ( this . _site . resourceGroup , this . _site . siteName , config , this . _site . slotName ) : await this . _client . webApps . updateDiagnosticLogsConfig ( this . _site . resourceGroup , this . _site . siteName , config ) ; } public async getAppServicePlan ( ) { return await tryGetAppServicePlan ( this . _client , this . _site . planResourceGroup , this . _site . planName ) ; } public async getSourceControl ( ) { return this . _site . slotName ? await this . _client . webApps . getSourceControlSlot ( this . _site . resourceGroup , this . _site . siteName , this . _site . slotName ) : await this . _client . webApps . getSourceControl ( this . _site . resourceGroup , this . _site . siteName ) ; } public async updateSourceControl ( siteSourceControl ) { return this . _site . slotName ? await this . _client . webApps . createOrUpdateSourceControlSlot ( this . _site . resourceGroup , this . _site . siteName , siteSourceControl , this . _site . slotName ) : await this . _client . webApps . createOrUpdateSourceControl ( this . _site . resourceGroup , this . _site . siteName , siteSourceControl ) ; } public async syncRepository ( ) { this . _site . slotName ? await this . _client . webApps . syncRepositorySlot ( this . _site . resourceGroup , this . _site . siteName , this . _site . slotName ) : await this . _client . webApps . syncRepository ( this . _site . resourceGroup , this . _site . siteName ) ; } public async listApplicationSettings ( ) { return this . _site . slotName ? await this . _client . webApps . listApplicationSettingsSlot ( this . _site . resourceGroup , this . _site . siteName , this . _site . slotName ) : await this . _client . webApps . listApplicationSettings ( this . _site . resourceGroup , this . _site . siteName ) ; } public async updateApplicationSettings ( appSettings ) { return this . _site . slotName ? await this . _client . webApps . updateApplicationSettingsSlot ( this . _site . resourceGroup , this . _site . siteName , appSettings , this . _site . slotName ) : await this . _client . webApps . updateApplicationSettings ( this . _site . resourceGroup , this . _site . siteName , appSettings ) ; } public async listSlotConfigurationNames ( ) { return await this . _client . webApps . listSlotConfigurationNames ( this . _site . resourceGroup , this . _site . siteName ) ; } public async updateSlotConfigurationNames ( appSettings ) { return await this . _client . webApps . updateSlotConfigurationNames ( this . _site . resourceGroup , this . _site . siteName , appSettings ) ; } public async deleteMethod ( options ? ) { this . _site . slotName ? await this . _client . webApps . deleteSlot ( this . _site . resourceGroup , this . _site . siteName , this . _site . slotName , options ) : await this . _client . webApps . deleteMethod ( this . _site . resourceGroup , this . _site . siteName , options ) ; } public async listInstanceIdentifiers ( ) { return this . _site . slotName ? await this . _client . webApps . listInstanceIdentifiersSlot ( this . _site . resourceGroup , this . _site . siteName , this . _site . slotName ) : await this . _client . webApps . listInstanceIdentifiers ( this . _site . resourceGroup , this . _site . siteName ) ; } public async listSourceControls ( ) { return await this . _client . listSourceControls ( ) ; } public async listFunctions ( ) { if ( this . _site . slotName ) { return await listFunctionsSlot ( this . _genericClient , this . _site . id ) ; } else { return await this . _client . webApps . listFunctions ( this . _site . resourceGroup , this . _site . siteName ) ; } } public async listFunctionsNext ( nextPageLink ) { return await this . _client . webApps . listFunctionsNext ( nextPageLink ) ; } public async getFunction ( functionName ) { if ( this . _site . slotName ) { return await getFunctionSlot ( this . _genericClient , this . _site . id , functionName ) ; } else { return await this . _client . webApps . getFunction ( this . _site . resourceGroup , this . _site . siteName , functionName ) ; } } public async deleteFunction ( functionName ) { if ( this . _site . slotName ) { await deleteFunctionSlot ( this . _genericClient , this . _site . id , functionName ) ; } else { await this . _client . webApps . deleteFunction ( this . _site . resourceGroup , this . _site . siteName , functionName ) ; } } public async listFunctionSecrets ( functionName ) { return this . _site . slotName ? await this . _client . webApps . listFunctionSecretsSlot ( this . _site . resourceGroup , this . _site . siteName , functionName , this . _site . slotName ) : await this . _client . webApps . listFunctionSecrets ( this . _site . resourceGroup , this . _site . siteName , functionName ) ; } public async syncFunctionTriggers ( ) { try { this . _site . slotName ? await this . _client . webApps . syncFunctionTriggersSlot ( this . _site . resourceGroup , this . _site . siteName , this . _site . slotName ) : await this . _client . webApps . syncFunctionTriggers ( this . _site . resourceGroup , this . _site . siteName ) ; } catch ( error ) { if ( parseError ( error ) . errorType !== '200' ) { throw error ; } } } public async getPublishingUser ( ) { return await this . _client . getPublishingUser ( { } ) ; } public async listWebJobs ( ) { return this . _site . slotName ? await this . _client . webApps . listWebJobsSlot ( this . _site . resourceGroup , this . _site . siteName , this . _site . slotName ) : await this . _client . webApps . listWebJobs ( this . _site . resourceGroup , this . _site . siteName ) ; } public async listHostKeys ( ) { return this . _site . slotName ? await this . _client . webApps . listHostKeysSlot ( this . _site . resourceGroup , this . _site . siteName , this . _site . slotName ) : await this . _client . webApps . listHostKeys ( this . _site . resourceGroup , this . _site . siteName ) ; } public async listFunctionKeys ( functionName ) { return this . _site . slotName ? await this . _client . webApps . listFunctionKeysSlot ( this . _site . resourceGroup , this . _site . siteName , functionName , this . _site . slotName ) : await this . _client . webApps . listFunctionKeys ( this . _site . resourceGroup , this . _site . siteName , functionName ) ; } /**
     * Temporary workaround because the azure sdk doesn't return the full site object from Azure
     * Hopefully this can be removed when we move to the new sdk
     * Also, we're caching the sku - for better performance and because it's unlikely to change
     */ private async getCachedSku ( context ) { if ( ! this . _cachedSku ) { const client = await createGenericClient ( context , this . _site . subscription ) ; const response = await client . sendRequest ( { method : 'GET' , url : `${ this . _site . id }?api-version=2016-08-01` } ) ; this . _cachedSku = ( < { properties : { sku ? : string ; } ; } > response . parsedBody ) . properties . sku ; } return this . _cachedSku ; } } /**
 * The type in the sdk doesn't seem to be accurate
 */ export interface IFunctionKeys extends Models . WebAppsListFunctionKeysResponse { default ? : string ; }