diff --git a/package-lock.json b/package-lock.json index 4682834a9..c8c242674 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "@microsoft/vscode-azext-azureappservice": "^3.6.3", "@microsoft/vscode-azext-azureappsettings": "^0.2.8", "@microsoft/vscode-azext-azureutils": "^3.4.0", - "@microsoft/vscode-azext-utils": "^3.1.1", + "@microsoft/vscode-azext-utils": "^3.2.0", "@microsoft/vscode-azureresources-api": "^2.0.4", "@microsoft/vscode-container-client": "^0.1.2", "cross-fetch": "^4.0.0", @@ -1448,9 +1448,9 @@ } }, "node_modules/@microsoft/vscode-azext-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-3.1.1.tgz", - "integrity": "sha512-90ywJWsjyPaPTxQgNVidSb5TwJ8OfoJF9cYdhAzbHmxO7rqFq/suWXbYU+kSIix7tMBVlzPIshGESv+vpEPlyw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-3.2.0.tgz", + "integrity": "sha512-cOTcklPwfpltpj717kKAR2bMxxJWiqBCnmgwK/bc9x9YoMvee2cQt5L8HZRW35etgPjVaF+JAyXqdowyYksdXQ==", "dependencies": { "@microsoft/vscode-azureresources-api": "^2.3.1", "@vscode/extension-telemetry": "^0.9.6", diff --git a/package.json b/package.json index d4b1c9129..430ecda40 100644 --- a/package.json +++ b/package.json @@ -1484,7 +1484,7 @@ "@microsoft/vscode-azext-azureappservice": "^3.6.3", "@microsoft/vscode-azext-azureappsettings": "^0.2.8", "@microsoft/vscode-azext-azureutils": "^3.4.0", - "@microsoft/vscode-azext-utils": "^3.1.1", + "@microsoft/vscode-azext-utils": "^3.2.0", "@microsoft/vscode-azureresources-api": "^2.0.4", "@microsoft/vscode-container-client": "^0.1.2", "cross-fetch": "^4.0.0", diff --git a/src/commands/appSettings/connectionSettings/durableTaskScheduler/DTSConnectionSetSettingStep.ts b/src/commands/appSettings/connectionSettings/durableTaskScheduler/DTSConnectionSetSettingStep.ts index 3c01f2f9b..bcb1f18e0 100644 --- a/src/commands/appSettings/connectionSettings/durableTaskScheduler/DTSConnectionSetSettingStep.ts +++ b/src/commands/appSettings/connectionSettings/durableTaskScheduler/DTSConnectionSetSettingStep.ts @@ -3,13 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { nonNullProp } from '@microsoft/vscode-azext-utils'; +import { ActivityChildItem, ActivityChildType, activityFailContext, activityFailIcon, activityProgressContext, activityProgressIcon, activitySuccessContext, activitySuccessIcon, createContextValue, nonNullProp, type ExecuteActivityOutput } from '@microsoft/vscode-azext-utils'; import { ConnectionKey } from '../../../../constants'; +import { localize } from '../../../../localize'; import { SetConnectionSettingStepBase } from '../SetConnectionSettingStepBase'; import { type IDTSAzureConnectionWizardContext, type IDTSConnectionWizardContext } from './IDTSConnectionWizardContext'; export class DTSConnectionSetSettingStep extends SetConnectionSettingStepBase { public priority: number = 240; + public stepName: string = 'dtsConnectionSetSettingStep'; public debugDeploySetting: ConnectionKey = ConnectionKey.DTS; public async execute(context: T): Promise { @@ -17,10 +19,49 @@ export class DTSConnectionSetSettingStep if ((context as unknown as IDTSAzureConnectionWizardContext).managedIdentity) { newDTSConnectionSetting = newDTSConnectionSetting.replace('', (context as unknown as IDTSAzureConnectionWizardContext).managedIdentity?.clientId ?? ''); } + await this.setConnectionSetting(context, newDTSConnectionSetting); + context.newDTSConnectionSetting = newDTSConnectionSetting; + + context.valuesToMask.push(context.newDTSConnectionSetting); } public shouldExecute(context: T): boolean { return !!context.newDTSConnectionSetting; } + + public createSuccessOutput(context: T): ExecuteActivityOutput { + return { + item: new ActivityChildItem({ + label: localize('prepareDTSConnectionProgressLabel', 'Prepare DTS connection: "{0}"', 'Endpoint=...'), + contextValue: createContextValue([`${this.stepName}Item`, activitySuccessContext]), + activityType: ActivityChildType.Success, + iconPath: activitySuccessIcon, + }), + message: localize('prepareDTSConnectionSuccess', 'Successfully prepared DTS connection: "{0}".', context.newDTSConnectionSetting), + }; + } + + public createProgressOutput(): ExecuteActivityOutput { + return { + item: new ActivityChildItem({ + label: localize('prepareDTSConnectionProgressLabel', 'Prepare DTS connection: "{0}"', 'Endpoint=...'), + contextValue: createContextValue([`${this.stepName}Item`, activityProgressContext]), + activityType: ActivityChildType.Progress, + iconPath: activityProgressIcon, + }), + }; + } + + public createFailOutput(context: T): ExecuteActivityOutput { + return { + item: new ActivityChildItem({ + label: localize('prepareDTSConnectionProgressLabel', 'Prepare DTS connection: "{0}"', 'Endpoint=...'), + contextValue: createContextValue([`${this.stepName}Item`, activityFailContext]), + activityType: ActivityChildType.Fail, + iconPath: activityFailIcon, + }), + message: localize('prepareDTSConnectionFail', 'Failed to prepare DTS connection: "{0}".', context.newDTSConnectionSetting), + }; + } } diff --git a/src/commands/appSettings/connectionSettings/durableTaskScheduler/DTSHubNameSetSettingStep.ts b/src/commands/appSettings/connectionSettings/durableTaskScheduler/DTSHubNameSetSettingStep.ts index 46d2ead71..60b4cf5ae 100644 --- a/src/commands/appSettings/connectionSettings/durableTaskScheduler/DTSHubNameSetSettingStep.ts +++ b/src/commands/appSettings/connectionSettings/durableTaskScheduler/DTSHubNameSetSettingStep.ts @@ -3,13 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { nonNullProp } from '@microsoft/vscode-azext-utils'; +import { ActivityChildItem, ActivityChildType, activityFailIcon, activityProgressContext, activityProgressIcon, activitySuccessContext, activitySuccessIcon, createContextValue, nonNullProp, type ExecuteActivityOutput } from '@microsoft/vscode-azext-utils'; import { ConnectionKey } from '../../../../constants'; +import { localize } from '../../../../localize'; import { SetConnectionSettingStepBase } from '../SetConnectionSettingStepBase'; import { type IDTSConnectionWizardContext } from './IDTSConnectionWizardContext'; export class DTSHubNameSetSettingStep extends SetConnectionSettingStepBase { public priority: number = 241; + public stepName: string = 'dtsHubNameSetSettingStep'; public debugDeploySetting: ConnectionKey = ConnectionKey.DTSHub; public async execute(context: T): Promise { @@ -19,4 +21,39 @@ export class DTSHubNameSetSettingStep ext public shouldExecute(context: T): boolean { return !!context.newDTSHubNameConnectionSetting; } + + public createSuccessOutput(context: T): ExecuteActivityOutput { + return { + item: new ActivityChildItem({ + label: localize('prepareDTSHubNameLabel', 'Prepare DTS hub connection: "{0}"', context.newDTSHubNameConnectionSetting), + contextValue: createContextValue([`${this.stepName}Item`, activitySuccessContext]), + activityType: ActivityChildType.Success, + iconPath: activitySuccessIcon, + }), + message: localize('prepareDTSHubNameSuccess', 'Successfully prepared DTS hub connection: "{0}".', context.newDTSConnectionSetting), + }; + } + + public createProgressOutput(): ExecuteActivityOutput { + return { + item: new ActivityChildItem({ + label: localize('prepareDTSHubNameProgressLabel', 'Prepare DTS hub connection: "..."'), + contextValue: createContextValue([`${this.stepName}Item`, activityProgressContext]), + activityType: ActivityChildType.Progress, + iconPath: activityProgressIcon, + }), + }; + } + + public createFailOutput(context: T): ExecuteActivityOutput { + return { + item: new ActivityChildItem({ + label: localize('prepareDTSHubNameLabel', 'Prepare DTS hub connection: "{0}"', context.newDTSHubNameConnectionSetting), + contextValue: createContextValue([`${this.stepName}Item`, activitySuccessContext]), + activityType: ActivityChildType.Fail, + iconPath: activityFailIcon, + }), + message: localize('prepareDTSHubNameFail', 'Failed to prepare DTS hub connection: "{0}".', context.newDTSConnectionSetting), + }; + } } diff --git a/src/commands/appSettings/connectionSettings/durableTaskScheduler/IDTSConnectionWizardContext.ts b/src/commands/appSettings/connectionSettings/durableTaskScheduler/IDTSConnectionWizardContext.ts index 43ceb26d8..01614577e 100644 --- a/src/commands/appSettings/connectionSettings/durableTaskScheduler/IDTSConnectionWizardContext.ts +++ b/src/commands/appSettings/connectionSettings/durableTaskScheduler/IDTSConnectionWizardContext.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { type IActionContext } from "@microsoft/vscode-azext-utils"; +import { type ExecuteActivityContext, type IActionContext } from "@microsoft/vscode-azext-utils"; import { type AzureSubscription } from "@microsoft/vscode-azureresources-api"; import { type ConnectionType } from "../../../../constants"; import { type DurableTaskHubResource, type DurableTaskSchedulerResource } from "../../../../tree/durableTaskScheduler/DurableTaskSchedulerClient"; @@ -20,7 +20,7 @@ export interface IDTSConnectionWizardContext extends IActionContext, ISetConnect newDTSHubNameConnectionSetting?: string; } -export interface IDTSAzureConnectionWizardContext extends IFunctionAppUserAssignedIdentitiesContext, IDTSConnectionWizardContext { +export interface IDTSAzureConnectionWizardContext extends IFunctionAppUserAssignedIdentitiesContext, IDTSConnectionWizardContext, Partial { subscription?: AzureSubscription; /** diff --git a/src/commands/appSettings/connectionSettings/durableTaskScheduler/azure/DTSStartingResourcesLogStep.ts b/src/commands/appSettings/connectionSettings/durableTaskScheduler/azure/DTSStartingResourcesLogStep.ts new file mode 100644 index 000000000..2f5f83525 --- /dev/null +++ b/src/commands/appSettings/connectionSettings/durableTaskScheduler/azure/DTSStartingResourcesLogStep.ts @@ -0,0 +1,81 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ActivityChildItem, ActivityChildType, activityInfoContext, activityInfoIcon, AzureWizardPromptStep, createContextValue, prependOrInsertAfterLastInfoChild, type ActivityInfoChild } from "@microsoft/vscode-azext-utils"; +import { ext } from "../../../../../extensionVariables"; +import { localize } from "../../../../../localize"; +import { type IDTSAzureConnectionWizardContext } from "../IDTSConnectionWizardContext"; + +const startingResourcesContext: string = 'startingResourcesLogStepItem'; + +export class DTSStartingResourcesLogStep extends AzureWizardPromptStep { + public hideStepCount: boolean = true; + protected hasLogged: boolean = false; + + public async configureBeforePrompt(context: T): Promise { + if (this.hasLogged) { + return; + } + + if (context.resourceGroup) { + prependOrInsertAfterLastInfoChild(context, + new ActivityChildItem({ + contextValue: createContextValue([startingResourcesContext, activityInfoContext]), + label: localize('useResourceGroup', 'Use resource group "{0}"', context.resourceGroup.name), + activityType: ActivityChildType.Info, + iconPath: activityInfoIcon + }) as ActivityInfoChild + ); + ext.outputChannel.appendLog(localize('usingResourceGroup', 'Using resource group "{0}".', context.resourceGroup.name)); + } + + if (context.site) { + prependOrInsertAfterLastInfoChild(context, + new ActivityChildItem({ + label: localize('useFunctionApp', 'Use function app "{0}"', context.site.fullName), + contextValue: createContextValue([startingResourcesContext, activityInfoContext]), + activityType: ActivityChildType.Info, + iconPath: activityInfoIcon, + }) as ActivityInfoChild, + ); + ext.outputChannel.appendLog(localize('usingFunctionApp', 'Using function app "{0}".', context.site.fullName)); + } + + if (context.dts) { + prependOrInsertAfterLastInfoChild(context, + new ActivityChildItem({ + label: localize('useDTS', 'Use durable task scheduler "{0}"', context.dts.name), + contextValue: createContextValue([startingResourcesContext, activityInfoContext]), + activityType: ActivityChildType.Info, + iconPath: activityInfoIcon + }) as ActivityInfoChild, + ); + ext.outputChannel.appendLog(localize('usingDTS', 'Using durable task scheduler "{0}".', context.dts.name)); + } + + if (context.dtsHub) { + prependOrInsertAfterLastInfoChild(context, + new ActivityChildItem({ + label: localize('useDTSHub', 'Use durable task hub "{0}"', context.dtsHub.name), + contextValue: createContextValue([startingResourcesContext, activityInfoContext]), + activityType: ActivityChildType.Info, + iconPath: activityInfoIcon, + }) as ActivityInfoChild, + ); + ext.outputChannel.appendLog(localize('usingDTSHub', 'Using durable task hub "{0}".', context.dtsHub.name)); + } + + ext.outputChannel.appendLog(localize('prioritizingSiteLocation', 'Prioritizing site location: "{0}".', context.site?.location)); + this.hasLogged = true; + } + + public async prompt(): Promise { + // Don't prompt, just use to log starting resources + } + + public shouldPrompt(): boolean { + return false; + } +} diff --git a/src/commands/appSettings/connectionSettings/durableTaskScheduler/azure/DurableTaskHubCreateStep.ts b/src/commands/appSettings/connectionSettings/durableTaskScheduler/azure/DurableTaskHubCreateStep.ts index d9699c6bc..3d265e0d9 100644 --- a/src/commands/appSettings/connectionSettings/durableTaskScheduler/azure/DurableTaskHubCreateStep.ts +++ b/src/commands/appSettings/connectionSettings/durableTaskScheduler/azure/DurableTaskHubCreateStep.ts @@ -3,25 +3,31 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardExecuteStep, nonNullProp, nonNullValueAndProp } from "@microsoft/vscode-azext-utils"; +import { AzureWizardExecuteStepWithActivityOutput, nonNullProp, nonNullValueAndProp } from "@microsoft/vscode-azext-utils"; import { type Progress } from "vscode"; import { localize } from "../../../../../localize"; import { HttpDurableTaskSchedulerClient, type DurableTaskSchedulerClient } from "../../../../../tree/durableTaskScheduler/DurableTaskSchedulerClient"; import { type IDTSAzureConnectionWizardContext } from "../IDTSConnectionWizardContext"; -export class DurableTaskHubCreateStep extends AzureWizardExecuteStep { - priority: number = 160; - private readonly schedulerClient: DurableTaskSchedulerClient; +export class DurableTaskHubCreateStep extends AzureWizardExecuteStepWithActivityOutput { + public priority: number = 160; + public stepName: string = 'durableTaskHubCreateStep'; + + protected getOutputLogSuccess = (context: T) => localize('createTaskHubSuccess', 'Created durable task hub "{0}"', context.dtsHub?.name); + protected getOutputLogFail = (context: T) => localize('createTaskHubFail', 'Failed to create durable task hub "{0}"', context.newDTSHubName); + protected getTreeItemLabel = (context: T) => localize('createTaskHubLabel', 'Create durable task hub "{0}"', context.newDTSHubName); + + private readonly _schedulerClient: DurableTaskSchedulerClient; constructor(schedulerClient?: DurableTaskSchedulerClient) { super(); - this.schedulerClient = schedulerClient ?? new HttpDurableTaskSchedulerClient(); + this._schedulerClient = schedulerClient ?? new HttpDurableTaskSchedulerClient(); } public async execute(context: T, progress: Progress<{ message?: string; increment?: number; }>): Promise { progress.report({ message: localize('createTaskHub', 'Creating durable task hub...') }); - context.dtsHub = await this.schedulerClient.createTaskHub( + context.dtsHub = await this._schedulerClient.createTaskHub( nonNullProp(context, 'subscription'), nonNullValueAndProp(context.resourceGroup, 'name'), nonNullValueAndProp(context.dts, 'name'), diff --git a/src/commands/appSettings/connectionSettings/durableTaskScheduler/azure/DurableTaskSchedulerCreateStep.ts b/src/commands/appSettings/connectionSettings/durableTaskScheduler/azure/DurableTaskSchedulerCreateStep.ts index 8bd4aac27..8ae17d708 100644 --- a/src/commands/appSettings/connectionSettings/durableTaskScheduler/azure/DurableTaskSchedulerCreateStep.ts +++ b/src/commands/appSettings/connectionSettings/durableTaskScheduler/azure/DurableTaskSchedulerCreateStep.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { LocationListStep } from "@microsoft/vscode-azext-azureutils"; -import { AzureWizardExecuteStep, nonNullProp, nonNullValueAndProp } from "@microsoft/vscode-azext-utils"; +import { ActivityChildItem, ActivityChildType, activityProgressContext, activityProgressIcon, AzureWizardExecuteStepWithActivityOutput, createContextValue, nonNullProp, nonNullValueAndProp, type ExecuteActivityOutput } from "@microsoft/vscode-azext-utils"; import { type Progress } from "vscode"; import { localize } from "../../../../../localize"; import { HttpDurableTaskSchedulerClient, type DurableTaskSchedulerClient } from "../../../../../tree/durableTaskScheduler/DurableTaskSchedulerClient"; @@ -12,19 +12,25 @@ import { withCancellation } from "../../../../../utils/cancellation"; import { getSchedulerConnectionString, SchedulerAuthenticationType } from "../../../../durableTaskScheduler/copySchedulerConnectionString"; import { type IDTSAzureConnectionWizardContext } from "../IDTSConnectionWizardContext"; -export class DurableTaskSchedulerCreateStep extends AzureWizardExecuteStep { - priority: number = 150; - private readonly schedulerClient: DurableTaskSchedulerClient; +export class DurableTaskSchedulerCreateStep extends AzureWizardExecuteStepWithActivityOutput { + public priority: number = 150; + public stepName: string = 'durableTaskSchedulerCreateStep'; + + protected getOutputLogSuccess = (context: T) => localize('createTaskSchedulerSuccess', 'Created durable task scheduler "{0}"', context.dts?.name); + protected getOutputLogFail = (context: T) => localize('createTaskSchedulerFail', 'Failed to create durable task scheduler "{0}"', context.newDTSName); + protected getTreeItemLabel = (context: T) => localize('createTaskSchedulerLabel', 'Create durable task scheduler "{0}"', context.newDTSName); + + private readonly _schedulerClient: DurableTaskSchedulerClient; public constructor(schedulerClient?: DurableTaskSchedulerClient) { super(); - this.schedulerClient = schedulerClient ?? new HttpDurableTaskSchedulerClient(); + this._schedulerClient = schedulerClient ?? new HttpDurableTaskSchedulerClient(); } public async execute(context: T, progress: Progress<{ message?: string; increment?: number; }>): Promise { progress.report({ message: localize('createTaskScheduler', 'Creating durable task scheduler...') }); - const response = (await this.schedulerClient.createScheduler( + const response = (await this._schedulerClient.createScheduler( nonNullProp(context, 'subscription'), nonNullValueAndProp(context.resourceGroup, 'name'), (await LocationListStep.getLocation(context)).name, @@ -44,4 +50,16 @@ export class DurableTaskSchedulerCreateStep = new AzureWizard(wizardContext, { - title: localize('prepareDTSConnection', 'Prepare durable task scheduler connection'), + title: localize('prepareDTSConnection', 'Prepare durable task scheduler connections'), promptSteps: [ new ResourceGroupListStep(), new DTSConnectionListStep(availableDeployConnectionTypes), + new DTSStartingResourcesLogStep(), ], showLoadingPrompt: true, }); diff --git a/src/commands/identity/listUserAssignedIdentities/FunctionAppUserAssignedIdentitiesListStep.ts b/src/commands/identity/listUserAssignedIdentities/FunctionAppUserAssignedIdentitiesListStep.ts index 2a6b182b7..50946ced4 100644 --- a/src/commands/identity/listUserAssignedIdentities/FunctionAppUserAssignedIdentitiesListStep.ts +++ b/src/commands/identity/listUserAssignedIdentities/FunctionAppUserAssignedIdentitiesListStep.ts @@ -6,7 +6,7 @@ import { type ManagedServiceIdentityClient } from '@azure/arm-msi'; import { type ParsedSite } from '@microsoft/vscode-azext-azureappservice'; import { createAuthorizationManagementClient, createManagedServiceIdentityClient, parseAzureResourceId, uiUtils, type ParsedAzureResourceId, type Role } from '@microsoft/vscode-azext-azureutils'; -import { AzureWizardPromptStep, nonNullProp, type IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; +import { ActivityChildItem, ActivityChildType, activityInfoContext, activityInfoIcon, AzureWizardPromptStep, createContextValue, nonNullProp, prependOrInsertAfterLastInfoChild, type ActivityInfoChild, type IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; import { ext } from '../../../extensionVariables'; import { localize } from '../../../localize'; import { type IFunctionAppUserAssignedIdentitiesContext } from './IFunctionAppUserAssignedIdentitiesContext'; @@ -72,9 +72,19 @@ export class FunctionAppUserAssignedIdentitiesListStep { diff --git a/src/commands/identity/listUserAssignedIdentities/IFunctionAppUserAssignedIdentitiesContext.ts b/src/commands/identity/listUserAssignedIdentities/IFunctionAppUserAssignedIdentitiesContext.ts index 752cdf625..6de24f97f 100644 --- a/src/commands/identity/listUserAssignedIdentities/IFunctionAppUserAssignedIdentitiesContext.ts +++ b/src/commands/identity/listUserAssignedIdentities/IFunctionAppUserAssignedIdentitiesContext.ts @@ -5,7 +5,8 @@ import { type ParsedSite } from "@microsoft/vscode-azext-azureappservice"; import { type IResourceGroupWizardContext } from "@microsoft/vscode-azext-azureutils"; +import { type ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; -export interface IFunctionAppUserAssignedIdentitiesContext extends IResourceGroupWizardContext { +export interface IFunctionAppUserAssignedIdentitiesContext extends IResourceGroupWizardContext, Partial { site?: ParsedSite; } diff --git a/src/utils/activityUtils.ts b/src/utils/activityUtils.ts index 419702ee4..d22e4ca37 100644 --- a/src/utils/activityUtils.ts +++ b/src/utils/activityUtils.ts @@ -7,9 +7,10 @@ import { type ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; import { ext } from "../extensionVariables"; import { getWorkspaceSetting } from "../vsCodeConfig/settings"; -export async function createActivityContext(): Promise { +export async function createActivityContext(options?: { withChildren?: boolean }): Promise { return { registerActivity: async (activity) => ext.rgApi.registerActivity(activity), suppressNotification: await getWorkspaceSetting('suppressActivityNotifications', undefined, 'azureResourceGroups'), + activityChildren: options?.withChildren ? [] : undefined, }; }