From db845754c61f0f3f6cc3060748c5c3a936fd54f2 Mon Sep 17 00:00:00 2001 From: Charles Gagnon Date: Thu, 28 Jan 2021 17:19:08 -0800 Subject: [PATCH] Add resource deployment filtering by option values (#14101) * Add resource deployment filtering by option values * Fix compile error --- .../controllerDashboardOverviewPage.ts | 2 +- extensions/resource-deployment/src/main.ts | 19 +++++++++++++------ .../src/services/resourceTypeService.ts | 13 ++++++++++--- .../src/ui/resourceTypePickerDialog.ts | 7 ++++--- .../src/ui/resourceTypeWizard.ts | 8 +++++--- .../src/ui/toolsAndEulaSettingsPage.ts | 14 +++++++++++--- 6 files changed, 44 insertions(+), 19 deletions(-) diff --git a/extensions/arc/src/ui/dashboards/controller/controllerDashboardOverviewPage.ts b/extensions/arc/src/ui/dashboards/controller/controllerDashboardOverviewPage.ts index ed68d7abad..72d62f2e95 100644 --- a/extensions/arc/src/ui/dashboards/controller/controllerDashboardOverviewPage.ts +++ b/extensions/arc/src/ui/dashboards/controller/controllerDashboardOverviewPage.ts @@ -147,7 +147,7 @@ export class ControllerDashboardOverviewPage extends DashboardPage { this.disposables.push( newInstance.onDidClick(async () => { - await vscode.commands.executeCommand('azdata.resource.deploy', 'arc.sql', ['arc.sql', 'arc.postgres']); + await vscode.commands.executeCommand('azdata.resource.deploy', 'azure-sql-mi', ['azure-sql-mi', 'arc.postgres'], { 'azure-sql-mi': { 'mi-type': ['arc-mi'] } }); })); // Refresh diff --git a/extensions/resource-deployment/src/main.ts b/extensions/resource-deployment/src/main.ts index cfb60dc5e2..cc2421ac5c 100644 --- a/extensions/resource-deployment/src/main.ts +++ b/extensions/resource-deployment/src/main.ts @@ -8,7 +8,7 @@ import * as nls from 'vscode-nls'; import { NotebookBasedDialogInfo } from './interfaces'; import { NotebookService } from './services/notebookService'; import { PlatformService } from './services/platformService'; -import { ResourceTypeService } from './services/resourceTypeService'; +import { OptionValuesFilter, ResourceTypeService } from './services/resourceTypeService'; import { ToolsService } from './services/toolsService'; import { DeploymentInputDialog } from './ui/deploymentInputDialog'; import { ResourceTypePickerDialog } from './ui/resourceTypePickerDialog'; @@ -37,12 +37,12 @@ export async function activate(context: vscode.ExtensionContext): Promise { + const openDialog = (defaultResourceTypeName: string, resourceTypeNameFilters?: string[], optionValuesFilter?: OptionValuesFilter) => { const defaultResourceType = resourceTypes.find(resourceType => resourceType.name === defaultResourceTypeName); if (!defaultResourceType) { vscode.window.showErrorMessage(localize('resourceDeployment.UnknownResourceType', "The resource type: {0} is not defined", defaultResourceTypeName)); } else { - const dialog = new ResourceTypePickerDialog(resourceTypeService, defaultResourceType, resourceTypeNameFilters); + const dialog = new ResourceTypePickerDialog(resourceTypeService, defaultResourceType, resourceTypeNameFilters, optionValuesFilter); dialog.open(); } }; @@ -53,14 +53,21 @@ export async function activate(context: vscode.ExtensionContext): Promise { openDialog('sql-bdc'); }); - vscode.commands.registerCommand('azdata.resource.deploy', (defaultResourceTypeName?: string, resourceTypeNameFilters?: string[]) => { + /** + * Command to open the Resource Deployment wizard - with options to filter the values shown + * @param defaultResourceTypeName - The default resourceType to be selected + * @param resourceTypeNameFilters - The list of resourceTypes to show in the wizard + * @param optionValuesFilter - The list of resourceType option values to show in the wizard. This is an object in the format + * { "resource-type-name": { "option-name": ["option-value-1", "option-value-2"] } } + */ + vscode.commands.registerCommand('azdata.resource.deploy', (defaultResourceTypeName?: string, resourceTypeNameFilters?: string[], optionValuesFilter?: OptionValuesFilter) => { if ((resourceTypeNameFilters && !Array.isArray(resourceTypeNameFilters) || (resourceTypeNameFilters && resourceTypeNameFilters.length > 0 && typeof resourceTypeNameFilters[0] !== 'string'))) { throw new Error('resourceTypeNameFilters must either be undefined or an array of strings'); } if (typeof defaultResourceTypeName === 'string') { - openDialog(defaultResourceTypeName, resourceTypeNameFilters); + openDialog(defaultResourceTypeName, resourceTypeNameFilters, optionValuesFilter); } else { let defaultDeploymentType: string; if (platformService.platform() === 'win32') { @@ -68,7 +75,7 @@ export async function activate(context: vscode.ExtensionContext): Promise { diff --git a/extensions/resource-deployment/src/services/resourceTypeService.ts b/extensions/resource-deployment/src/services/resourceTypeService.ts index c0d5405074..ed0137bedc 100644 --- a/extensions/resource-deployment/src/services/resourceTypeService.ts +++ b/extensions/resource-deployment/src/services/resourceTypeService.ts @@ -21,10 +21,17 @@ import { deepClone } from '../common/utils'; const localize = nls.loadMessageBundle(); +/** + * Used to filter the specific optionValues that the deployment wizard shows + */ +export interface OptionValuesFilter { + [key: string]: Record +} + export interface IResourceTypeService { getResourceTypes(filterByPlatform?: boolean): ResourceType[]; validateResourceTypes(resourceTypes: ResourceType[]): string[]; - startDeployment(resourceType: ResourceType): void; + startDeployment(resourceType: ResourceType, optionValuesFilter?: OptionValuesFilter): void; } export class ResourceTypeService implements IResourceTypeService { @@ -301,8 +308,8 @@ export class ResourceTypeService implements IResourceTypeService { return undefined; } - public startDeployment(resourceType: ResourceType): void { - const wizard = new ResourceTypeWizard(resourceType, new KubeService(), new AzdataService(this.platformService), this.notebookService, this.toolsService, this.platformService, this); + public startDeployment(resourceType: ResourceType, optionValuesFilter?: OptionValuesFilter): void { + const wizard = new ResourceTypeWizard(resourceType, new KubeService(), new AzdataService(this.platformService), this.notebookService, this.toolsService, this.platformService, this, optionValuesFilter); wizard.open(); } diff --git a/extensions/resource-deployment/src/ui/resourceTypePickerDialog.ts b/extensions/resource-deployment/src/ui/resourceTypePickerDialog.ts index 9f6ab7e66f..639353ef40 100644 --- a/extensions/resource-deployment/src/ui/resourceTypePickerDialog.ts +++ b/extensions/resource-deployment/src/ui/resourceTypePickerDialog.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode'; import * as azdata from 'azdata'; import * as nls from 'vscode-nls'; import { ResourceType } from '../interfaces'; -import { IResourceTypeService } from '../services/resourceTypeService'; +import { IResourceTypeService, OptionValuesFilter } from '../services/resourceTypeService'; import * as loc from './../localizedConstants'; import { DialogBase } from './dialogBase'; import * as constants from '../constants'; @@ -27,7 +27,8 @@ export class ResourceTypePickerDialog extends DialogBase { constructor( private resourceTypeService: IResourceTypeService, defaultResourceType: ResourceType, - private _resourceTypeNameFilters?: string[]) { + private _resourceTypeNameFilters?: string[], + private _optionValuesFilter?: OptionValuesFilter) { super(loc.resourceTypePickerDialogTitle, 'ResourceTypePickerDialog', true); this._selectedResourceType = defaultResourceType; this._dialogObject.okButton.label = loc.select; @@ -188,7 +189,7 @@ export class ResourceTypePickerDialog extends DialogBase { } protected async onComplete(): Promise { - this.resourceTypeService.startDeployment(this._selectedResourceType); + this.resourceTypeService.startDeployment(this._selectedResourceType, this._optionValuesFilter); } private getAllResourceTags(): string[] { diff --git a/extensions/resource-deployment/src/ui/resourceTypeWizard.ts b/extensions/resource-deployment/src/ui/resourceTypeWizard.ts index 52590fc3d7..86c687b4bf 100644 --- a/extensions/resource-deployment/src/ui/resourceTypeWizard.ts +++ b/extensions/resource-deployment/src/ui/resourceTypeWizard.ts @@ -19,7 +19,7 @@ import { ResourceTypePage } from './resourceTypePage'; import { NotebookWizardModel } from './notebookWizard/notebookWizardModel'; import { DeployAzureSQLDBWizardModel } from './deployAzureSQLDBWizard/deployAzureSQLDBWizardModel'; import { ToolsAndEulaPage } from './toolsAndEulaSettingsPage'; -import { ResourceTypeService } from '../services/resourceTypeService'; +import { OptionValuesFilter, ResourceTypeService } from '../services/resourceTypeService'; import { PageLessDeploymentModel } from './pageLessDeploymentModel'; export class ResourceTypeWizard { @@ -58,7 +58,8 @@ export class ResourceTypeWizard { public notebookService: INotebookService, public toolsService: IToolsService, public platformService: IPlatformService, - public resourceTypeService: ResourceTypeService) { + public resourceTypeService: ResourceTypeService, + private _optionValuesFilter?: OptionValuesFilter) { /** * Setting the first provider from the first value of the dropdowns. * If there are no options (dropdowns) then the resource type has only one provider which is set as default here. @@ -93,6 +94,7 @@ export class ResourceTypeWizard { })); this.toDispose.push(this.wizardObject.doneButton.onClick(async () => { + // TODO - Don't close this when the button is clicked, set up a page validator instead await this._model.onOk(); this.dispose(); })); @@ -144,7 +146,7 @@ export class ResourceTypeWizard { } public setPages(pages: ResourceTypePage[]) { - pages.unshift(new ToolsAndEulaPage(this)); + pages.unshift(new ToolsAndEulaPage(this, this._optionValuesFilter)); this.wizardObject!.pages = pages.map(p => p.pageObject); this.pages = pages; this.pages.forEach((page) => { diff --git a/extensions/resource-deployment/src/ui/toolsAndEulaSettingsPage.ts b/extensions/resource-deployment/src/ui/toolsAndEulaSettingsPage.ts index 872c6626ee..17e0a3fc86 100644 --- a/extensions/resource-deployment/src/ui/toolsAndEulaSettingsPage.ts +++ b/extensions/resource-deployment/src/ui/toolsAndEulaSettingsPage.ts @@ -13,6 +13,7 @@ import { IToolsService } from '../services/toolsService'; import { getErrorMessage } from '../common/utils'; import { ResourceTypePage } from './resourceTypePage'; import { ResourceTypeWizard } from './resourceTypeWizard'; +import { OptionValuesFilter as OptionValuesFilter } from '../services/resourceTypeService'; const localize = nls.loadMessageBundle(); @@ -41,7 +42,7 @@ export class ToolsAndEulaPage extends ResourceTypePage { return this.wizard.toolsService; } - constructor(wizard: ResourceTypeWizard) { + constructor(wizard: ResourceTypeWizard, private optionValuesFilter?: OptionValuesFilter) { super(localize('notebookWizard.toolsAndEulaPageTitle', "Deployment pre-requisites"), '', wizard); this._resourceType = wizard.resourceType; } @@ -192,19 +193,25 @@ export class ToolsAndEulaPage extends ResourceTypePage { }).component(); this._optionsContainer.addItem(optionsTitle); this._resourceType.options.forEach((option, index) => { + let optionValues = option.values; + const optionValueFilter = this.optionValuesFilter?.[this._resourceType.name]?.[option.name]; + if (optionValueFilter) { + optionValues = optionValues.filter(optionValue => optionValueFilter.includes(optionValue.name)); + } const optionLabel = this.view.modelBuilder.text().withProperties({ value: option.displayName, }).component(); optionLabel.width = '150px'; - const optionSelectedValue = (this.wizard.toolsEulaPagePresets) ? this.wizard.toolsEulaPagePresets[index] : option.values[0]; + const optionSelectedValue = (this.wizard.toolsEulaPagePresets) ? this.wizard.toolsEulaPagePresets[index] : optionValues[0]; const optionSelectBox = this.view.modelBuilder.dropDown().withProperties({ - values: option.values, + values: optionValues, value: optionSelectedValue, width: '300px', ariaLabel: option.displayName }).component(); + resourceTypeOptions.push(optionSelectedValue); this.wizard.registerDisposable(optionSelectBox.onValueChanged(async () => { @@ -216,6 +223,7 @@ export class ToolsAndEulaPage extends ResourceTypePage { })); this._optionDropDownMap.set(option.name, optionSelectBox); + this.wizard.provider = this.getCurrentProvider(); const row = this.view.modelBuilder.flexContainer().withItems([optionLabel, optionSelectBox], { flex: '0 0 auto', CSSStyles: { 'margin-right': '20px' } }).withLayout({ flexFlow: 'row', alignItems: 'center' }).component(); this._optionsContainer.addItem(row); });