-
Notifications
You must be signed in to change notification settings - Fork 76
Expand file tree
/
Copy pathAppServicePlanListStep.ts
More file actions
137 lines (119 loc) · 6.83 KB
/
AppServicePlanListStep.ts
File metadata and controls
137 lines (119 loc) · 6.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import type { AppServicePlan, WebSiteManagementClient } from '@azure/arm-appservice';
import { AzExtLocation, LocationListStep, ResourceGroupListStep, uiUtils } from '@microsoft/vscode-azext-azureutils';
import { AzureWizardPromptStep, IAzureQuickPickItem, IAzureQuickPickOptions, IWizardOptions, nonNullProp } from '@microsoft/vscode-azext-utils';
import * as vscode from 'vscode';
import { webProvider } from '../constants';
import { createWebSiteClient } from '../utils/azureClients';
import { AppKind, getWebsiteOSDisplayName, WebsiteOS } from './AppKind';
import { AppServicePlanCreateStep } from './AppServicePlanCreateStep';
import { AppServicePlanNameStep } from './AppServicePlanNameStep';
import { AppServicePlanRedundancyStep } from './AppServicePlanRedundancyStep';
import { AppServicePlanSkuStep } from './AppServicePlanSkuStep';
import { IAppServiceWizardContext } from './IAppServiceWizardContext';
export class AppServicePlanListStep extends AzureWizardPromptStep<IAppServiceWizardContext> {
private _suppressCreate: boolean | undefined;
public constructor(suppressCreate?: boolean) {
super();
this._suppressCreate = suppressCreate;
}
public static async getPlans(context: IAppServiceWizardContext): Promise<AppServicePlan[]> {
if (context.plansTask === undefined) {
const client: WebSiteManagementClient = await createWebSiteClient(context);
context.plansTask = uiUtils.listAllIterator(client.appServicePlans.list());
}
return await context.plansTask;
}
public static async isNameAvailable(context: IAppServiceWizardContext, name: string, resourceGroupName: string): Promise<boolean> {
const plans: AppServicePlan[] = await AppServicePlanListStep.getPlans(context);
return !plans.some(plan =>
nonNullProp(plan, 'resourceGroup').toLowerCase() === resourceGroupName.toLowerCase() &&
nonNullProp(plan, 'name').toLowerCase() === name.toLowerCase()
);
}
public async prompt(context: IAppServiceWizardContext): Promise<void> {
// Cache hosting plan separately per subscription
// Logic Apps only supports Workflow Standard sku and for App Service Plan it only supports one Isolated sku.
// Since create is not enabled for isolated skus, we explicitly reference the type of plan picked in the placeHolder.
const options: IAzureQuickPickOptions = {
placeHolder: context.newSiteKind?.includes(AppKind.workflowapp) && context.planSkuFamilyFilter?.test('IV2')
? vscode.l10n.t('Select an App Service Environment (v3) Plan')
: vscode.l10n.t('Select a {0} App Service plan.', getWebsiteOSDisplayName(nonNullProp(context, 'newSiteOS'))),
id: `AppServicePlanListStep/${context.subscriptionId}`
};
context.plan = (await context.ui.showQuickPick(this.getQuickPicks(context), options)).data;
context.telemetry.properties.newPlan = String(!context.plan);
if (context.plan) {
await LocationListStep.setLocation(context, context.plan.location);
}
}
public async getSubWizard(context: IAppServiceWizardContext): Promise<IWizardOptions<IAppServiceWizardContext> | undefined> {
if (!context.plan) {
const promptSteps: AzureWizardPromptStep<IAppServiceWizardContext>[] = [new AppServicePlanNameStep(), new AppServicePlanSkuStep(), new AppServicePlanRedundancyStep(), new ResourceGroupListStep()];
LocationListStep.addStep(context, promptSteps);
return Promise.resolve({
promptSteps: promptSteps,
executeSteps: [new AppServicePlanCreateStep()]
});
} else {
context.valuesToMask.push(nonNullProp(context.plan, 'name'));
return Promise.resolve(undefined);
}
}
public shouldPrompt(context: IAppServiceWizardContext): boolean {
return !context.plan && !context.newPlanName;
}
private async getQuickPicks(context: IAppServiceWizardContext): Promise<IAzureQuickPickItem<AppServicePlan | undefined>[]> {
const picks: IAzureQuickPickItem<AppServicePlan | undefined>[] = !this._suppressCreate
? [{
label: vscode.l10n.t('$(plus) Create new App Service plan'),
description: '',
data: undefined
}]
: [];
let plans: AppServicePlan[] = await AppServicePlanListStep.getPlans(context);
const famFilter: RegExp | undefined = context.planSkuFamilyFilter;
if (famFilter) {
plans = plans.filter(plan => !plan.sku?.family || famFilter.test(plan.sku.family));
}
let location: AzExtLocation | undefined;
if (LocationListStep.hasLocation(context)) {
location = await LocationListStep.getLocation(context, webProvider);
}
let hasFilteredLocations: boolean = false;
for (const plan of plans) {
const isNewSiteLinux: boolean = context.newSiteOS === WebsiteOS.linux;
let isPlanLinux: boolean = nonNullProp(plan, 'kind').toLowerCase().includes(WebsiteOS.linux);
if (plan.sku && (plan.sku.family === 'EP' || plan.sku.family === 'WS')) {
// Elastic premium and workflow standard plans do not have the OS in the `kind` string,
// so we check the `reserved` property instead. As of API version 2024-11-01+, `reserved`
// is correctly returned by the list operation (no extra per-plan GET needed).
isPlanLinux = !!plan.reserved;
}
// plan.kind will contain "linux" for Linux plans, but will _not_ contain "windows" for Windows plans. Thus we check "isLinux" for both cases
if (isNewSiteLinux === isPlanLinux) {
if (location && !LocationListStep.locationMatchesName(location, plan.location)) {
hasFilteredLocations = true;
} else {
picks.push({
id: plan.id,
label: nonNullProp(plan, 'name'),
description: plan.sku?.name,
data: plan
});
}
}
}
if (hasFilteredLocations && location) {
picks.push({
label: vscode.l10n.t('$(warning) Only plans in the region "{0}" are shown.', location.displayName),
onPicked: () => { /* do nothing */ },
data: undefined
});
}
return picks;
}
}