mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-08 01:28:26 -05:00
wizard for deploying bdc (#7183)
* wip * wip2 * wip eod 820 * wip 822 * text component improvements and misc changes * aria-label * targetClusterPage wip * target cluster page * target cluster page * wip 827 * wip deployment profile page * profile page * service settings page * wip 0903 * 0909 wip * 0910 * 0911 * sql instance and working directory * notebooks * docker version on windows * EULA env var * 917 updates * address comments * use async file access * fix the summary page display issue for ad auth * add save json file buttons * use promise for private methds * review feedbacks * refactor * pass json to notebooks * fix no tool scenario * bypass tool check if installed * update hint text * update notebooks * workaround azdata first time use * comments * accept eula and some text update * fix the error in package.json * promise instead of thenable * comments * fix typo
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export const DeploymentProfile_VariableName = 'AZDATA_NB_VAR_BDC_DEPLOYMENT_PROFILE';
|
||||
export const ClusterName_VariableName = 'AZDATA_NB_VAR_BDC_CLUSTER_NAME';
|
||||
export const AdminUserName_VariableName = 'AZDATA_NB_VAR_BDC_CONTROLLER_USERNAME';
|
||||
export const AdminPassword_VariableName = 'AZDATA_NB_VAR_BDC_ADMIN_PASSWORD';
|
||||
export const AuthenticationMode_VariableName = 'AZDATA_NB_VAR_BDC_AUTHENTICATION_MODE';
|
||||
export const DistinguishedName_VariableName = 'AZDATA_NB_VAR_BDC_AD_DN';
|
||||
export const AdminPrincipals_VariableName = 'AZDATA_NB_VAR_BDC_AD_ADMIN_PRINCIPALS';
|
||||
export const UserPrincipals_VariableName = 'AZDATA_NB_VAR_BDC_AD_USER_PRINCIPALS';
|
||||
export const UpstreamIPAddresses_VariableName = 'AZDATA_NB_VAR_BDC_AD_UPSTREAM_IPADDRESSES';
|
||||
export const DnsName_VariableName = 'AZDATA_NB_VAR_BDC_AD_DNS_NAME';
|
||||
export const Realm_VariableName = 'AZDATA_NB_VAR_BDC_AD_REALM';
|
||||
export const AppOwnerPrincipals_VariableName = 'AZDATA_NB_VAR_AD_BDC_APP_OWNER_PRINCIPALS';
|
||||
export const AppReaderPrincipals_VariableName = 'AZDATA_NB_VAR_AD_BDC_APP_READER_PRINCIPALS';
|
||||
export const SubscriptionId_VariableName = 'AZDATA_NB_VAR_BDC_AZURE_SUBSCRIPTION';
|
||||
export const ResourceGroup_VariableName = 'AZDATA_NB_VAR_BDC_RESOURCEGROUP_NAME';
|
||||
export const Region_VariableName = 'AZDATA_NB_VAR_BDC_AZURE_REGION';
|
||||
export const AksName_VariableName = 'AZDATA_NB_VAR_BDC_AKS_NAME';
|
||||
export const VMSize_VariableName = 'AZDATA_NB_VAR_BDC_AZURE_VM_SIZE';
|
||||
export const VMCount_VariableName = 'AZDATA_NB_VAR_BDC_VM_COUNT';
|
||||
export const KubeConfigPath_VariableName = 'AZDATA_NB_VAR_BDC_KUBECONFIG_PATH';
|
||||
export const ClusterContext_VariableName = 'AZDATA_NB_VAR_BDC_CLUSTER_CONTEXT';
|
||||
export const SQLServerScale_VariableName = 'AZDATA_NB_VAR_BDC_SQLSERVER_SCALE';
|
||||
export const HDFSPoolScale_VariableName = 'AZDATA_NB_VAR_BDC_HDFSPOOL_SCALE';
|
||||
export const HDFSNameNodeScale_VariableName = 'AZDATA_NB_VAR_BDC_NAMENODE_SCALE';
|
||||
export const ZooKeeperScale_VariableName = 'AZDATA_NB_VAR_BDC_ZOOKEEPER_SCALE';
|
||||
export const SparkHeadScale_VariableName = 'AZDATA_NB_VAR_BDC_SPARKHEAD_SCALE';
|
||||
export const IncludeSpark_VariableName = 'AZDATA_NB_VAR_BDC_INCLUDESPARK';
|
||||
export const ComputePoolScale_VariableName = 'AZDATA_NB_VAR_BDC_COMPUTEPOOL_SCALE';
|
||||
export const DataPoolScale_VariableName = 'AZDATA_NB_VAR_BDC_DATAPOOL_SCALE';
|
||||
export const SparkPoolScale_VariableName = 'AZDATA_NB_VAR_BDC_SPARKPOOL_SCALE';
|
||||
export const ControllerDataStorageClassName_VariableName = 'AZDATA_NB_VAR_BDC_CONTROLLER_DATA_STORAGE_CLASS';
|
||||
export const ControllerDataStorageSize_VariableName = 'AZDATA_NB_VAR_BDC_CONTROLLER_DATA_STORAGE_SIZE';
|
||||
export const ControllerLogsStorageClassName_VariableName = 'AZDATA_NB_VAR_BDC_CONTROLLER_LOGS_STORAGE_CLASS';
|
||||
export const ControllerLogsStorageSize_VariableName = 'AZDATA_NB_VAR_BDC_CONTROLLER_LOGS_STORAGE_SIZE';
|
||||
export const DataPoolDataStorageClassName_VariableName = 'AZDATA_NB_VAR_BDC_DATA_DATA_STORAGE_CLASS';
|
||||
export const DataPoolDataStorageSize_VariableName = 'AZDATA_NB_VAR_BDC_DATA_DATA_STORAGE_SIZE';
|
||||
export const DataPoolLogsStorageClassName_VariableName = 'AZDATA_NB_VAR_BDC_DATA_LOGS_STORAGE_CLASS';
|
||||
export const DataPoolLogsStorageSize_VariableName = 'AZDATA_NB_VAR_BDC_DATA_LOGS_STORAGE_SIZE';
|
||||
export const HDFSDataStorageClassName_VariableName = 'AZDATA_NB_VAR_BDC_HDFS_DATA_STORAGE_CLASS';
|
||||
export const HDFSDataStorageSize_VariableName = 'AZDATA_NB_VAR_BDC_HDFS_DATA_STORAGE_SIZE';
|
||||
export const HDFSLogsStorageClassName_VariableName = 'AZDATA_NB_VAR_BDC_HDFS_LOGS_STORAGE_CLASS';
|
||||
export const HDFSLogsStorageSize_VariableName = 'AZDATA_NB_VAR_BDC_HDFS_LOGS_STORAGE_SIZE';
|
||||
export const SQLServerDataStorageClassName_VariableName = 'AZDATA_NB_VAR_BDC_SQL_DATA_STORAGE_CLASS';
|
||||
export const SQLServerDataStorageSize_VariableName = 'AZDATA_NB_VAR_BDC_SQL_DATA_STORAGE_SIZE';
|
||||
export const SQLServerLogsStorageClassName_VariableName = 'AZDATA_NB_VAR_BDC_SQL_LOGS_STORAGE_CLASS';
|
||||
export const SQLServerLogsStorageSize_VariableName = 'AZDATA_NB_VAR_BDC_SQL_LOGS_STORAGE_SIZE';
|
||||
export const ControllerDNSName_VariableName = 'AZDATA_NB_VAR_BDC_CONTROLLER_DNS';
|
||||
export const ControllerPort_VariableName = 'AZDATA_NB_VAR_BDC_CONTROLLER_PORT';
|
||||
export const SQLServerDNSName_VariableName = 'AZDATA_NB_VAR_BDC_SQL_DNS';
|
||||
export const SQLServerPort_VariableName = 'AZDATA_NB_VAR_BDC_SQL_PORT';
|
||||
export const GatewayDNSName_VariableName = 'AZDATA_NB_VAR_BDC_GATEWAY_DNS';
|
||||
export const GateWayPort_VariableName = 'AZDATA_NB_VAR_BDC_GATEWAY_PORT';
|
||||
export const ReadableSecondaryDNSName_VariableName = 'AZDATA_NB_VAR_BDC_READABLE_SECONDARY_DNS';
|
||||
export const ReadableSecondaryPort_VariableName = 'AZDATA_NB_VAR_BDC_READABLE_SECONDARY_PORT';
|
||||
export const EnableHADR_VariableName = 'AZDATA_NB_VAR_BDC_ENABLE_HADR';
|
||||
@@ -0,0 +1,115 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 { SummaryPage } from './pages/summaryPage';
|
||||
import { WizardBase } from '../wizardBase';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { WizardInfo, BdcDeploymentType } from '../../interfaces';
|
||||
import { WizardPageBase } from '../wizardPageBase';
|
||||
import { AzureSettingsPage } from './pages/azureSettingsPage';
|
||||
import { ClusterSettingsPage } from './pages/clusterSettingsPage';
|
||||
import { ServiceSettingsPage } from './pages/serviceSettingsPage';
|
||||
import { TargetClusterContextPage } from './pages/targetClusterPage';
|
||||
import { IKubeService } from '../../services/kubeService';
|
||||
import { IAzdataService } from '../../services/azdataService';
|
||||
import { DeploymentProfilePage } from './pages/deploymentProfilePage';
|
||||
import { INotebookService } from '../../services/notebookService';
|
||||
import { DeployClusterWizardModel } from './deployClusterWizardModel';
|
||||
import * as VariableNames from './constants';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class DeployClusterWizard extends WizardBase<DeployClusterWizard, DeployClusterWizardModel> {
|
||||
|
||||
public get kubeService(): IKubeService {
|
||||
return this._kubeService;
|
||||
}
|
||||
|
||||
public get azdataService(): IAzdataService {
|
||||
return this._azdataService;
|
||||
}
|
||||
|
||||
public get notebookService(): INotebookService {
|
||||
return this._notebookService;
|
||||
}
|
||||
|
||||
constructor(private wizardInfo: WizardInfo, private _kubeService: IKubeService, private _azdataService: IAzdataService, private _notebookService: INotebookService) {
|
||||
super(DeployClusterWizard.getTitle(wizardInfo.type), new DeployClusterWizardModel(wizardInfo.type));
|
||||
}
|
||||
|
||||
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.openNotebook', 'Open Notebook');
|
||||
}
|
||||
|
||||
protected onCancel(): void {
|
||||
}
|
||||
|
||||
protected onOk(): void {
|
||||
process.env[VariableNames.AdminPassword_VariableName] = this.model.getStringValue(VariableNames.AdminPassword_VariableName);
|
||||
this.notebookService.launchNotebook(this.wizardInfo.notebook).then((notebook: azdata.nb.NotebookEditor) => {
|
||||
notebook.edit((editBuilder: azdata.nb.NotebookEditorEdit) => {
|
||||
editBuilder.insertCell({
|
||||
cell_type: 'code',
|
||||
source: this.model.getCodeCellContentForNotebook()
|
||||
}, 7);
|
||||
});
|
||||
}, (error) => {
|
||||
vscode.window.showErrorMessage(error);
|
||||
});
|
||||
}
|
||||
|
||||
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:
|
||||
pages.push(
|
||||
new DeploymentProfilePage(this),
|
||||
new TargetClusterContextPage(this),
|
||||
new ClusterSettingsPage(this),
|
||||
new ServiceSettingsPage(this),
|
||||
new SummaryPage(this));
|
||||
break;
|
||||
case BdcDeploymentType.ExistingKubeAdm:
|
||||
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;
|
||||
}
|
||||
|
||||
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");
|
||||
default:
|
||||
throw new Error(`Unknown deployment type: ${type}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Model } from '../model';
|
||||
import * as VariableNames from './constants';
|
||||
import { BigDataClusterDeploymentProfile, DataResource, SqlServerMasterResource, HdfsResource } from '../../services/bigDataClusterDeploymentProfile';
|
||||
import { BdcDeploymentType } from '../../interfaces';
|
||||
import { EOL } from 'os';
|
||||
|
||||
export class DeployClusterWizardModel extends Model {
|
||||
constructor(public deploymentTarget: BdcDeploymentType) {
|
||||
super();
|
||||
}
|
||||
public adAuthSupported: boolean = false;
|
||||
|
||||
public get hadrEnabled(): boolean {
|
||||
return this.getBooleanValue(VariableNames.EnableHADR_VariableName);
|
||||
}
|
||||
|
||||
public set hadrEnabled(value: boolean) {
|
||||
this.setPropertyValue(VariableNames.EnableHADR_VariableName, value);
|
||||
}
|
||||
|
||||
public get authenticationMode(): string | undefined {
|
||||
return this.getStringValue(VariableNames.AuthenticationMode_VariableName);
|
||||
}
|
||||
|
||||
public set authenticationMode(value: string | undefined) {
|
||||
this.setPropertyValue(VariableNames.AuthenticationMode_VariableName, value);
|
||||
}
|
||||
|
||||
public getStorageSettingValue(propertyName: string, defaultValuePropertyName: string): string | undefined {
|
||||
const value = this.getStringValue(propertyName);
|
||||
return (value === undefined || value === '') ? this.getStringValue(defaultValuePropertyName) : value;
|
||||
}
|
||||
|
||||
private setStorageSettingValue(propertyName: string, defaultValuePropertyName: string): void {
|
||||
const value = this.getStringValue(propertyName);
|
||||
if (value === undefined || value === '') {
|
||||
this.setPropertyValue(propertyName, this.getStringValue(defaultValuePropertyName));
|
||||
}
|
||||
}
|
||||
|
||||
private setStorageSettingValues(): void {
|
||||
this.setStorageSettingValue(VariableNames.DataPoolDataStorageClassName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName);
|
||||
this.setStorageSettingValue(VariableNames.DataPoolDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName);
|
||||
this.setStorageSettingValue(VariableNames.DataPoolLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName);
|
||||
this.setStorageSettingValue(VariableNames.DataPoolLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName);
|
||||
|
||||
this.setStorageSettingValue(VariableNames.HDFSDataStorageClassName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName);
|
||||
this.setStorageSettingValue(VariableNames.HDFSDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName);
|
||||
this.setStorageSettingValue(VariableNames.HDFSLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName);
|
||||
this.setStorageSettingValue(VariableNames.HDFSLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName);
|
||||
|
||||
this.setStorageSettingValue(VariableNames.SQLServerDataStorageClassName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName);
|
||||
this.setStorageSettingValue(VariableNames.SQLServerDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName);
|
||||
this.setStorageSettingValue(VariableNames.SQLServerLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName);
|
||||
this.setStorageSettingValue(VariableNames.SQLServerLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName);
|
||||
}
|
||||
|
||||
public setEnvironmentVariables(): void {
|
||||
this.setStorageSettingValues();
|
||||
}
|
||||
|
||||
public selectedProfile: BigDataClusterDeploymentProfile | undefined;
|
||||
|
||||
public createTargetProfile(): BigDataClusterDeploymentProfile {
|
||||
// create a copy of the source files to avoid changing the source profile values
|
||||
const sourceBdcJson = Object.assign({}, this.selectedProfile!.bdcConfig);
|
||||
const sourceControlJson = Object.assign({}, this.selectedProfile!.controlConfig);
|
||||
const targetDeploymentProfile = new BigDataClusterDeploymentProfile('', sourceBdcJson, sourceControlJson);
|
||||
// cluster name
|
||||
targetDeploymentProfile.clusterName = this.getStringValue(VariableNames.ClusterName_VariableName)!;
|
||||
// storage settings
|
||||
targetDeploymentProfile.controllerDataStorageClass = this.getStringValue(VariableNames.ControllerDataStorageClassName_VariableName)!;
|
||||
targetDeploymentProfile.controllerDataStorageSize = this.getIntegerValue(VariableNames.ControllerDataStorageSize_VariableName)!;
|
||||
targetDeploymentProfile.controllerLogsStorageClass = this.getStringValue(VariableNames.ControllerLogsStorageClassName_VariableName)!;
|
||||
targetDeploymentProfile.controllerLogsStorageSize = this.getIntegerValue(VariableNames.ControllerLogsStorageSize_VariableName)!;
|
||||
targetDeploymentProfile.setResourceStorage(DataResource,
|
||||
this.getStorageSettingValue(VariableNames.DataPoolDataStorageClassName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName)!,
|
||||
Number.parseInt(this.getStorageSettingValue(VariableNames.DataPoolDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName)!),
|
||||
this.getStorageSettingValue(VariableNames.DataPoolLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName)!,
|
||||
Number.parseInt(this.getStorageSettingValue(VariableNames.DataPoolLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName)!)
|
||||
);
|
||||
targetDeploymentProfile.setResourceStorage(SqlServerMasterResource,
|
||||
this.getStorageSettingValue(VariableNames.SQLServerDNSName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName)!,
|
||||
Number.parseInt(this.getStorageSettingValue(VariableNames.SQLServerDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName)!),
|
||||
this.getStorageSettingValue(VariableNames.SQLServerLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName)!,
|
||||
Number.parseInt(this.getStorageSettingValue(VariableNames.SQLServerLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName)!)
|
||||
);
|
||||
targetDeploymentProfile.setResourceStorage(HdfsResource,
|
||||
this.getStorageSettingValue(VariableNames.HDFSDataStorageClassName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName)!,
|
||||
Number.parseInt(this.getStorageSettingValue(VariableNames.HDFSDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName)!),
|
||||
this.getStorageSettingValue(VariableNames.HDFSLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName)!,
|
||||
Number.parseInt(this.getStorageSettingValue(VariableNames.HDFSLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName)!)
|
||||
);
|
||||
|
||||
// scale settings
|
||||
targetDeploymentProfile.dataReplicas = this.getIntegerValue(VariableNames.DataPoolScale_VariableName);
|
||||
targetDeploymentProfile.computeReplicas = this.getIntegerValue(VariableNames.ComputePoolScale_VariableName);
|
||||
targetDeploymentProfile.hdfsReplicas = this.getIntegerValue(VariableNames.HDFSPoolScale_VariableName);
|
||||
targetDeploymentProfile.sqlServerReplicas = this.getIntegerValue(VariableNames.SQLServerScale_VariableName);
|
||||
targetDeploymentProfile.hdfsNameNodeReplicas = this.getIntegerValue(VariableNames.HDFSNameNodeScale_VariableName);
|
||||
targetDeploymentProfile.sparkHeadReplicas = this.getIntegerValue(VariableNames.SparkHeadScale_VariableName);
|
||||
targetDeploymentProfile.zooKeeperReplicas = this.getIntegerValue(VariableNames.ZooKeeperScale_VariableName);
|
||||
const sparkScale = this.getIntegerValue(VariableNames.SparkPoolScale_VariableName);
|
||||
if (sparkScale > 0) {
|
||||
targetDeploymentProfile.addSparkResource(sparkScale);
|
||||
}
|
||||
|
||||
targetDeploymentProfile.includeSpark = this.getBooleanValue(VariableNames.IncludeSpark_VariableName);
|
||||
targetDeploymentProfile.hadrEnabled = this.getBooleanValue(VariableNames.EnableHADR_VariableName);
|
||||
|
||||
// port settings
|
||||
targetDeploymentProfile.gatewayPort = this.getIntegerValue(VariableNames.GateWayPort_VariableName);
|
||||
targetDeploymentProfile.sqlServerPort = this.getIntegerValue(VariableNames.SQLServerPort_VariableName);
|
||||
targetDeploymentProfile.controllerPort = this.getIntegerValue(VariableNames.ControllerPort_VariableName);
|
||||
targetDeploymentProfile.sqlServerReadableSecondaryPort = this.getIntegerValue(VariableNames.ReadableSecondaryPort_VariableName);
|
||||
|
||||
return targetDeploymentProfile;
|
||||
}
|
||||
|
||||
public getCodeCellContentForNotebook(): string {
|
||||
const profile = this.createTargetProfile();
|
||||
const statements: string[] = [];
|
||||
if (this.deploymentTarget === BdcDeploymentType.NewAKS) {
|
||||
statements.push(`azure_subscription_id = '${this.getStringValue(VariableNames.SubscriptionId_VariableName, '')}'`);
|
||||
statements.push(`azure_region = '${this.getStringValue(VariableNames.Region_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) {
|
||||
statements.push(`mssql_kube_config_path = '${this.getStringValue(VariableNames.KubeConfigPath_VariableName)}'`);
|
||||
statements.push(`mssql_cluster_context = '${this.getStringValue(VariableNames.ClusterContext_VariableName)}'`);
|
||||
statements.push('os.environ["KUBECONFIG"] = mssql_kube_config_path');
|
||||
}
|
||||
statements.push(`mssql_cluster_name = '${this.getStringValue(VariableNames.ClusterName_VariableName)}'`);
|
||||
statements.push(`mssql_controller_username = '${this.getStringValue(VariableNames.AdminUserName_VariableName)}'`);
|
||||
statements.push(`bdc_json = '${profile.getBdcJson(false)}'`);
|
||||
statements.push(`control_json = '${profile.getControlJson(false)}'`);
|
||||
statements.push(`print('Variables have been set successfully.')`);
|
||||
return statements.join(EOL);
|
||||
}
|
||||
}
|
||||
|
||||
export enum AuthenticationMode {
|
||||
ActiveDirectory = 'ad',
|
||||
Basic = 'basic'
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 * as nls from 'vscode-nls';
|
||||
import { DeployClusterWizard } from '../deployClusterWizard';
|
||||
import { SectionInfo, FieldType, LabelPosition } from '../../../interfaces';
|
||||
import { WizardPageBase } from '../../wizardPageBase';
|
||||
import { createSection, InputComponents, setModelValues, Validator } from '../../modelViewUtils';
|
||||
import { SubscriptionId_VariableName, ResourceGroup_VariableName, Region_VariableName, AksName_VariableName, VMCount_VariableName, VMSize_VariableName } from '../constants';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class AzureSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
private inputComponents: InputComponents = {};
|
||||
|
||||
constructor(wizard: DeployClusterWizard) {
|
||||
super(localize('deployCluster.AzureSettingsPageTitle', "Azure settings"),
|
||||
localize('deployCluster.AzureSettingsPageDescription', "Configure the settings to create an Azure Kubernetes Service cluster"), wizard);
|
||||
}
|
||||
|
||||
public initialize(): void {
|
||||
const self = this;
|
||||
const azureSection: SectionInfo = {
|
||||
title: '',
|
||||
labelPosition: LabelPosition.Left,
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.SubscriptionField', "Subscription id"),
|
||||
required: false,
|
||||
variableName: SubscriptionId_VariableName,
|
||||
placeHolder: localize('deployCluster.SubscriptionPlaceholder', "Use my default Azure subscription"),
|
||||
description: localize('deployCluster.SubscriptionDescription', "The default subscription will be used if you leave this field blank.")
|
||||
}, {
|
||||
type: FieldType.DateTimeText,
|
||||
label: localize('deployCluster.ResourceGroupName', "New resource group name"),
|
||||
required: true,
|
||||
variableName: ResourceGroup_VariableName,
|
||||
defaultValue: 'mssql-'
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.Region', "Region"),
|
||||
required: true,
|
||||
variableName: Region_VariableName,
|
||||
defaultValue: 'eastus'
|
||||
}, {
|
||||
type: FieldType.DateTimeText,
|
||||
label: localize('deployCluster.AksName', "AKS cluster name"),
|
||||
required: true,
|
||||
variableName: AksName_VariableName,
|
||||
defaultValue: 'mssql-',
|
||||
}, {
|
||||
type: FieldType.Number,
|
||||
label: localize('deployCluster.VMCount', "VM count"),
|
||||
required: true,
|
||||
variableName: VMCount_VariableName,
|
||||
defaultValue: '5',
|
||||
min: 1,
|
||||
max: 999
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.VMSize', "VM size"),
|
||||
required: true,
|
||||
variableName: VMSize_VariableName,
|
||||
defaultValue: 'Standard_E4s_v3'
|
||||
}
|
||||
]
|
||||
};
|
||||
this.pageObject.registerContent((view: azdata.ModelView) => {
|
||||
|
||||
const azureGroup = createSection({
|
||||
sectionInfo: azureSection,
|
||||
view: view,
|
||||
onNewDisposableCreated: (disposable: vscode.Disposable): void => {
|
||||
self.wizard.registerDisposable(disposable);
|
||||
},
|
||||
onNewInputComponentCreated: (name: string, component: azdata.InputBoxComponent | azdata.DropDownComponent | azdata.CheckBoxComponent): void => {
|
||||
self.inputComponents[name] = component;
|
||||
},
|
||||
onNewValidatorCreated: (validator: Validator): void => {
|
||||
self.validators.push(validator);
|
||||
},
|
||||
container: this.wizard.wizardObject
|
||||
});
|
||||
const formBuilder = view.modelBuilder.formContainer().withFormItems(
|
||||
[{
|
||||
title: '',
|
||||
component: azureGroup
|
||||
}],
|
||||
{
|
||||
horizontal: false,
|
||||
componentWidth: '100%'
|
||||
}
|
||||
);
|
||||
|
||||
const form = formBuilder.withLayout({ width: '100%' }).component();
|
||||
return view.initializeModel(form);
|
||||
});
|
||||
}
|
||||
|
||||
public onLeave(): void {
|
||||
setModelValues(this.inputComponents, this.wizard.model);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 * as nls from 'vscode-nls';
|
||||
import { DeployClusterWizard } from '../deployClusterWizard';
|
||||
import { SectionInfo, FieldType, LabelPosition } from '../../../interfaces';
|
||||
import { createSection, InputComponents, setModelValues, Validator, isInputBoxEmpty, getInputBoxComponent, isValidSQLPassword, getInvalidSQLPasswordMessage, getPasswordMismatchMessage, MissingRequiredInformationErrorMessage } from '../../modelViewUtils';
|
||||
import { WizardPageBase } from '../../wizardPageBase';
|
||||
import * as VariableNames from '../constants';
|
||||
import { EOL } from 'os';
|
||||
import { AuthenticationMode } from '../deployClusterWizardModel';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
const ConfirmPasswordName = 'ConfirmPassword';
|
||||
export class ClusterSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
private inputComponents: InputComponents = {};
|
||||
|
||||
constructor(wizard: DeployClusterWizard) {
|
||||
super(localize('deployCluster.ClusterSettingsPageTitle', "Cluster settings"),
|
||||
localize('deployCluster.ClusterSettingsPageDescription', "Configure the SQL Server Big Data Cluster settings"), wizard);
|
||||
}
|
||||
|
||||
public initialize(): void {
|
||||
const self = this;
|
||||
const basicSection: SectionInfo = {
|
||||
labelPosition: LabelPosition.Left,
|
||||
title: '',
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.ClusterName', "Cluster name"),
|
||||
required: true,
|
||||
variableName: VariableNames.ClusterName_VariableName,
|
||||
defaultValue: 'mssql-cluster',
|
||||
useCustomValidator: true
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.ControllerUsername', "Controller username"),
|
||||
required: true,
|
||||
variableName: VariableNames.AdminUserName_VariableName,
|
||||
defaultValue: 'admin',
|
||||
useCustomValidator: true
|
||||
}, {
|
||||
type: FieldType.Password,
|
||||
label: localize('deployCluster.AdminPassword', "Password"),
|
||||
required: true,
|
||||
variableName: VariableNames.AdminPassword_VariableName,
|
||||
defaultValue: '',
|
||||
useCustomValidator: true,
|
||||
description: localize('deployCluster.AdminPasswordDescription', "You can also use this password to access SQL Server and gateway.")
|
||||
}, {
|
||||
type: FieldType.Password,
|
||||
label: localize('deployCluster.ConfirmPassword', "Confirm password"),
|
||||
required: true,
|
||||
variableName: ConfirmPasswordName,
|
||||
defaultValue: '',
|
||||
useCustomValidator: true,
|
||||
}, {
|
||||
type: FieldType.Options,
|
||||
label: localize('deployCluster.AuthenticationMode', "Authentication mode"),
|
||||
required: true,
|
||||
variableName: VariableNames.AuthenticationMode_VariableName,
|
||||
defaultValue: AuthenticationMode.Basic,
|
||||
options: [
|
||||
{
|
||||
name: AuthenticationMode.Basic,
|
||||
displayName: localize('deployCluster.AuthenticationMode.Basic', "Basic")
|
||||
},
|
||||
{
|
||||
name: AuthenticationMode.ActiveDirectory,
|
||||
displayName: localize('deployCluster.AuthenticationMode.ActiveDirectory', "Active Directory")
|
||||
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const activeDirectorySection: SectionInfo = {
|
||||
labelPosition: LabelPosition.Left,
|
||||
title: localize('deployCluster.ActiveDirectorySettings', "Active Directory settings"),
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.DistinguishedName', "Distinguished name"),
|
||||
required: true,
|
||||
variableName: VariableNames.DistinguishedName_VariableName,
|
||||
useCustomValidator: true
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.AdminPrincipals', "Admin principals"),
|
||||
required: true,
|
||||
variableName: VariableNames.AdminPrincipals_VariableName,
|
||||
useCustomValidator: true
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.UserPrincipals', "User principals"),
|
||||
required: true,
|
||||
variableName: VariableNames.UserPrincipals_VariableName,
|
||||
useCustomValidator: true
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.UpstreamIPAddresses', "Upstream IP Addresses"),
|
||||
required: true,
|
||||
variableName: VariableNames.UpstreamIPAddresses_VariableName,
|
||||
useCustomValidator: true
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.DNSName', "DNS name"),
|
||||
required: true,
|
||||
variableName: VariableNames.DnsName_VariableName,
|
||||
useCustomValidator: true
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.Realm', "Realm"),
|
||||
required: true,
|
||||
variableName: VariableNames.Realm_VariableName,
|
||||
useCustomValidator: true
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.AppOnwerPrincipals', "App owner principals"),
|
||||
required: true,
|
||||
variableName: VariableNames.AppOwnerPrincipals_VariableName,
|
||||
useCustomValidator: true
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.AppReaderPrincipals', "App reader principals"),
|
||||
required: true,
|
||||
variableName: VariableNames.AppReaderPrincipals_VariableName,
|
||||
useCustomValidator: true
|
||||
}
|
||||
]
|
||||
};
|
||||
this.pageObject.registerContent((view: azdata.ModelView) => {
|
||||
const basicSettingsGroup = createSection({
|
||||
view: view,
|
||||
container: self.wizard.wizardObject,
|
||||
sectionInfo: basicSection,
|
||||
onNewDisposableCreated: (disposable: vscode.Disposable): void => {
|
||||
self.wizard.registerDisposable(disposable);
|
||||
},
|
||||
onNewInputComponentCreated: (name: string, component: azdata.DropDownComponent | azdata.InputBoxComponent | azdata.CheckBoxComponent): void => {
|
||||
self.inputComponents[name] = component;
|
||||
},
|
||||
onNewValidatorCreated: (validator: Validator): void => {
|
||||
self.validators.push(validator);
|
||||
}
|
||||
});
|
||||
const activeDirectorySettingsGroup = createSection({
|
||||
view: view,
|
||||
container: self.wizard.wizardObject,
|
||||
sectionInfo: activeDirectorySection,
|
||||
onNewDisposableCreated: (disposable: vscode.Disposable): void => {
|
||||
self.wizard.registerDisposable(disposable);
|
||||
},
|
||||
onNewInputComponentCreated: (name: string, component: azdata.DropDownComponent | azdata.InputBoxComponent | azdata.CheckBoxComponent): void => {
|
||||
self.inputComponents[name] = component;
|
||||
},
|
||||
onNewValidatorCreated: (validator: Validator): void => {
|
||||
self.validators.push(validator);
|
||||
}
|
||||
});
|
||||
const basicSettingsFormItem = { title: '', component: basicSettingsGroup };
|
||||
const activeDirectoryFormItem = { title: '', component: activeDirectorySettingsGroup };
|
||||
const authModeDropdown = <azdata.DropDownComponent>this.inputComponents[VariableNames.AuthenticationMode_VariableName];
|
||||
const formBuilder = view.modelBuilder.formContainer().withFormItems(
|
||||
[basicSettingsFormItem],
|
||||
{
|
||||
horizontal: false,
|
||||
componentWidth: '100%'
|
||||
}
|
||||
);
|
||||
this.wizard.registerDisposable(authModeDropdown.onValueChanged(() => {
|
||||
const isBasicAuthMode = (<azdata.CategoryValue>authModeDropdown.value).name === 'basic';
|
||||
|
||||
if (isBasicAuthMode) {
|
||||
formBuilder.removeFormItem(activeDirectoryFormItem);
|
||||
} else {
|
||||
formBuilder.insertFormItem(activeDirectoryFormItem);
|
||||
}
|
||||
}));
|
||||
|
||||
const form = formBuilder.withLayout({ width: '100%' }).component();
|
||||
return view.initializeModel(form);
|
||||
});
|
||||
}
|
||||
|
||||
public onLeave() {
|
||||
setModelValues(this.inputComponents, this.wizard.model);
|
||||
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public onEnter() {
|
||||
const authModeDropdown = <azdata.DropDownComponent>this.inputComponents[VariableNames.AuthenticationMode_VariableName];
|
||||
if (authModeDropdown) {
|
||||
authModeDropdown.enabled = this.wizard.model.adAuthSupported;
|
||||
}
|
||||
|
||||
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
|
||||
this.wizard.wizardObject.message = { text: '' };
|
||||
if (pcInfo.newPage > pcInfo.lastPage) {
|
||||
const messages: string[] = [];
|
||||
const authMode = typeof authModeDropdown.value === 'string' ? authModeDropdown.value : authModeDropdown.value!.name;
|
||||
const requiredFieldsFilled: boolean = !isInputBoxEmpty(getInputBoxComponent(VariableNames.ClusterName_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.AdminUserName_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.AdminPassword_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(ConfirmPasswordName, this.inputComponents))
|
||||
&& (!(authMode === AuthenticationMode.ActiveDirectory) || (
|
||||
!isInputBoxEmpty(getInputBoxComponent(VariableNames.DistinguishedName_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.AdminPrincipals_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.UserPrincipals_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.UpstreamIPAddresses_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.DnsName_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.Realm_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.AppOwnerPrincipals_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.AppReaderPrincipals_VariableName, this.inputComponents))));
|
||||
if (!requiredFieldsFilled) {
|
||||
messages.push(MissingRequiredInformationErrorMessage);
|
||||
}
|
||||
|
||||
if (!isInputBoxEmpty(getInputBoxComponent(VariableNames.AdminPassword_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(ConfirmPasswordName, this.inputComponents))) {
|
||||
const password = getInputBoxComponent(VariableNames.AdminPassword_VariableName, this.inputComponents).value!;
|
||||
const confirmPassword = getInputBoxComponent(ConfirmPasswordName, this.inputComponents).value!;
|
||||
if (password !== confirmPassword) {
|
||||
messages.push(getPasswordMismatchMessage(localize('deployCluster.AdminPasswordField', "Password")));
|
||||
}
|
||||
if (!isValidSQLPassword(password)) {
|
||||
messages.push(getInvalidSQLPasswordMessage(localize('deployCluster.AdminPasswordField', "Password")));
|
||||
}
|
||||
}
|
||||
|
||||
if (messages.length > 0) {
|
||||
this.wizard.wizardObject.message = {
|
||||
text: messages.length === 1 ? messages[0] : localize('deployCluster.ValidationError', "There are some errors on this page, click 'Show Details' to view the errors."),
|
||||
description: messages.length === 1 ? undefined : messages.join(EOL),
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
}
|
||||
return messages.length === 0;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 nls from 'vscode-nls';
|
||||
import { DeployClusterWizard } from '../deployClusterWizard';
|
||||
import { WizardPageBase } from '../../wizardPageBase';
|
||||
import * as VariableNames from '../constants';
|
||||
import { createFlexContainer } from '../../modelViewUtils';
|
||||
import { BdcDeploymentType } from '../../../interfaces';
|
||||
import { BigDataClusterDeploymentProfile } from '../../../services/bigDataClusterDeploymentProfile';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class DeploymentProfilePage extends WizardPageBase<DeployClusterWizard> {
|
||||
|
||||
private _cards: azdata.CardComponent[] = [];
|
||||
private _cardContainer: azdata.FlexContainer | undefined;
|
||||
private _loadingComponent: azdata.LoadingComponent | undefined;
|
||||
private _view: azdata.ModelView | undefined;
|
||||
|
||||
constructor(wizard: DeployClusterWizard) {
|
||||
super(localize('deployCluster.summaryPageTitle', "Deployment configuration template"),
|
||||
localize('deployCluster.summaryPageDescription', "Select the target configuration template"), wizard);
|
||||
}
|
||||
|
||||
public initialize(): void {
|
||||
this.pageObject.registerContent((view: azdata.ModelView) => {
|
||||
this._view = view;
|
||||
this._cardContainer = view.modelBuilder.flexContainer().withLayout({ flexFlow: 'row', flexWrap: 'wrap' }).component();
|
||||
const hintText = view.modelBuilder.text().withProperties<azdata.TextComponentProperties>({
|
||||
value: localize('deployCluster.ProfileHintText', "Note: The settings of the deployment profile can be customized in later steps.")
|
||||
}).component();
|
||||
const container = createFlexContainer(view, [this._cardContainer, hintText], false);
|
||||
this._loadingComponent = view.modelBuilder.loadingComponent().withItem(container).withProperties<azdata.LoadingComponentProperties>({
|
||||
loading: true
|
||||
}).component();
|
||||
let formBuilder = view.modelBuilder.formContainer().withFormItems(
|
||||
[
|
||||
{
|
||||
title: '',
|
||||
component: this._loadingComponent
|
||||
}
|
||||
],
|
||||
{
|
||||
horizontal: false
|
||||
}
|
||||
).withLayout({ width: '100%', height: '100%' });
|
||||
const form = formBuilder.withLayout({ width: '100%' }).component();
|
||||
this.loadCards().then(() => {
|
||||
this._loadingComponent!.loading = false;
|
||||
}, (error) => {
|
||||
this.wizard.wizardObject.message = {
|
||||
level: azdata.window.MessageLevel.Error,
|
||||
text: localize('deployCluster.loadProfileFailed', "Failed to load the deployment profiles: {0}", error.message)
|
||||
};
|
||||
this._loadingComponent!.loading = false;
|
||||
});
|
||||
return view.initializeModel(form);
|
||||
});
|
||||
}
|
||||
|
||||
private createProfileCard(profile: BigDataClusterDeploymentProfile, view: azdata.ModelView): azdata.CardComponent {
|
||||
const descriptions: azdata.CardDescriptionItem[] = [{
|
||||
label: localize('deployCluster.serviceLabel', "Service"),
|
||||
value: localize('deployCluster.instancesLabel', "Instances"),
|
||||
fontWeight: 'bold'
|
||||
}, {
|
||||
label: localize('deployCluster.masterPoolLabel', "SQL Server Master"),
|
||||
value: profile.sqlServerReplicas.toString()
|
||||
}, {
|
||||
label: localize('deployCluster.computePoolLable', "Compute"),
|
||||
value: profile.computeReplicas.toString()
|
||||
}, {
|
||||
label: localize('deployCluster.dataPoolLabel', "Data"),
|
||||
value: profile.dataReplicas.toString()
|
||||
}, {
|
||||
label: localize('deployCluster.hdfsLabel', "HDFS + Spark"),
|
||||
value: profile.hdfsReplicas.toString()
|
||||
}, {
|
||||
label: '' // line separator
|
||||
}, {
|
||||
label: localize('deployCluster.defaultDataStorage', "Data storage size (GB)"),
|
||||
value: profile.controllerDataStorageSize.toString()
|
||||
}, {
|
||||
label: localize('deployCluster.defaultLogStorage', "Log storage size (GB)"),
|
||||
value: profile.controllerLogsStorageSize.toString()
|
||||
}, {
|
||||
label: '' // line separator
|
||||
}
|
||||
];
|
||||
if (profile.activeDirectorySupported) {
|
||||
descriptions.push({
|
||||
label: localize('deployCluster.activeDirectoryAuthentication', "Active Directory authentication"),
|
||||
value: '✅'
|
||||
});
|
||||
} else {
|
||||
descriptions.push({
|
||||
label: localize('deployCluster.basicAuthentication', "Basic authentication"),
|
||||
value: '✅'
|
||||
});
|
||||
}
|
||||
|
||||
if (profile.hadrEnabled) {
|
||||
descriptions.push({
|
||||
label: localize('deployCluster.hadr', "High Availability"),
|
||||
value: '✅'
|
||||
});
|
||||
}
|
||||
|
||||
const card = view.modelBuilder.card().withProperties<azdata.CardProperties>({
|
||||
cardType: azdata.CardType.VerticalButton,
|
||||
label: profile.profileName,
|
||||
descriptions: descriptions,
|
||||
width: '240px',
|
||||
height: '300px',
|
||||
}).component();
|
||||
this._cards.push(card);
|
||||
this.wizard.registerDisposable(card.onCardSelectedChanged(() => {
|
||||
if (card.selected) {
|
||||
this.wizard.wizardObject.message = { text: '' };
|
||||
this.setModelValuesByProfile(profile);
|
||||
// clear the selected state of the previously selected card
|
||||
this._cards.forEach(c => {
|
||||
if (c !== card) {
|
||||
c.selected = false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// keep the selected state if no other card is selected
|
||||
if (this._cards.filter(c => { return c !== card && c.selected; }).length === 0) {
|
||||
card.selected = true;
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
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.EnableHADR_VariableName, selectedProfile.hadrEnabled);
|
||||
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.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.adAuthSupported = selectedProfile.activeDirectorySupported;
|
||||
this.wizard.model.selectedProfile = selectedProfile;
|
||||
}
|
||||
|
||||
private loadCards(): Promise<void> {
|
||||
return this.wizard.azdataService.getDeploymentProfiles().then((profiles: BigDataClusterDeploymentProfile[]) => {
|
||||
const defaultProfile: string = this.getDefaultProfile();
|
||||
|
||||
profiles.forEach(profile => {
|
||||
const card = this.createProfileCard(profile, this._view!);
|
||||
if (profile.profileName === defaultProfile) {
|
||||
card.selected = true;
|
||||
this.setModelValuesByProfile(profile);
|
||||
}
|
||||
this._cardContainer!.addItem(card, { flex: '0 0 auto' });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public onEnter() {
|
||||
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
|
||||
this.wizard.wizardObject.message = { text: '' };
|
||||
if (pcInfo.newPage > pcInfo.lastPage) {
|
||||
const isValid = this.wizard.model.getStringValue(VariableNames.DeploymentProfile_VariableName) !== undefined;
|
||||
if (!isValid) {
|
||||
this.wizard.wizardObject.message = {
|
||||
text: localize('deployCluster.ProfileNotSelectedError', "Please select a deployment profile."),
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public onLeave() {
|
||||
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private getDefaultProfile(): string {
|
||||
switch (this.wizard.deploymentType) {
|
||||
case BdcDeploymentType.NewAKS:
|
||||
case BdcDeploymentType.ExistingAKS:
|
||||
return 'aks-dev-test';
|
||||
case BdcDeploymentType.ExistingKubeAdm:
|
||||
return 'kubeadm-dev-test';
|
||||
default:
|
||||
throw new Error(`Unknown deployment type: ${this.wizard.deploymentType}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,563 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 * as nls from 'vscode-nls';
|
||||
import { DeployClusterWizard } from '../deployClusterWizard';
|
||||
import { SectionInfo, FieldType } from '../../../interfaces';
|
||||
import { Validator, InputComponents, createSection, createGroupContainer, createLabel, createFlexContainer, createTextInput, createNumberInput, setModelValues, getInputBoxComponent, getCheckboxComponent, isInputBoxEmpty, getDropdownComponent, MissingRequiredInformationErrorMessage } from '../../modelViewUtils';
|
||||
import { WizardPageBase } from '../../wizardPageBase';
|
||||
import * as VariableNames from '../constants';
|
||||
import { AuthenticationMode } from '../deployClusterWizardModel';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
const PortInputWidth = '100px';
|
||||
const inputWidth = '180px';
|
||||
const labelWidth = '150px';
|
||||
const spaceBetweenFields = '5px';
|
||||
|
||||
export class ServiceSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
private inputComponents: InputComponents = {};
|
||||
private endpointHeaderRow!: azdata.FlexContainer;
|
||||
private dnsColumnHeader!: azdata.TextComponent;
|
||||
private portColumnHeader!: azdata.TextComponent;
|
||||
private controllerDNSInput!: azdata.InputBoxComponent;
|
||||
private controllerPortInput!: azdata.InputBoxComponent;
|
||||
private controllerEndpointRow!: azdata.FlexContainer;
|
||||
private sqlServerDNSInput!: azdata.InputBoxComponent;
|
||||
private sqlServerEndpointRow!: azdata.FlexContainer;
|
||||
private sqlServerPortInput!: azdata.InputBoxComponent;
|
||||
private gatewayDNSInput!: azdata.InputBoxComponent;
|
||||
private gatewayPortInput!: azdata.InputBoxComponent;
|
||||
private gatewayEndpointRow!: azdata.FlexContainer;
|
||||
private readableSecondaryDNSInput!: azdata.InputBoxComponent;
|
||||
private readableSecondaryPortInput!: azdata.InputBoxComponent;
|
||||
private readableSecondaryEndpointRow!: azdata.FlexContainer;
|
||||
private endpointNameColumnHeader!: azdata.TextComponent;
|
||||
private controllerNameLabel!: azdata.TextComponent;
|
||||
private SqlServerNameLabel!: azdata.TextComponent;
|
||||
private gatewayNameLabel!: azdata.TextComponent;
|
||||
private readableSecondaryNameLabel!: azdata.TextComponent;
|
||||
|
||||
constructor(wizard: DeployClusterWizard) {
|
||||
super(localize('deployCluster.ServiceSettingsPageTitle', "Service settings"), '', wizard);
|
||||
}
|
||||
public initialize(): void {
|
||||
const scaleSectionInfo: SectionInfo = {
|
||||
title: localize('deployCluster.scaleSectionTitle', "Scale settings"),
|
||||
labelWidth: labelWidth,
|
||||
inputWidth: inputWidth,
|
||||
spaceBetweenFields: spaceBetweenFields,
|
||||
rows: [{
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Number,
|
||||
label: localize('deployCluster.ComputeText', "Compute"),
|
||||
min: 1,
|
||||
max: 100,
|
||||
defaultValue: '1',
|
||||
useCustomValidator: true,
|
||||
required: true,
|
||||
variableName: VariableNames.ComputePoolScale_VariableName,
|
||||
}
|
||||
]
|
||||
}, {
|
||||
fields: [{
|
||||
type: FieldType.Number,
|
||||
label: localize('deployCluster.DataText', "Data"),
|
||||
min: 1,
|
||||
max: 100,
|
||||
defaultValue: '1',
|
||||
useCustomValidator: true,
|
||||
required: true,
|
||||
variableName: VariableNames.DataPoolScale_VariableName,
|
||||
}]
|
||||
}, {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Number,
|
||||
label: localize('deployCluster.HDFSText', "HDFS"),
|
||||
min: 1,
|
||||
max: 100,
|
||||
defaultValue: '1',
|
||||
useCustomValidator: true,
|
||||
required: true,
|
||||
variableName: VariableNames.HDFSPoolScale_VariableName
|
||||
}, {
|
||||
type: FieldType.Checkbox,
|
||||
label: localize('deployCluster.includeSparkInHDFSPool', "Include Spark"),
|
||||
defaultValue: 'true',
|
||||
variableName: VariableNames.IncludeSpark_VariableName,
|
||||
required: false
|
||||
}
|
||||
]
|
||||
}, {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Number,
|
||||
label: localize('deployCluster.SparkText', "Spark"),
|
||||
min: 0,
|
||||
max: 100,
|
||||
defaultValue: '0',
|
||||
useCustomValidator: true,
|
||||
required: true,
|
||||
variableName: VariableNames.SparkPoolScale_VariableName
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const hadrSectionInfo: SectionInfo = {
|
||||
title: localize('deployCluster.HadrSection', "High availability settings"),
|
||||
labelWidth: labelWidth,
|
||||
inputWidth: inputWidth,
|
||||
spaceBetweenFields: spaceBetweenFields,
|
||||
rows: [{
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Options,
|
||||
label: localize('deployCluster.MasterSqlText', "SQL Server Master"),
|
||||
options: ['1', '3', '4', '5', '6', '7', '8', '9'],
|
||||
defaultValue: '1',
|
||||
required: true,
|
||||
variableName: VariableNames.SQLServerScale_VariableName,
|
||||
}, {
|
||||
type: FieldType.Checkbox,
|
||||
label: localize('deployCluster.EnableHADR', "Enable Availability Groups"),
|
||||
defaultValue: 'false',
|
||||
variableName: VariableNames.EnableHADR_VariableName,
|
||||
required: false
|
||||
}
|
||||
]
|
||||
}, {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Number,
|
||||
label: localize('deployCluster.HDFSNameNodeText', "HDFS name node"),
|
||||
min: 1,
|
||||
max: 100,
|
||||
defaultValue: '1',
|
||||
useCustomValidator: true,
|
||||
required: true,
|
||||
variableName: VariableNames.HDFSNameNodeScale_VariableName
|
||||
}
|
||||
]
|
||||
}, {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Number,
|
||||
label: localize('deployCluster.SparkHeadText', "SparkHead"),
|
||||
min: 0,
|
||||
max: 100,
|
||||
defaultValue: '1',
|
||||
useCustomValidator: true,
|
||||
required: true,
|
||||
variableName: VariableNames.SparkHeadScale_VariableName
|
||||
}
|
||||
]
|
||||
}, {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Number,
|
||||
label: localize('deployCluster.ZooKeeperText', "ZooKeeper"),
|
||||
min: 0,
|
||||
max: 100,
|
||||
defaultValue: '1',
|
||||
useCustomValidator: true,
|
||||
required: true,
|
||||
variableName: VariableNames.ZooKeeperScale_VariableName
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const hintTextForStorageFields = localize('deployCluster.storageFieldTooltip', "Use controller settings");
|
||||
const storageSectionInfo: SectionInfo = {
|
||||
title: '',
|
||||
labelWidth: '0px',
|
||||
inputWidth: inputWidth,
|
||||
spaceBetweenFields: spaceBetweenFields,
|
||||
rows: [{
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: '',
|
||||
required: false,
|
||||
defaultValue: localize('deployCluster.DataStorageClassName', "Storage class for data"),
|
||||
variableName: '',
|
||||
labelWidth: labelWidth
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: '',
|
||||
required: false,
|
||||
defaultValue: localize('deployCluster.DataClaimSize', "Claim size for data (GB)"),
|
||||
variableName: ''
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: '',
|
||||
required: false,
|
||||
defaultValue: localize('deployCluster.LogStorageClassName', "Storage class for logs"),
|
||||
variableName: '',
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: '',
|
||||
required: false,
|
||||
defaultValue: localize('deployCluster.LogsClaimSize', "Claim size for logs (GB)"),
|
||||
variableName: ''
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.ControllerText', "Controller"),
|
||||
useCustomValidator: true,
|
||||
variableName: VariableNames.ControllerDataStorageClassName_VariableName,
|
||||
required: true,
|
||||
description: localize('deployCluster.AdvancedStorageDescription', "By default Controller storage settings will be applied to other services as well, you can expand the advanced storage settings to configure storage for other services."),
|
||||
labelWidth: labelWidth
|
||||
}, {
|
||||
type: FieldType.Number,
|
||||
label: '',
|
||||
useCustomValidator: true,
|
||||
min: 1,
|
||||
variableName: VariableNames.ControllerDataStorageSize_VariableName,
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: '',
|
||||
useCustomValidator: true,
|
||||
min: 1,
|
||||
variableName: VariableNames.ControllerLogsStorageClassName_VariableName,
|
||||
}, {
|
||||
type: FieldType.Number,
|
||||
label: '',
|
||||
useCustomValidator: true,
|
||||
min: 1,
|
||||
variableName: VariableNames.ControllerLogsStorageSize_VariableName,
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
const advancedStorageSectionInfo: SectionInfo = {
|
||||
title: localize('deployCluster.AdvancedStorageSectionTitle', "Advanced storage settings"),
|
||||
labelWidth: '0px',
|
||||
inputWidth: inputWidth,
|
||||
spaceBetweenFields: spaceBetweenFields,
|
||||
collapsible: true,
|
||||
collapsed: true,
|
||||
rows: [{
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.HDFSText', "HDFS"),
|
||||
required: false,
|
||||
variableName: VariableNames.HDFSDataStorageClassName_VariableName,
|
||||
placeHolder: hintTextForStorageFields,
|
||||
labelWidth: labelWidth
|
||||
}, {
|
||||
type: FieldType.Number,
|
||||
label: '',
|
||||
required: false,
|
||||
min: 1,
|
||||
variableName: VariableNames.HDFSDataStorageSize_VariableName,
|
||||
placeHolder: hintTextForStorageFields
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: '',
|
||||
required: false,
|
||||
variableName: VariableNames.HDFSLogsStorageClassName_VariableName,
|
||||
placeHolder: hintTextForStorageFields
|
||||
}, {
|
||||
type: FieldType.Number,
|
||||
label: '',
|
||||
required: false,
|
||||
min: 1,
|
||||
variableName: VariableNames.HDFSLogsStorageSize_VariableName,
|
||||
placeHolder: hintTextForStorageFields
|
||||
}
|
||||
]
|
||||
}, {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.DataText', "Data"),
|
||||
required: false,
|
||||
variableName: VariableNames.DataPoolDataStorageClassName_VariableName,
|
||||
labelWidth: labelWidth,
|
||||
placeHolder: hintTextForStorageFields
|
||||
}, {
|
||||
type: FieldType.Number,
|
||||
label: '',
|
||||
required: false,
|
||||
min: 1,
|
||||
variableName: VariableNames.DataPoolDataStorageSize_VariableName,
|
||||
placeHolder: hintTextForStorageFields
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: '',
|
||||
required: false,
|
||||
variableName: VariableNames.DataPoolLogsStorageClassName_VariableName,
|
||||
placeHolder: hintTextForStorageFields
|
||||
}, {
|
||||
type: FieldType.Number,
|
||||
label: '',
|
||||
required: false,
|
||||
min: 1,
|
||||
variableName: VariableNames.DataPoolLogsStorageSize_VariableName,
|
||||
placeHolder: hintTextForStorageFields
|
||||
}
|
||||
]
|
||||
}, {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.MasterSqlText', "SQL Server Master"),
|
||||
required: false,
|
||||
variableName: VariableNames.SQLServerDataStorageClassName_VariableName,
|
||||
labelWidth: labelWidth,
|
||||
placeHolder: hintTextForStorageFields
|
||||
}, {
|
||||
type: FieldType.Number,
|
||||
label: '',
|
||||
required: false,
|
||||
min: 1,
|
||||
variableName: VariableNames.SQLServerDataStorageSize_VariableName,
|
||||
placeHolder: hintTextForStorageFields
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: '',
|
||||
required: false,
|
||||
variableName: VariableNames.SQLServerLogsStorageClassName_VariableName,
|
||||
placeHolder: hintTextForStorageFields
|
||||
}, {
|
||||
type: FieldType.Number,
|
||||
label: '',
|
||||
required: false,
|
||||
min: 1,
|
||||
variableName: VariableNames.SQLServerLogsStorageSize_VariableName,
|
||||
placeHolder: hintTextForStorageFields
|
||||
}
|
||||
]
|
||||
}]
|
||||
};
|
||||
|
||||
this.pageObject.registerContent((view: azdata.ModelView) => {
|
||||
const createSectionFunc = (sectionInfo: SectionInfo): azdata.GroupContainer => {
|
||||
return createSection({
|
||||
view: view,
|
||||
container: this.wizard.wizardObject,
|
||||
sectionInfo: sectionInfo,
|
||||
onNewDisposableCreated: (disposable: vscode.Disposable): void => {
|
||||
this.wizard.registerDisposable(disposable);
|
||||
},
|
||||
onNewInputComponentCreated: (name: string, component: azdata.DropDownComponent | azdata.InputBoxComponent | azdata.CheckBoxComponent): void => {
|
||||
this.inputComponents[name] = component;
|
||||
},
|
||||
onNewValidatorCreated: (validator: Validator): void => {
|
||||
}
|
||||
});
|
||||
};
|
||||
const scaleSection = createSectionFunc(scaleSectionInfo);
|
||||
const hadrSection = createSectionFunc(hadrSectionInfo);
|
||||
const endpointSection = this.createEndpointSection(view);
|
||||
const storageSection = createSectionFunc(storageSectionInfo);
|
||||
const advancedStorageSection = createSectionFunc(advancedStorageSectionInfo);
|
||||
const storageContainer = createGroupContainer(view, [storageSection, advancedStorageSection], {
|
||||
header: localize('deployCluster.StorageSectionTitle', "Storage settings"),
|
||||
collapsible: true
|
||||
});
|
||||
this.setSQLServerMasterFieldEventHandler();
|
||||
const form = view.modelBuilder.formContainer().withFormItems([
|
||||
{
|
||||
title: '',
|
||||
component: scaleSection
|
||||
}, {
|
||||
title: '',
|
||||
component: hadrSection
|
||||
}, {
|
||||
title: '',
|
||||
component: endpointSection
|
||||
}, {
|
||||
title: '',
|
||||
component: storageContainer
|
||||
}
|
||||
]).withLayout({ width: '100%' }).component();
|
||||
return view.initializeModel(form);
|
||||
});
|
||||
}
|
||||
|
||||
private createEndpointSection(view: azdata.ModelView): azdata.GroupContainer {
|
||||
this.endpointNameColumnHeader = createLabel(view, { text: '', width: labelWidth });
|
||||
this.dnsColumnHeader = createLabel(view, { text: localize('deployCluster.DNSNameHeader', "DNS name"), width: inputWidth });
|
||||
this.portColumnHeader = createLabel(view, { text: localize('deployCluster.PortHeader', "Port"), width: PortInputWidth });
|
||||
this.endpointHeaderRow = createFlexContainer(view, [this.endpointNameColumnHeader, this.dnsColumnHeader, this.portColumnHeader]);
|
||||
|
||||
this.controllerNameLabel = createLabel(view, { text: localize('deployCluster.ControllerText', "Controller"), width: labelWidth, required: true });
|
||||
this.controllerDNSInput = createTextInput(view, { ariaLabel: localize('deployCluster.ControllerDNSName', "Controller DNS name"), required: false, width: inputWidth });
|
||||
this.controllerPortInput = createNumberInput(view, { ariaLabel: localize('deployCluster.ControllerPortName', "Controller port"), required: true, width: PortInputWidth, min: 1 });
|
||||
this.controllerEndpointRow = createFlexContainer(view, [this.controllerNameLabel, this.controllerDNSInput, this.controllerPortInput]);
|
||||
this.inputComponents[VariableNames.ControllerDNSName_VariableName] = this.controllerDNSInput;
|
||||
this.inputComponents[VariableNames.ControllerPort_VariableName] = this.controllerPortInput;
|
||||
|
||||
this.SqlServerNameLabel = createLabel(view, { text: localize('deployCluster.MasterSqlText', "SQL Server Master"), width: labelWidth, required: true });
|
||||
this.sqlServerDNSInput = createTextInput(view, { ariaLabel: localize('deployCluster.MasterSQLServerDNSName', "SQL Server Master DNS name"), required: false, width: inputWidth });
|
||||
this.sqlServerPortInput = createNumberInput(view, { ariaLabel: localize('deployCluster.MasterSQLServerPortName', "SQL Server Master port"), required: true, width: PortInputWidth, min: 1 });
|
||||
this.sqlServerEndpointRow = createFlexContainer(view, [this.SqlServerNameLabel, this.sqlServerDNSInput, this.sqlServerPortInput]);
|
||||
this.inputComponents[VariableNames.SQLServerDNSName_VariableName] = this.sqlServerDNSInput;
|
||||
this.inputComponents[VariableNames.SQLServerPort_VariableName] = this.sqlServerPortInput;
|
||||
|
||||
this.gatewayNameLabel = createLabel(view, { text: localize('deployCluster.GatewayText', "Gateway"), width: labelWidth, required: true });
|
||||
this.gatewayDNSInput = createTextInput(view, { ariaLabel: localize('deployCluster.GatewayDNSName', "Gateway DNS name"), required: false, width: inputWidth });
|
||||
this.gatewayPortInput = createNumberInput(view, { ariaLabel: localize('deployCluster.GatewayPortName', "Gateway port"), required: true, width: PortInputWidth, min: 1 });
|
||||
this.gatewayEndpointRow = createFlexContainer(view, [this.gatewayNameLabel, this.gatewayDNSInput, this.gatewayPortInput]);
|
||||
this.inputComponents[VariableNames.GatewayDNSName_VariableName] = this.gatewayDNSInput;
|
||||
this.inputComponents[VariableNames.GateWayPort_VariableName] = this.gatewayPortInput;
|
||||
|
||||
this.readableSecondaryNameLabel = createLabel(view, { text: localize('deployCluster.ReadableSecondaryText', "Readable secondary"), width: labelWidth, required: true });
|
||||
this.readableSecondaryDNSInput = createTextInput(view, { ariaLabel: localize('deployCluster.ReadableSecondaryDNSName', "Readable secondary DNS name"), required: false, width: inputWidth });
|
||||
this.readableSecondaryPortInput = createNumberInput(view, { ariaLabel: localize('deployCluster.ReadableSecondaryPortName', "Readable secondary port"), required: false, width: PortInputWidth, min: 1 });
|
||||
this.readableSecondaryEndpointRow = createFlexContainer(view, [this.readableSecondaryNameLabel, this.readableSecondaryDNSInput, this.readableSecondaryPortInput]);
|
||||
this.inputComponents[VariableNames.ReadableSecondaryDNSName_VariableName] = this.readableSecondaryDNSInput;
|
||||
this.inputComponents[VariableNames.ReadableSecondaryPort_VariableName] = this.readableSecondaryPortInput;
|
||||
|
||||
return createGroupContainer(view, [this.endpointHeaderRow, this.controllerEndpointRow, this.sqlServerEndpointRow, this.gatewayEndpointRow, this.readableSecondaryEndpointRow], {
|
||||
header: localize('deployCluster.EndpointSettings', "Endpoint settings"),
|
||||
collapsible: true
|
||||
});
|
||||
}
|
||||
|
||||
public onEnter(): void {
|
||||
this.setDropdownValue(VariableNames.SQLServerScale_VariableName);
|
||||
this.setCheckboxValue(VariableNames.EnableHADR_VariableName);
|
||||
this.setInputBoxValue(VariableNames.ComputePoolScale_VariableName);
|
||||
this.setInputBoxValue(VariableNames.DataPoolScale_VariableName);
|
||||
this.setInputBoxValue(VariableNames.HDFSPoolScale_VariableName);
|
||||
this.setInputBoxValue(VariableNames.HDFSNameNodeScale_VariableName);
|
||||
this.setInputBoxValue(VariableNames.SparkPoolScale_VariableName);
|
||||
this.setInputBoxValue(VariableNames.SparkHeadScale_VariableName);
|
||||
this.setInputBoxValue(VariableNames.ZooKeeperScale_VariableName);
|
||||
this.setCheckboxValue(VariableNames.IncludeSpark_VariableName);
|
||||
this.setEnableHadrCheckboxState(this.wizard.model.getIntegerValue(VariableNames.SQLServerScale_VariableName));
|
||||
this.setInputBoxValue(VariableNames.ControllerPort_VariableName);
|
||||
this.setInputBoxValue(VariableNames.SQLServerPort_VariableName);
|
||||
this.setInputBoxValue(VariableNames.GateWayPort_VariableName);
|
||||
this.setInputBoxValue(VariableNames.ReadableSecondaryPort_VariableName);
|
||||
|
||||
this.setInputBoxValue(VariableNames.ControllerDataStorageClassName_VariableName);
|
||||
this.setInputBoxValue(VariableNames.ControllerDataStorageSize_VariableName);
|
||||
this.setInputBoxValue(VariableNames.ControllerLogsStorageClassName_VariableName);
|
||||
this.setInputBoxValue(VariableNames.ControllerLogsStorageSize_VariableName);
|
||||
|
||||
this.endpointHeaderRow.clearItems();
|
||||
if (this.wizard.model.authenticationMode === AuthenticationMode.ActiveDirectory) {
|
||||
this.endpointHeaderRow.addItems([this.endpointNameColumnHeader, this.dnsColumnHeader, this.portColumnHeader]);
|
||||
}
|
||||
this.loadEndpointRow(this.controllerEndpointRow, this.controllerNameLabel, this.controllerDNSInput, this.controllerPortInput);
|
||||
this.loadEndpointRow(this.gatewayEndpointRow, this.gatewayNameLabel, this.gatewayDNSInput, this.gatewayPortInput);
|
||||
this.loadEndpointRow(this.sqlServerEndpointRow, this.SqlServerNameLabel, this.sqlServerDNSInput, this.sqlServerPortInput);
|
||||
this.updateReadableSecondaryEndpointComponents(this.wizard.model.hadrEnabled);
|
||||
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
|
||||
this.wizard.wizardObject.message = { text: '' };
|
||||
if (pcInfo.newPage > pcInfo.lastPage) {
|
||||
const isValid: boolean = !isInputBoxEmpty(getInputBoxComponent(VariableNames.ComputePoolScale_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.DataPoolScale_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.HDFSNameNodeScale_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.HDFSPoolScale_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.SparkPoolScale_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.SparkHeadScale_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.ZooKeeperScale_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.ControllerDataStorageClassName_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.ControllerDataStorageSize_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.ControllerLogsStorageClassName_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.ControllerLogsStorageSize_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.ControllerPort_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.SQLServerPort_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.GateWayPort_VariableName, this.inputComponents))
|
||||
&& (!getCheckboxComponent(VariableNames.EnableHADR_VariableName, this.inputComponents).checked
|
||||
|| !isInputBoxEmpty(this.readableSecondaryPortInput))
|
||||
&& (this.wizard.model.authenticationMode !== AuthenticationMode.ActiveDirectory
|
||||
|| (!isInputBoxEmpty(this.gatewayDNSInput)
|
||||
&& !isInputBoxEmpty(this.controllerDNSInput)
|
||||
&& !isInputBoxEmpty(this.sqlServerDNSInput)
|
||||
&& !isInputBoxEmpty(this.readableSecondaryDNSInput)
|
||||
));
|
||||
if (!isValid) {
|
||||
this.wizard.wizardObject.message = {
|
||||
text: MissingRequiredInformationErrorMessage,
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public onLeave(): void {
|
||||
setModelValues(this.inputComponents, this.wizard.model);
|
||||
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private setInputBoxValue(variableName: string): void {
|
||||
getInputBoxComponent(variableName, this.inputComponents).value = this.wizard.model.getStringValue(variableName);
|
||||
}
|
||||
|
||||
private setCheckboxValue(variableName: string): void {
|
||||
getCheckboxComponent(variableName, this.inputComponents).checked = this.wizard.model.getBooleanValue(variableName);
|
||||
}
|
||||
|
||||
private setDropdownValue(variableName: string): void {
|
||||
getDropdownComponent(variableName, this.inputComponents).value = this.wizard.model.getStringValue(variableName);
|
||||
}
|
||||
|
||||
private setSQLServerMasterFieldEventHandler() {
|
||||
const sqlScaleDropdown = getDropdownComponent(VariableNames.SQLServerScale_VariableName, this.inputComponents);
|
||||
const enableHadrCheckbox = getCheckboxComponent(VariableNames.EnableHADR_VariableName, this.inputComponents);
|
||||
this.wizard.registerDisposable(sqlScaleDropdown.onValueChanged(() => {
|
||||
const selectedValue = typeof sqlScaleDropdown.value === 'string' ? sqlScaleDropdown.value : sqlScaleDropdown.value!.name;
|
||||
this.setEnableHadrCheckboxState(Number.parseInt(selectedValue));
|
||||
}));
|
||||
this.wizard.registerDisposable(enableHadrCheckbox.onChanged(() => {
|
||||
this.updateReadableSecondaryEndpointComponents(enableHadrCheckbox.checked);
|
||||
}));
|
||||
}
|
||||
|
||||
private setEnableHadrCheckboxState(sqlInstances: number) {
|
||||
// 1. it is ok to enable HADR when there is only 1 replica
|
||||
// 2. if there are multiple replicas, the hadr.enabled switch must be set to true.
|
||||
const enableHadrCheckbox = getCheckboxComponent(VariableNames.EnableHADR_VariableName, this.inputComponents);
|
||||
const hadrEnabled = sqlInstances === 1 ? enableHadrCheckbox.checked : true;
|
||||
if (sqlInstances === 1) {
|
||||
enableHadrCheckbox.enabled = true;
|
||||
} else {
|
||||
enableHadrCheckbox.enabled = false;
|
||||
}
|
||||
enableHadrCheckbox.checked = hadrEnabled;
|
||||
this.updateReadableSecondaryEndpointComponents(hadrEnabled);
|
||||
}
|
||||
|
||||
private updateReadableSecondaryEndpointComponents(hadrEnabled: boolean) {
|
||||
this.readableSecondaryEndpointRow.clearItems();
|
||||
if (hadrEnabled) {
|
||||
this.loadEndpointRow(this.readableSecondaryEndpointRow, this.readableSecondaryNameLabel, this.readableSecondaryDNSInput, this.readableSecondaryPortInput);
|
||||
}
|
||||
}
|
||||
|
||||
private loadEndpointRow(row: azdata.FlexContainer, label: azdata.TextComponent, dnsInput: azdata.InputBoxComponent, portInput: azdata.InputBoxComponent): void {
|
||||
row.clearItems();
|
||||
const itemLayout: azdata.FlexItemLayout = { CSSStyles: { 'margin-right': '20px' } };
|
||||
row.addItem(label);
|
||||
if (this.wizard.model.authenticationMode === AuthenticationMode.ActiveDirectory) {
|
||||
row.addItem(dnsInput, itemLayout);
|
||||
}
|
||||
row.addItem(portInput);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,415 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 nls from 'vscode-nls';
|
||||
import * as vscode from 'vscode';
|
||||
import { DeployClusterWizard } from '../deployClusterWizard';
|
||||
import { SectionInfo, FieldType, LabelPosition, FontStyle, BdcDeploymentType } from '../../../interfaces';
|
||||
import { createSection, createGroupContainer, createFlexContainer, createLabel } from '../../modelViewUtils';
|
||||
import { WizardPageBase } from '../../wizardPageBase';
|
||||
import * as VariableNames from '../constants';
|
||||
import * as os from 'os';
|
||||
import { join } from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { AuthenticationMode } from '../deployClusterWizardModel';
|
||||
import { BigDataClusterDeploymentProfile } from '../../../services/bigDataClusterDeploymentProfile';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class SummaryPage extends WizardPageBase<DeployClusterWizard> {
|
||||
private formItems: azdata.FormComponent[] = [];
|
||||
private form!: azdata.FormBuilder;
|
||||
private view!: azdata.ModelView;
|
||||
private targetDeploymentProfile!: BigDataClusterDeploymentProfile;
|
||||
|
||||
constructor(wizard: DeployClusterWizard) {
|
||||
super(localize('deployCluster.summaryPageTitle', "Summary"), '', wizard);
|
||||
}
|
||||
|
||||
public initialize(): void {
|
||||
this.pageObject.registerContent((view: azdata.ModelView) => {
|
||||
this.view = view;
|
||||
const deploymentJsonSection = createGroupContainer(view, [
|
||||
view.modelBuilder.flexContainer().withItems([
|
||||
this.createSaveJsonButton(localize('deployCluster.SaveBdcJson', "Save bdc.json"), 'bdc.json', () => { return this.targetDeploymentProfile.getBdcJson(); }),
|
||||
this.createSaveJsonButton(localize('deployCluster.SaveControlJson', "Save control.json"), 'control.json', () => { return this.targetDeploymentProfile.getControlJson(); })
|
||||
], {
|
||||
CSSStyles: { 'margin-right': '10px' }
|
||||
}).withLayout({ flexFlow: 'row', alignItems: 'center' }).component()
|
||||
], {
|
||||
header: localize('deployCluster.DeploymentJSON', "Deployment JSON files"),
|
||||
collapsible: true
|
||||
});
|
||||
|
||||
this.form = view.modelBuilder.formContainer().withFormItems([
|
||||
{
|
||||
title: '',
|
||||
component: deploymentJsonSection
|
||||
}
|
||||
]);
|
||||
return view.initializeModel(this.form!.withLayout({ width: '100%' }).component());
|
||||
});
|
||||
}
|
||||
|
||||
public onEnter() {
|
||||
this.targetDeploymentProfile = this.wizard.model.createTargetProfile();
|
||||
this.formItems.forEach(item => {
|
||||
this.form!.removeFormItem(item);
|
||||
});
|
||||
this.formItems = [];
|
||||
|
||||
const deploymentTargetSectionInfo: SectionInfo = {
|
||||
labelPosition: LabelPosition.Left,
|
||||
labelWidth: '150px',
|
||||
inputWidth: '200px',
|
||||
title: localize('deployCluster.DeploymentTarget', "Deployment target"),
|
||||
rows: [
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.Kubeconfig', "Kube config"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.KubeConfigPath_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
},
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.ClusterContext', "Cluster context"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.ClusterContext_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
}]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const clusterSectionInfo: SectionInfo = {
|
||||
labelPosition: LabelPosition.Left,
|
||||
labelWidth: '150px',
|
||||
inputWidth: '200px',
|
||||
title: localize('deployCluster.ClusterSettings', "Cluster settings"),
|
||||
rows: [
|
||||
{
|
||||
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.DeploymentProfile', "Deployment profile"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.DeploymentProfile_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
},
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.ClusterName', "Cluster name"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.ClusterName_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
}]
|
||||
}, {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.ControllerUsername', "Controller username"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.AdminUserName_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.AuthenticationMode', "Authentication mode"),
|
||||
defaultValue: this.wizard.model.authenticationMode === AuthenticationMode.ActiveDirectory ?
|
||||
localize('deployCluster.AuthenticationMode.ActiveDirectory', "Active Directory") :
|
||||
localize('deployCluster.AuthenticationMode.Basic', "Basic"),
|
||||
fontStyle: FontStyle.Italic
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const azureSectionInfo: SectionInfo = {
|
||||
labelPosition: LabelPosition.Left,
|
||||
labelWidth: '150px',
|
||||
inputWidth: '200px',
|
||||
title: localize('deployCluster.AzureSettings', "Azure settings"),
|
||||
rows: [{
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.SubscriptionId', "Subscription id"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.SubscriptionId_VariableName) || localize('deployCluster.DefaultSubscription', "Default Azure Subscription"),
|
||||
fontStyle: FontStyle.Italic
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.ResourceGroup', "Resource group"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.ResourceGroup_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
}
|
||||
]
|
||||
}, {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.Region', "Region"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.DeploymentProfile_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.AksClusterName', "AKS cluster name"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.AksName_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
}
|
||||
]
|
||||
}, {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.VMSize', "VM size"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.VMSize_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.VMCount', "VM count"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.VMCount_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const scaleSectionInfo: SectionInfo = {
|
||||
labelPosition: LabelPosition.Left,
|
||||
labelWidth: '150px',
|
||||
inputWidth: '200px',
|
||||
title: localize('deployCluster.ScaleSettings', "Scale settings"),
|
||||
rows: [
|
||||
{
|
||||
fields: [{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.ComputeText', "Compute"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.ComputePoolScale_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.DataText', "Data"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.DataPoolScale_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
}
|
||||
]
|
||||
}, {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.HDFSText', "HDFS"),
|
||||
defaultValue: `${this.wizard.model.getStringValue(VariableNames.HDFSPoolScale_VariableName)} ${this.wizard.model.getBooleanValue(VariableNames.IncludeSpark_VariableName) ? localize('deployCluster.WithSpark', "(Spark included)") : ''}`,
|
||||
fontStyle: FontStyle.Italic
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.SparkText', "Spark"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.SparkPoolScale_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const hadrSectionInfo: SectionInfo = {
|
||||
labelPosition: LabelPosition.Left,
|
||||
labelWidth: '150px',
|
||||
inputWidth: '200px',
|
||||
title: localize('deployCluster.HadrSection', "High availability settings"),
|
||||
rows: [
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.SqlServerText', "SQL Server Master"),
|
||||
defaultValue: `${this.wizard.model.getStringValue(VariableNames.SQLServerScale_VariableName)} ${this.wizard.model.hadrEnabled ? localize('deployCluster.WithHADR', "(Availability Groups Enabled)") : ''}`,
|
||||
fontStyle: FontStyle.Italic
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.HDFSNameNodeText', "HDFS name node"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.HDFSNameNodeScale_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
}
|
||||
]
|
||||
}, {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.ZooKeeperText', "ZooKeeper"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.ZooKeeperScale_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.SparkHeadText', "SparkHead"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.SparkHeadScale_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const createSectionFunc = (sectionInfo: SectionInfo): azdata.FormComponent => {
|
||||
return {
|
||||
title: '',
|
||||
component: createSection({
|
||||
container: this.wizard.wizardObject,
|
||||
sectionInfo: sectionInfo,
|
||||
view: this.view,
|
||||
onNewDisposableCreated: () => { },
|
||||
onNewInputComponentCreated: () => { },
|
||||
onNewValidatorCreated: () => { }
|
||||
})
|
||||
};
|
||||
};
|
||||
|
||||
if (this.wizard.deploymentType === BdcDeploymentType.ExistingAKS || this.wizard.deploymentType === BdcDeploymentType.ExistingKubeAdm) {
|
||||
const deploymentTargetSection = createSectionFunc(deploymentTargetSectionInfo);
|
||||
this.formItems.push(deploymentTargetSection);
|
||||
}
|
||||
|
||||
const clusterSection = createSectionFunc(clusterSectionInfo);
|
||||
const scaleSection = createSectionFunc(scaleSectionInfo);
|
||||
const hadrSection = createSectionFunc(hadrSectionInfo);
|
||||
const endpointSection = {
|
||||
title: '',
|
||||
component: this.createEndpointSection()
|
||||
};
|
||||
const storageSection = {
|
||||
title: '',
|
||||
component: this.createStorageSection()
|
||||
};
|
||||
if (this.wizard.model.getStringValue(VariableNames.AksName_VariableName)) {
|
||||
const azureSection = createSectionFunc(azureSectionInfo);
|
||||
this.formItems.push(azureSection);
|
||||
}
|
||||
|
||||
this.formItems.push(clusterSection, scaleSection, hadrSection, endpointSection, storageSection);
|
||||
this.form.addFormItems(this.formItems);
|
||||
}
|
||||
|
||||
private getStorageSettingValue(propertyName: string, defaultValuePropertyName: string): string | undefined {
|
||||
const value = this.wizard.model.getStringValue(propertyName);
|
||||
return (value === undefined || value === '') ? this.wizard.model.getStringValue(defaultValuePropertyName) : value;
|
||||
}
|
||||
|
||||
private createStorageSection(): azdata.GroupContainer {
|
||||
const serviceNameColumn: azdata.TableColumn = {
|
||||
value: ' ',
|
||||
width: 150
|
||||
};
|
||||
const dataStorageClassColumn: azdata.TableColumn = {
|
||||
value: localize('deployCluster.DataStorageClassName', "Storage class for data"),
|
||||
width: 180
|
||||
};
|
||||
const dataStorageSizeColumn: azdata.TableColumn = {
|
||||
value: localize('deployCluster.DataClaimSize', "Claim size for data (GB)"),
|
||||
width: 180
|
||||
};
|
||||
const logStorageClassColumn: azdata.TableColumn = {
|
||||
value: localize('deployCluster.LogStorageClassName', "Storage class for logs"),
|
||||
width: 180
|
||||
};
|
||||
const logStorageSizeColumn: azdata.TableColumn = {
|
||||
value: localize('deployCluster.LogsClaimSize', "Claim size for logs (GB)"),
|
||||
width: 180
|
||||
};
|
||||
const storageTable = this.view.modelBuilder.table().withProperties<azdata.TableComponentProperties>({
|
||||
data: [
|
||||
[
|
||||
localize('deployCluster.ControllerText', "Controller"),
|
||||
this.wizard.model.getStringValue(VariableNames.ControllerDataStorageClassName_VariableName),
|
||||
this.wizard.model.getStringValue(VariableNames.ControllerDataStorageSize_VariableName),
|
||||
this.wizard.model.getStringValue(VariableNames.ControllerLogsStorageClassName_VariableName),
|
||||
this.wizard.model.getStringValue(VariableNames.ControllerLogsStorageSize_VariableName)],
|
||||
[
|
||||
localize('deployCluster.HDFSText', "HDFS"),
|
||||
this.getStorageSettingValue(VariableNames.HDFSDataStorageClassName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName),
|
||||
this.getStorageSettingValue(VariableNames.HDFSDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName),
|
||||
this.getStorageSettingValue(VariableNames.HDFSLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName),
|
||||
this.getStorageSettingValue(VariableNames.HDFSLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName)
|
||||
], [
|
||||
localize('deployCluster.DataText', "Data"),
|
||||
this.getStorageSettingValue(VariableNames.DataPoolDataStorageClassName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName),
|
||||
this.getStorageSettingValue(VariableNames.DataPoolDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName),
|
||||
this.getStorageSettingValue(VariableNames.DataPoolLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName),
|
||||
this.getStorageSettingValue(VariableNames.DataPoolLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName)
|
||||
], [
|
||||
localize('deployCluster.MasterSqlText', "SQL Server Master"),
|
||||
this.getStorageSettingValue(VariableNames.SQLServerDataStorageClassName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName),
|
||||
this.getStorageSettingValue(VariableNames.SQLServerDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName),
|
||||
this.getStorageSettingValue(VariableNames.SQLServerLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName),
|
||||
this.getStorageSettingValue(VariableNames.SQLServerLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName)
|
||||
]
|
||||
],
|
||||
columns: [serviceNameColumn, dataStorageClassColumn, dataStorageSizeColumn, logStorageClassColumn, logStorageSizeColumn],
|
||||
width: '1000px',
|
||||
height: '140px'
|
||||
}).component();
|
||||
return createGroupContainer(this.view, [storageTable], {
|
||||
header: localize('deployCluster.StorageSettings', "Storage settings"),
|
||||
collapsible: true
|
||||
});
|
||||
}
|
||||
|
||||
private createEndpointSection(): azdata.GroupContainer {
|
||||
const endpointRows = [
|
||||
this.createEndpointRow(localize('deployCluster.ControllerText', "Controller"), VariableNames.ControllerDNSName_VariableName, VariableNames.ControllerPort_VariableName),
|
||||
this.createEndpointRow(localize('deployCluster.SqlServerText', "SQL Server Master"), VariableNames.SQLServerDNSName_VariableName, VariableNames.SQLServerPort_VariableName),
|
||||
this.createEndpointRow(localize('deployCluster.GatewayText', "Gateway"), VariableNames.GatewayDNSName_VariableName, VariableNames.GateWayPort_VariableName)
|
||||
];
|
||||
|
||||
if (this.wizard.model.hadrEnabled) {
|
||||
endpointRows.push(
|
||||
this.createEndpointRow(localize('deployCluster.ReadableSecondaryText', "Readable secondary"), VariableNames.ReadableSecondaryDNSName_VariableName, VariableNames.ReadableSecondaryPort_VariableName)
|
||||
);
|
||||
}
|
||||
return createGroupContainer(this.view, endpointRows, {
|
||||
header: localize('deployCluster.EndpointSettings', "Endpoint settings"),
|
||||
collapsible: true
|
||||
});
|
||||
}
|
||||
|
||||
private createEndpointRow(name: string, dnsVariableName: string, portVariableName: string): azdata.FlexContainer {
|
||||
const items = [];
|
||||
items.push(createLabel(this.view, { text: name, width: '150px' }));
|
||||
if (this.wizard.model.authenticationMode === AuthenticationMode.ActiveDirectory) {
|
||||
items.push(createLabel(this.view, { text: this.wizard.model.getStringValue(dnsVariableName)!, width: '200px', fontStyle: FontStyle.Italic }));
|
||||
}
|
||||
items.push(createLabel(this.view, { text: this.wizard.model.getStringValue(portVariableName)!, width: '100px', fontStyle: FontStyle.Italic }));
|
||||
return createFlexContainer(this.view, items);
|
||||
}
|
||||
|
||||
private createSaveJsonButton(label: string, fileName: string, getContent: () => string): azdata.ButtonComponent {
|
||||
const button = this.view.modelBuilder.button().withProperties<azdata.ButtonProperties>({
|
||||
title: label,
|
||||
label: fileName,
|
||||
ariaLabel: label,
|
||||
width: '150px'
|
||||
}).component();
|
||||
this.wizard.registerDisposable(button.onDidClick(() => {
|
||||
vscode.window.showSaveDialog({
|
||||
defaultUri: vscode.Uri.file(join(os.homedir(), fileName)),
|
||||
filters: {
|
||||
'JSON': ['json']
|
||||
}
|
||||
}).then((path) => {
|
||||
if (path) {
|
||||
fs.promises.writeFile(path.fsPath, getContent()).then(() => {
|
||||
this.wizard.wizardObject.message = {
|
||||
text: localize('deployCluster.SaveJsonFileMessage', "File saved: {0}", path.fsPath),
|
||||
level: azdata.window.MessageLevel.Information
|
||||
};
|
||||
}).catch((error) => {
|
||||
this.wizard.wizardObject.message = {
|
||||
text: error.message,
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
}));
|
||||
return button;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 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';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
const ClusterRadioButtonGroupName = 'ClusterRadioGroup';
|
||||
|
||||
export class TargetClusterContextPage extends WizardPageBase<DeployClusterWizard> {
|
||||
private existingClusterControl: azdata.FlexContainer | undefined;
|
||||
private clusterContextsLabel: azdata.TextComponent | undefined;
|
||||
private errorLoadingClustersLabel: azdata.TextComponent | undefined;
|
||||
private clusterContextList: azdata.DivContainer | undefined;
|
||||
private clusterContextLoadingComponent: azdata.LoadingComponent | undefined;
|
||||
private configFileInput: azdata.InputBoxComponent | undefined;
|
||||
private browseFileButton: azdata.ButtonComponent | undefined;
|
||||
private loadDefaultKubeConfigFile: boolean = true;
|
||||
private view: azdata.ModelView | undefined;
|
||||
|
||||
constructor(wizard: DeployClusterWizard) {
|
||||
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);
|
||||
}
|
||||
|
||||
public initialize(): void {
|
||||
this.pageObject.registerContent((view: azdata.ModelView) => {
|
||||
this.view = view;
|
||||
this.initExistingClusterControl();
|
||||
let formBuilder = view.modelBuilder.formContainer().withFormItems(
|
||||
[
|
||||
{
|
||||
component: this.existingClusterControl!,
|
||||
title: ''
|
||||
}
|
||||
],
|
||||
{
|
||||
horizontal: false
|
||||
}
|
||||
).withLayout({ width: '100%', height: '100%' });
|
||||
const form = formBuilder.withLayout({ width: '100%' }).component();
|
||||
return view.initializeModel(form);
|
||||
});
|
||||
}
|
||||
|
||||
public onEnter() {
|
||||
if (this.loadDefaultKubeConfigFile) {
|
||||
let defaultKubeConfigPath = this.wizard.kubeService.getDefautConfigPath();
|
||||
this.loadClusterContexts(defaultKubeConfigPath);
|
||||
this.loadDefaultKubeConfigFile = false;
|
||||
}
|
||||
|
||||
this.wizard.wizardObject.registerNavigationValidator((e) => {
|
||||
if (e.lastPage > e.newPage) {
|
||||
this.wizard.wizardObject.message = { text: '' };
|
||||
return true;
|
||||
}
|
||||
let clusterSelected = this.wizard.model.getStringValue(ClusterContext_VariableName) !== undefined;
|
||||
if (!clusterSelected) {
|
||||
this.wizard.wizardObject.message = {
|
||||
text: localize('deployCluster.ClusterContextNotSelectedMessage', 'Please select a cluster context.'),
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
}
|
||||
return clusterSelected;
|
||||
});
|
||||
}
|
||||
|
||||
public onLeave() {
|
||||
this.wizard.wizardObject.registerNavigationValidator((e) => {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private initExistingClusterControl(): void {
|
||||
let self = this;
|
||||
const labelWidth = '150px';
|
||||
let configFileLabel = this.view!.modelBuilder.text().withProperties({ value: localize('deployCluster.kubeConfigFileLabelText', 'Kube config file path') }).component();
|
||||
configFileLabel.width = labelWidth;
|
||||
this.configFileInput = this.view!.modelBuilder.inputBox().withProperties({ width: '300px' }).component();
|
||||
this.configFileInput.enabled = false;
|
||||
this.browseFileButton = this.view!.modelBuilder.button().withProperties({ label: localize('deployCluster.browseText', 'Browse'), width: '100px' }).component();
|
||||
let configFileContainer = this.view!.modelBuilder.flexContainer()
|
||||
.withLayout({ flexFlow: 'row', alignItems: 'baseline' })
|
||||
.withItems([configFileLabel, this.configFileInput, this.browseFileButton], { CSSStyles: { 'margin-right': '10px' } }).component();
|
||||
this.clusterContextsLabel = this.view!.modelBuilder.text().withProperties({ value: localize('deployCluster.clusterContextsLabelText', 'Cluster Contexts') }).component();
|
||||
this.clusterContextsLabel.width = labelWidth;
|
||||
this.errorLoadingClustersLabel = this.view!.modelBuilder.text().withProperties({ value: localize('deployCluster.errorLoadingClustersText', 'No cluster information is found in the config file or an error ocurred while loading the config file') }).component();
|
||||
this.clusterContextList = this.view!.modelBuilder.divContainer().component();
|
||||
this.clusterContextLoadingComponent = this.view!.modelBuilder.loadingComponent().withItem(this.clusterContextList).component();
|
||||
this.existingClusterControl = this.view!.modelBuilder.divContainer().withProperties<azdata.DivContainerProperties>({ clickable: false }).component();
|
||||
let clusterContextContainer = this.view!.modelBuilder.flexContainer().withLayout({ flexFlow: 'row', alignItems: 'start' }).component();
|
||||
clusterContextContainer.addItem(this.clusterContextsLabel, { flex: '0 0 auto' });
|
||||
clusterContextContainer.addItem(this.clusterContextLoadingComponent, { flex: '0 0 auto', CSSStyles: { 'width': '400px', 'margin-left': '10px', 'margin-top': '10px' } });
|
||||
|
||||
this.existingClusterControl.addItem(configFileContainer, { CSSStyles: { 'margin-top': '0px' } });
|
||||
this.existingClusterControl.addItem(clusterContextContainer, {
|
||||
CSSStyles: { 'margin- top': '10px' }
|
||||
});
|
||||
|
||||
this.wizard.registerDisposable(this.browseFileButton.onDidClick(async () => {
|
||||
let fileUris = await vscode.window.showOpenDialog(
|
||||
{
|
||||
canSelectFiles: true,
|
||||
canSelectFolders: false,
|
||||
canSelectMany: false,
|
||||
defaultUri: vscode.Uri.file(os.homedir()),
|
||||
openLabel: localize('deployCluster.selectKubeConfigFileText', 'Select'),
|
||||
filters: {
|
||||
'Config Files': ['*'],
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (!fileUris || fileUris.length === 0) {
|
||||
return;
|
||||
}
|
||||
self.clusterContextList!.clearItems();
|
||||
|
||||
let fileUri = fileUris[0];
|
||||
|
||||
self.loadClusterContexts(fileUri.fsPath);
|
||||
}));
|
||||
}
|
||||
|
||||
private async loadClusterContexts(configPath: string): Promise<void> {
|
||||
this.clusterContextLoadingComponent!.loading = true;
|
||||
this.wizard.model.setPropertyValue(ClusterContext_VariableName, undefined);
|
||||
this.wizard.wizardObject.message = { text: '' };
|
||||
let self = this;
|
||||
this.configFileInput!.value = configPath;
|
||||
|
||||
let clusterContexts: KubeClusterContext[] = [];
|
||||
try {
|
||||
clusterContexts = await this.wizard.kubeService.getClusterContexts(configPath);
|
||||
} catch (error) {
|
||||
this.wizard.wizardObject.message = {
|
||||
text: localize('deployCluster.ConfigParseError', "Failed to load the config file"),
|
||||
description: error.message || error, level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
}
|
||||
if (clusterContexts.length !== 0) {
|
||||
self.wizard.model.setPropertyValue(KubeConfigPath_VariableName, configPath);
|
||||
let options = clusterContexts.map(clusterContext => {
|
||||
let option = this.view!.modelBuilder.radioButton().withProperties<azdata.RadioButtonProperties>({
|
||||
label: clusterContext.name,
|
||||
checked: clusterContext.isCurrentContext,
|
||||
name: ClusterRadioButtonGroupName
|
||||
}).component();
|
||||
|
||||
if (clusterContext.isCurrentContext) {
|
||||
self.wizard.model.setPropertyValue(ClusterContext_VariableName, clusterContext.name);
|
||||
self.wizard.wizardObject.message = { text: '' };
|
||||
}
|
||||
|
||||
this.wizard.registerDisposable(option.onDidClick(() => {
|
||||
self.wizard.model.setPropertyValue(ClusterContext_VariableName, clusterContext.name);
|
||||
self.wizard.wizardObject.message = { text: '' };
|
||||
}));
|
||||
return option;
|
||||
});
|
||||
self.clusterContextList!.addItems(options);
|
||||
} else {
|
||||
self.clusterContextList!.addItem(this.errorLoadingClustersLabel!);
|
||||
}
|
||||
this.clusterContextLoadingComponent!.loading = false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user