Skip to content

Commit b3e9c40

Browse files
committed
Reorganize code, add activity children
1 parent 0dbbf41 commit b3e9c40

File tree

5 files changed

+73
-77
lines changed

5 files changed

+73
-77
lines changed

src/commands/appSettings/connectionSettings/durableTaskScheduler/azure/DTSStartingResourcesLogStep.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,12 @@ const startingResourcesContext: string = 'startingResourcesLogStepItem';
1212

1313
export class DTSStartingResourcesLogStep<T extends IDTSAzureConnectionWizardContext> extends AzureWizardPromptStep<T> {
1414
public hideStepCount: boolean = true;
15-
protected hasLogged: boolean = false;
1615

1716
public async configureBeforePrompt(context: T): Promise<void> {
18-
if (this.hasLogged) {
19-
return;
20-
}
21-
2217
if (context.resourceGroup) {
2318
prependOrInsertAfterLastInfoChild(context,
2419
new ActivityChildItem({
20+
stepId: this.id,
2521
contextValue: createContextValue([startingResourcesContext, activityInfoContext]),
2622
label: localize('useResourceGroup', 'Use resource group "{0}"', context.resourceGroup.name),
2723
activityType: ActivityChildType.Info,
@@ -34,6 +30,7 @@ export class DTSStartingResourcesLogStep<T extends IDTSAzureConnectionWizardCont
3430
if (context.site) {
3531
prependOrInsertAfterLastInfoChild(context,
3632
new ActivityChildItem({
33+
stepId: this.id,
3734
label: localize('useFunctionApp', 'Use function app "{0}"', context.site.fullName),
3835
contextValue: createContextValue([startingResourcesContext, activityInfoContext]),
3936
activityType: ActivityChildType.Info,
@@ -46,6 +43,7 @@ export class DTSStartingResourcesLogStep<T extends IDTSAzureConnectionWizardCont
4643
if (context.dts) {
4744
prependOrInsertAfterLastInfoChild(context,
4845
new ActivityChildItem({
46+
stepId: this.id,
4947
label: localize('useDTS', 'Use durable task scheduler "{0}"', context.dts.name),
5048
contextValue: createContextValue([startingResourcesContext, activityInfoContext]),
5149
activityType: ActivityChildType.Info,
@@ -58,6 +56,7 @@ export class DTSStartingResourcesLogStep<T extends IDTSAzureConnectionWizardCont
5856
if (context.dtsHub) {
5957
prependOrInsertAfterLastInfoChild(context,
6058
new ActivityChildItem({
59+
stepId: this.id,
6160
label: localize('useDTSHub', 'Use durable task hub "{0}"', context.dtsHub.name),
6261
contextValue: createContextValue([startingResourcesContext, activityInfoContext]),
6362
activityType: ActivityChildType.Info,
@@ -74,8 +73,6 @@ export class DTSStartingResourcesLogStep<T extends IDTSAzureConnectionWizardCont
7473
if (context.newDTSHubConnectionSettingKey) {
7574
ext.outputChannel.appendLog(localize('dtsHubConnectionKey', 'Using DTS hub host connection key "{0}"', context.newDTSHubConnectionSettingKey));
7675
}
77-
78-
this.hasLogged = true;
7976
}
8077

8178
public async prompt(): Promise<void> {

src/commands/appSettings/connectionSettings/durableTaskScheduler/azure/DurableTaskHubListStep.ts

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { parseAzureResourceId } from '@microsoft/vscode-azext-azureutils';
7-
import { AzureWizardPromptStep, nonNullProp, type IAzureQuickPickItem, type IWizardOptions } from '@microsoft/vscode-azext-utils';
6+
import { CommonRoleDefinitions, createAuthorizationManagementClient, createRoleId, parseAzureResourceId, RoleAssignmentExecuteStep, uiUtils, type Role } from '@microsoft/vscode-azext-azureutils';
7+
import { ActivityChildItem, ActivityChildType, activitySuccessContext, activitySuccessIcon, AzureWizardPromptStep, createContextValue, nonNullProp, type AzureWizardExecuteStep, type IAzureQuickPickItem, type IWizardOptions } from '@microsoft/vscode-azext-utils';
88
import { localSettingsDescription } from '../../../../../constants-nls';
9+
import { ext } from '../../../../../extensionVariables';
910
import { localize } from '../../../../../localize';
1011
import { HttpDurableTaskSchedulerClient, type DurableTaskHubResource, type DurableTaskSchedulerClient } from '../../../../../tree/durableTaskScheduler/DurableTaskSchedulerClient';
12+
import { FunctionAppUserAssignedIdentitiesListStep } from '../../../../identity/FunctionAppUserAssignedIdentitiesListStep';
1113
import { type IDTSAzureConnectionWizardContext } from '../IDTSConnectionWizardContext';
1214
import { DurableTaskHubCreateStep } from './DurableTaskHubCreateStep';
1315
import { DurableTaskHubNameStep } from './DurableTaskHubNameStep';
@@ -22,7 +24,7 @@ export class DurableTaskHubListStep<T extends IDTSAzureConnectionWizardContext>
2224

2325
public async prompt(context: T): Promise<void> {
2426
context.dtsHub = (await context.ui.showQuickPick(await this.getPicks(context), {
25-
placeHolder: localize('selectTaskScheduler', 'Select a Durable Task Scheduler'),
27+
placeHolder: localize('selectTaskScheduler', 'Select a durable task hub'),
2628
})).data;
2729

2830
if (context.dtsHub) {
@@ -35,17 +37,6 @@ export class DurableTaskHubListStep<T extends IDTSAzureConnectionWizardContext>
3537
return !context.dtsHub;
3638
}
3739

38-
public async getSubWizard(context: T): Promise<IWizardOptions<T> | undefined> {
39-
if (context.dtsHub) {
40-
return undefined;
41-
}
42-
43-
return {
44-
promptSteps: [new DurableTaskHubNameStep(this.schedulerClient)],
45-
executeSteps: [new DurableTaskHubCreateStep(this.schedulerClient)],
46-
};
47-
}
48-
4940
private async getPicks(context: T): Promise<IAzureQuickPickItem<DurableTaskHubResource | undefined>[]> {
5041
const taskHubs: DurableTaskHubResource[] = context.dts ?
5142
await this.schedulerClient.getSchedulerTaskHubs(nonNullProp(context, 'subscription'), parseAzureResourceId(context.dts.id).resourceGroup, context.dts.name) : [];
@@ -66,4 +57,65 @@ export class DurableTaskHubListStep<T extends IDTSAzureConnectionWizardContext>
6657
}),
6758
];
6859
}
60+
61+
public async getSubWizard(context: T): Promise<IWizardOptions<T> | undefined> {
62+
const promptSteps: AzureWizardPromptStep<T>[] = [];
63+
const executeSteps: AzureWizardExecuteStep<T>[] = [];
64+
65+
if (!context.dtsHub) {
66+
promptSteps.push(new DurableTaskHubNameStep(this.schedulerClient));
67+
executeSteps.push(new DurableTaskHubCreateStep(this.schedulerClient));
68+
}
69+
70+
const dtsContributorRole: Role = {
71+
scopeId: context.dtsHub?.id,
72+
roleDefinitionId: createRoleId(context.subscriptionId, CommonRoleDefinitions.durableTaskDataContributor),
73+
roleDefinitionName: CommonRoleDefinitions.durableTaskDataContributor.roleName,
74+
};
75+
76+
promptSteps.push(new FunctionAppUserAssignedIdentitiesListStep(dtsContributorRole /** targetRole */, { identityAssignStepPriority: 180 }));
77+
executeSteps.push(new RoleAssignmentExecuteStep(this.getDTSRoleAssignmentCallback(context, dtsContributorRole), { priority: 190 }));
78+
79+
return { promptSteps, executeSteps };
80+
}
81+
82+
private getDTSRoleAssignmentCallback(context: T, role: Role): () => Promise<Role[]> {
83+
return async () => {
84+
const roleAssignment: Role = {
85+
...role,
86+
// This id may be missing when the role is initially passed in,
87+
// but by the time we run the step, we should have the populated id ready.
88+
scopeId: context.dtsHub?.id,
89+
};
90+
91+
if (!roleAssignment.scopeId) {
92+
return [];
93+
}
94+
95+
const amClient = await createAuthorizationManagementClient(context);
96+
const roleAssignments = await uiUtils.listAllIterator(amClient.roleAssignments.listForScope(
97+
roleAssignment.scopeId,
98+
{
99+
// $filter=principalId eq {id}
100+
filter: `principalId eq '{${context.managedIdentity?.principalId}}'`,
101+
}
102+
));
103+
104+
const hasRoleAssignment = roleAssignments.some(r => !!r.roleDefinitionId?.endsWith(role.roleDefinitionId));
105+
if (hasRoleAssignment) {
106+
context.activityChildren?.push(
107+
new ActivityChildItem({
108+
label: localize('verifyIdentityWithRoleLabel', 'Verify identity "{0}" has role "{1}"', context.managedIdentity?.name, role.roleDefinitionName),
109+
description: '0s',
110+
contextValue: createContextValue(['roleAssignmentExecuteStepItem', activitySuccessContext]),
111+
activityType: ActivityChildType.Success,
112+
iconPath: activitySuccessIcon,
113+
}),
114+
);
115+
ext.outputChannel.appendLog(localize('verifyIdentity', 'Successfully verified identity "{0}" has role "{1}".', context.managedIdentity?.name, role.roleDefinitionName));
116+
}
117+
118+
return hasRoleAssignment ? [] : [roleAssignment];
119+
};
120+
}
69121
}

src/commands/appSettings/connectionSettings/durableTaskScheduler/azure/DurableTaskHubNameStep.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export class DurableTaskHubNameStep<T extends IDTSAzureConnectionWizardContext>
2020
public async prompt(context: T): Promise<void> {
2121
context.newDTSHubName = (await context.ui.showInputBox({
2222
prompt: localize('taskSchedulerName', 'Enter a name for the durable task hub'),
23-
value: context.suggestedDTSHubNameLocalSettings,
23+
value: context.suggestedDTSHubNameLocalSettings ?? 'default',
2424
validateInput: this.validateInput,
2525
asyncValidationTask: (name: string) => this.validateNameAvailable(context, name),
2626
})).trim();

src/commands/appSettings/connectionSettings/durableTaskScheduler/azure/DurableTaskSchedulerListStep.ts

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { CommonRoleDefinitions, createAuthorizationManagementClient, createRoleId, LocationListStep, parseAzureResourceId, RoleAssignmentExecuteStep, uiUtils, type ILocationWizardContext, type Role } from '@microsoft/vscode-azext-azureutils';
6+
import { LocationListStep, parseAzureResourceId, type ILocationWizardContext } from '@microsoft/vscode-azext-azureutils';
77
import { AzureWizardPromptStep, nonNullProp, type AzureWizardExecuteStep, type IAzureQuickPickItem, type IWizardOptions } from '@microsoft/vscode-azext-utils';
88
import { localSettingsDescription } from '../../../../../constants-nls';
99
import { localize } from '../../../../../localize';
1010
import { HttpDurableTaskSchedulerClient, type DurableTaskSchedulerClient, type DurableTaskSchedulerResource } from '../../../../../tree/durableTaskScheduler/DurableTaskSchedulerClient';
11-
import { FunctionAppUserAssignedIdentitiesListStep } from '../../../../identity/FunctionAppUserAssignedIdentitiesListStep';
1211
import { type IDTSAzureConnectionWizardContext } from '../IDTSConnectionWizardContext';
1312
import { DurableTaskHubListStep } from './DurableTaskHubListStep';
1413
import { DurableTaskSchedulerCreateStep } from './DurableTaskSchedulerCreateStep';
@@ -52,43 +51,7 @@ export class DurableTaskSchedulerListStep<T extends IDTSAzureConnectionWizardCon
5251
promptSteps.push(new DurableTaskHubListStep(this._schedulerClient));
5352
}
5453

55-
const dtsContributorRole: Role = {
56-
scopeId: context.dtsHub?.id,
57-
roleDefinitionId: createRoleId(context.subscriptionId, CommonRoleDefinitions.durableTaskDataContributor),
58-
roleDefinitionName: CommonRoleDefinitions.durableTaskDataContributor.roleName,
59-
};
60-
61-
promptSteps.push(new FunctionAppUserAssignedIdentitiesListStep(dtsContributorRole /** targetRole */, { identityAssignStepPriority: 180 }));
62-
executeSteps.push(new RoleAssignmentExecuteStep(getDTSRoleAssignmentCallback(context, dtsContributorRole), { priority: 190 }));
63-
6454
return { promptSteps, executeSteps };
65-
66-
function getDTSRoleAssignmentCallback(context: T, role: Role): () => Promise<Role[]> {
67-
return async () => {
68-
const roleAssignment: Role = {
69-
...role,
70-
// This id may be missing when the role is initially passed in,
71-
// but by the time we run the step, we should have the populated id ready.
72-
scopeId: context.dtsHub?.id,
73-
};
74-
75-
if (!roleAssignment.scopeId) {
76-
return [];
77-
}
78-
79-
const amClient = await createAuthorizationManagementClient(context);
80-
const roleAssignments = await uiUtils.listAllIterator(amClient.roleAssignments.listForScope(
81-
roleAssignment.scopeId,
82-
{
83-
// $filter=principalId eq {id}
84-
filter: `principalId eq '{${context.managedIdentity?.principalId}}'`,
85-
}
86-
));
87-
88-
const hasRoleAssignment = roleAssignments.some(r => !!r.roleDefinitionId?.endsWith(role.roleDefinitionId));
89-
return hasRoleAssignment ? [] : [roleAssignment];
90-
};
91-
}
9255
}
9356

9457
private async getPicks(context: T): Promise<IAzureQuickPickItem<DurableTaskSchedulerResource | undefined>[]> {

src/commands/identity/FunctionAppUserAssignedIdentitiesListStep.ts

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
import { type ManagedServiceIdentityClient } from '@azure/arm-msi';
77
import { type ParsedSite } from '@microsoft/vscode-azext-azureappservice';
88
import { createAuthorizationManagementClient, createManagedServiceIdentityClient, parseAzureResourceId, uiUtils, UserAssignedIdentityListStep, type ParsedAzureResourceId, type Role } from '@microsoft/vscode-azext-azureutils';
9-
import { ActivityChildItem, ActivityChildType, activityInfoContext, activityInfoIcon, AzureWizardPromptStep, createContextValue, nonNullProp, prependOrInsertAfterLastInfoChild, type ActivityInfoChild, type IAzureQuickPickItem, type IWizardOptions } from '@microsoft/vscode-azext-utils';
10-
import { ext } from '../../extensionVariables';
9+
import { AzureWizardPromptStep, nonNullProp, type IAzureQuickPickItem, type IWizardOptions } from '@microsoft/vscode-azext-utils';
1110
import { localize } from '../../localize';
1211
import { type ManagedIdentityAssignContext } from './ManagedIdentityAssignContext';
1312
import { ManagedIdentityAssignStep } from './ManagedIdentityAssignStep';
@@ -65,21 +64,6 @@ export class FunctionAppUserAssignedIdentitiesListStep<T extends ManagedIdentity
6564
}
6665

6766
context.telemetry.properties.functionAppHasIdentityWithTargetRole = String(hasTargetRole);
68-
69-
if (hasTargetRole) {
70-
prependOrInsertAfterLastInfoChild(context,
71-
new ActivityChildItem({
72-
stepId: this.id,
73-
label: localize('useIdentityWithRole', 'Use identity "{0}" with role "{1}"', context.managedIdentity?.name, this.targetRole.roleDefinitionName),
74-
contextValue: createContextValue(['functionAppUserAssignedIdentitiesListStepItem', activityInfoContext]),
75-
activityType: ActivityChildType.Info,
76-
iconPath: activityInfoIcon,
77-
}) as ActivityInfoChild,
78-
);
79-
ext.outputChannel.appendLog(localize('foundIdentity', 'Located existing user assigned identity "{0}" with role "{1}".', context.managedIdentity?.name, this.targetRole.roleDefinitionName));
80-
} else {
81-
ext.outputChannel.appendLog(localize('foundNoIdentity', 'Found no existing user assigned identity with role "{0}".', this.targetRole.roleDefinitionName));
82-
}
8367
}
8468

8569
public async prompt(context: T): Promise<void> {

0 commit comments

Comments
 (0)