mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-01 09:35:41 -05:00
deploy BDC wizard improvement for CU1 (#7756)
* unified admin user account (#7485) * azdata changes * spaces * error message * comments * support AD authentication for bdc deployment (#7518) * enable ad authentication * remove export for internal interface * add comments * more changes after testing * update notebooks * escape slash * more comments * Update deploy-bdc-aks.ipynb * Update deploy-bdc-existing-aks.ipynb * Update deploy-bdc-existing-kubeadm.ipynb * AD changes and review feedback (#7618) * enable ad authentication * remove export for internal interface * add comments * more changes after testing * update notebooks * escape slash * more comments * Update deploy-bdc-aks.ipynb * Update deploy-bdc-existing-aks.ipynb * Update deploy-bdc-existing-kubeadm.ipynb * address comments from scenario review (#7546) * support AD authentication for bdc deployment (#7518) * enable ad authentication * remove export for internal interface * add comments * more changes after testing * update notebooks * escape slash * more comments * Update deploy-bdc-aks.ipynb * Update deploy-bdc-existing-aks.ipynb * Update deploy-bdc-existing-kubeadm.ipynb * scenario review feedbacks * more fixes * adjust the display order of resource types * different way to implement left side buttons * revert unwanted changes * rename variable * more fixes for the scenario review feedback (#7589) * fix more issues * add help links * model view readonly text with links * fix size string * address comments * update notebooks * text update * address the feedback of 2nd round of deploy BDC wizard review (#7646) * 2nd review meeting comments * fix the unit test failure * recent changes in azdata * notebook background execution with azdata (#7741) * notebook background execution with azdata * prompt to open notebook in case of failure * fix path quote issue * better temp file handling * expose docker settings (#7751) * add docker settings * new icon for container image
This commit is contained in:
@@ -8,17 +8,20 @@ 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 OrganizationalUnitDistinguishedName_VariableName = 'AZDATA_NB_VAR_BDC_AD_OUDN';
|
||||
export const ClusterAdmins_VariableName = 'AZDATA_NB_VAR_BDC_AD_CLUSTER_ADMINS';
|
||||
export const ClusterUsers_VariableName = 'AZDATA_NB_VAR_BDC_AD_CLUSTER_USERS';
|
||||
export const DomainDNSIPAddresses_VariableName = 'AZDATA_NB_VAR_BDC_AD_UPSTREAM_IPADDRESSES';
|
||||
export const DomainControllerFQDNs_VariableName = 'AZDATA_NB_VAR_BDC_AD_DC_FQDNs';
|
||||
export const DomainDNSName_VariableName = 'AZDATA_NB_VAR_BDC_AD_DOMAIN_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 DomainServiceAccountUserName_VariableName = 'AZDATA_NB_VAR_BDC_AD_DOMAIN_SVC_USERNAME';
|
||||
export const DomainServiceAccountPassword_VariableName = 'AZDATA_NB_VAR_BDC_AD_DOMAIN_SVC_PASSWORD';
|
||||
export const AppOwners_VariableName = 'AZDATA_NB_VAR_AD_BDC_APP_OWNERS';
|
||||
export const AppReaders_VariableName = 'AZDATA_NB_VAR_AD_BDC_APP_READERS';
|
||||
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 Location_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';
|
||||
@@ -57,4 +60,12 @@ 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';
|
||||
export const ServiceProxyDNSName_VariableName = 'AZDATA_NB_VAR_BDC_SERVICEPROXY_DNS';
|
||||
export const ServiceProxyPort_VariableName = 'AZDATA_NB_VAR_BDC_SERVICEPROXY_PORT';
|
||||
export const AppServiceProxyDNSName_VariableName = 'AZDATA_NB_VAR_BDC_APPSERVICEPROXY_DNS';
|
||||
export const AppServiceProxyPort_VariableName = 'AZDATA_NB_VAR_BDC_APPSERVICEPROXY_PORT';
|
||||
export const DockerRepository_VariableName = 'AZDATA_NB_VAR_BDC_REPOSITORY';
|
||||
export const DockerRegistry_VariableName = 'AZDATA_NB_VAR_BDC_REGISTRY';
|
||||
export const DockerImageTag_VariableName = 'AZDATA_NB_VAR_BDC_DOCKER_IMAGE_TAG';
|
||||
export const DockerUsername_VariableName = 'AZDATA_NB_VAR_BDC_DOCKER_USERNAME';
|
||||
export const DockerPassword_VariableName = 'AZDATA_NB_VAR_BDC_DOCKER_PASSWORD';
|
||||
|
||||
@@ -15,14 +15,20 @@ 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 { IAzdataService, BdcEndpoint } from '../../services/azdataService';
|
||||
import { DeploymentProfilePage } from './pages/deploymentProfilePage';
|
||||
import { INotebookService } from '../../services/notebookService';
|
||||
import { DeployClusterWizardModel } from './deployClusterWizardModel';
|
||||
import { getErrorMessage, getDateTimeString } from '../../utils';
|
||||
import { DeployClusterWizardModel, AuthenticationMode } from './deployClusterWizardModel';
|
||||
import * as VariableNames from './constants';
|
||||
import * as os from 'os';
|
||||
import { join } from 'path';
|
||||
import * as fs from 'fs';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class DeployClusterWizard extends WizardBase<DeployClusterWizard, DeployClusterWizardModel> {
|
||||
private _saveConfigButton: azdata.window.Button;
|
||||
private _scriptToNotebookButton: azdata.window.Button;
|
||||
|
||||
public get kubeService(): IKubeService {
|
||||
return this._kubeService;
|
||||
@@ -36,8 +42,24 @@ export class DeployClusterWizard extends WizardBase<DeployClusterWizard, DeployC
|
||||
return this._notebookService;
|
||||
}
|
||||
|
||||
public get saveConfigButton(): azdata.window.Button {
|
||||
return this._saveConfigButton;
|
||||
}
|
||||
|
||||
public get scriptToNotebookButton(): azdata.window.Button {
|
||||
return this._scriptToNotebookButton;
|
||||
}
|
||||
|
||||
constructor(private wizardInfo: WizardInfo, private _kubeService: IKubeService, private _azdataService: IAzdataService, private _notebookService: INotebookService) {
|
||||
super(DeployClusterWizard.getTitle(wizardInfo.type), new DeployClusterWizardModel(wizardInfo.type));
|
||||
this._saveConfigButton = azdata.window.createButton(localize('deployCluster.SaveConfigFiles', "Save config files"), 'left');
|
||||
this._saveConfigButton.hidden = true;
|
||||
this._scriptToNotebookButton = azdata.window.createButton(localize('deployCluster.ScriptToNotebook', 'Script to Notebook'), 'left');
|
||||
this._scriptToNotebookButton.hidden = true;
|
||||
this.addButton(this._saveConfigButton);
|
||||
this.addButton(this._scriptToNotebookButton);
|
||||
this.registerDisposable(this._saveConfigButton.onClick(() => this.saveConfigFiles()));
|
||||
this.registerDisposable(this._scriptToNotebookButton.onClick(() => this.scriptToNotebook()));
|
||||
}
|
||||
|
||||
public get deploymentType(): BdcDeploymentType {
|
||||
@@ -47,23 +69,79 @@ export class DeployClusterWizard extends WizardBase<DeployClusterWizard, DeployC
|
||||
protected initialize(): void {
|
||||
this.setPages(this.getPages());
|
||||
this.wizardObject.generateScriptButton.hidden = true;
|
||||
this.wizardObject.doneButton.label = localize('deployCluster.ScriptToNotebook', 'Script to Notebook');
|
||||
this.wizardObject.doneButton.label = localize('deployCluster.Deploy', "Deploy");
|
||||
}
|
||||
|
||||
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({
|
||||
const taskName = localize('resourceDeployment.DeployBDCTask', "Deploy SQL Server Big Data Cluster \"{0}\"", this.model.getStringValue(VariableNames.ClusterName_VariableName));
|
||||
azdata.tasks.startBackgroundOperation({
|
||||
displayName: taskName,
|
||||
description: taskName,
|
||||
isCancelable: false,
|
||||
operation: async op => {
|
||||
op.updateStatus(azdata.TaskStatus.InProgress);
|
||||
const env: NodeJS.ProcessEnv = {};
|
||||
this.setEnvironmentVariables(env);
|
||||
const notebook = await this.notebookService.getNotebook(this.wizardInfo.azdata_notebook);
|
||||
notebook.cells.splice(3, 0, {
|
||||
cell_type: 'code',
|
||||
source: this.model.getCodeCellContentForNotebook()
|
||||
}, 7);
|
||||
});
|
||||
}, (error) => {
|
||||
vscode.window.showErrorMessage(error);
|
||||
source: this.model.getCodeCellContentForNotebook(),
|
||||
metadata: {},
|
||||
execution_count: 0,
|
||||
outputs: []
|
||||
});
|
||||
const result = await this.notebookService.executeNotebook(notebook, env);
|
||||
if (result.succeeded) {
|
||||
op.updateStatus(azdata.TaskStatus.Succeeded);
|
||||
const connectToMasterSql = localize('resourceDeployment.ConnectToMasterSQLServer', "Connect to Master SQL Server");
|
||||
const selectedOption = await vscode.window.showInformationMessage(localize('resourceDeployment.DeploymentSucceeded', "Successfully deployed SQL Server Big Data Cluster: {0}",
|
||||
this.model.getStringValue(VariableNames.ClusterName_VariableName)),
|
||||
connectToMasterSql);
|
||||
if (selectedOption === connectToMasterSql) {
|
||||
let endpoints: BdcEndpoint[];
|
||||
try {
|
||||
endpoints = await this.azdataService.getEndpoints(this.model.getStringValue(VariableNames.ClusterName_VariableName)!,
|
||||
this.model.getStringValue(VariableNames.AdminUserName_VariableName)!,
|
||||
this.model.getStringValue(VariableNames.AdminPassword_VariableName)!);
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(localize('resourceDeployment.ErroRetrievingEndpoints', "Failed to retrieve the endpoint list. {0}{1}", os.EOL, getErrorMessage(error)));
|
||||
return;
|
||||
}
|
||||
const sqlEndpoint = endpoints.find(endpoint => endpoint.name === 'sql-server-master');
|
||||
if (sqlEndpoint) {
|
||||
vscode.commands.executeCommand('azdata.connect', {
|
||||
serverName: sqlEndpoint.endpoint,
|
||||
providerName: 'MSSQL',
|
||||
authenticationType: 'SqlLogin',
|
||||
userName: this.model.getStringValue(VariableNames.AdminUserName_VariableName)!,
|
||||
password: this.model.getStringValue(VariableNames.AdminPassword_VariableName)!
|
||||
});
|
||||
} else {
|
||||
vscode.window.showErrorMessage(localize('resourceDeployment.NoSQLEndpointFound', "Master SQL Server endpoint is not found."));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
op.updateStatus(azdata.TaskStatus.Failed, result.errorMessage);
|
||||
if (result.outputNotebook) {
|
||||
const viewErrorDetail = localize('resourceDeployment.ViewErrorDetail', "View error detail");
|
||||
const selectedOption = await vscode.window.showErrorMessage(localize('resourceDeployment.DeployFailed', "Failed to deploy SQL Server Big Data Cluster \"{0}\".",
|
||||
this.model.getStringValue(VariableNames.ClusterName_VariableName)),
|
||||
viewErrorDetail);
|
||||
if (selectedOption === viewErrorDetail) {
|
||||
try {
|
||||
this.notebookService.launchNotebookWithContent(`deploy-${getDateTimeString()}`, result.outputNotebook);
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(localize('resourceDeployment.FailedToOpenNotebook', "An error occured launching the output notebook. {1}{2}.", os.EOL, getErrorMessage(error)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vscode.window.showErrorMessage(localize('resourceDeployment.DeployFailedNoOutputNotebook', "Failed to deploy SQL Server Big Data Cluster and no output notebook was generated."));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -100,6 +178,58 @@ export class DeployClusterWizard extends WizardBase<DeployClusterWizard, DeployC
|
||||
return pages;
|
||||
}
|
||||
|
||||
private async saveConfigFiles(): Promise<void> {
|
||||
const options: vscode.OpenDialogOptions = {
|
||||
defaultUri: vscode.Uri.file(os.homedir()),
|
||||
canSelectFiles: false,
|
||||
canSelectFolders: true,
|
||||
canSelectMany: false,
|
||||
openLabel: localize('deployCluster.SelectConfigFileFolder', "Save config files")
|
||||
};
|
||||
const pathArray = await vscode.window.showOpenDialog(options);
|
||||
if (pathArray && pathArray[0]) {
|
||||
const targetFolder = pathArray[0].fsPath;
|
||||
try {
|
||||
const profile = this.model.createTargetProfile();
|
||||
await fs.promises.writeFile(join(targetFolder, 'bdc.json'), profile.getBdcJson());
|
||||
await fs.promises.writeFile(join(targetFolder, 'control.json'), profile.getControlJson());
|
||||
this.wizardObject.message = {
|
||||
text: localize('deployCluster.SaveConfigFileSucceeded', "Config files saved to {0}", targetFolder),
|
||||
level: azdata.window.MessageLevel.Information
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
this.wizardObject.message = {
|
||||
text: error.message,
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private scriptToNotebook(): void {
|
||||
this.setEnvironmentVariables(process.env);
|
||||
this.notebookService.launchNotebook(this.wizardInfo.notebook).then((notebook: azdata.nb.NotebookEditor) => {
|
||||
notebook.edit((editBuilder: azdata.nb.NotebookEditorEdit) => {
|
||||
// 5 is the position after the 'Set variables' cell in the deployment notebooks
|
||||
editBuilder.insertCell({
|
||||
cell_type: 'code',
|
||||
source: this.model.getCodeCellContentForNotebook()
|
||||
}, 5);
|
||||
});
|
||||
}, (error) => {
|
||||
vscode.window.showErrorMessage(error);
|
||||
});
|
||||
}
|
||||
|
||||
private setEnvironmentVariables(env: NodeJS.ProcessEnv): void {
|
||||
env[VariableNames.AdminPassword_VariableName] = this.model.getStringValue(VariableNames.AdminPassword_VariableName);
|
||||
env[VariableNames.DockerPassword_VariableName] = this.model.getStringValue(VariableNames.DockerPassword_VariableName);
|
||||
if (this.model.authenticationMode === AuthenticationMode.ActiveDirectory) {
|
||||
env[VariableNames.DomainServiceAccountPassword_VariableName] = this.model.getStringValue(VariableNames.DomainServiceAccountPassword_VariableName);
|
||||
}
|
||||
}
|
||||
|
||||
static getTitle(type: BdcDeploymentType): string {
|
||||
switch (type) {
|
||||
case BdcDeploymentType.NewAKS:
|
||||
|
||||
@@ -15,14 +15,6 @@ export class DeployClusterWizardModel extends Model {
|
||||
}
|
||||
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);
|
||||
}
|
||||
@@ -71,6 +63,13 @@ export class DeployClusterWizardModel extends Model {
|
||||
const sourceBdcJson = Object.assign({}, this.selectedProfile!.bdcConfig);
|
||||
const sourceControlJson = Object.assign({}, this.selectedProfile!.controlConfig);
|
||||
const targetDeploymentProfile = new BigDataClusterDeploymentProfile('', sourceBdcJson, sourceControlJson);
|
||||
// docker settings
|
||||
targetDeploymentProfile.controlConfig.spec.docker = {
|
||||
registry: this.getStringValue(VariableNames.DockerRegistry_VariableName),
|
||||
repository: this.getStringValue(VariableNames.DockerRepository_VariableName),
|
||||
imageTag: this.getStringValue(VariableNames.DockerImageTag_VariableName),
|
||||
imagePullPolicy: 'Always'
|
||||
};
|
||||
// cluster name
|
||||
targetDeploymentProfile.clusterName = this.getStringValue(VariableNames.ClusterName_VariableName)!;
|
||||
// storage settings
|
||||
@@ -111,23 +110,37 @@ export class DeployClusterWizardModel extends Model {
|
||||
}
|
||||
|
||||
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);
|
||||
// endpoint settings
|
||||
targetDeploymentProfile.setGatewayEndpoint(this.getIntegerValue(VariableNames.GateWayPort_VariableName), this.getStringValue(VariableNames.GatewayDNSName_VariableName));
|
||||
targetDeploymentProfile.setSqlServerEndpoint(this.getIntegerValue(VariableNames.SQLServerPort_VariableName), this.getStringValue(VariableNames.SQLServerDNSName_VariableName));
|
||||
targetDeploymentProfile.setControllerEndpoint(this.getIntegerValue(VariableNames.ControllerPort_VariableName), this.getStringValue(VariableNames.ControllerDNSName_VariableName));
|
||||
targetDeploymentProfile.setSqlServerReadableSecondaryEndpoint(this.getIntegerValue(VariableNames.ReadableSecondaryPort_VariableName), this.getStringValue(VariableNames.ReadableSecondaryDNSName_VariableName));
|
||||
targetDeploymentProfile.setServiceProxyEndpoint(this.getIntegerValue(VariableNames.ServiceProxyPort_VariableName), this.getStringValue(VariableNames.ServiceProxyDNSName_VariableName));
|
||||
targetDeploymentProfile.setAppServiceProxyEndpoint(this.getIntegerValue(VariableNames.AppServiceProxyPort_VariableName), this.getStringValue(VariableNames.AppServiceProxyDNSName_VariableName));
|
||||
|
||||
targetDeploymentProfile.setAuthenticationMode(this.authenticationMode!);
|
||||
if (this.authenticationMode === AuthenticationMode.ActiveDirectory) {
|
||||
targetDeploymentProfile.setActiveDirectorySettings({
|
||||
organizationalUnit: this.getStringValue(VariableNames.OrganizationalUnitDistinguishedName_VariableName)!,
|
||||
domainControllerFQDNs: this.getStringValue(VariableNames.DomainControllerFQDNs_VariableName)!,
|
||||
domainDNSName: this.getStringValue(VariableNames.DomainDNSName_VariableName)!,
|
||||
dnsIPAddresses: this.getStringValue(VariableNames.DomainDNSIPAddresses_VariableName)!,
|
||||
clusterAdmins: this.getStringValue(VariableNames.ClusterAdmins_VariableName)!,
|
||||
clusterUsers: this.getStringValue(VariableNames.ClusterUsers_VariableName)!,
|
||||
appOwners: this.getStringValue(VariableNames.AppOwners_VariableName),
|
||||
appReaders: this.getStringValue(VariableNames.AppReaders_VariableName)
|
||||
});
|
||||
}
|
||||
return targetDeploymentProfile;
|
||||
}
|
||||
|
||||
public getCodeCellContentForNotebook(): string {
|
||||
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_region = '${this.getStringValue(VariableNames.Location_VariableName)}'`);
|
||||
statements.push(`azure_resource_group = '${this.getStringValue(VariableNames.ResourceGroup_VariableName)}'`);
|
||||
statements.push(`azure_vm_size = '${this.getStringValue(VariableNames.VMSize_VariableName)}'`);
|
||||
statements.push(`azure_vm_count = '${this.getStringValue(VariableNames.VMCount_VariableName)}'`);
|
||||
@@ -137,12 +150,20 @@ export class DeployClusterWizardModel extends Model {
|
||||
statements.push(`mssql_cluster_context = '${this.getStringValue(VariableNames.ClusterContext_VariableName)}'`);
|
||||
statements.push('os.environ["KUBECONFIG"] = mssql_kube_config_path');
|
||||
}
|
||||
if (this.authenticationMode === AuthenticationMode.ActiveDirectory) {
|
||||
statements.push(`mssql_domain_service_account_username = '${this.escapeForNotebookCodeCell(this.getStringValue(VariableNames.DomainServiceAccountUserName_VariableName)!)}'`);
|
||||
}
|
||||
statements.push(`mssql_cluster_name = '${this.getStringValue(VariableNames.ClusterName_VariableName)}'`);
|
||||
statements.push(`mssql_controller_username = '${this.getStringValue(VariableNames.AdminUserName_VariableName)}'`);
|
||||
statements.push(`mssql_username = '${this.getStringValue(VariableNames.AdminUserName_VariableName)}'`);
|
||||
statements.push(`mssql_auth_mode = '${this.authenticationMode}'`);
|
||||
statements.push(`bdc_json = '${profile.getBdcJson(false)}'`);
|
||||
statements.push(`control_json = '${profile.getControlJson(false)}'`);
|
||||
if (this.getStringValue(VariableNames.DockerUsername_VariableName) && this.getStringValue(VariableNames.DockerPassword_VariableName)) {
|
||||
statements.push(`os.environ["DOCKER_USERNAME"] = '${this.getStringValue(VariableNames.DockerUsername_VariableName)}'`);
|
||||
statements.push(`os.environ["DOCKER_PASSWORD"] = os.environ["${VariableNames.DockerPassword_VariableName}"]`);
|
||||
}
|
||||
statements.push(`print('Variables have been set successfully.')`);
|
||||
return statements.join(EOL);
|
||||
return statements.map(line => line + EOL);
|
||||
}
|
||||
|
||||
private escapeForNotebookCodeCell(original: string): string {
|
||||
|
||||
@@ -9,8 +9,8 @@ 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';
|
||||
import { createSection, InputComponents, setModelValues, Validator, getDropdownComponent, MissingRequiredInformationErrorMessage } from '../../modelViewUtils';
|
||||
import { SubscriptionId_VariableName, ResourceGroup_VariableName, Location_VariableName, AksName_VariableName, VMCount_VariableName, VMSize_VariableName } from '../constants';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class AzureSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
@@ -26,8 +26,9 @@ export class AzureSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
const azureSection: SectionInfo = {
|
||||
title: '',
|
||||
labelPosition: LabelPosition.Left,
|
||||
fields: [
|
||||
{
|
||||
spaceBetweenFields: '5px',
|
||||
rows: [{
|
||||
fields: [{
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.SubscriptionField', "Subscription id"),
|
||||
required: false,
|
||||
@@ -35,42 +36,100 @@ export class AzureSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
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.ReadonlyText,
|
||||
label: '',
|
||||
labelWidth: '0px',
|
||||
defaultValue: localize('deployCluster.SubscriptionHelpText', "{0}"),
|
||||
links: [
|
||||
{
|
||||
text: localize('deployCluster.SubscriptionHelpLink', "View available Azure subscriptions"),
|
||||
url: 'https://portal.azure.com/#blade/Microsoft_Azure_Billing/SubscriptionsBlade'
|
||||
}
|
||||
]
|
||||
}]
|
||||
}, {
|
||||
fields: [{
|
||||
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"),
|
||||
}]
|
||||
}, {
|
||||
fields: [{
|
||||
type: FieldType.Options,
|
||||
label: localize('deployCluster.Location', "Location"),
|
||||
required: true,
|
||||
variableName: Region_VariableName,
|
||||
defaultValue: 'eastus'
|
||||
variableName: Location_VariableName,
|
||||
defaultValue: 'eastus',
|
||||
editable: true,
|
||||
// The options are not localized because this is an editable dropdown,
|
||||
// It would cause confusion to user about what value to type in, if they type in the localized value, we don't know how to process.
|
||||
options: [
|
||||
'centralus',
|
||||
'eastus',
|
||||
'eastus2',
|
||||
'northcentralus',
|
||||
'southcentralus',
|
||||
'westus',
|
||||
'westus2',
|
||||
'canadacentral',
|
||||
'canadaeast'
|
||||
]
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: '',
|
||||
labelWidth: '0px',
|
||||
defaultValue: localize('deployCluster.LocationHelpText', "{0}"),
|
||||
links: [
|
||||
{
|
||||
text: localize('deployCluster.AzureLocationHelpLink', "View available Azure locations"),
|
||||
url: 'https://azure.microsoft.com/global-infrastructure/services/?products=kubernetes-service'
|
||||
}
|
||||
]
|
||||
}]
|
||||
}, {
|
||||
fields: [{
|
||||
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
|
||||
}, {
|
||||
}]
|
||||
}, {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Number,
|
||||
label: localize('deployCluster.VMCount', "VM count"),
|
||||
required: true,
|
||||
variableName: VMCount_VariableName,
|
||||
defaultValue: '5',
|
||||
min: 1,
|
||||
max: 999
|
||||
}
|
||||
]
|
||||
}, {
|
||||
fields: [{
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.VMSize', "VM size"),
|
||||
required: true,
|
||||
variableName: VMSize_VariableName,
|
||||
defaultValue: 'Standard_E4s_v3'
|
||||
}
|
||||
]
|
||||
defaultValue: 'Standard_E8s_v3'
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: '',
|
||||
labelWidth: '0px',
|
||||
defaultValue: localize('deployCluster.VMSizeHelpText', "{0}"),
|
||||
links: [
|
||||
{
|
||||
text: localize('deployCluster.VMSizeHelpLink', "View available VM sizes"),
|
||||
url: 'https://docs.microsoft.com/azure/virtual-machines/linux/sizes'
|
||||
}
|
||||
]
|
||||
}]
|
||||
}]
|
||||
};
|
||||
this.pageObject.registerContent((view: azdata.ModelView) => {
|
||||
|
||||
const azureGroup = createSection({
|
||||
sectionInfo: azureSection,
|
||||
view: view,
|
||||
@@ -101,7 +160,28 @@ export class AzureSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
});
|
||||
}
|
||||
|
||||
public onEnter(): void {
|
||||
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
|
||||
this.wizard.wizardObject.message = { text: '' };
|
||||
if (pcInfo.newPage > pcInfo.lastPage) {
|
||||
const location = getDropdownComponent(Location_VariableName, this.inputComponents).value;
|
||||
if (!location) {
|
||||
this.wizard.wizardObject.message = {
|
||||
text: MissingRequiredInformationErrorMessage,
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
}
|
||||
return !!location;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public onLeave(): void {
|
||||
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
|
||||
return true;
|
||||
});
|
||||
setModelValues(this.inputComponents, this.wizard.model);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ const localize = nls.loadMessageBundle();
|
||||
const ConfirmPasswordName = 'ConfirmPassword';
|
||||
export class ClusterSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
private inputComponents: InputComponents = {};
|
||||
private activeDirectorySection!: azdata.FormComponent;
|
||||
private formBuilder!: azdata.FormBuilder;
|
||||
|
||||
constructor(wizard: DeployClusterWizard) {
|
||||
super(localize('deployCluster.ClusterSettingsPageTitle', "Cluster settings"),
|
||||
@@ -39,11 +41,12 @@ export class ClusterSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
useCustomValidator: true
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.ControllerUsername', "Controller username"),
|
||||
label: localize('deployCluster.AdminUsername', "Admin username"),
|
||||
required: true,
|
||||
variableName: VariableNames.AdminUserName_VariableName,
|
||||
defaultValue: 'admin',
|
||||
useCustomValidator: true
|
||||
useCustomValidator: true,
|
||||
description: localize('deployCluster.AdminUsernameDescription', "This username will be used for controller and SQL Server. Username for the gateway will be root.")
|
||||
}, {
|
||||
type: FieldType.Password,
|
||||
label: localize('deployCluster.AdminPassword', "Password"),
|
||||
@@ -51,7 +54,7 @@ export class ClusterSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
variableName: VariableNames.AdminPassword_VariableName,
|
||||
defaultValue: '',
|
||||
useCustomValidator: true,
|
||||
description: localize('deployCluster.AdminPasswordDescription', "You can also use this password to access SQL Server and gateway.")
|
||||
description: localize('deployCluster.AdminPasswordDescription', "This password can be used to access the controller, SQL Server and gateway.")
|
||||
}, {
|
||||
type: FieldType.Password,
|
||||
label: localize('deployCluster.ConfirmPassword', "Confirm password"),
|
||||
@@ -80,58 +83,118 @@ export class ClusterSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
]
|
||||
};
|
||||
|
||||
const dockerSection: SectionInfo = {
|
||||
labelPosition: LabelPosition.Left,
|
||||
collapsed: true,
|
||||
collapsible: true,
|
||||
title: localize('deployCluster.DockerSettings', "Docker settings"),
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.DockerRegistry', "Registry"),
|
||||
required: true,
|
||||
variableName: VariableNames.DockerRegistry_VariableName
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.DockerRepository', "Repository"),
|
||||
required: true,
|
||||
variableName: VariableNames.DockerRepository_VariableName
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.DockerImageTag', "Image tag"),
|
||||
required: true,
|
||||
variableName: VariableNames.DockerImageTag_VariableName
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.DockerUsername', "Username"),
|
||||
required: false,
|
||||
variableName: VariableNames.DockerUsername_VariableName
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.DockerPassword', "Password"),
|
||||
required: false,
|
||||
variableName: VariableNames.DockerPassword_VariableName
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const activeDirectorySection: SectionInfo = {
|
||||
labelPosition: LabelPosition.Left,
|
||||
title: localize('deployCluster.ActiveDirectorySettings', "Active Directory settings"),
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.DistinguishedName', "Distinguished name"),
|
||||
label: localize('deployCluster.OuDistinguishedName', "Organizational unit"),
|
||||
required: true,
|
||||
variableName: VariableNames.DistinguishedName_VariableName,
|
||||
variableName: VariableNames.OrganizationalUnitDistinguishedName_VariableName,
|
||||
useCustomValidator: true,
|
||||
description: localize('deployCluster.OuDistinguishedNameDescription', "Distinguished name for the organizational unit. For example: OU=bdc,DC=contoso,DC=com.")
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.DomainControllerFQDNs', "Domain controller FQDNs"),
|
||||
required: true,
|
||||
variableName: VariableNames.DomainControllerFQDNs_VariableName,
|
||||
useCustomValidator: true,
|
||||
placeHolder: localize('deployCluster.DomainControllerFQDNsPlaceHolder', "Use comma to separate the values."),
|
||||
description: localize('deployCluster.DomainControllerFQDNDescription', "Fully qualified domain names for the domain controller. For example: DC1.CONTOSO.COM. Use comma to separate multiple FQDNs.")
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.DomainDNSIPAddresses', "Domain DNS IP addresses"),
|
||||
required: true,
|
||||
variableName: VariableNames.DomainDNSIPAddresses_VariableName,
|
||||
useCustomValidator: true,
|
||||
placeHolder: localize('deployCluster.DomainDNSIPAddressesPlaceHolder', "Use comma to separate the values."),
|
||||
description: localize('deployCluster.DomainDNSIPAddressesDescription', "Domain DNS servers' IP Addresses. Use comma to separate multiple IP addresses.")
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.DomainDNSName', "Domain DNS name"),
|
||||
required: true,
|
||||
variableName: VariableNames.DomainDNSName_VariableName,
|
||||
useCustomValidator: true
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.AdminPrincipals', "Admin principals"),
|
||||
label: localize('deployCluster.ClusterAdmins', "Cluster admin group"),
|
||||
required: true,
|
||||
variableName: VariableNames.AdminPrincipals_VariableName,
|
||||
variableName: VariableNames.ClusterAdmins_VariableName,
|
||||
useCustomValidator: true,
|
||||
description: localize('deployCluster.ClusterAdminsDescription', "The Active Directory group for cluster admin.")
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.ClusterUsers', "Cluster users"),
|
||||
required: true,
|
||||
variableName: VariableNames.ClusterUsers_VariableName,
|
||||
useCustomValidator: true,
|
||||
placeHolder: localize('deployCluster.ClusterUsersPlaceHolder', "Use comma to separate the values."),
|
||||
description: localize('deployCluster.ClusterUsersDescription', "The Active Directory users/groups with cluster users role. Use comma to separate multiple users/groups.")
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.DomainServiceAccountUserName', "Service account username"),
|
||||
required: true,
|
||||
variableName: VariableNames.DomainServiceAccountUserName_VariableName,
|
||||
useCustomValidator: true,
|
||||
description: localize('deployCluster.DomainServiceAccountUserNameDescription', "Domain service account for Big Data Cluster")
|
||||
}, {
|
||||
type: FieldType.Password,
|
||||
label: localize('deployCluster.DomainServiceAccountPassword', "Service account password"),
|
||||
required: true,
|
||||
variableName: VariableNames.DomainServiceAccountPassword_VariableName,
|
||||
useCustomValidator: true
|
||||
}, {
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.UserPrincipals', "User principals"),
|
||||
required: true,
|
||||
variableName: VariableNames.UserPrincipals_VariableName,
|
||||
useCustomValidator: true
|
||||
label: localize('deployCluster.AppOwers', "App owners"),
|
||||
required: false,
|
||||
variableName: VariableNames.AppOwners_VariableName,
|
||||
useCustomValidator: true,
|
||||
placeHolder: localize('deployCluster.AppOwnersPlaceHolder', "Use comma to separate the values."),
|
||||
description: localize('deployCluster.AppOwnersDescription', "The Active Directory users or groups with app owners role. Use comma to separate multiple users/groups.")
|
||||
}, {
|
||||
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
|
||||
label: localize('deployCluster.AppReaders', "App readers"),
|
||||
required: false,
|
||||
variableName: VariableNames.AppReaders_VariableName,
|
||||
useCustomValidator: true,
|
||||
placeHolder: localize('deployCluster.AppReadersPlaceHolder', "Use comma to separate the values."),
|
||||
description: localize('deployCluster.AppReadersDescription', "The Active Directory users or groups of app readers. Use comma as separator them if there are multiple users/groups.")
|
||||
}
|
||||
]
|
||||
};
|
||||
@@ -164,11 +227,26 @@ export class ClusterSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
self.validators.push(validator);
|
||||
}
|
||||
});
|
||||
const dockerSettingsGroup = createSection({
|
||||
view: view,
|
||||
container: self.wizard.wizardObject,
|
||||
sectionInfo: dockerSection,
|
||||
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 dockerSettingsFormItem = { title: '', component: dockerSettingsGroup };
|
||||
this.activeDirectorySection = { title: '', component: activeDirectorySettingsGroup };
|
||||
const authModeDropdown = <azdata.DropDownComponent>this.inputComponents[VariableNames.AuthenticationMode_VariableName];
|
||||
const formBuilder = view.modelBuilder.formContainer().withFormItems(
|
||||
[basicSettingsFormItem],
|
||||
this.formBuilder = view.modelBuilder.formContainer().withFormItems(
|
||||
[basicSettingsFormItem, dockerSettingsFormItem],
|
||||
{
|
||||
horizontal: false,
|
||||
componentWidth: '100%'
|
||||
@@ -176,76 +254,99 @@ export class ClusterSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
);
|
||||
this.wizard.registerDisposable(authModeDropdown.onValueChanged(() => {
|
||||
const isBasicAuthMode = (<azdata.CategoryValue>authModeDropdown.value).name === 'basic';
|
||||
|
||||
if (isBasicAuthMode) {
|
||||
formBuilder.removeFormItem(activeDirectoryFormItem);
|
||||
this.formBuilder.removeFormItem(this.activeDirectorySection);
|
||||
} else {
|
||||
formBuilder.insertFormItem(activeDirectoryFormItem);
|
||||
this.formBuilder.insertFormItem(this.activeDirectorySection);
|
||||
}
|
||||
}));
|
||||
|
||||
const form = formBuilder.withLayout({ width: '100%' }).component();
|
||||
const form = this.formBuilder.withLayout({ width: '100%' }).component();
|
||||
return view.initializeModel(form);
|
||||
});
|
||||
}
|
||||
|
||||
public onLeave() {
|
||||
setModelValues(this.inputComponents, this.wizard.model);
|
||||
if (this.wizard.model.authenticationMode === AuthenticationMode.ActiveDirectory) {
|
||||
const variableDNSPrefixMapping: { [s: string]: string } = {};
|
||||
variableDNSPrefixMapping[VariableNames.AppServiceProxyDNSName_VariableName] = 'bdc-appproxy';
|
||||
variableDNSPrefixMapping[VariableNames.ControllerDNSName_VariableName] = 'bdc-control';
|
||||
variableDNSPrefixMapping[VariableNames.GatewayDNSName_VariableName] = 'bdc-gateway';
|
||||
variableDNSPrefixMapping[VariableNames.ReadableSecondaryDNSName_VariableName] = 'bdc-sqlread';
|
||||
variableDNSPrefixMapping[VariableNames.SQLServerDNSName_VariableName] = 'bdc-sql';
|
||||
variableDNSPrefixMapping[VariableNames.ServiceProxyDNSName_VariableName] = 'bdc-proxy';
|
||||
|
||||
Object.keys(variableDNSPrefixMapping).forEach((variableName: string) => {
|
||||
if (!this.wizard.model.getStringValue(variableName)) {
|
||||
this.wizard.model.setPropertyValue(variableName, `${variableDNSPrefixMapping[variableName]}.${this.wizard.model.getStringValue(VariableNames.DomainDNSName_VariableName)}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public onEnter() {
|
||||
getInputBoxComponent(VariableNames.DockerRegistry_VariableName, this.inputComponents).value = this.wizard.model.getStringValue(VariableNames.DockerRegistry_VariableName);
|
||||
getInputBoxComponent(VariableNames.DockerRepository_VariableName, this.inputComponents).value = this.wizard.model.getStringValue(VariableNames.DockerRepository_VariableName);
|
||||
getInputBoxComponent(VariableNames.DockerImageTag_VariableName, this.inputComponents).value = this.wizard.model.getStringValue(VariableNames.DockerImageTag_VariableName);
|
||||
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;
|
||||
const adAuthSelected = (<azdata.CategoryValue>authModeDropdown.value).name === 'ad';
|
||||
if (!this.wizard.model.adAuthSupported && adAuthSelected) {
|
||||
this.formBuilder.removeFormItem(this.activeDirectorySection);
|
||||
authModeDropdown.value = {
|
||||
name: AuthenticationMode.Basic,
|
||||
displayName: localize('deployCluster.AuthenticationMode.Basic', "Basic")
|
||||
};
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
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.OrganizationalUnitDistinguishedName_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.DomainControllerFQDNs_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.ClusterAdmins_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.ClusterUsers_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.DomainDNSIPAddresses_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.DomainDNSName_VariableName, this.inputComponents))));
|
||||
if (!requiredFieldsFilled) {
|
||||
messages.push(MissingRequiredInformationErrorMessage);
|
||||
}
|
||||
|
||||
if (!isInputBoxEmpty(getInputBoxComponent(VariableNames.AdminUserName_VariableName, this.inputComponents))
|
||||
&& !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, getInputBoxComponent(VariableNames.AdminUserName_VariableName, this.inputComponents).value!)) {
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,31 +81,36 @@ export class DeploymentProfilePage extends WizardPageBase<DeployClusterWizard> {
|
||||
}, {
|
||||
label: '' // line separator
|
||||
}, {
|
||||
label: localize('deployCluster.defaultDataStorage', "Data storage size (GB)"),
|
||||
label: localize('deployCluster.storageSize', "Storage size"),
|
||||
value: localize('deployCluster.gbPerInstance', "GB per Instance"),
|
||||
fontWeight: 'bold'
|
||||
}, {
|
||||
label: localize('deployCluster.defaultDataStorage', "Data storage"),
|
||||
value: profile.controllerDataStorageSize.toString()
|
||||
}, {
|
||||
label: localize('deployCluster.defaultLogStorage', "Log storage size (GB)"),
|
||||
label: localize('deployCluster.defaultLogStorage', "Log storage"),
|
||||
value: profile.controllerLogsStorageSize.toString()
|
||||
}, {
|
||||
label: '' // line separator
|
||||
}
|
||||
];
|
||||
}, {
|
||||
label: localize('deployCluster.features', "Features"),
|
||||
value: '',
|
||||
fontWeight: 'bold'
|
||||
}, {
|
||||
label: localize('deployCluster.basicAuthentication', "Basic authentication"),
|
||||
value: ''
|
||||
}];
|
||||
if (profile.activeDirectorySupported) {
|
||||
descriptions.push({
|
||||
label: localize('deployCluster.activeDirectoryAuthentication', "Active Directory authentication"),
|
||||
value: '✅'
|
||||
});
|
||||
} else {
|
||||
descriptions.push({
|
||||
label: localize('deployCluster.basicAuthentication', "Basic authentication"),
|
||||
value: '✅'
|
||||
value: ''
|
||||
});
|
||||
}
|
||||
|
||||
if (profile.hadrEnabled) {
|
||||
if (profile.sqlServerReplicas > 1) {
|
||||
descriptions.push({
|
||||
label: localize('deployCluster.hadr', "High Availability"),
|
||||
value: '✅'
|
||||
value: ''
|
||||
});
|
||||
}
|
||||
|
||||
@@ -114,7 +119,7 @@ export class DeploymentProfilePage extends WizardPageBase<DeployClusterWizard> {
|
||||
label: profile.profileName,
|
||||
descriptions: descriptions,
|
||||
width: '240px',
|
||||
height: '300px',
|
||||
height: '320px',
|
||||
}).component();
|
||||
this._cards.push(card);
|
||||
this.wizard.registerDisposable(card.onCardSelectedChanged(() => {
|
||||
@@ -150,20 +155,24 @@ export class DeploymentProfilePage extends WizardPageBase<DeployClusterWizard> {
|
||||
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.ServiceProxyPort_VariableName, selectedProfile.serviceProxyPort);
|
||||
this.wizard.model.setPropertyValue(VariableNames.AppServiceProxyPort_VariableName, selectedProfile.appServiceProxyPort);
|
||||
this.wizard.model.setPropertyValue(VariableNames.IncludeSpark_VariableName, selectedProfile.includeSpark);
|
||||
this.wizard.model.setPropertyValue(VariableNames.ControllerDataStorageClassName_VariableName, selectedProfile.controllerDataStorageClass);
|
||||
this.wizard.model.setPropertyValue(VariableNames.ControllerLogsStorageClassName_VariableName, selectedProfile.controllerLogsStorageClass);
|
||||
this.wizard.model.setPropertyValue(VariableNames.ReadableSecondaryPort_VariableName, selectedProfile.sqlServerReadableSecondaryPort);
|
||||
this.wizard.model.setPropertyValue(VariableNames.DockerRegistry_VariableName, selectedProfile.registry);
|
||||
this.wizard.model.setPropertyValue(VariableNames.DockerRepository_VariableName, selectedProfile.repository);
|
||||
this.wizard.model.setPropertyValue(VariableNames.DockerImageTag_VariableName, selectedProfile.imageTag);
|
||||
this.wizard.model.adAuthSupported = selectedProfile.activeDirectorySupported;
|
||||
this.wizard.model.selectedProfile = selectedProfile;
|
||||
}
|
||||
|
||||
private loadCards(): Promise<void> {
|
||||
return this.wizard.azdataService.getDeploymentProfiles().then((profiles: BigDataClusterDeploymentProfile[]) => {
|
||||
return this.wizard.azdataService.getDeploymentProfiles(this.wizard.deploymentType).then((profiles: BigDataClusterDeploymentProfile[]) => {
|
||||
const defaultProfile: string = this.getDefaultProfile();
|
||||
|
||||
profiles.forEach(profile => {
|
||||
|
||||
@@ -13,9 +13,9 @@ import * as VariableNames from '../constants';
|
||||
import { AuthenticationMode } from '../deployClusterWizardModel';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
const PortInputWidth = '100px';
|
||||
const NumberInputWidth = '100px';
|
||||
const inputWidth = '180px';
|
||||
const labelWidth = '150px';
|
||||
const labelWidth = '200px';
|
||||
const spaceBetweenFields = '5px';
|
||||
|
||||
export class ServiceSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
@@ -32,6 +32,12 @@ export class ServiceSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
private gatewayDNSInput!: azdata.InputBoxComponent;
|
||||
private gatewayPortInput!: azdata.InputBoxComponent;
|
||||
private gatewayEndpointRow!: azdata.FlexContainer;
|
||||
private serviceProxyDNSInput!: azdata.InputBoxComponent;
|
||||
private serviceProxyPortInput!: azdata.InputBoxComponent;
|
||||
private serviceProxyEndpointRow!: azdata.FlexContainer;
|
||||
private appServiceProxyDNSInput!: azdata.InputBoxComponent;
|
||||
private appServiceProxyPortInput!: azdata.InputBoxComponent;
|
||||
private appServiceProxyEndpointRow!: azdata.FlexContainer;
|
||||
private readableSecondaryDNSInput!: azdata.InputBoxComponent;
|
||||
private readableSecondaryPortInput!: azdata.InputBoxComponent;
|
||||
private readableSecondaryEndpointRow!: azdata.FlexContainer;
|
||||
@@ -39,7 +45,10 @@ export class ServiceSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
private controllerNameLabel!: azdata.TextComponent;
|
||||
private SqlServerNameLabel!: azdata.TextComponent;
|
||||
private gatewayNameLabel!: azdata.TextComponent;
|
||||
private serviceProxyNameLabel!: azdata.TextComponent;
|
||||
private appServiceProxyNameLabel!: azdata.TextComponent;
|
||||
private readableSecondaryNameLabel!: azdata.TextComponent;
|
||||
private endpointSection!: azdata.GroupContainer;
|
||||
|
||||
constructor(wizard: DeployClusterWizard) {
|
||||
super(localize('deployCluster.ServiceSettingsPageTitle', "Service settings"), '', wizard);
|
||||
@@ -48,37 +57,51 @@ export class ServiceSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
const scaleSectionInfo: SectionInfo = {
|
||||
title: localize('deployCluster.scaleSectionTitle', "Scale settings"),
|
||||
labelWidth: labelWidth,
|
||||
inputWidth: inputWidth,
|
||||
spaceBetweenFields: spaceBetweenFields,
|
||||
inputWidth: NumberInputWidth,
|
||||
spaceBetweenFields: '40px',
|
||||
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.Options,
|
||||
label: localize('deployCluster.MasterSqlServerInstances', "SQL Server master instances"),
|
||||
options: ['1', '3', '4', '5', '6', '7', '8', '9'],
|
||||
defaultValue: '1',
|
||||
required: true,
|
||||
variableName: VariableNames.SQLServerScale_VariableName,
|
||||
}, {
|
||||
type: FieldType.Number,
|
||||
label: localize('deployCluster.ComputePoolInstances', "Compute pool instances"),
|
||||
min: 1,
|
||||
max: 100,
|
||||
defaultValue: '1',
|
||||
useCustomValidator: true,
|
||||
required: true,
|
||||
variableName: VariableNames.ComputePoolScale_VariableName,
|
||||
}]
|
||||
}, {
|
||||
fields: [{
|
||||
type: FieldType.Number,
|
||||
label: localize('deployCluster.DataText', "Data"),
|
||||
label: localize('deployCluster.DataPoolInstances', "Data pool instances"),
|
||||
min: 1,
|
||||
max: 100,
|
||||
defaultValue: '1',
|
||||
useCustomValidator: true,
|
||||
required: true,
|
||||
variableName: VariableNames.DataPoolScale_VariableName,
|
||||
}, {
|
||||
type: FieldType.Number,
|
||||
label: localize('deployCluster.SparkPoolInstances', "Spark pool instances"),
|
||||
min: 0,
|
||||
max: 100,
|
||||
defaultValue: '0',
|
||||
useCustomValidator: true,
|
||||
required: true,
|
||||
variableName: VariableNames.SparkPoolScale_VariableName
|
||||
}]
|
||||
}, {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Number,
|
||||
label: localize('deployCluster.HDFSText', "HDFS"),
|
||||
label: localize('deployCluster.StoragePoolInstances', "Storage pool (HDFS) instances"),
|
||||
min: 1,
|
||||
max: 100,
|
||||
defaultValue: '1',
|
||||
@@ -87,90 +110,12 @@ export class ServiceSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
variableName: VariableNames.HDFSPoolScale_VariableName
|
||||
}, {
|
||||
type: FieldType.Checkbox,
|
||||
label: localize('deployCluster.includeSparkInHDFSPool', "Include Spark"),
|
||||
label: localize('deployCluster.IncludeSparkInStoragePool', "Include Spark in storage pool"),
|
||||
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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
@@ -255,7 +200,7 @@ export class ServiceSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.HDFSText', "HDFS"),
|
||||
label: localize('deployCluster.StoragePool', "Storage pool (HDFS)"),
|
||||
required: false,
|
||||
variableName: VariableNames.HDFSDataStorageClassName_VariableName,
|
||||
placeHolder: hintTextForStorageFields,
|
||||
@@ -286,7 +231,7 @@ export class ServiceSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.Text,
|
||||
label: localize('deployCluster.DataText', "Data"),
|
||||
label: localize('deployCluster.DataPool', "Data pool"),
|
||||
required: false,
|
||||
variableName: VariableNames.DataPoolDataStorageClassName_VariableName,
|
||||
labelWidth: labelWidth,
|
||||
@@ -364,25 +309,22 @@ export class ServiceSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
});
|
||||
};
|
||||
const scaleSection = createSectionFunc(scaleSectionInfo);
|
||||
const hadrSection = createSectionFunc(hadrSectionInfo);
|
||||
const endpointSection = this.createEndpointSection(view);
|
||||
this.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();
|
||||
|
||||
this.handleSparkSettingEvents();
|
||||
const form = view.modelBuilder.formContainer().withFormItems([
|
||||
{
|
||||
title: '',
|
||||
component: scaleSection
|
||||
}, {
|
||||
title: '',
|
||||
component: hadrSection
|
||||
}, {
|
||||
title: '',
|
||||
component: endpointSection
|
||||
component: this.endpointSection
|
||||
}, {
|
||||
title: '',
|
||||
component: storageContainer
|
||||
@@ -392,86 +334,120 @@ export class ServiceSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
});
|
||||
}
|
||||
|
||||
private handleSparkSettingEvents(): void {
|
||||
const sparkInstanceInput = getInputBoxComponent(VariableNames.SparkPoolScale_VariableName, this.inputComponents);
|
||||
const includeSparkCheckbox = getCheckboxComponent(VariableNames.IncludeSpark_VariableName, this.inputComponents);
|
||||
this.wizard.registerDisposable(includeSparkCheckbox.onChanged(() => {
|
||||
if (!includeSparkCheckbox.checked && !(sparkInstanceInput.value && Number.parseInt(sparkInstanceInput.value) > 0)) {
|
||||
sparkInstanceInput.value = '1';
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
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.portColumnHeader = createLabel(view, { text: localize('deployCluster.PortHeader', "Port"), width: NumberInputWidth });
|
||||
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.controllerPortInput = createNumberInput(view, { ariaLabel: localize('deployCluster.ControllerPortName', "Controller port"), required: true, width: NumberInputWidth, 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.sqlServerPortInput = createNumberInput(view, { ariaLabel: localize('deployCluster.MasterSQLServerPortName', "SQL Server Master port"), required: true, width: NumberInputWidth, 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.gatewayPortInput = createNumberInput(view, { ariaLabel: localize('deployCluster.GatewayPortName', "Gateway port"), required: true, width: NumberInputWidth, 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.serviceProxyNameLabel = createLabel(view, { text: localize('deployCluster.ServiceProxyText', "Management proxy"), width: labelWidth, required: true });
|
||||
this.serviceProxyDNSInput = createTextInput(view, { ariaLabel: localize('deployCluster.ServiceProxyDNSName', "Management proxy DNS name"), required: false, width: inputWidth });
|
||||
this.serviceProxyPortInput = createNumberInput(view, { ariaLabel: localize('deployCluster.ServiceProxyPortName', "Management proxy port"), required: true, width: NumberInputWidth, min: 1 });
|
||||
this.serviceProxyEndpointRow = createFlexContainer(view, [this.serviceProxyNameLabel, this.serviceProxyDNSInput, this.serviceProxyPortInput]);
|
||||
this.inputComponents[VariableNames.ServiceProxyDNSName_VariableName] = this.serviceProxyDNSInput;
|
||||
this.inputComponents[VariableNames.ServiceProxyPort_VariableName] = this.serviceProxyPortInput;
|
||||
|
||||
this.appServiceProxyNameLabel = createLabel(view, { text: localize('deployCluster.AppServiceProxyText', "Application proxy"), width: labelWidth, required: true });
|
||||
this.appServiceProxyDNSInput = createTextInput(view, { ariaLabel: localize('deployCluster.AppServiceProxyDNSName', "Application proxy DNS name"), required: false, width: inputWidth });
|
||||
this.appServiceProxyPortInput = createNumberInput(view, { ariaLabel: localize('deployCluster.AppServiceProxyPortName', "Application proxy port"), required: true, width: NumberInputWidth, min: 1 });
|
||||
this.appServiceProxyEndpointRow = createFlexContainer(view, [this.appServiceProxyNameLabel, this.appServiceProxyDNSInput, this.appServiceProxyPortInput]);
|
||||
this.inputComponents[VariableNames.AppServiceProxyDNSName_VariableName] = this.appServiceProxyDNSInput;
|
||||
this.inputComponents[VariableNames.AppServiceProxyPort_VariableName] = this.appServiceProxyPortInput;
|
||||
|
||||
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.readableSecondaryPortInput = createNumberInput(view, { ariaLabel: localize('deployCluster.ReadableSecondaryPortName', "Readable secondary port"), required: false, width: NumberInputWidth, 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], {
|
||||
return createGroupContainer(view, [this.endpointHeaderRow, this.controllerEndpointRow, this.sqlServerEndpointRow, this.gatewayEndpointRow, this.serviceProxyEndpointRow, this.appServiceProxyEndpointRow, 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.ServiceProxyPort_VariableName);
|
||||
this.setInputBoxValue(VariableNames.AppServiceProxyPort_VariableName);
|
||||
this.setInputBoxValue(VariableNames.ReadableSecondaryPort_VariableName);
|
||||
|
||||
this.setInputBoxValue(VariableNames.GatewayDNSName_VariableName);
|
||||
this.setInputBoxValue(VariableNames.AppServiceProxyDNSName_VariableName);
|
||||
this.setInputBoxValue(VariableNames.SQLServerDNSName_VariableName);
|
||||
this.setInputBoxValue(VariableNames.ReadableSecondaryDNSName_VariableName);
|
||||
this.setInputBoxValue(VariableNames.ServiceProxyDNSName_VariableName);
|
||||
this.setInputBoxValue(VariableNames.ControllerDNSName_VariableName);
|
||||
this.setInputBoxValue(VariableNames.ControllerDataStorageClassName_VariableName);
|
||||
this.setInputBoxValue(VariableNames.ControllerDataStorageSize_VariableName);
|
||||
this.setInputBoxValue(VariableNames.ControllerLogsStorageClassName_VariableName);
|
||||
this.setInputBoxValue(VariableNames.ControllerLogsStorageSize_VariableName);
|
||||
|
||||
this.endpointHeaderRow.clearItems();
|
||||
this.endpointSection.collapsed = this.wizard.model.authenticationMode !== AuthenticationMode.ActiveDirectory;
|
||||
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.loadEndpointRow(this.appServiceProxyEndpointRow, this.appServiceProxyNameLabel, this.appServiceProxyDNSInput, this.appServiceProxyPortInput);
|
||||
this.loadEndpointRow(this.serviceProxyEndpointRow, this.serviceProxyNameLabel, this.serviceProxyDNSInput, this.serviceProxyPortInput);
|
||||
const sqlServerScaleDropdown = getDropdownComponent(VariableNames.SQLServerScale_VariableName, this.inputComponents);
|
||||
const sqlServerScale = this.wizard.model.getIntegerValue(VariableNames.SQLServerScale_VariableName);
|
||||
if (sqlServerScale > 1) {
|
||||
sqlServerScaleDropdown.values = ['3', '4', '5', '6', '7', '8', '9'];
|
||||
this.loadEndpointRow(this.readableSecondaryEndpointRow, this.readableSecondaryNameLabel, this.readableSecondaryDNSInput, this.readableSecondaryPortInput);
|
||||
} else {
|
||||
this.readableSecondaryEndpointRow.clearItems();
|
||||
sqlServerScaleDropdown.values = ['1'];
|
||||
}
|
||||
sqlServerScaleDropdown.value = sqlServerScale.toString();
|
||||
|
||||
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))
|
||||
const allInputFilled: 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))
|
||||
@@ -479,21 +455,34 @@ export class ServiceSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
&& !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))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.AppServiceProxyPort_VariableName, this.inputComponents))
|
||||
&& !isInputBoxEmpty(getInputBoxComponent(VariableNames.ServiceProxyPort_VariableName, this.inputComponents))
|
||||
&& (getDropdownComponent(VariableNames.SQLServerScale_VariableName, this.inputComponents).value === '1'
|
||||
|| (!isInputBoxEmpty(this.readableSecondaryPortInput)
|
||||
&& (this.wizard.model.authenticationMode !== AuthenticationMode.ActiveDirectory || !isInputBoxEmpty(this.readableSecondaryDNSInput))))
|
||||
&& (this.wizard.model.authenticationMode !== AuthenticationMode.ActiveDirectory
|
||||
|| (!isInputBoxEmpty(this.gatewayDNSInput)
|
||||
&& !isInputBoxEmpty(this.controllerDNSInput)
|
||||
&& !isInputBoxEmpty(this.sqlServerDNSInput)
|
||||
&& !isInputBoxEmpty(this.readableSecondaryDNSInput)
|
||||
&& !isInputBoxEmpty(this.appServiceProxyDNSInput)
|
||||
&& !isInputBoxEmpty(this.serviceProxyDNSInput)
|
||||
));
|
||||
if (!isValid) {
|
||||
const sparkEnabled = Number.parseInt(getInputBoxComponent(VariableNames.SparkPoolScale_VariableName, this.inputComponents).value!) !== 0
|
||||
|| getCheckboxComponent(VariableNames.IncludeSpark_VariableName, this.inputComponents).checked!;
|
||||
|
||||
let errorMessage: string | undefined;
|
||||
if (!allInputFilled) {
|
||||
errorMessage = MissingRequiredInformationErrorMessage;
|
||||
} else if (!sparkEnabled) {
|
||||
errorMessage = localize('deployCluster.SparkMustBeIncluded', "Invalid Spark configuration, you must check the 'Include Spark' checkbox or set the 'Spark pool instances' to at least 1.");
|
||||
}
|
||||
if (errorMessage) {
|
||||
this.wizard.wizardObject.message = {
|
||||
text: MissingRequiredInformationErrorMessage,
|
||||
text: errorMessage,
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
}
|
||||
return isValid;
|
||||
return allInputFilled && sparkEnabled;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
@@ -514,43 +503,6 @@ export class ServiceSettingsPage extends WizardPageBase<DeployClusterWizard> {
|
||||
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' } };
|
||||
|
||||
@@ -4,24 +4,18 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
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 { SectionInfo, FieldType, LabelPosition, BdcDeploymentType, FontWeight } 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);
|
||||
@@ -30,30 +24,20 @@ export class SummaryPage extends WizardPageBase<DeployClusterWizard> {
|
||||
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
|
||||
}
|
||||
]);
|
||||
this.form = view.modelBuilder.formContainer();
|
||||
return view.initializeModel(this.form!.withLayout({ width: '100%' }).component());
|
||||
});
|
||||
}
|
||||
|
||||
public onEnter() {
|
||||
this.targetDeploymentProfile = this.wizard.model.createTargetProfile();
|
||||
if (this.wizard.model.deploymentTarget === BdcDeploymentType.NewAKS) {
|
||||
this.wizard.wizardObject.message = {
|
||||
level: azdata.window.MessageLevel.Information,
|
||||
text: localize('resourceDeployment.NewAKSBrowserWindowPrompt', "A browser window for logging to Azure will be opened during the SQL Server Big Data Cluster deployment.")
|
||||
};
|
||||
}
|
||||
this.wizard.saveConfigButton.hidden = false;
|
||||
this.wizard.scriptToNotebookButton.hidden = false;
|
||||
this.formItems.forEach(item => {
|
||||
this.form!.removeFormItem(item);
|
||||
});
|
||||
@@ -71,13 +55,13 @@ export class SummaryPage extends WizardPageBase<DeployClusterWizard> {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.Kubeconfig', "Kube config"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.KubeConfigPath_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
labelFontWeight: FontWeight.Bold
|
||||
},
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.ClusterContext', "Cluster context"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.ClusterContext_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}]
|
||||
}
|
||||
]
|
||||
@@ -96,13 +80,13 @@ export class SummaryPage extends WizardPageBase<DeployClusterWizard> {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.DeploymentProfile', "Deployment profile"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.DeploymentProfile_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
labelFontWeight: FontWeight.Bold
|
||||
},
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.ClusterName', "Cluster name"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.ClusterName_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}]
|
||||
}, {
|
||||
fields: [
|
||||
@@ -110,20 +94,92 @@ export class SummaryPage extends WizardPageBase<DeployClusterWizard> {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.ControllerUsername', "Controller username"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.AdminUserName_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}, {
|
||||
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
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
if (this.wizard.model.authenticationMode === AuthenticationMode.ActiveDirectory) {
|
||||
clusterSectionInfo.rows!.push({
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.OuDistinguishedName', "Organizational unit"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.OrganizationalUnitDistinguishedName_VariableName),
|
||||
labelFontWeight: FontWeight.Bold
|
||||
},
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.DomainControllerFQDNs', "Domain controller FQDNs"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.DomainControllerFQDNs_VariableName),
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}]
|
||||
});
|
||||
clusterSectionInfo.rows!.push({
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.DomainDNSIPAddresses', "Domain DNS IP addresses"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.DomainDNSIPAddresses_VariableName),
|
||||
labelFontWeight: FontWeight.Bold
|
||||
},
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.DomainDNSName', "Domain DNS name"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.DomainDNSName_VariableName),
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}]
|
||||
});
|
||||
clusterSectionInfo.rows!.push({
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.ClusterAdmins', "Cluster admin group"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.ClusterAdmins_VariableName),
|
||||
labelFontWeight: FontWeight.Bold
|
||||
},
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.ClusterUsers', "Cluster users"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.ClusterUsers_VariableName),
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}]
|
||||
});
|
||||
clusterSectionInfo.rows!.push({
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.AppOwers', "App owners"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.AppOwners_VariableName),
|
||||
labelFontWeight: FontWeight.Bold
|
||||
},
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.AppReaders', "App readers"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.AppReaders_VariableName),
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}]
|
||||
});
|
||||
clusterSectionInfo.rows!.push({
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.DomainServiceAccountUserName', "Service account username"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.DomainServiceAccountUserName_VariableName),
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
const azureSectionInfo: SectionInfo = {
|
||||
labelPosition: LabelPosition.Left,
|
||||
labelWidth: '150px',
|
||||
@@ -135,26 +191,26 @@ export class SummaryPage extends WizardPageBase<DeployClusterWizard> {
|
||||
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
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.ResourceGroup', "Resource group"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.ResourceGroup_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}
|
||||
]
|
||||
}, {
|
||||
fields: [
|
||||
{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.Region', "Region"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.Region_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
label: localize('deployCluster.Location', "Location"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.Location_VariableName),
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.AksClusterName', "AKS cluster name"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.AksName_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}
|
||||
]
|
||||
}, {
|
||||
@@ -163,12 +219,12 @@ export class SummaryPage extends WizardPageBase<DeployClusterWizard> {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.VMSize', "VM size"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.VMSize_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.VMCount', "VM count"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.VMCount_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -184,68 +240,34 @@ export class SummaryPage extends WizardPageBase<DeployClusterWizard> {
|
||||
{
|
||||
fields: [{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.ComputeText', "Compute"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.ComputePoolScale_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
label: localize('deployCluster.MasterSqlServerInstances', "SQL Server master instances"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.SQLServerScale_VariableName),
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.DataText', "Data"),
|
||||
label: localize('deployCluster.ComputePoolInstances', "Compute pool instances"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.ComputePoolScale_VariableName),
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}]
|
||||
}, {
|
||||
fields: [{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.DataPoolInstances', "Data pool instances"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.DataPoolScale_VariableName),
|
||||
fontStyle: FontStyle.Italic
|
||||
}
|
||||
]
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}, {
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.SparkPoolInstances', "Spark pool instances"),
|
||||
defaultValue: this.wizard.model.getStringValue(VariableNames.SparkPoolScale_VariableName),
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}]
|
||||
}, {
|
||||
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
|
||||
}
|
||||
]
|
||||
fields: [{
|
||||
type: FieldType.ReadonlyText,
|
||||
label: localize('deployCluster.StoragePoolInstances', "Storage pool (HDFS) instances"),
|
||||
defaultValue: `${this.wizard.model.getStringValue(VariableNames.HDFSPoolScale_VariableName)} ${this.wizard.model.getBooleanValue(VariableNames.IncludeSpark_VariableName) ? localize('deployCluster.WithSpark', "(Spark included)") : ''}`,
|
||||
labelFontWeight: FontWeight.Bold
|
||||
}]
|
||||
}
|
||||
]
|
||||
};
|
||||
@@ -271,7 +293,6 @@ export class SummaryPage extends WizardPageBase<DeployClusterWizard> {
|
||||
|
||||
const clusterSection = createSectionFunc(clusterSectionInfo);
|
||||
const scaleSection = createSectionFunc(scaleSectionInfo);
|
||||
const hadrSection = createSectionFunc(hadrSectionInfo);
|
||||
const endpointSection = {
|
||||
title: '',
|
||||
component: this.createEndpointSection()
|
||||
@@ -285,10 +306,16 @@ export class SummaryPage extends WizardPageBase<DeployClusterWizard> {
|
||||
this.formItems.push(azureSection);
|
||||
}
|
||||
|
||||
this.formItems.push(clusterSection, scaleSection, hadrSection, endpointSection, storageSection);
|
||||
this.formItems.push(clusterSection, scaleSection, endpointSection, storageSection);
|
||||
this.form.addFormItems(this.formItems);
|
||||
}
|
||||
|
||||
public onLeave() {
|
||||
this.wizard.saveConfigButton.hidden = true;
|
||||
this.wizard.scriptToNotebookButton.hidden = true;
|
||||
this.wizard.wizardObject.message = { text: '' };
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -324,7 +351,7 @@ export class SummaryPage extends WizardPageBase<DeployClusterWizard> {
|
||||
this.wizard.model.getStringValue(VariableNames.ControllerLogsStorageClassName_VariableName),
|
||||
this.wizard.model.getStringValue(VariableNames.ControllerLogsStorageSize_VariableName)],
|
||||
[
|
||||
localize('deployCluster.HDFSText', "HDFS"),
|
||||
localize('deployCluster.StoragePool', "Storage pool (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),
|
||||
@@ -357,10 +384,12 @@ export class SummaryPage extends WizardPageBase<DeployClusterWizard> {
|
||||
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)
|
||||
this.createEndpointRow(localize('deployCluster.GatewayText', "Gateway"), VariableNames.GatewayDNSName_VariableName, VariableNames.GateWayPort_VariableName),
|
||||
this.createEndpointRow(localize('deployCluster.AppServiceProxyText', "Application proxy"), VariableNames.AppServiceProxyDNSName_VariableName, VariableNames.AppServiceProxyPort_VariableName),
|
||||
this.createEndpointRow(localize('deployCluster.ServiceProxyText', "Management proxy"), VariableNames.ServiceProxyDNSName_VariableName, VariableNames.ServiceProxyPort_VariableName)
|
||||
];
|
||||
|
||||
if (this.wizard.model.hadrEnabled) {
|
||||
if (this.wizard.model.getIntegerValue(VariableNames.SQLServerScale_VariableName) > 1) {
|
||||
endpointRows.push(
|
||||
this.createEndpointRow(localize('deployCluster.ReadableSecondaryText', "Readable secondary"), VariableNames.ReadableSecondaryDNSName_VariableName, VariableNames.ReadableSecondaryPort_VariableName)
|
||||
);
|
||||
@@ -373,43 +402,15 @@ export class SummaryPage extends WizardPageBase<DeployClusterWizard> {
|
||||
|
||||
private createEndpointRow(name: string, dnsVariableName: string, portVariableName: string): azdata.FlexContainer {
|
||||
const items = [];
|
||||
items.push(createLabel(this.view, { text: name, width: '150px' }));
|
||||
items.push(createLabel(this.view, { text: name, width: '150px', fontWeight: FontWeight.Bold }));
|
||||
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(dnsVariableName)!, width: '200px'
|
||||
}));
|
||||
}
|
||||
items.push(createLabel(this.view, { text: this.wizard.model.getStringValue(portVariableName)!, width: '100px', fontStyle: FontStyle.Italic }));
|
||||
items.push(createLabel(this.view, {
|
||||
text: this.wizard.model.getStringValue(portVariableName)!, width: '100px'
|
||||
}));
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user