diff --git a/extensions/resource-deployment/src/services/resourceTypeService.ts b/extensions/resource-deployment/src/services/resourceTypeService.ts index 07c7f39b98..e2430b7b5a 100644 --- a/extensions/resource-deployment/src/services/resourceTypeService.ts +++ b/extensions/resource-deployment/src/services/resourceTypeService.ts @@ -13,7 +13,6 @@ import * as nls from 'vscode-nls'; import { DeploymentProvider, instanceOfAzureSQLVMDeploymentProvider, instanceOfAzureSQLDBDeploymentProvider, instanceOfCommandDeploymentProvider, instanceOfDialogDeploymentProvider, instanceOfDownloadDeploymentProvider, instanceOfNotebookBasedDialogInfo, instanceOfNotebookDeploymentProvider, instanceOfNotebookWizardDeploymentProvider, instanceOfWebPageDeploymentProvider, instanceOfWizardDeploymentProvider, NotebookInfo, NotebookPathInfo, ResourceType, ResourceTypeOption } from '../interfaces'; import { DeployAzureSQLVMWizard } from '../ui/deployAzureSQLVMWizard/deployAzureSQLVMWizard'; import { DeployAzureSQLDBWizard } from '../ui/deployAzureSQLDBWizard/deployAzureSQLDBWizard'; -import { DeployClusterWizard } from '../ui/deployClusterWizard/deployClusterWizard'; import { DeploymentInputDialog } from '../ui/deploymentInputDialog'; import { NotebookWizard } from '../ui/notebookWizard/notebookWizard'; import { AzdataService } from './azdataService'; @@ -22,13 +21,14 @@ import { INotebookService } from './notebookService'; import { IPlatformService } from './platformService'; import { IToolsService } from './toolsService'; import * as loc from './../localizedConstants'; +import { ResourceTypeWizard } from '../ui/resourceTypeWizard'; const localize = nls.loadMessageBundle(); export interface IResourceTypeService { getResourceTypes(filterByPlatform?: boolean): ResourceType[]; validateResourceTypes(resourceTypes: ResourceType[]): string[]; - startDeployment(provider: DeploymentProvider): void; + startDeployment(resourceType: ResourceType, provider: DeploymentProvider): void; } export class ResourceTypeService implements IResourceTypeService { @@ -251,10 +251,10 @@ export class ResourceTypeService implements IResourceTypeService { } - public startDeployment(provider: DeploymentProvider): void { + public startDeployment(resourceType: ResourceType, provider: DeploymentProvider): void { const self = this; if (instanceOfWizardDeploymentProvider(provider)) { - const wizard = new DeployClusterWizard(provider.bdcWizard, new KubeService(), new AzdataService(this.platformService), this.notebookService, this.toolsService); + const wizard = new ResourceTypeWizard(resourceType, provider, new KubeService(), new AzdataService(this.platformService), this.notebookService, this.toolsService, this.platformService); wizard.open(); } else if (instanceOfNotebookWizardDeploymentProvider(provider)) { const wizard = new NotebookWizard(provider.notebookWizard, this.notebookService, this.platformService, this.toolsService); diff --git a/extensions/resource-deployment/src/ui/deployClusterWizard/deployClusterWizard.ts b/extensions/resource-deployment/src/ui/deployClusterWizard/deployClusterWizard.ts deleted file mode 100644 index 6879c3e864..0000000000 --- a/extensions/resource-deployment/src/ui/deployClusterWizard/deployClusterWizard.ts +++ /dev/null @@ -1,178 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as azdata from 'azdata'; -import * as fs from 'fs'; -import * as os from 'os'; -import { join } from 'path'; -import * as vscode from 'vscode'; -import * as nls from 'vscode-nls'; -import { BdcDeploymentType, BdcWizardInfo } from '../../interfaces'; -import { IAzdataService } from '../../services/azdataService'; -import { IKubeService } from '../../services/kubeService'; -import { INotebookService } from '../../services/notebookService'; -import { IToolsService } from '../../services/toolsService'; -import { getErrorMessage } from '../../common/utils'; -import { InputComponents } from '../modelViewUtils'; -import { WizardBase } from '../wizardBase'; -import { WizardPageBase } from '../wizardPageBase'; -import * as VariableNames from './constants'; -import { AuthenticationMode, DeployClusterWizardModel } from './deployClusterWizardModel'; -import { AzureSettingsPage } from './pages/azureSettingsPage'; -import { ClusterSettingsPage } from './pages/clusterSettingsPage'; -import { DeploymentProfilePage } from './pages/deploymentProfilePage'; -import { ServiceSettingsPage } from './pages/serviceSettingsPage'; -import { SummaryPage } from './pages/summaryPage'; -import { TargetClusterContextPage } from './pages/targetClusterPage'; -const localize = nls.loadMessageBundle(); - -export class DeployClusterWizard extends WizardBase, DeployClusterWizardModel> { - private _inputComponents: InputComponents = {}; - - private _saveConfigButton: azdata.window.Button; - - public get kubeService(): IKubeService { - return this._kubeService; - } - - public get azdataService(): IAzdataService { - return this._azdataService; - } - - public get notebookService(): INotebookService { - return this._notebookService; - } - - public get inputComponents(): InputComponents { - return this._inputComponents; - } - - public showCustomButtons(): void { - this._saveConfigButton.hidden = false; - } - - public hideCustomButtons(): void { - this._saveConfigButton.hidden = true; - } - - constructor(private wizardInfo: BdcWizardInfo, private _kubeService: IKubeService, private _azdataService: IAzdataService, private _notebookService: INotebookService, toolsService: IToolsService) { - super(DeployClusterWizard.getTitle(wizardInfo.type), 'DeployBdcClusterWizard', new DeployClusterWizardModel(wizardInfo.type), toolsService); - this._saveConfigButton = azdata.window.createButton(localize('deployCluster.SaveConfigFiles', "Save config files"), 'left'); - this._saveConfigButton.hidden = true; - this.addButton(this._saveConfigButton); - this.registerDisposable(this._saveConfigButton.onClick(() => this.saveConfigFiles())); - } - - public get deploymentType(): BdcDeploymentType { - return this.wizardInfo.type; - } - - protected initialize(): void { - this.setPages(this.getPages()); - this.wizardObject.generateScriptButton.hidden = true; - this.wizardObject.doneButton.label = localize('deployCluster.ScriptToNotebook', "Script to Notebook"); - } - - protected onCancel(): void { - } - - protected async onOk(): Promise { - await this.scriptToNotebook(); - } - - private getPages(): WizardPageBase[] { - const pages: WizardPageBase[] = []; - switch (this.deploymentType) { - case BdcDeploymentType.NewAKS: - pages.push( - new DeploymentProfilePage(this), - new AzureSettingsPage(this), - new ClusterSettingsPage(this), - new ServiceSettingsPage(this), - new SummaryPage(this)); - break; - case BdcDeploymentType.ExistingAKS: - case BdcDeploymentType.ExistingKubeAdm: - case BdcDeploymentType.ExistingARO: - case BdcDeploymentType.ExistingOpenShift: - pages.push( - new DeploymentProfilePage(this), - new TargetClusterContextPage(this), - new ClusterSettingsPage(this), - new ServiceSettingsPage(this), - new SummaryPage(this)); - break; - default: - throw new Error(`Unknown deployment type: ${this.deploymentType}`); - } - return pages; - } - - private async saveConfigFiles(): Promise { - const options: vscode.OpenDialogOptions = { - defaultUri: vscode.Uri.file(os.homedir()), - canSelectFiles: false, - canSelectFolders: true, - canSelectMany: false, - openLabel: localize('deployCluster.SelectConfigFileFolder', "Save config files") - }; - const pathArray = await vscode.window.showOpenDialog(options); - if (pathArray && pathArray[0]) { - const targetFolder = pathArray[0].fsPath; - try { - const profile = this.model.createTargetProfile(); - await fs.promises.writeFile(join(targetFolder, 'bdc.json'), profile.getBdcJson()); - await fs.promises.writeFile(join(targetFolder, 'control.json'), profile.getControlJson()); - this.wizardObject.message = { - text: localize('deployCluster.SaveConfigFileSucceeded', "Config files saved to {0}", targetFolder), - level: azdata.window.MessageLevel.Information - }; - } - catch (error) { - this.wizardObject.message = { - text: error.message, - level: azdata.window.MessageLevel.Error - }; - } - } - } - - private async scriptToNotebook(): Promise { - this.setEnvironmentVariables(process.env); - const variableValueStatements = this.model.getCodeCellContentForNotebook(this.toolsService.toolsForCurrentProvider); - const insertionPosition = 5; // Cell number 5 is the position where the python variable setting statements need to be inserted in this.wizardInfo.notebook. - try { - await this.notebookService.openNotebookWithEdits(this.wizardInfo.notebook, variableValueStatements, insertionPosition); - } catch (error) { - vscode.window.showErrorMessage(getErrorMessage(error)); - } - } - - private setEnvironmentVariables(env: NodeJS.ProcessEnv): void { - env[VariableNames.AdminPassword_VariableName] = this.model.getStringValue(VariableNames.AdminPassword_VariableName); - env[VariableNames.DockerPassword_VariableName] = this.model.getStringValue(VariableNames.DockerPassword_VariableName); - if (this.model.authenticationMode === AuthenticationMode.ActiveDirectory) { - env[VariableNames.DomainServiceAccountPassword_VariableName] = this.model.getStringValue(VariableNames.DomainServiceAccountPassword_VariableName); - } - } - - static getTitle(type: BdcDeploymentType): string { - switch (type) { - case BdcDeploymentType.NewAKS: - return localize('deployCluster.NewAKSWizardTitle', "Deploy SQL Server 2019 Big Data Cluster on a new AKS cluster"); - case BdcDeploymentType.ExistingAKS: - return localize('deployCluster.ExistingAKSWizardTitle', "Deploy SQL Server 2019 Big Data Cluster on an existing AKS cluster"); - case BdcDeploymentType.ExistingKubeAdm: - return localize('deployCluster.ExistingKubeAdm', "Deploy SQL Server 2019 Big Data Cluster on an existing kubeadm cluster"); - case BdcDeploymentType.ExistingARO: - return localize('deployCluster.ExistingARO', "Deploy SQL Server 2019 Big Data Cluster on an existing Azure Red Hat OpenShift cluster"); - case BdcDeploymentType.ExistingOpenShift: - return localize('deployCluster.ExistingOpenShift', "Deploy SQL Server 2019 Big Data Cluster on an existing OpenShift cluster"); - - default: - throw new Error(`Unknown deployment type: ${type}`); - } - } -} diff --git a/extensions/resource-deployment/src/ui/deployClusterWizard/deployClusterWizardModel.ts b/extensions/resource-deployment/src/ui/deployClusterWizard/deployClusterWizardModel.ts index 6e973712e3..7ea4bd62ff 100644 --- a/extensions/resource-deployment/src/ui/deployClusterWizard/deployClusterWizardModel.ts +++ b/extensions/resource-deployment/src/ui/deployClusterWizard/deployClusterWizardModel.ts @@ -2,19 +2,93 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { EOL } from 'os'; -import { delimiter } from 'path'; -import { BdcDeploymentType, ITool } from '../../interfaces'; +import * as azdata from 'azdata'; +import * as vscode from 'vscode'; +import { delimiter, join } from 'path'; +import * as fs from 'fs'; +import * as os from 'os'; +import { BdcDeploymentType, BdcWizardDeploymentProvider, ITool } from '../../interfaces'; import { BigDataClusterDeploymentProfile, DataResource, HdfsResource, SqlServerMasterResource } from '../../services/bigDataClusterDeploymentProfile'; import { KubeCtlToolName } from '../../services/tools/kubeCtlTool'; -import { getRuntimeBinaryPathEnvironmentVariableName, setEnvironmentVariablesForInstallPaths } from '../../common/utils'; -import { Model } from '../model'; -import { ToolsInstallPath } from './../../constants'; +import { getErrorMessage, getRuntimeBinaryPathEnvironmentVariableName, setEnvironmentVariablesForInstallPaths } from '../../common/utils'; +import { ToolsInstallPath } from '../../constants'; import * as VariableNames from './constants'; +import { ResourceTypeModel, ResourceTypePage, ResourceTypeWizard } from '../resourceTypeWizard'; +import * as nls from 'vscode-nls'; +import { InputComponents } from '../modelViewUtils'; +import { INotebookService } from '../../services/notebookService'; +import { IAzdataService } from '../../services/azdataService'; +import { IKubeService } from '../../services/kubeService'; +import { DeploymentProfilePage } from './pages/deploymentProfilePage'; +import { AzureSettingsPage } from './pages/azureSettingsPage'; +import { ClusterSettingsPage } from './pages/clusterSettingsPage'; +import { ServiceSettingsPage } from './pages/serviceSettingsPage'; +import { SummaryPage } from './pages/summaryPage'; +import { TargetClusterContextPage } from './pages/targetClusterPage'; +import { IToolsService } from '../../services/toolsService'; +const localize = nls.loadMessageBundle(); -export class DeployClusterWizardModel extends Model { - constructor(public deploymentTarget: BdcDeploymentType) { - super(); +export class DeployClusterWizardModel extends ResourceTypeModel { + private _inputComponents: InputComponents = {}; + private _kubeService: IKubeService; + private _azdataService: IAzdataService; + private _notebookService: INotebookService; + private toolsService: IToolsService; + + private _saveConfigButton: azdata.window.Button; + + public get kubeService(): IKubeService { + return this._kubeService; + } + + public get azdataService(): IAzdataService { + return this._azdataService; + } + + public get notebookService(): INotebookService { + return this._notebookService; + } + + public get inputComponents(): InputComponents { + return this._inputComponents; + } + + public showCustomButtons(): void { + this._saveConfigButton.hidden = false; + } + + public hideCustomButtons(): void { + this._saveConfigButton.hidden = true; + } + + + public get deploymentType(): BdcDeploymentType { + return this.bdcProvider.bdcWizard.type; + } + + initialize(): void { + this.wizard.setPages(this.getPages()); + this.wizard.wizardObject.generateScriptButton.hidden = true; + this.wizard.wizardObject.doneButton.label = localize('deployCluster.ScriptToNotebook', "Script to Notebook"); + } + + async onOk(): Promise { + await this.scriptToNotebook(); + } + + onCancel(): void { } + + constructor(public bdcProvider: BdcWizardDeploymentProvider, wizard: ResourceTypeWizard) { + super(bdcProvider, wizard); + this._kubeService = this.wizard._kubeService; + this._azdataService = this.wizard.azdataService; + this._notebookService = this.wizard.notebookService; + this.toolsService = this.wizard.toolsService; + this.wizard.wizardObject.title = this.getTitle(this.deploymentType); + this._saveConfigButton = azdata.window.createButton(localize('deployCluster.SaveConfigFiles', "Save config files"), 'left'); + this._saveConfigButton.hidden = true; + this.wizard.addButton(this._saveConfigButton); + this.wizard.registerDisposable(this._saveConfigButton.onClick(() => this.saveConfigFiles())); } public adAuthSupported: boolean = false; @@ -144,17 +218,17 @@ export class DeployClusterWizardModel extends Model { public getCodeCellContentForNotebook(tools: ITool[]): string[] { const profile = this.createTargetProfile(); const statements: string[] = []; - if (this.deploymentTarget === BdcDeploymentType.NewAKS) { + if (this.deploymentType === BdcDeploymentType.NewAKS) { statements.push(`azure_subscription_id = '${this.getStringValue(VariableNames.SubscriptionId_VariableName, '')}'`); statements.push(`azure_region = '${this.getStringValue(VariableNames.Location_VariableName)}'`); statements.push(`azure_resource_group = '${this.getStringValue(VariableNames.ResourceGroup_VariableName)}'`); statements.push(`azure_vm_size = '${this.getStringValue(VariableNames.VMSize_VariableName)}'`); statements.push(`azure_vm_count = '${this.getStringValue(VariableNames.VMCount_VariableName)}'`); statements.push(`aks_cluster_name = '${this.getStringValue(VariableNames.AksName_VariableName)}'`); - } else if (this.deploymentTarget === BdcDeploymentType.ExistingAKS - || this.deploymentTarget === BdcDeploymentType.ExistingKubeAdm - || this.deploymentTarget === BdcDeploymentType.ExistingARO - || this.deploymentTarget === BdcDeploymentType.ExistingOpenShift) { + } else if (this.deploymentType === BdcDeploymentType.ExistingAKS + || this.deploymentType === BdcDeploymentType.ExistingKubeAdm + || this.deploymentType === BdcDeploymentType.ExistingARO + || this.deploymentType === BdcDeploymentType.ExistingOpenShift) { statements.push(`mssql_kube_config_path = '${this.escapeForNotebookCodeCell(this.getStringValue(VariableNames.KubeConfigPath_VariableName)!)}'`); statements.push(`mssql_cluster_context = '${this.getStringValue(VariableNames.ClusterContext_VariableName)}'`); statements.push('os.environ["KUBECONFIG"] = mssql_kube_config_path'); @@ -177,7 +251,102 @@ export class DeployClusterWizardModel extends Model { statements.push(`os.environ["${kubeCtlEnvVarName}"] = "${this.escapeForNotebookCodeCell(env[kubeCtlEnvVarName]!)}"`); statements.push(`os.environ["PATH"] = os.environ["PATH"] + "${delimiter}" + "${this.escapeForNotebookCodeCell(env[ToolsInstallPath]!)}"`); statements.push(`print('Variables have been set successfully.')`); - return statements.map(line => line + EOL); + return statements.map(line => line + os.EOL); + } + + private async saveConfigFiles(): Promise { + const options: vscode.OpenDialogOptions = { + defaultUri: vscode.Uri.file(os.homedir()), + canSelectFiles: false, + canSelectFolders: true, + canSelectMany: false, + openLabel: localize('deployCluster.SelectConfigFileFolder', "Save config files") + }; + const pathArray = await vscode.window.showOpenDialog(options); + if (pathArray && pathArray[0]) { + const targetFolder = pathArray[0].fsPath; + try { + const profile = this.createTargetProfile(); + await fs.promises.writeFile(join(targetFolder, 'bdc.json'), profile.getBdcJson()); + await fs.promises.writeFile(join(targetFolder, 'control.json'), profile.getControlJson()); + this.wizard.wizardObject.message = { + text: localize('deployCluster.SaveConfigFileSucceeded', "Config files saved to {0}", targetFolder), + level: azdata.window.MessageLevel.Information + }; + } + catch (error) { + this.wizard.wizardObject.message = { + text: error.message, + level: azdata.window.MessageLevel.Error + }; + } + } + } + + private getPages(): ResourceTypePage[] { + const pages: ResourceTypePage[] = []; + switch (this.deploymentType) { + case BdcDeploymentType.NewAKS: + pages.push( + new DeploymentProfilePage(this), + new AzureSettingsPage(this), + new ClusterSettingsPage(this), + new ServiceSettingsPage(this), + new SummaryPage(this)); + break; + case BdcDeploymentType.ExistingAKS: + case BdcDeploymentType.ExistingKubeAdm: + case BdcDeploymentType.ExistingARO: + case BdcDeploymentType.ExistingOpenShift: + pages.push( + new DeploymentProfilePage(this), + new TargetClusterContextPage(this), + new ClusterSettingsPage(this), + new ServiceSettingsPage(this), + new SummaryPage(this)); + break; + default: + throw new Error(`Unknown deployment type: ${this.deploymentType}`); + } + return pages; + } + + private async scriptToNotebook(): Promise { + this.setNotebookEnvironmentVariables(process.env); + const variableValueStatements = this.getCodeCellContentForNotebook(this.toolsService.toolsForCurrentProvider); + const insertionPosition = 5; // Cell number 5 is the position where the python variable setting statements need to be inserted in this.wizardInfo.notebook. + try { + await this.notebookService.openNotebookWithEdits(this.bdcProvider.bdcWizard.notebook, variableValueStatements, insertionPosition); + } catch (error) { + vscode.window.showErrorMessage(getErrorMessage(error)); + } + } + + + private setNotebookEnvironmentVariables(env: NodeJS.ProcessEnv): void { + env[VariableNames.AdminPassword_VariableName] = this.getStringValue(VariableNames.AdminPassword_VariableName); + env[VariableNames.DockerPassword_VariableName] = this.getStringValue(VariableNames.DockerPassword_VariableName); + if (this.authenticationMode === AuthenticationMode.ActiveDirectory) { + env[VariableNames.DomainServiceAccountPassword_VariableName] = this.getStringValue(VariableNames.DomainServiceAccountPassword_VariableName); + } + } + + private getTitle(type: BdcDeploymentType): string { + switch (type) { + case BdcDeploymentType.NewAKS: + return localize('deployCluster.NewAKSWizardTitle', "Deploy SQL Server 2019 Big Data Cluster on a new AKS cluster"); + case BdcDeploymentType.ExistingAKS: + return localize('deployCluster.ExistingAKSWizardTitle', "Deploy SQL Server 2019 Big Data Cluster on an existing AKS cluster"); + case BdcDeploymentType.ExistingKubeAdm: + return localize('deployCluster.ExistingKubeAdm', "Deploy SQL Server 2019 Big Data Cluster on an existing kubeadm cluster"); + case BdcDeploymentType.ExistingARO: + return localize('deployCluster.ExistingARO', "Deploy SQL Server 2019 Big Data Cluster on an existing Azure Red Hat OpenShift cluster"); + case BdcDeploymentType.ExistingOpenShift: + return localize('deployCluster.ExistingOpenShift', "Deploy SQL Server 2019 Big Data Cluster on an existing OpenShift cluster"); + + default: + throw new Error(`Unknown deployment type: ${type}`); + } } } diff --git a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/azureSettingsPage.ts b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/azureSettingsPage.ts index 05e3aa936b..cf880ee270 100644 --- a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/azureSettingsPage.ts +++ b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/azureSettingsPage.ts @@ -8,19 +8,19 @@ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; import { FieldType, LabelPosition, SectionInfo } from '../../../interfaces'; import { createSection, getDropdownComponent, InputComponentInfo, InputComponents, setModelValues, Validator } from '../../modelViewUtils'; -import { WizardPageBase } from '../../wizardPageBase'; import { AksName_VariableName, Location_VariableName, ResourceGroup_VariableName, SubscriptionId_VariableName, VMCount_VariableName, VMSize_VariableName } from '../constants'; -import { DeployClusterWizard } from '../deployClusterWizard'; import { AzureRegion } from 'azurecore'; +import { DeployClusterWizardModel } from '../deployClusterWizardModel'; +import { ResourceTypePage } from '../../resourceTypeWizard'; const localize = nls.loadMessageBundle(); const MissingRequiredInformationErrorMessage = localize('deployCluster.MissingRequiredInfoError', "Please fill out the required fields marked with red asterisks."); -export class AzureSettingsPage extends WizardPageBase { +export class AzureSettingsPage extends ResourceTypePage { private inputComponents: InputComponents = {}; - constructor(wizard: DeployClusterWizard) { + constructor(private _model: DeployClusterWizardModel) { super(localize('deployCluster.AzureSettingsPageTitle', "Azure settings"), - localize('deployCluster.AzureSettingsPageDescription', "Configure the settings to create an Azure Kubernetes Service cluster"), wizard); + localize('deployCluster.AzureSettingsPageDescription', "Configure the settings to create an Azure Kubernetes Service cluster"), _model.wizard); } public initialize(): void { @@ -134,13 +134,13 @@ export class AzureSettingsPage extends WizardPageBase { }, onNewInputComponentCreated: (name: string, inputComponentInfo: InputComponentInfo): void => { self.inputComponents[name] = inputComponentInfo; - self.wizard.inputComponents[name] = inputComponentInfo; + self._model.inputComponents[name] = inputComponentInfo; }, onNewValidatorCreated: (validator: Validator): void => { self.validators.push(validator); }, container: this.wizard.wizardObject, - inputComponents: this.wizard.inputComponents, + inputComponents: this._model.inputComponents, toolsService: this.wizard.toolsService }); const formBuilder = view.modelBuilder.formContainer().withFormItems( diff --git a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/clusterSettingsPage.ts b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/clusterSettingsPage.ts index 5d50f6162a..f2fa12fff0 100644 --- a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/clusterSettingsPage.ts +++ b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/clusterSettingsPage.ts @@ -9,24 +9,23 @@ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; import { FieldType, LabelPosition, SectionInfo } from '../../../interfaces'; import { createSection, getInputBoxComponent, getInvalidSQLPasswordMessage, getPasswordMismatchMessage, InputComponentInfo, InputComponents, isValidSQLPassword, setModelValues, Validator } from '../../modelViewUtils'; -import { WizardPageBase } from '../../wizardPageBase'; import * as VariableNames from '../constants'; -import { DeployClusterWizard } from '../deployClusterWizard'; -import { AuthenticationMode } from '../deployClusterWizardModel'; +import { AuthenticationMode, DeployClusterWizardModel } from '../deployClusterWizardModel'; import * as localizedConstants from '../../../localizedConstants'; +import { ResourceTypePage } from '../../resourceTypeWizard'; const localize = nls.loadMessageBundle(); const ConfirmPasswordName = 'ConfirmPassword'; const clusterNameFieldDescription = localize('deployCluster.ClusterNameDescription', "The cluster name must consist only of alphanumeric lowercase characters or '-' and must start and end with an alphanumeric character."); -export class ClusterSettingsPage extends WizardPageBase { +export class ClusterSettingsPage extends ResourceTypePage { private inputComponents: InputComponents = {}; private activeDirectorySection!: azdata.FormComponent; private formBuilder!: azdata.FormBuilder; - constructor(wizard: DeployClusterWizard) { + constructor(private _model: DeployClusterWizardModel) { super(localize('deployCluster.ClusterSettingsPageTitle', "Cluster settings"), - localize('deployCluster.ClusterSettingsPageDescription', "Configure the SQL Server Big Data Cluster settings"), wizard); + localize('deployCluster.ClusterSettingsPageDescription', "Configure the SQL Server Big Data Cluster settings"), _model.wizard); } public initialize(): void { @@ -212,14 +211,14 @@ export class ClusterSettingsPage extends WizardPageBase { const basicSettingsGroup = await createSection({ view: view, container: self.wizard.wizardObject, - inputComponents: this.wizard.inputComponents, + inputComponents: this._model.inputComponents, sectionInfo: basicSection, onNewDisposableCreated: (disposable: vscode.Disposable): void => { self.wizard.registerDisposable(disposable); }, onNewInputComponentCreated: (name: string, inputComponentInfo: InputComponentInfo): void => { self.inputComponents[name] = inputComponentInfo; - self.wizard.inputComponents[name] = inputComponentInfo; + self._model.inputComponents[name] = inputComponentInfo; }, onNewValidatorCreated: (validator: Validator): void => { self.validators.push(validator); @@ -229,14 +228,14 @@ export class ClusterSettingsPage extends WizardPageBase { const activeDirectorySettingsGroup = await createSection({ view: view, container: self.wizard.wizardObject, - inputComponents: this.wizard.inputComponents, + inputComponents: this._model.inputComponents, sectionInfo: activeDirectorySection, onNewDisposableCreated: (disposable: vscode.Disposable): void => { self.wizard.registerDisposable(disposable); }, onNewInputComponentCreated: (name: string, inputComponentInfo: InputComponentInfo): void => { self.inputComponents[name] = inputComponentInfo; - self.wizard.inputComponents[name] = inputComponentInfo; + self._model.inputComponents[name] = inputComponentInfo; }, onNewValidatorCreated: (validator: Validator): void => { self.validators.push(validator); @@ -246,14 +245,14 @@ export class ClusterSettingsPage extends WizardPageBase { const dockerSettingsGroup = await createSection({ view: view, container: self.wizard.wizardObject, - inputComponents: this.wizard.inputComponents, + inputComponents: this._model.inputComponents, sectionInfo: dockerSection, onNewDisposableCreated: (disposable: vscode.Disposable): void => { self.wizard.registerDisposable(disposable); }, onNewInputComponentCreated: (name: string, inputComponentInfo: InputComponentInfo): void => { self.inputComponents[name] = inputComponentInfo; - self.wizard.inputComponents[name] = inputComponentInfo; + self._model.inputComponents[name] = inputComponentInfo; }, onNewValidatorCreated: (validator: Validator): void => { self.validators.push(validator); @@ -294,7 +293,7 @@ export class ClusterSettingsPage extends WizardPageBase { public async onLeave(): Promise { await setModelValues(this.inputComponents, this.wizard.model); - if (this.wizard.model.authenticationMode === AuthenticationMode.ActiveDirectory) { + if (this._model.authenticationMode === AuthenticationMode.ActiveDirectory) { const variableDNSPrefixMapping: { [s: string]: string } = {}; variableDNSPrefixMapping[VariableNames.AppServiceProxyDNSName_VariableName] = 'bdc-appproxy'; variableDNSPrefixMapping[VariableNames.ControllerDNSName_VariableName] = 'bdc-control'; @@ -319,9 +318,9 @@ export class ClusterSettingsPage extends WizardPageBase { getInputBoxComponent(VariableNames.DockerImageTag_VariableName, this.inputComponents).value = this.wizard.model.getStringValue(VariableNames.DockerImageTag_VariableName); const authModeDropdown = this.inputComponents[VariableNames.AuthenticationMode_VariableName].component; if (authModeDropdown) { - authModeDropdown.enabled = this.wizard.model.adAuthSupported; + authModeDropdown.enabled = this._model.adAuthSupported; const adAuthSelected = (authModeDropdown.value).name === 'ad'; - if (!this.wizard.model.adAuthSupported && adAuthSelected) { + if (!this._model.adAuthSupported && adAuthSelected) { this.formBuilder.removeFormItem(this.activeDirectorySection); authModeDropdown.value = { name: AuthenticationMode.Basic, diff --git a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/deploymentProfilePage.ts b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/deploymentProfilePage.ts index 09ded8bc10..9451addd8f 100644 --- a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/deploymentProfilePage.ts +++ b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/deploymentProfilePage.ts @@ -8,9 +8,9 @@ import * as nls from 'vscode-nls'; import { BdcDeploymentType } from '../../../interfaces'; import { BigDataClusterDeploymentProfile } from '../../../services/bigDataClusterDeploymentProfile'; import { createFlexContainer, createLabel } from '../../modelViewUtils'; -import { WizardPageBase } from '../../wizardPageBase'; +import { ResourceTypePage } from '../../resourceTypeWizard'; import * as VariableNames from '../constants'; -import { DeployClusterWizard } from '../deployClusterWizard'; +import { DeployClusterWizardModel } from '../deployClusterWizardModel'; const localize = nls.loadMessageBundle(); const serviceScaleTableTitle = localize('deployCluster.serviceScaleTableTitle', "Service scale settings (Instances)"); @@ -19,13 +19,13 @@ const featureTableTitle = localize('deployCluster.featureTableTitle', "Features" const YesText = localize('deployCluster.yesText', "Yes"); const NoText = localize('deployCluster.noText', "No"); -export class DeploymentProfilePage extends WizardPageBase { +export class DeploymentProfilePage extends ResourceTypePage { private _loadingComponent: azdata.LoadingComponent | undefined; private _container: azdata.FlexContainer | undefined; - constructor(wizard: DeployClusterWizard) { + constructor(private _model: DeployClusterWizardModel) { super(localize('deployCluster.summaryPageTitle', "Deployment configuration profile"), - localize('deployCluster.summaryPageDescription', "Select the target configuration profile"), wizard); + localize('deployCluster.summaryPageDescription', "Select the target configuration profile"), _model.wizard); } public initialize(): void { @@ -59,36 +59,36 @@ export class DeploymentProfilePage extends WizardPageBase { } private setModelValuesByProfile(selectedProfile: BigDataClusterDeploymentProfile): void { - this.wizard.model.setPropertyValue(VariableNames.DeploymentProfile_VariableName, selectedProfile.profileName); - this.wizard.model.setPropertyValue(VariableNames.SparkPoolScale_VariableName, selectedProfile.sparkReplicas); - this.wizard.model.setPropertyValue(VariableNames.DataPoolScale_VariableName, selectedProfile.dataReplicas); - this.wizard.model.setPropertyValue(VariableNames.HDFSPoolScale_VariableName, selectedProfile.hdfsReplicas); - this.wizard.model.setPropertyValue(VariableNames.ComputePoolScale_VariableName, selectedProfile.computeReplicas); - this.wizard.model.setPropertyValue(VariableNames.HDFSNameNodeScale_VariableName, selectedProfile.hdfsNameNodeReplicas); - this.wizard.model.setPropertyValue(VariableNames.SQLServerScale_VariableName, selectedProfile.sqlServerReplicas); - this.wizard.model.setPropertyValue(VariableNames.SparkHeadScale_VariableName, selectedProfile.sparkHeadReplicas); - this.wizard.model.setPropertyValue(VariableNames.ZooKeeperScale_VariableName, selectedProfile.zooKeeperReplicas); - this.wizard.model.setPropertyValue(VariableNames.ControllerDataStorageSize_VariableName, selectedProfile.controllerDataStorageSize); - this.wizard.model.setPropertyValue(VariableNames.ControllerLogsStorageSize_VariableName, selectedProfile.controllerLogsStorageSize); - this.wizard.model.setPropertyValue(VariableNames.SQLServerPort_VariableName, selectedProfile.sqlServerPort); - this.wizard.model.setPropertyValue(VariableNames.GateWayPort_VariableName, selectedProfile.gatewayPort); - this.wizard.model.setPropertyValue(VariableNames.ControllerPort_VariableName, selectedProfile.controllerPort); - this.wizard.model.setPropertyValue(VariableNames.ServiceProxyPort_VariableName, selectedProfile.serviceProxyPort); - this.wizard.model.setPropertyValue(VariableNames.AppServiceProxyPort_VariableName, selectedProfile.appServiceProxyPort); - this.wizard.model.setPropertyValue(VariableNames.IncludeSpark_VariableName, selectedProfile.includeSpark); - this.wizard.model.setPropertyValue(VariableNames.ControllerDataStorageClassName_VariableName, selectedProfile.controllerDataStorageClass); - this.wizard.model.setPropertyValue(VariableNames.ControllerLogsStorageClassName_VariableName, selectedProfile.controllerLogsStorageClass); - this.wizard.model.setPropertyValue(VariableNames.ReadableSecondaryPort_VariableName, selectedProfile.sqlServerReadableSecondaryPort); - this.wizard.model.setPropertyValue(VariableNames.DockerRegistry_VariableName, selectedProfile.registry); - this.wizard.model.setPropertyValue(VariableNames.DockerRepository_VariableName, selectedProfile.repository); - this.wizard.model.setPropertyValue(VariableNames.DockerImageTag_VariableName, selectedProfile.imageTag); - this.wizard.model.adAuthSupported = selectedProfile.activeDirectorySupported; - this.wizard.model.selectedProfile = selectedProfile; + this._model.setPropertyValue(VariableNames.DeploymentProfile_VariableName, selectedProfile.profileName); + this._model.setPropertyValue(VariableNames.SparkPoolScale_VariableName, selectedProfile.sparkReplicas); + this._model.setPropertyValue(VariableNames.DataPoolScale_VariableName, selectedProfile.dataReplicas); + this._model.setPropertyValue(VariableNames.HDFSPoolScale_VariableName, selectedProfile.hdfsReplicas); + this._model.setPropertyValue(VariableNames.ComputePoolScale_VariableName, selectedProfile.computeReplicas); + this._model.setPropertyValue(VariableNames.HDFSNameNodeScale_VariableName, selectedProfile.hdfsNameNodeReplicas); + this._model.setPropertyValue(VariableNames.SQLServerScale_VariableName, selectedProfile.sqlServerReplicas); + this._model.setPropertyValue(VariableNames.SparkHeadScale_VariableName, selectedProfile.sparkHeadReplicas); + this._model.setPropertyValue(VariableNames.ZooKeeperScale_VariableName, selectedProfile.zooKeeperReplicas); + this._model.setPropertyValue(VariableNames.ControllerDataStorageSize_VariableName, selectedProfile.controllerDataStorageSize); + this._model.setPropertyValue(VariableNames.ControllerLogsStorageSize_VariableName, selectedProfile.controllerLogsStorageSize); + this._model.setPropertyValue(VariableNames.SQLServerPort_VariableName, selectedProfile.sqlServerPort); + this._model.setPropertyValue(VariableNames.GateWayPort_VariableName, selectedProfile.gatewayPort); + this._model.setPropertyValue(VariableNames.ControllerPort_VariableName, selectedProfile.controllerPort); + this._model.setPropertyValue(VariableNames.ServiceProxyPort_VariableName, selectedProfile.serviceProxyPort); + this._model.setPropertyValue(VariableNames.AppServiceProxyPort_VariableName, selectedProfile.appServiceProxyPort); + this._model.setPropertyValue(VariableNames.IncludeSpark_VariableName, selectedProfile.includeSpark); + this._model.setPropertyValue(VariableNames.ControllerDataStorageClassName_VariableName, selectedProfile.controllerDataStorageClass); + this._model.setPropertyValue(VariableNames.ControllerLogsStorageClassName_VariableName, selectedProfile.controllerLogsStorageClass); + this._model.setPropertyValue(VariableNames.ReadableSecondaryPort_VariableName, selectedProfile.sqlServerReadableSecondaryPort); + this._model.setPropertyValue(VariableNames.DockerRegistry_VariableName, selectedProfile.registry); + this._model.setPropertyValue(VariableNames.DockerRepository_VariableName, selectedProfile.repository); + this._model.setPropertyValue(VariableNames.DockerImageTag_VariableName, selectedProfile.imageTag); + this._model.adAuthSupported = selectedProfile.activeDirectorySupported; + this._model.selectedProfile = selectedProfile; } private async loadProfiles(view: azdata.ModelView): Promise { try { - const profiles = await this.wizard.azdataService.getDeploymentProfiles(this.wizard.deploymentType); + const profiles = await this.wizard.azdataService.getDeploymentProfiles(this._model.deploymentType); const radioButtonGroup = this.createRadioButtonGroup(view, profiles); const serviceScaleTable = this.createServiceScaleTable(view, profiles); const storageTable = this.createStorageTable(view, profiles); @@ -240,7 +240,7 @@ export class DeploymentProfilePage extends WizardPageBase { } private getDefaultProfile(): string { - switch (this.wizard.deploymentType) { + switch (this._model.deploymentType) { case BdcDeploymentType.NewAKS: case BdcDeploymentType.ExistingAKS: return 'aks-dev-test'; @@ -251,7 +251,7 @@ export class DeploymentProfilePage extends WizardPageBase { case BdcDeploymentType.ExistingOpenShift: return 'openshift-dev-test'; default: - throw new Error(`Unknown deployment type: ${this.wizard.deploymentType}`); + throw new Error(`Unknown deployment type: ${this._model.deploymentType}`); } } } diff --git a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/serviceSettingsPage.ts b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/serviceSettingsPage.ts index 1f45fd210b..65ba361a08 100644 --- a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/serviceSettingsPage.ts +++ b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/serviceSettingsPage.ts @@ -7,17 +7,16 @@ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; import { FieldType, SectionInfo } from '../../../interfaces'; import { createFlexContainer, createGroupContainer, createLabel, createNumberInput, createSection, createTextInput, getCheckboxComponent, getDropdownComponent, getInputBoxComponent, InputComponentInfo, InputComponents, setModelValues, Validator } from '../../modelViewUtils'; -import { WizardPageBase } from '../../wizardPageBase'; +import { ResourceTypePage } from '../../resourceTypeWizard'; import * as VariableNames from '../constants'; -import { DeployClusterWizard } from '../deployClusterWizard'; -import { AuthenticationMode } from '../deployClusterWizardModel'; +import { AuthenticationMode, DeployClusterWizardModel } from '../deployClusterWizardModel'; const localize = nls.loadMessageBundle(); const NumberInputWidth = '100px'; const inputWidth = '180px'; const labelWidth = '200px'; -export class ServiceSettingsPage extends WizardPageBase { +export class ServiceSettingsPage extends ResourceTypePage { private inputComponents: InputComponents = {}; private endpointHeaderRow!: azdata.FlexContainer; private dnsColumnHeader!: azdata.TextComponent; @@ -49,8 +48,8 @@ export class ServiceSettingsPage extends WizardPageBase { private readableSecondaryNameLabel!: azdata.TextComponent; private endpointSection!: azdata.GroupContainer; - constructor(wizard: DeployClusterWizard) { - super(localize('deployCluster.ServiceSettingsPageTitle', "Service settings"), '', wizard); + constructor(private _model: DeployClusterWizardModel) { + super(localize('deployCluster.ServiceSettingsPageTitle', "Service settings"), '', _model.wizard); } public initialize(): void { const self = this; @@ -120,7 +119,7 @@ export class ServiceSettingsPage extends WizardPageBase { return await createSection({ view: view, container: this.wizard.wizardObject, - inputComponents: this.wizard.inputComponents, + inputComponents: this._model.inputComponents, sectionInfo: sectionInfo, onNewDisposableCreated: (disposable: vscode.Disposable): void => { self.wizard.registerDisposable(disposable); @@ -156,7 +155,7 @@ export class ServiceSettingsPage extends WizardPageBase { private onNewInputComponentCreated(name: string, inputComponentInfo: InputComponentInfo) { this.inputComponents[name] = inputComponentInfo; - this.wizard.inputComponents[name] = inputComponentInfo; + this._model.inputComponents[name] = inputComponentInfo; } private handleSparkSettingEvents(): void { @@ -352,7 +351,7 @@ export class ServiceSettingsPage extends WizardPageBase { this.setInputBoxValue(VariableNames.ControllerLogsStorageClassName_VariableName); this.setInputBoxValue(VariableNames.ControllerLogsStorageSize_VariableName); this.endpointHeaderRow.clearItems(); - const adAuth = this.wizard.model.authenticationMode === AuthenticationMode.ActiveDirectory; + const adAuth = this._model.authenticationMode === AuthenticationMode.ActiveDirectory; const sqlServerScale = this.wizard.model.getIntegerValue(VariableNames.SQLServerScale_VariableName); this.endpointSection.collapsed = !adAuth; @@ -425,7 +424,7 @@ export class ServiceSettingsPage extends WizardPageBase { row.clearItems(); const itemLayout: azdata.FlexItemLayout = { CSSStyles: { 'margin-right': '20px' } }; row.addItem(label); - if (this.wizard.model.authenticationMode === AuthenticationMode.ActiveDirectory) { + if (this._model.authenticationMode === AuthenticationMode.ActiveDirectory) { row.addItem(dnsInput, itemLayout); } row.addItem(portInput); diff --git a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/summaryPage.ts b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/summaryPage.ts index 1d1639bef6..49c640c9e7 100644 --- a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/summaryPage.ts +++ b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/summaryPage.ts @@ -4,22 +4,21 @@ *--------------------------------------------------------------------------------------------*/ import * as azdata from 'azdata'; import * as nls from 'vscode-nls'; -import { DeployClusterWizard } from '../deployClusterWizard'; import { SectionInfo, FieldType, LabelPosition, BdcDeploymentType, FontWeight } from '../../../interfaces'; import { createSection, createGroupContainer, createFlexContainer, createLabel } from '../../modelViewUtils'; -import { WizardPageBase } from '../../wizardPageBase'; import * as VariableNames from '../constants'; -import { AuthenticationMode } from '../deployClusterWizardModel'; +import { AuthenticationMode, DeployClusterWizardModel } from '../deployClusterWizardModel'; import * as localizedConstants from '../../../localizedConstants'; +import { ResourceTypePage } from '../../resourceTypeWizard'; const localize = nls.loadMessageBundle(); -export class SummaryPage extends WizardPageBase { +export class SummaryPage extends ResourceTypePage { private formItems: azdata.FormComponent[] = []; private form!: azdata.FormBuilder; private view!: azdata.ModelView; - constructor(wizard: DeployClusterWizard) { - super(localize('deployCluster.summaryPageTitle', "Summary"), '', wizard); + constructor(private _model: DeployClusterWizardModel) { + super(localize('deployCluster.summaryPageTitle', "Summary"), '', _model.wizard); } public initialize(): void { @@ -31,7 +30,7 @@ export class SummaryPage extends WizardPageBase { } public async onEnter(): Promise { - this.wizard.showCustomButtons(); + this._model.showCustomButtons(); this.formItems.forEach(item => { this.form!.removeFormItem(item); }); @@ -92,7 +91,7 @@ export class SummaryPage extends WizardPageBase { }, { type: FieldType.ReadonlyText, label: localize('deployCluster.AuthenticationMode', "Authentication mode"), - defaultValue: this.wizard.model.authenticationMode === AuthenticationMode.ActiveDirectory ? + defaultValue: this._model.authenticationMode === AuthenticationMode.ActiveDirectory ? localize('deployCluster.AuthenticationMode.ActiveDirectory', "Active Directory") : localize('deployCluster.AuthenticationMode.Basic', "Basic"), labelCSSStyles: { fontWeight: FontWeight.Bold } @@ -102,13 +101,13 @@ export class SummaryPage extends WizardPageBase { ] }; - if (this.wizard.model.authenticationMode === AuthenticationMode.ActiveDirectory) { + if (this._model.authenticationMode === AuthenticationMode.ActiveDirectory) { clusterSectionInfo.rows!.push({ items: [ { type: FieldType.ReadonlyText, label: localize('deployCluster.OuDistinguishedName', "Organizational unit"), - defaultValue: this.wizard.model.getStringValue(VariableNames.OrganizationalUnitDistinguishedName_VariableName), + defaultValue: this._model.getStringValue(VariableNames.OrganizationalUnitDistinguishedName_VariableName), labelCSSStyles: { fontWeight: FontWeight.Bold } }, { @@ -291,7 +290,7 @@ export class SummaryPage extends WizardPageBase { title: '', component: await createSection({ container: this.wizard.wizardObject, - inputComponents: this.wizard.inputComponents, + inputComponents: this._model.inputComponents, sectionInfo: sectionInfo, view: this.view, onNewDisposableCreated: () => { }, @@ -302,7 +301,7 @@ export class SummaryPage extends WizardPageBase { }; }; - if (this.wizard.deploymentType === BdcDeploymentType.ExistingAKS || this.wizard.deploymentType === BdcDeploymentType.ExistingKubeAdm) { + if (this._model.deploymentType === BdcDeploymentType.ExistingAKS || this._model.deploymentType === BdcDeploymentType.ExistingKubeAdm) { const deploymentTargetSection = await createSectionFunc(deploymentTargetSectionInfo); this.formItems.push(deploymentTargetSection); } @@ -327,7 +326,7 @@ export class SummaryPage extends WizardPageBase { } public async onLeave(): Promise { - this.wizard.hideCustomButtons(); + this._model.hideCustomButtons(); this.wizard.wizardObject.message = { text: '' }; } @@ -422,7 +421,7 @@ export class SummaryPage extends WizardPageBase { private createEndpointRow(name: string, dnsVariableName: string, portVariableName: string): azdata.FlexContainer { const items = []; items.push(createLabel(this.view, { text: name, width: '150px', cssStyles: { fontWeight: FontWeight.Bold } })); - if (this.wizard.model.authenticationMode === AuthenticationMode.ActiveDirectory) { + if (this._model.authenticationMode === AuthenticationMode.ActiveDirectory) { items.push(createLabel(this.view, { text: this.wizard.model.getStringValue(dnsVariableName)!, width: '200px' })); diff --git a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/targetClusterPage.ts b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/targetClusterPage.ts index 19f7560f86..69d0e7a667 100644 --- a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/targetClusterPage.ts +++ b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/targetClusterPage.ts @@ -7,15 +7,15 @@ import * as azdata from 'azdata'; import * as os from 'os'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; -import { DeployClusterWizard } from '../deployClusterWizard'; -import { WizardPageBase } from '../../wizardPageBase'; import { KubeClusterContext } from '../../../services/kubeService'; import { ClusterContext_VariableName, KubeConfigPath_VariableName } from '../constants'; +import { ResourceTypePage } from '../../resourceTypeWizard'; +import { DeployClusterWizardModel } from '../deployClusterWizardModel'; const localize = nls.loadMessageBundle(); const ClusterRadioButtonGroupName = 'ClusterRadioGroup'; -export class TargetClusterContextPage extends WizardPageBase { +export class TargetClusterContextPage extends ResourceTypePage { private existingClusterControl: azdata.FlexContainer | undefined; private clusterContextsLabel: azdata.TextComponent | undefined; private errorLoadingClustersLabel: azdata.TextComponent | undefined; @@ -26,9 +26,9 @@ export class TargetClusterContextPage extends WizardPageBase { if (this.loadDefaultKubeConfigFile) { - let defaultKubeConfigPath = this.wizard.kubeService.getDefaultConfigPath(); + let defaultKubeConfigPath = this._model.kubeService.getDefaultConfigPath(); this.loadClusterContexts(defaultKubeConfigPath); this.loadDefaultKubeConfigFile = false; } @@ -140,7 +140,7 @@ export class TargetClusterContextPage extends WizardPageBase { this.toolsService.toolsForCurrentProvider = this._tools; - this.resourceTypeService.startDeployment(this.getCurrentProvider()); + this.resourceTypeService.startDeployment(this._selectedResourceType, this.getCurrentProvider()); } protected updateToolsDisplayTableData(tool: ITool) { diff --git a/extensions/resource-deployment/src/ui/resourceTypeWizard.ts b/extensions/resource-deployment/src/ui/resourceTypeWizard.ts new file mode 100644 index 0000000000..836b2b42b0 --- /dev/null +++ b/extensions/resource-deployment/src/ui/resourceTypeWizard.ts @@ -0,0 +1,140 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as azdata from 'azdata'; +import * as vscode from 'vscode'; +import { DeploymentProvider, instanceOfWizardDeploymentProvider, ResourceType } from '../interfaces'; +import { Model } from './model'; +import { WizardPageBase } from './wizardPageBase'; +import { DeployClusterWizardModel } from './deployClusterWizard/deployClusterWizardModel'; +import { WizardPageInfo } from './wizardPageInfo'; +import { IKubeService } from '../services/kubeService'; +import { IAzdataService } from '../services/azdataService'; +import { INotebookService } from '../services/notebookService'; +import { IToolsService } from '../services/toolsService'; +import { IPlatformService } from '../services/platformService'; + +export class ResourceTypeWizard { + private customButtons: azdata.window.Button[] = []; + public pages: ResourceTypePage[] = []; + public wizardObject: azdata.window.Wizard; + public toDispose: vscode.Disposable[] = []; + public model: ResourceTypeModel; + private _useGenerateScriptButton!: boolean; + + public get useGenerateScriptButton(): boolean { + return this._useGenerateScriptButton; + } + + public set useGenerateScriptButton(value: boolean) { + this._useGenerateScriptButton = value; + } + + //TODO: eventually only resourceType will be passed. For now, we are passing both the resourceType and provider + constructor( + public resourceType: ResourceType, + public provider: DeploymentProvider, + public _kubeService: IKubeService, + public azdataService: IAzdataService, + public notebookService: INotebookService, + public toolsService: IToolsService, + public platformService: IPlatformService) { + this.wizardObject = azdata.window.createWizard(resourceType.displayName, resourceType.name, 'wide'); + this.model = this.getResourceProviderModel()!; + } + + + public getResourceProviderModel(): ResourceTypeModel | undefined { + if (instanceOfWizardDeploymentProvider(this.provider)) { + return new DeployClusterWizardModel(this.provider, this); + } + // other types are undefined for now. + return undefined; + } + + public async open(): Promise { + this.model.initialize(); + this.wizardObject.generateScriptButton.hidden = true; // by default generateScriptButton stays hidden. + this.wizardObject.customButtons = this.customButtons; + this.toDispose.push(this.wizardObject.onPageChanged(async (e) => { + let previousPage = this.pages[e.lastPage]; + let newPage = this.pages[e.newPage]; + //if we are changing to the first page from no page before, essentially when we load the wizard for the first time, e.lastPage is -1 and previousPage is undefined. + await previousPage?.onLeave(new WizardPageInfo(e.lastPage, this.pages.length)); + if (this.useGenerateScriptButton) { + if (newPage === this.pages.slice(-1)[0]) { + // if newPage is the last page + this.wizardObject.generateScriptButton.hidden = false; //un-hide generateScriptButton on last page + } else { + // if newPage is not the last page + this.wizardObject.generateScriptButton.hidden = true; //hide generateScriptButton if it is not the last page + } + } + await newPage.onEnter(new WizardPageInfo(e.newPage, this.pages.length)); + })); + + this.toDispose.push(this.wizardObject.doneButton.onClick(async () => { + await this.model.onOk(); + this.dispose(); + })); + this.toDispose.push(this.wizardObject.generateScriptButton.onClick(async () => { + await this.model.onGenerateScript(); + this.dispose(); + this.wizardObject.close(); // close the wizard. This is already hooked up into doneButton, so it is not needed for that button above. + })); + this.toDispose.push(this.wizardObject.cancelButton.onClick(() => { + this.model.onCancel(); + this.dispose(); + })); + + await this.wizardObject.open(); + } + + public addButton(button: azdata.window.Button) { + this.customButtons.push(button); + } + + public setPages(pages: ResourceTypePage[]) { + this.wizardObject!.pages = pages.map(p => p.pageObject); + this.pages = pages; + this.pages.forEach((page) => { + page.pageObject.onValidityChanged((isValid: boolean) => { + // generateScriptButton is enabled only when the page is valid. + this.wizardObject.generateScriptButton.enabled = isValid; + }); + page.initialize(); + }); + } + + protected dispose() { + this.toDispose.forEach((disposable: vscode.Disposable) => { + disposable.dispose(); + }); + } + + public registerDisposable(disposable: vscode.Disposable): void { + this.toDispose.push(disposable); + } + +} + + + +export abstract class ResourceTypePage extends WizardPageBase{ + abstract initialize(): void; +} + +export abstract class ResourceTypeModel extends Model { + + constructor(public provider: DeploymentProvider, public wizard: ResourceTypeWizard) { + super(); + } + + abstract initialize(): void; + abstract async onOk(): Promise; + abstract onCancel(): void; + async onGenerateScript(): Promise { } + +}