Skip to content

Commit 8746b9c

Browse files
authored
Add DTS management commands (#4370)
* Scaffold BDP. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Refactor type hierarchy. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Sketch retrieval of task hubs. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Update task hub icon. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Enable "open in portal" command for task hubs. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Scaffold "open in dashboard" command. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Sketch "open in dashboard" implementation. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Move DTS management to separate client type. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Support viewing task hub properties. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Split apart types. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Add file headers. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Consolidate client logic and add localizable strings. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Scaffold creation of task hub. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Sketch creation of schedulers. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Expose DTS creation from common new menu. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Sketch deletion of task hubs. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Sketch deletion of schedulers. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Sketch refreshing models post-creation. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Add tree refresh to remainder of DTS commands. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Provide extended schduler properties. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Add provisioning state when not "normal". Signed-off-by: Phillip Hoff <phillip@orst.edu> * Move creation command to top of context menu. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Add copy scheduler endpoint command. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Sketch copy connections string command. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Add task hub selection for connection string. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Add async waits. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Wrap deletion in an activity. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Add some robustness to API call failures. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Tweak strings for task hub selection. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Wrap task hub creation with activity. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Wrap task hub deletion with activity. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Add retry for task hub retrieval. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Hide DTS commands from palette. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Add verify providers step to scheduler creation. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Un-hide create scheduler command. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Sketch DTS setting. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Refactor DTS preview setting name. Signed-off-by: Phillip Hoff <phillip@orst.edu> * Add preview features enabled check during create. Signed-off-by: Phillip Hoff <phillip@orst.edu> --------- Signed-off-by: Phillip Hoff <phillip@orst.edu>
1 parent bd6d276 commit 8746b9c

19 files changed

+1116
-39
lines changed

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@
6363
"resources": true
6464
},
6565
"commands": [
66+
{
67+
"command": "azureFunctions.durableTaskScheduler.createScheduler",
68+
"title": "%azureFunctions.durableTaskScheduler.createScheduler%",
69+
"type": "DurableTaskScheduler",
70+
"detail": "%azureFunctions.durableTaskScheduler.createScheduler.detail%"
71+
},
6672
{
6773
"command": "azureFunctions.createFunctionApp",
6874
"title": "%azureFunctions.createFunctionApp%",
@@ -375,6 +381,36 @@
375381
"category": "Azure Functions",
376382
"icon": "$(notebook-execute)"
377383
},
384+
{
385+
"command": "azureFunctions.durableTaskScheduler.copySchedulerConnectionString",
386+
"title": "%azureFunctions.durableTaskScheduler.copySchedulerConnectionString%",
387+
"category": "Azure Functions"
388+
},
389+
{
390+
"command": "azureFunctions.durableTaskScheduler.copySchedulerEndpoint",
391+
"title": "%azureFunctions.durableTaskScheduler.copySchedulerEndpoint%",
392+
"category": "Azure Functions"
393+
},
394+
{
395+
"command": "azureFunctions.durableTaskScheduler.createScheduler",
396+
"title": "%azureFunctions.durableTaskScheduler.createScheduler%",
397+
"category": "Azure Functions"
398+
},
399+
{
400+
"command": "azureFunctions.durableTaskScheduler.createTaskHub",
401+
"title": "%azureFunctions.durableTaskScheduler.createTaskHub%",
402+
"category": "Azure Functions"
403+
},
404+
{
405+
"command": "azureFunctions.durableTaskScheduler.deleteScheduler",
406+
"title": "%azureFunctions.durableTaskScheduler.deleteScheduler%",
407+
"category": "Azure Functions"
408+
},
409+
{
410+
"command": "azureFunctions.durableTaskScheduler.deleteTaskHub",
411+
"title": "%azureFunctions.durableTaskScheduler.deleteTaskHub%",
412+
"category": "Azure Functions"
413+
},
378414
{
379415
"command": "azureFunctions.durableTaskScheduler.openTaskHubDashboard",
380416
"title": "%azureFunctions.durableTaskScheduler.openTaskHubDashboard%",
@@ -673,9 +709,40 @@
673709
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /azFunc.*folder/",
674710
"group": "1@1"
675711
},
712+
{
713+
"command": "azureFunctions.durableTaskScheduler.copySchedulerConnectionString",
714+
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /azFunc.dts.scheduler/",
715+
"group": "3@1"
716+
},
717+
{
718+
"command": "azureFunctions.durableTaskScheduler.copySchedulerEndpoint",
719+
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /azFunc.dts.scheduler/",
720+
"group": "3@2"
721+
},
722+
{
723+
"command": "azureFunctions.durableTaskScheduler.createScheduler",
724+
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /DurableTaskScheduler/i && viewItem =~ /azureResourceTypeGroup/i && config.azureFunctions.durableTaskScheduler.enablePreviewFeatures == true",
725+
"group": "1@1"
726+
},
727+
{
728+
"command": "azureFunctions.durableTaskScheduler.createTaskHub",
729+
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /azFunc.dts.scheduler/",
730+
"group": "1@1"
731+
},
732+
{
733+
"command": "azureFunctions.durableTaskScheduler.deleteScheduler",
734+
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /azFunc.dts.scheduler/",
735+
"group": "2@1"
736+
},
737+
{
738+
"command": "azureFunctions.durableTaskScheduler.deleteTaskHub",
739+
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /azFunc.dts.taskHub/",
740+
"group": "2@1"
741+
},
676742
{
677743
"command": "azureFunctions.durableTaskScheduler.openTaskHubDashboard",
678-
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /azFunc.dts.taskHub/"
744+
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /azFunc.dts.taskHub/",
745+
"group": "1@1"
679746
}
680747
],
681748
"explorer/context": [
@@ -728,6 +795,34 @@
728795
{
729796
"command": "azureFunctions.viewProperties",
730797
"when": "never"
798+
},
799+
{
800+
"command": "azureFunctions.durableTaskScheduler.copySchedulerConnectionString",
801+
"when": "never"
802+
},
803+
{
804+
"command": "azureFunctions.durableTaskScheduler.copySchedulerEndpoint",
805+
"when": "never"
806+
},
807+
{
808+
"command": "azureFunctions.durableTaskScheduler.createScheduler",
809+
"when": "config.azureFunctions.durableTaskScheduler.enablePreviewFeatures == true"
810+
},
811+
{
812+
"command": "azureFunctions.durableTaskScheduler.createTaskHub",
813+
"when": "never"
814+
},
815+
{
816+
"command": "azureFunctions.durableTaskScheduler.deleteScheduler",
817+
"when": "never"
818+
},
819+
{
820+
"command": "azureFunctions.durableTaskScheduler.deleteTaskHub",
821+
"when": "never"
822+
},
823+
{
824+
"command": "azureFunctions.durableTaskScheduler.openTaskHubDashboard",
825+
"when": "never"
731826
}
732827
],
733828
"editor/context": [
@@ -835,6 +930,16 @@
835930
}
836931
],
837932
"configuration": [
933+
{
934+
"title": "Durable Task Scheduler",
935+
"properties": {
936+
"azureFunctions.durableTaskScheduler.enablePreviewFeatures": {
937+
"type": "boolean",
938+
"default": false,
939+
"description": "%azureFunctions.durableTaskScheduler.enablePreviewFeatures%"
940+
}
941+
}
942+
},
838943
{
839944
"title": "Azure Functions",
840945
"properties": {
@@ -1232,6 +1337,7 @@
12321337
"@azure/arm-appservice": "^15.0.0",
12331338
"@azure/arm-cosmosdb": "^15.0.0",
12341339
"@azure/arm-eventhub": "^5.1.0",
1340+
"@azure/arm-resources-profile-2020-09-01-hybrid": "^2.1.0",
12351341
"@azure/arm-servicebus": "^5.0.0",
12361342
"@azure/arm-sql": "^9.1.0",
12371343
"@azure/arm-storage": "^18.1.0",

package.nls.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,5 +120,14 @@
120120
"azureFunctions.walkthrough.functionsStart.scenarios.title": "Explore common scenarios",
121121
"azureFunctions.walkthrough.functionsStart.title": "Get Started with Azure Functions",
122122

123-
"azureFunctions.durableTaskScheduler.openTaskHubDashboard": "Open in Dashboard"
123+
"azureFunctions.durableTaskScheduler.copySchedulerConnectionString": "Copy Connection String",
124+
"azureFunctions.durableTaskScheduler.copySchedulerEndpoint": "Copy Endpoint",
125+
"azureFunctions.durableTaskScheduler.createScheduler": "Create Durable Task Scheduler...",
126+
"azureFunctions.durableTaskScheduler.createScheduler.detail": "For long-running and reliable workflows.",
127+
"azureFunctions.durableTaskScheduler.createTaskHub": "Create Task Hub...",
128+
"azureFunctions.durableTaskScheduler.deleteScheduler": "Delete Scheduler...",
129+
"azureFunctions.durableTaskScheduler.deleteTaskHub": "Delete Task Hub...",
130+
"azureFunctions.durableTaskScheduler.openTaskHubDashboard": "Open in Dashboard",
131+
132+
"azureFunctions.durableTaskScheduler.enablePreviewFeatures": "Enable Durable Task Scheduler preview features"
124133
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { type IActionContext } from "@microsoft/vscode-azext-utils";
7+
import { type DurableTaskSchedulerClient } from "../../tree/durableTaskScheduler/DurableTaskSchedulerClient";
8+
import { type DurableTaskSchedulerResourceModel } from "../../tree/durableTaskScheduler/DurableTaskSchedulerResourceModel";
9+
import { localize } from "../../localize";
10+
import { ext } from "../../extensionVariables";
11+
import { env, QuickPickItemKind, type QuickPickItem } from "vscode";
12+
13+
export function copySchedulerConnectionStringCommandFactory(schedulerClient: DurableTaskSchedulerClient) {
14+
return async (actionContext: IActionContext, scheduler: DurableTaskSchedulerResourceModel | undefined): Promise<void> => {
15+
if (!scheduler) {
16+
throw new Error(localize('noSchedulerSelectedErrorMessage', 'No scheduler was selected.'));
17+
}
18+
19+
const schedulerJson = await schedulerClient.getScheduler(
20+
scheduler.subscription,
21+
scheduler.resourceGroup,
22+
scheduler.name);
23+
24+
if (!schedulerJson) {
25+
throw new Error(localize('schedulerNotFoundErrorMessage', 'Scheduler does not exist.'));
26+
}
27+
28+
const { endpoint } = schedulerJson.properties;
29+
30+
const noAuthentication: QuickPickItem = {
31+
detail: localize('noAuthenticationDetail', 'No credentials will be used.'),
32+
label: localize('noAuthenticationLabel', 'None')
33+
}
34+
35+
const localDevelopment: QuickPickItem = {
36+
detail: localize('localDevelopmentDetail', 'Use the credentials of the local developer.'),
37+
label: localize('localDevelopmentLabel', 'Local development')
38+
};
39+
40+
const userAssignedManagedIdentity: QuickPickItem = {
41+
detail: localize('userAssignedManagedIdentityDetail', 'Use managed identity credentials for a specific client.'),
42+
label: localize('userAssignedManagedIdentityLabel', 'User-assigned managed identity')
43+
}
44+
45+
const systemAssignedManagedIdentity: QuickPickItem = {
46+
detail: localize('systemAssignedManagedIdentityDetail', 'Use managed identity credentials for a client assigned to a specific Azure resource.'),
47+
label: localize('systemAssignedManagedIdentityLabel', 'System-assigned managed identity')
48+
}
49+
50+
const result = await actionContext.ui.showQuickPick(
51+
[
52+
noAuthentication,
53+
localDevelopment,
54+
userAssignedManagedIdentity,
55+
systemAssignedManagedIdentity
56+
],
57+
{
58+
canPickMany: false,
59+
placeHolder: localize('authenticationTypePlaceholder', 'Select the credentials to be used to connect to the scheduler')
60+
});
61+
62+
let connectionString = `Endpoint=${endpoint};Authentication=`
63+
64+
if (result === noAuthentication) {
65+
connectionString += 'None';
66+
}
67+
else if (result === localDevelopment) {
68+
connectionString += 'DefaultAzure';
69+
}
70+
else {
71+
connectionString += 'ManagedIdentity';
72+
73+
if (result === userAssignedManagedIdentity) {
74+
connectionString += ';ClientID=<ClientID>';
75+
}
76+
}
77+
78+
const taskHubs = await schedulerClient.getSchedulerTaskHubs(
79+
scheduler.subscription,
80+
scheduler.resourceGroup,
81+
scheduler.name);
82+
83+
if (taskHubs.length > 0) {
84+
85+
const noTaskHubItem: QuickPickItem = {
86+
detail: localize('noTaskHubDetail', 'Do not connect to a specific task hub.'),
87+
label: localize('noTaskHubLabel', 'None')
88+
}
89+
90+
const taskHubItems: QuickPickItem[] =
91+
taskHubs.map(taskHub => ({ label: taskHub.name }));
92+
93+
const taskHubResult = await actionContext.ui.showQuickPick(
94+
[
95+
noTaskHubItem,
96+
{
97+
kind: QuickPickItemKind.Separator,
98+
label: localize('taskHubSepratorLabel', 'Task Hubs')
99+
},
100+
...taskHubItems
101+
],
102+
{
103+
canPickMany: false,
104+
placeHolder: localize('taskHubSelectionPlaceholder', 'Select a task hub to connect to')
105+
});
106+
107+
if (taskHubResult && taskHubResult !== noTaskHubItem) {
108+
connectionString += `;TaskHub=${taskHubResult.label}`;
109+
}
110+
}
111+
112+
await env.clipboard.writeText(connectionString);
113+
114+
ext.outputChannel.show();
115+
ext.outputChannel.appendLog(localize('schedulerConnectionStringCopiedMessage', 'Connection string copied to clipboard: {0}', connectionString));
116+
}
117+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { type IActionContext } from "@microsoft/vscode-azext-utils";
7+
import { type DurableTaskSchedulerClient } from "../../tree/durableTaskScheduler/DurableTaskSchedulerClient";
8+
import { type DurableTaskSchedulerResourceModel } from "../../tree/durableTaskScheduler/DurableTaskSchedulerResourceModel";
9+
import { localize } from "../../localize";
10+
import { ext } from "../../extensionVariables";
11+
import { env } from "vscode";
12+
13+
export function copySchedulerEndpointCommandFactory(schedulerClient: DurableTaskSchedulerClient) {
14+
return async (_: IActionContext, scheduler: DurableTaskSchedulerResourceModel | undefined): Promise<void> => {
15+
if (!scheduler) {
16+
throw new Error(localize('noSchedulerSelectedErrorMessage', 'No scheduler was selected.'));
17+
}
18+
19+
const schedulerJson = await schedulerClient.getScheduler(
20+
scheduler.subscription,
21+
scheduler.resourceGroup,
22+
scheduler.name);
23+
24+
if (!schedulerJson) {
25+
throw new Error(localize('schedulerNotFoundErrorMessage', 'Scheduler does not exist.'));
26+
}
27+
28+
const { endpoint } = schedulerJson.properties;
29+
30+
await env.clipboard.writeText(endpoint);
31+
32+
ext.outputChannel.show();
33+
ext.outputChannel.appendLog(localize('schedulerEndpointCopiedMessage', 'Endpoint copied to clipboard: {0}', endpoint));
34+
}
35+
}

0 commit comments

Comments
 (0)