Refactoring Deploy Cluster to use the a generic Wizard (#13105)

* Refactoring Deploy Cluster to use the generic ResourceTypeWizard

* - Remove unnecessary error message
- Fixed spacing
- Fixed onCancel method implementation in deploy cluster
This commit is contained in:
Aasim Khan
2020-10-28 20:47:27 -07:00
committed by GitHub
parent 9fcd85e640
commit dd77c79090
11 changed files with 412 additions and 284 deletions

View File

@@ -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<DeployClusterWizard, WizardPageBase<DeployClusterWizard>, 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<void> {
await this.scriptToNotebook();
}
private getPages(): WizardPageBase<DeployClusterWizard>[] {
const pages: WizardPageBase<DeployClusterWizard>[] = [];
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<void> {
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<void> {
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}`);
}
}
}

View File

@@ -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<void> {
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<void> {
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<void> {
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}`);
}
}
}

View File

@@ -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<DeployClusterWizard> {
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<DeployClusterWizard> {
},
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(

View File

@@ -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<DeployClusterWizard> {
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<DeployClusterWizard> {
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<DeployClusterWizard> {
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<DeployClusterWizard> {
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<DeployClusterWizard> {
public async onLeave(): Promise<void> {
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<DeployClusterWizard> {
getInputBoxComponent(VariableNames.DockerImageTag_VariableName, this.inputComponents).value = this.wizard.model.getStringValue(VariableNames.DockerImageTag_VariableName);
const authModeDropdown = <azdata.DropDownComponent>this.inputComponents[VariableNames.AuthenticationMode_VariableName].component;
if (authModeDropdown) {
authModeDropdown.enabled = this.wizard.model.adAuthSupported;
authModeDropdown.enabled = this._model.adAuthSupported;
const adAuthSelected = (<azdata.CategoryValue>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,

View File

@@ -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<DeployClusterWizard> {
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<DeployClusterWizard> {
}
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<void> {
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<DeployClusterWizard> {
}
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<DeployClusterWizard> {
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}`);
}
}
}

View File

@@ -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<DeployClusterWizard> {
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<DeployClusterWizard> {
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<DeployClusterWizard> {
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<DeployClusterWizard> {
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<DeployClusterWizard> {
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<DeployClusterWizard> {
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);

View File

@@ -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<DeployClusterWizard> {
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<DeployClusterWizard> {
}
public async onEnter(): Promise<void> {
this.wizard.showCustomButtons();
this._model.showCustomButtons();
this.formItems.forEach(item => {
this.form!.removeFormItem(item);
});
@@ -92,7 +91,7 @@ export class SummaryPage extends WizardPageBase<DeployClusterWizard> {
}, {
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<DeployClusterWizard> {
]
};
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<DeployClusterWizard> {
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<DeployClusterWizard> {
};
};
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<DeployClusterWizard> {
}
public async onLeave(): Promise<void> {
this.wizard.hideCustomButtons();
this._model.hideCustomButtons();
this.wizard.wizardObject.message = { text: '' };
}
@@ -422,7 +421,7 @@ export class SummaryPage extends WizardPageBase<DeployClusterWizard> {
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'
}));

View File

@@ -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<DeployClusterWizard> {
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<DeployClusterWizard
private loadDefaultKubeConfigFile: boolean = true;
private view: azdata.ModelView | undefined;
constructor(wizard: DeployClusterWizard) {
constructor(private _model: DeployClusterWizardModel) {
super(localize('deployCluster.TargetClusterContextPageTitle', "Target cluster context"),
localize('deployCluster.TargetClusterContextPageDescription', "Select the kube config file and then select a cluster context from the list"), wizard);
localize('deployCluster.TargetClusterContextPageDescription', "Select the kube config file and then select a cluster context from the list"), _model.wizard);
}
public initialize(): void {
@@ -53,7 +53,7 @@ export class TargetClusterContextPage extends WizardPageBase<DeployClusterWizard
public async onEnter(): Promise<void> {
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<DeployClusterWizard
let clusterContexts: KubeClusterContext[] = [];
try {
clusterContexts = await this.wizard.kubeService.getClusterContexts(configPath);
clusterContexts = await this._model.kubeService.getClusterContexts(configPath);
} catch (error) {
this.wizard.wizardObject.message = {
text: localize('deployCluster.ConfigParseError', "Failed to load the config file"),