Skip to content

Commit 78a0e42

Browse files
Check for DTS trigger before app creation to ensure premium plan is used (#4529)
* Add new storage type pick and host/local settings logic * Update host.json preview dep * Install deps * Update extension bundle * Update durable detection logic * Check for DTS trigger before app creation to ensure premium plan is used. * Remove extra prop * Remove some of my code * Fix weird merge * Remove todo comment --------- Co-authored-by: MicroFish91 <[email protected]>
1 parent 5c6400c commit 78a0e42

File tree

5 files changed

+35
-5
lines changed

5 files changed

+35
-5
lines changed

src/commands/createFunctionApp/FunctionAppHostingPlanStep.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@ import { getRandomHexString } from '../../utils/fs';
1313
import { nonNullProp } from '../../utils/nonNull';
1414
import { type IFunctionAppWizardContext } from './IFunctionAppWizardContext';
1515

16+
const premiumSkuFilter = /^EP$/i;
1617
export class FunctionAppHostingPlanStep extends AzureWizardPromptStep<IFunctionAppWizardContext> {
1718
public async prompt(context: IFunctionAppWizardContext): Promise<void> {
1819
const placeHolder: string = localize('selectHostingPlan', 'Select a hosting plan.');
1920
const picks: IAzureQuickPickItem<[boolean, boolean, RegExp | undefined]>[] = [
2021
{ label: localize('flexConsumption', 'Flex Consumption'), data: [false, true, undefined] },
2122
{ label: localize('consumption', 'Linux Consumption'), description: localize('legacy', 'Legacy'), data: [true, false, undefined] },
22-
{ label: localize('premium', 'Premium'), data: [false, false, /^EP$/i] },
23+
{ label: localize('premium', 'Premium'), data: [false, false, premiumSkuFilter] },
2324
{ label: localize('dedicated', 'App Service Plan'), data: [false, false, /^((?!EP|Y|FC).)*$/i] }
2425
];
2526

@@ -33,11 +34,19 @@ export class FunctionAppHostingPlanStep extends AzureWizardPromptStep<IFunctionA
3334
}
3435

3536
public shouldPrompt(context: IFunctionAppWizardContext): boolean {
36-
return context.useFlexConsumptionPlan === undefined && context.dockerfilePath === undefined;
37+
return (context.useFlexConsumptionPlan === undefined && context.dockerfilePath === undefined) && !context.planSkuFamilyFilter;
3738
}
3839

3940
public configureBeforePrompt(context: IFunctionAppWizardContext): void | Promise<void> {
40-
if (context.useFlexConsumptionPlan) {
41+
if (context.hasDurableTaskScheduler) {
42+
// premium is required for DTS
43+
if (context.advancedCreation) {
44+
// allows users to select/create a Elastic Premium plan
45+
context.planSkuFamilyFilter = premiumSkuFilter;
46+
} else {
47+
setPremiumPlanProperties(context);
48+
}
49+
} else if (context.useFlexConsumptionPlan) {
4150
setFlexConsumptionPlanProperties(context);
4251
}
4352
}
@@ -56,6 +65,16 @@ function setFlexConsumptionPlanProperties(context: IAppServiceWizardContext): vo
5665
LocationListStep.setLocationSubset(context, getFlexLocations(context), 'Microsoft.WebFlex');
5766
}
5867

68+
function setPremiumPlanProperties(context: IAppServiceWizardContext): void {
69+
context.newPlanName = `PREMIUM-${nonNullProp(context, 'newSiteName')}-${getRandomHexString(4)}`;
70+
context.newPlanSku = {
71+
name: 'P1v2',
72+
tier: 'Premium V2',
73+
size: 'P1v2',
74+
family: 'Pv2'
75+
};
76+
}
77+
5978
async function getFlexLocations(context: IAppServiceWizardContext): Promise<string[]> {
6079
const headers = createHttpHeaders({
6180
'Content-Type': 'application/json',

src/commands/createFunctionApp/IFunctionAppWizardContext.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export interface IFunctionAppWizardContext extends IAppServiceWizardContext, ICr
3131
hasAzureStorageConnection?: boolean;
3232
hasEventHubsConnection?: boolean;
3333
hasSqlDbConnection?: boolean;
34+
hasDurableTaskScheduler?: boolean;
3435
}
3536

3637
export interface IFlexFunctionAppWizardContext extends IFunctionAppWizardContext {

src/commands/createFunctionApp/containerImage/detectDockerfile.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import { isFunctionProject } from '../../createNewProject/verifyIsProject';
1313
import path = require('path');
1414

1515
export async function detectDockerfile(context: ICreateFunctionAppContext): Promise<void> {
16-
if (vscode.workspace.workspaceFolders) {
16+
// don't overwrite the workspace folder on the context if it's already set
17+
if (vscode.workspace.workspaceFolders && !context.workspaceFolder) {
1718
context.workspaceFolder = vscode.workspace.workspaceFolders[0];
1819
const workspacePath = context.workspaceFolder.uri.fsPath;
1920
let dockerfilePath: string = workspacePath

src/commands/createFunctionApp/createCreateFunctionAppComponents.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ import { AppInsightsCreateStep, AppInsightsListStep, AppKind, AppServicePlanCrea
77
import { CommonRoleDefinitions, createRoleId, LocationListStep, ResourceGroupCreateStep, ResourceGroupListStep, RoleAssignmentExecuteStep, StorageAccountCreateStep, StorageAccountKind, StorageAccountListStep, StorageAccountPerformance, StorageAccountReplication, UserAssignedIdentityListStep, type INewStorageAccountDefaults, type Role } from "@microsoft/vscode-azext-azureutils";
88
import { type AzureWizardExecuteStep, type AzureWizardPromptStep, type ISubscriptionContext } from "@microsoft/vscode-azext-utils";
99
import { FuncVersion, latestGAVersion, tryParseFuncVersion } from "../../FuncVersion";
10-
import { funcVersionSetting } from "../../constants";
10+
import { DurableBackend, funcVersionSetting } from "../../constants";
1111
import { tryGetLocalFuncVersion } from "../../funcCoreTools/tryGetLocalFuncVersion";
1212
import { type ICreateFunctionAppContext } from "../../tree/SubscriptionTreeItem";
1313
import { createActivityContext } from "../../utils/activityUtils";
14+
import { durableUtils } from "../../utils/durableUtils";
1415
import { getRootFunctionsWorkerRuntime, getWorkspaceSetting, getWorkspaceSettingFromAnyFolder } from "../../vsCodeConfig/settings";
1516
import { AuthenticationPromptStep } from "./AuthenticationPromptStep";
1617
import { FunctionAppCreateStep } from "./FunctionAppCreateStep";
@@ -53,6 +54,9 @@ export async function createCreateFunctionAppComponents(context: ICreateFunction
5354
};
5455

5556
await detectDockerfile(context);
57+
if (wizardContext.workspaceFolder) {
58+
wizardContext.hasDurableTaskScheduler = await durableUtils.getStorageTypeFromWorkspace(language, wizardContext.workspaceFolder.uri.fsPath) === DurableBackend.DTS;
59+
}
5660

5761
promptSteps.push(new SiteNameStep(context.dockerfilePath ? "containerizedFunctionApp" : "functionApp"));
5862

src/commands/createFunctionApp/createFunctionApp.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { localize } from '../../localize';
99
import { type SlotTreeItem } from '../../tree/SlotTreeItem';
1010
import { SubscriptionTreeItem, type ICreateFunctionAppContext } from '../../tree/SubscriptionTreeItem';
1111
import { type ContainerTreeItem } from '../../tree/containerizedFunctionApp/ContainerTreeItem';
12+
import { getRootWorkspaceFolder, isMultiRootWorkspace } from '../../utils/workspace';
1213

1314
function isSubscription(item?: AzExtParentTreeItem): boolean {
1415
try {
@@ -35,6 +36,10 @@ export async function createFunctionApp(context: IActionContext & Partial<ICreat
3536
}
3637

3738
context.newResourceGroupName = newResourceGroupName;
39+
if (!isMultiRootWorkspace()) {
40+
// only set the workspace if we're not doing in a multiroot project
41+
context.workspaceFolder = await getRootWorkspaceFolder();
42+
}
3843

3944
const funcAppNode: SlotTreeItem | ContainerTreeItem = await SubscriptionTreeItem.createChild(context as ICreateFunctionAppContext, node as SubscriptionTreeItem);
4045

0 commit comments

Comments
 (0)