Remove all Big Data Cluster features (#21369)

This commit is contained in:
Cory Rivera
2022-12-07 12:28:17 -08:00
committed by GitHub
parent bb1f5bfffe
commit e2327c393a
213 changed files with 346 additions and 46800 deletions

View File

@@ -77,10 +77,6 @@ export interface DialogDeploymentProvider extends DeploymentProviderBase {
dialog: DialogInfo;
}
export interface BdcWizardDeploymentProvider extends DeploymentProviderBase {
bdcWizard: BdcWizardInfo;
}
export interface NotebookWizardDeploymentProvider extends DeploymentProviderBase {
notebookWizard: NotebookWizardInfo;
}
@@ -113,10 +109,6 @@ export function instanceOfDialogDeploymentProvider(obj: any): obj is DialogDeplo
return obj && 'dialog' in obj;
}
export function instanceOfWizardDeploymentProvider(obj: any): obj is BdcWizardDeploymentProvider {
return obj && 'bdcWizard' in obj;
}
export function instanceOfNotebookWizardDeploymentProvider(obj: any): obj is NotebookWizardDeploymentProvider {
return obj && 'notebookWizard' in obj;
}
@@ -151,12 +143,8 @@ export interface DeploymentProviderBase {
when: string;
}
export type DeploymentProvider = DialogDeploymentProvider | BdcWizardDeploymentProvider | NotebookWizardDeploymentProvider | NotebookDeploymentProvider | WebPageDeploymentProvider | DownloadDeploymentProvider | CommandDeploymentProvider | AzureSQLVMDeploymentProvider | AzureSQLDBDeploymentProvider;
export type DeploymentProvider = DialogDeploymentProvider | NotebookWizardDeploymentProvider | NotebookDeploymentProvider | WebPageDeploymentProvider | DownloadDeploymentProvider | CommandDeploymentProvider | AzureSQLVMDeploymentProvider | AzureSQLDBDeploymentProvider;
export interface BdcWizardInfo {
notebook: string | NotebookPathInfo;
type: BdcDeploymentType;
}
/**
* An object that configures Script and Done buttons of the wizard.
*/
@@ -183,7 +171,6 @@ export interface NotebookWizardInfo extends WizardInfoBase {
}
export interface WizardInfoBase extends FieldInfoBase {
type?: DeploymentType;
/**
* done button attributes.
*/
@@ -461,7 +448,6 @@ export enum ToolType {
AzCli,
KubeCtl,
Docker,
Azdata
}
export const enum ToolStatus {
@@ -497,16 +483,6 @@ export interface ITool {
promptForEula(): Promise<boolean>;
}
export const enum BdcDeploymentType {
NewAKS = 'new-aks',
ExistingAKS = 'existing-aks',
ExistingKubeAdm = 'existing-kubeadm',
ExistingARO = 'existing-aro',
ExistingOpenShift = 'existing-openshift'
}
export type DeploymentType = BdcDeploymentType;
export interface Command {
command: string;
sudo?: boolean;

View File

@@ -49,9 +49,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<rd.IEx
vscode.commands.registerCommand('azdata.resource.sql-image.deploy', () => {
openDialog('sql-image');
});
vscode.commands.registerCommand('azdata.resource.sql-bdc.deploy', () => {
openDialog('sql-bdc');
});
/**
* Command to open the Resource Deployment wizard - with options to filter the values shown
* @param defaultResourceTypeName - The default resourceType to be selected

View File

@@ -1,75 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as path from 'path';
import { IPlatformService } from './platformService';
import { BigDataClusterDeploymentProfile } from './bigDataClusterDeploymentProfile';
import { BdcDeploymentType } from '../interfaces';
interface BdcConfigListOutput {
result: string[];
}
export interface BdcEndpoint {
endpoint: string;
name: 'sql-server-master';
}
export interface IAzdataService {
getDeploymentProfiles(deploymentType: BdcDeploymentType): Promise<BigDataClusterDeploymentProfile[]>;
}
export class AzdataService implements IAzdataService {
constructor(private platformService: IPlatformService) {
}
public async getDeploymentProfiles(deploymentType: BdcDeploymentType): Promise<BigDataClusterDeploymentProfile[]> {
let profilePrefix: string;
switch (deploymentType) {
case BdcDeploymentType.NewAKS:
case BdcDeploymentType.ExistingAKS:
profilePrefix = 'aks';
break;
case BdcDeploymentType.ExistingKubeAdm:
profilePrefix = 'kubeadm';
break;
case BdcDeploymentType.ExistingARO:
profilePrefix = 'aro';
break;
case BdcDeploymentType.ExistingOpenShift:
profilePrefix = 'openshift';
break;
default:
throw new Error(`Unknown deployment type: ${deploymentType}`);
}
const profileNames = await this.getDeploymentProfileNames();
return await Promise.all(profileNames.filter(profile => profile.startsWith(profilePrefix)).map(profile => this.getDeploymentProfileInfo(profile)));
}
private async getDeploymentProfileNames(): Promise<string[]> {
const env: NodeJS.ProcessEnv = {};
// azdata requires this environment variables to be set
env['ACCEPT_EULA'] = 'yes';
const cmd = 'azdata bdc config list -o json';
const stdout = await this.platformService.runCommand(cmd, { additionalEnvironmentVariables: env });
const output = <BdcConfigListOutput>JSON.parse(stdout);
return output.result;
}
private async getDeploymentProfileInfo(profileName: string): Promise<BigDataClusterDeploymentProfile> {
const env: NodeJS.ProcessEnv = {};
// azdata requires this environment variables to be set
env['ACCEPT_EULA'] = 'yes';
await this.platformService.runCommand(`azdata bdc config init --source ${profileName} --path ${profileName} --force`, { workingDirectory: this.platformService.storagePath(), additionalEnvironmentVariables: env });
const configObjects = await Promise.all([
this.getJsonObjectFromFile(path.join(this.platformService.storagePath(), profileName, 'bdc.json')),
this.getJsonObjectFromFile(path.join(this.platformService.storagePath(), profileName, 'control.json'))
]);
return new BigDataClusterDeploymentProfile(profileName, configObjects[0], configObjects[1]);
}
private async getJsonObjectFromFile(path: string): Promise<any> {
return JSON.parse(await this.platformService.readTextFile(path));
}
}

View File

@@ -1,349 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { AuthenticationMode } from '../ui/deployClusterWizard/deployClusterWizardModel';
export const SqlServerMasterResource = 'master';
export const DataResource = 'data-0';
export const HdfsResource = 'storage-0';
export const ComputeResource = 'compute-0';
export const NameNodeResource = 'nmnode-0';
export const SparkHeadResource = 'sparkhead';
export const ZooKeeperResource = 'zookeeper';
export const SparkResource = 'spark-0';
interface ServiceEndpoint {
port: number;
serviceType: ServiceType;
name: EndpointName;
dnsName?: string;
}
type ServiceType = 'NodePort' | 'LoadBalancer';
type EndpointName = 'Controller' | 'Master' | 'Knox' | 'MasterSecondary' | 'AppServiceProxy' | 'ServiceProxy';
export interface ActiveDirectorySettings {
organizationalUnit: string;
domainControllerFQDNs: string;
dnsIPAddresses: string;
domainDNSName: string;
realm?: string;
clusterUsers: string;
clusterAdmins: string;
appReaders?: string;
appOwners?: string;
subdomain?: string;
accountPrefix?: string;
}
export class BigDataClusterDeploymentProfile {
constructor(private _profileName: string, private _bdcConfig: any, private _controlConfig: any) {
// TODO: add validation logic for these 2 objects
// https://github.com/microsoft/azuredatastudio/issues/7344
}
public get profileName(): string {
return this._profileName;
}
public get clusterName(): string {
return this._bdcConfig.metadata.name;
}
public set clusterName(value: string) {
this._bdcConfig.metadata.name = value;
}
public get registry(): string {
return this._controlConfig.spec.docker.registry;
}
public set registry(value: string) {
this._controlConfig.spec.docker.registry = value;
}
public get repository(): string {
return this._controlConfig.spec.docker.repository;
}
public set repository(value: string) {
this._controlConfig.spec.docker.repository = value;
}
public get imageTag(): string {
return this._controlConfig.spec.docker.imageTag;
}
public set imageTag(value: string) {
this._controlConfig.spec.docker.imageTag = value;
}
public get bdcConfig(): any {
return this._bdcConfig;
}
public get controlConfig(): any {
return this._controlConfig;
}
public get sqlServerReplicas(): number {
return this.getReplicas(SqlServerMasterResource);
}
public set sqlServerReplicas(replicas: number) {
this.setReplicas(SqlServerMasterResource, replicas);
}
public get hdfsNameNodeReplicas(): number {
return this.getReplicas(NameNodeResource);
}
public set hdfsNameNodeReplicas(replicas: number) {
this.setReplicas(NameNodeResource, replicas);
}
public get sparkHeadReplicas(): number {
return this.getReplicas(SparkHeadResource);
}
public set sparkHeadReplicas(replicas: number) {
this.setReplicas(SparkHeadResource, replicas);
}
public get dataReplicas(): number {
return this.getReplicas(DataResource);
}
public set dataReplicas(replicas: number) {
this.setReplicas(SparkHeadResource, replicas);
}
public get hdfsReplicas(): number {
return this.getReplicas(HdfsResource);
}
public set hdfsReplicas(replicas: number) {
this.setReplicas(HdfsResource, replicas);
}
public get zooKeeperReplicas(): number {
return this.getReplicas(ZooKeeperResource);
}
public set zooKeeperReplicas(replicas: number) {
this.setReplicas(ZooKeeperResource, replicas);
}
public get computeReplicas(): number {
return this.getReplicas(ComputeResource);
}
public set computeReplicas(replicas: number) {
this.setReplicas(ComputeResource, replicas);
}
public get sparkReplicas(): number {
return this._bdcConfig.spec.resources[SparkResource] ? this.getReplicas(SparkResource) : 0;
}
public get includeSpark(): boolean {
return <boolean>this._bdcConfig.spec.resources[HdfsResource].spec.settings.spark.includeSpark;
}
public set includeSpark(value: boolean) {
this._bdcConfig.spec.resources[HdfsResource].spec.settings.spark.includeSpark = value;
}
public get controllerDataStorageClass(): string {
return <string>this._controlConfig.spec.storage.data.className;
}
public set controllerDataStorageClass(value: string) {
this._controlConfig.spec.storage.data.className = value;
}
public get controllerDataStorageSize(): number {
return <number>this._controlConfig.spec.storage.data.size.replace('Gi', '');
}
public set controllerDataStorageSize(value: number) {
this._controlConfig.spec.storage.data.size = `${value}Gi`;
}
public get controllerLogsStorageClass(): string {
return <string>this._controlConfig.spec.storage.logs.className;
}
public set controllerLogsStorageClass(value: string) {
this._controlConfig.spec.storage.logs.className = value;
}
public get controllerLogsStorageSize(): number {
return <number>this._controlConfig.spec.storage.logs.size.replace('Gi', '');
}
public set controllerLogsStorageSize(value: number) {
this._controlConfig.spec.storage.logs.size = `${value}Gi`;
}
public setResourceStorage(resourceName: 'data-0' | 'master' | 'storage-0', dataStorageClass: string, dataStorageSize: number, logsStorageClass: string, logsStorageSize: number) {
this.bdcConfig.spec.resources[resourceName].spec.storage = {
data: {
size: `${dataStorageSize}Gi`,
className: dataStorageClass,
accessMode: 'ReadWriteOnce'
},
logs: {
size: `${logsStorageSize}Gi`,
className: logsStorageClass,
accessMode: 'ReadWriteOnce'
}
};
}
public get controllerPort(): number {
return this.getEndpointPort(this._controlConfig.spec.endpoints, 'Controller', 30080);
}
public setControllerEndpoint(port: number, dnsName?: string) {
this.setEndpoint(this._controlConfig.spec.endpoints, 'Controller', port, dnsName);
}
public get serviceProxyPort(): number {
return this.getEndpointPort(this._controlConfig.spec.endpoints, 'ServiceProxy', 30080);
}
public setServiceProxyEndpoint(port: number, dnsName?: string) {
this.setEndpoint(this._controlConfig.spec.endpoints, 'ServiceProxy', port, dnsName);
}
public get appServiceProxyPort(): number {
return this.getEndpointPort(this._bdcConfig.spec.resources.appproxy.spec.endpoints, 'AppServiceProxy', 30777);
}
public setAppServiceProxyEndpoint(port: number, dnsName?: string) {
this.setEndpoint(this._bdcConfig.spec.resources.appproxy.spec.endpoints, 'AppServiceProxy', port, dnsName);
}
public get sqlServerPort(): number {
return this.getEndpointPort(this._bdcConfig.spec.resources.master.spec.endpoints, 'Master', 31433);
}
public setSqlServerEndpoint(port: number, dnsName?: string) {
this.setEndpoint(this._bdcConfig.spec.resources.master.spec.endpoints, 'Master', port, dnsName);
}
public get sqlServerReadableSecondaryPort(): number {
return this.getEndpointPort(this._bdcConfig.spec.resources.master.spec.endpoints, 'MasterSecondary', 31436);
}
public setSqlServerReadableSecondaryEndpoint(port: number, dnsName?: string) {
this.setEndpoint(this._bdcConfig.spec.resources.master.spec.endpoints, 'MasterSecondary', port, dnsName);
}
public get gatewayPort(): number {
return this.getEndpointPort(this._bdcConfig.spec.resources.gateway.spec.endpoints, 'Knox', 30443);
}
public setGatewayEndpoint(port: number, dnsName?: string) {
this.setEndpoint(this._bdcConfig.spec.resources.gateway.spec.endpoints, 'Knox', port, dnsName);
}
public addSparkResource(replicas: number): void {
this._bdcConfig.spec.resources[SparkResource] = {
metadata: {
kind: 'Pool',
name: 'default'
},
spec: {
type: 'Spark',
replicas: replicas
}
};
this._bdcConfig.spec.services.spark.resources.push(SparkResource);
this._bdcConfig.spec.services.hdfs.resources.push(SparkResource);
}
public get activeDirectorySupported(): boolean {
// The profiles that highlight the AD authentication feature will have a security secion in the control.json for the AD settings.
return 'security' in this._controlConfig;
}
public setAuthenticationMode(mode: string): void {
// If basic authentication is picked, the activeDirectory security section must be removed
// otherwise azdata will throw validation error
if (mode === AuthenticationMode.Basic && 'security' in this._controlConfig && 'activeDirectory' in this._controlConfig.security) {
delete this._controlConfig.security.activeDirectory;
}
}
public setActiveDirectorySettings(adSettings: ActiveDirectorySettings): void {
const activeDirectoryObject: any = {};
activeDirectoryObject.ouDistinguishedName = adSettings.organizationalUnit;
activeDirectoryObject.dnsIpAddresses = this.splitByComma(adSettings.dnsIPAddresses);
activeDirectoryObject.domainControllerFullyQualifiedDns = this.splitByComma(adSettings.domainControllerFQDNs.toLowerCase());
activeDirectoryObject.domainDnsName = adSettings.domainDNSName;
activeDirectoryObject.subdomain = adSettings.subdomain;
activeDirectoryObject.accountPrefix = adSettings.accountPrefix;
activeDirectoryObject.realm = adSettings.realm ?? adSettings.domainDNSName.toUpperCase();
activeDirectoryObject.clusterAdmins = this.splitByComma(adSettings.clusterAdmins);
activeDirectoryObject.clusterUsers = this.splitByComma(adSettings.clusterUsers);
if (adSettings.appReaders) {
activeDirectoryObject.appReaders = this.splitByComma(adSettings.appReaders);
}
if (adSettings.appOwners) {
activeDirectoryObject.appOwners = this.splitByComma(adSettings.appOwners);
}
this._controlConfig.security.activeDirectory = activeDirectoryObject;
}
public getBdcJson(readable: boolean = true): string {
return this.stringifyJson(this._bdcConfig, readable);
}
public getControlJson(readable: boolean = true): string {
return this.stringifyJson(this._controlConfig, readable);
}
private stringifyJson(obj: any, readable: boolean): string {
return JSON.stringify(obj, undefined, readable ? 4 : 0);
}
private getReplicas(resourceName: string): number {
return <number>this._bdcConfig.spec.resources[resourceName].spec.replicas;
}
private setReplicas(resourceName: string, replicas: number): void {
this._bdcConfig.spec.resources[resourceName].spec.replicas = replicas;
}
private getEndpointPort(endpoints: ServiceEndpoint[], name: EndpointName, defaultValue: number): number {
const endpoint = endpoints.find(endpoint => endpoint.name === name);
return endpoint ? endpoint.port : defaultValue;
}
private setEndpoint(endpoints: ServiceEndpoint[], name: EndpointName, port: number, dnsName?: string): void {
const endpoint = endpoints.find(endpoint => endpoint.name === name);
if (endpoint) {
endpoint.port = port;
endpoint.dnsName = dnsName;
} else {
const newEndpoint: ServiceEndpoint = {
name: name,
serviceType: 'NodePort',
port: port
};
// for newly added endpoint, we cannot have blank value for the dnsName, only set it if it is not empty
if (dnsName) {
newEndpoint.dnsName = dnsName;
}
endpoints.push(newEndpoint);
}
}
private splitByComma(value: string): string[] {
// split by comma, then remove trailing spaces for each item and finally remove the empty values.
return value.split(',').map(v => v && v.trim()).filter(v => v !== '' && v !== undefined);
}
}

View File

@@ -9,8 +9,7 @@ import * as os from 'os';
import * as path from 'path';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { DeploymentProvider, instanceOfAzureSQLVMDeploymentProvider, instanceOfAzureSQLDBDeploymentProvider, instanceOfCommandDeploymentProvider, instanceOfDialogDeploymentProvider, instanceOfDownloadDeploymentProvider, instanceOfNotebookBasedDialogInfo, instanceOfNotebookDeploymentProvider, instanceOfNotebookWizardDeploymentProvider, instanceOfWebPageDeploymentProvider, instanceOfWizardDeploymentProvider, NotebookInfo, NotebookPathInfo, ResourceType, ResourceTypeOption, ResourceSubType, AgreementInfo, HelpText, InitialVariableValues } from '../interfaces';
import { AzdataService } from './azdataService';
import { DeploymentProvider, instanceOfAzureSQLVMDeploymentProvider, instanceOfAzureSQLDBDeploymentProvider, instanceOfCommandDeploymentProvider, instanceOfDialogDeploymentProvider, instanceOfDownloadDeploymentProvider, instanceOfNotebookBasedDialogInfo, instanceOfNotebookDeploymentProvider, instanceOfNotebookWizardDeploymentProvider, instanceOfWebPageDeploymentProvider, NotebookInfo, NotebookPathInfo, ResourceType, ResourceTypeOption, ResourceSubType, AgreementInfo, HelpText, InitialVariableValues } from '../interfaces';
import { KubeService } from './kubeService';
import { INotebookService } from './notebookService';
import { IPlatformService } from './platformService';
@@ -116,9 +115,6 @@ export class ResourceTypeService implements IResourceTypeService {
} else if (instanceOfDialogDeploymentProvider(provider) && instanceOfNotebookBasedDialogInfo(provider.dialog)) {
this.updateNotebookPath(provider.dialog, extensionPath);
}
else if ('bdcWizard' in provider) {
this.updateNotebookPath(provider.bdcWizard, extensionPath);
}
else if ('notebookWizard' in provider) {
this.updateNotebookPath(provider.notebookWizard, extensionPath);
}
@@ -245,8 +241,7 @@ export class ResourceTypeService implements IResourceTypeService {
let providerIndex = 1;
resourceType.providers.forEach(provider => {
const providerPositionInfo = `${positionInfo}, provider index: ${providerIndex} `;
if (!instanceOfWizardDeploymentProvider(provider)
&& !instanceOfNotebookWizardDeploymentProvider(provider)
if (!instanceOfNotebookWizardDeploymentProvider(provider)
&& !instanceOfDialogDeploymentProvider(provider)
&& !instanceOfNotebookDeploymentProvider(provider)
&& !instanceOfDownloadDeploymentProvider(provider)
@@ -328,7 +323,7 @@ export class ResourceTypeService implements IResourceTypeService {
}
public startDeployment(resourceType: ResourceType, optionValuesFilter?: OptionValuesFilter, initialVariableValues?: InitialVariableValues): void {
const wizard = new ResourceTypeWizard(resourceType, new KubeService(), new AzdataService(this.platformService), this.notebookService, this.toolsService, this.platformService, this, optionValuesFilter, initialVariableValues);
const wizard = new ResourceTypeWizard(resourceType, new KubeService(), this.notebookService, this.toolsService, this.platformService, this, optionValuesFilter, initialVariableValues);
wizard.open();
}

View File

@@ -1,182 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { EOL } from 'os';
import * as path from 'path';
import { SemVer } from 'semver';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { AzdataInstallLocationKey, DeploymentConfigurationKey } from '../../constants';
import { Command, OsDistribution, ToolType } from '../../interfaces';
import { IPlatformService } from '../platformService';
import { dependencyType, ToolBase } from './toolBase';
import { SemVerProxy } from './SemVerProxy';
const localize = nls.loadMessageBundle();
export const AzdataToolName = 'azdata';
const win32InstallationRoot = `${process.env['ProgramFiles(x86)']}\\Microsoft SDKs\\Azdata\\CLI\\wbin`;
const macInstallationRoot = '/usr/local/bin';
const debianInstallationRoot = '/usr/local/bin';
export class AzdataTool extends ToolBase {
constructor(platformService: IPlatformService) {
super(platformService);
}
get name(): string {
return AzdataToolName;
}
get description(): string {
return localize('resourceDeployment.AzdataDescription', "Azure Data command line interface");
}
get type(): ToolType {
return ToolType.Azdata;
}
get displayName(): string {
return localize('resourceDeployment.AzdataDisplayName', "Azure Data CLI");
}
get homePage(): string {
return 'https://docs.microsoft.com/sql/big-data-cluster/deploy-install-azdata';
}
protected get versionCommand(): Command {
return {
command: 'azdata -v'
};
}
protected get discoveryCommand(): Command {
return {
command: this.discoveryCommandString('azdata')
};
}
protected getVersionFromOutput(output: string): SemVer | undefined {
let version: SemVer | undefined = undefined;
if (output && output.split(EOL).length > 0) {
version = new SemVerProxy(output.split(EOL)[0].replace(/ /g, ''));
}
return version;
}
protected override async getSearchPaths(): Promise<string[]> {
switch (this.osDistribution) {
case OsDistribution.win32:
return [win32InstallationRoot];
case OsDistribution.darwin:
return [macInstallationRoot];
case OsDistribution.debian:
return [debianInstallationRoot];
default:
const azdataCliInstallLocation = await this.getPip3InstallLocation('azdata-cli');
if (azdataCliInstallLocation) {
return [path.join(azdataCliInstallLocation, '..', 'Scripts'), path.join(azdataCliInstallLocation, '..', '..', '..', 'bin')];
} else {
return [];
}
}
}
protected get allInstallationCommands(): Map<OsDistribution, Command[]> {
return new Map<OsDistribution, Command[]>([
[OsDistribution.debian, this.debianInstallationCommands],
[OsDistribution.win32, this.win32InstallationCommands],
[OsDistribution.darwin, this.macOsInstallationCommands],
[OsDistribution.others, []]
]);
}
private get azdataInstallLocation(): string {
return vscode.workspace.getConfiguration(DeploymentConfigurationKey)[AzdataInstallLocationKey] || this.defaultInstallLocationByDistribution.get(this.osDistribution);
}
private defaultInstallLocationByDistribution: Map<OsDistribution, string> = new Map<OsDistribution, string>([
[OsDistribution.debian, 'https://packages.microsoft.com/config/ubuntu/16.04/mssql-server-2019.list'],
[OsDistribution.win32, 'https://aka.ms/azdata-msi'],
[OsDistribution.darwin, 'microsoft/azdata-cli-release'],
[OsDistribution.others, '']
]);
protected override dependenciesByOsType: Map<OsDistribution, dependencyType[]> = new Map<OsDistribution, dependencyType[]>([
[OsDistribution.debian, []],
[OsDistribution.win32, []],
[OsDistribution.darwin, [dependencyType.Brew]],
[OsDistribution.others, []]
]);
private get win32InstallationCommands() {
return [
{
comment: localize('resourceDeployment.Azdata.DeletingPreviousAzdata.msi', "deleting previously downloaded Azdata.msi if one exists …"),
command: `IF EXIST .\\Azdata.msi DEL /F .\\Azdata.msi`
},
{
sudo: true,
comment: localize('resourceDeployment.Azdata.DownloadingAndInstallingAzdata', "downloading Azdata.msi and installing azdata-cli …"),
command: `powershell -NoLogo -NonInteractive -NoProfile -Command "& {try {(New-Object System.Net.WebClient).DownloadFile('${this.azdataInstallLocation}', 'Azdata.msi'); Start-Process msiexec.exe -Wait -ArgumentList '/I Azdata.msi /passive /quiet /lvx ADS_AzdataInstall.log'} catch { Write-Error $_.Exception; exit 1 }}"`
},
{
comment: localize('resourceDeployment.Azdata.DisplayingInstallationLog', "displaying the installation log …"),
command: `type ADS_AzdataInstall.log | findstr /i /v ^MSI"`,
ignoreError: true
}
];
}
private get macOsInstallationCommands() {
return [
{
comment: localize('resourceDeployment.Azdata.TappingBrewRepository', "tapping into the brew repository for azdata-cli …"),
command: `brew tap ${this.azdataInstallLocation}`
},
{
comment: localize('resourceDeployment.Azdata.UpdatingBrewRepository', "updating the brew repository for azdata-cli installation …"),
command: 'brew update'
},
{
comment: localize('resourceDeployment.Azdata.InstallingAzdata', "installing azdata …"),
command: 'brew install azdata-cli'
}
];
}
private get debianInstallationCommands() {
return [
{
sudo: true,
comment: localize('resourceDeployment.Azdata.AptGetUpdate', "updating repository information …"),
command: 'apt-get update'
},
{
sudo: true,
comment: localize('resourceDeployment.Azdata.AptGetPackages', "getting packages needed for azdata installation …"),
command: 'apt-get install gnupg ca-certificates curl apt-transport-https lsb-release -y'
},
{
sudo: true,
comment: localize('resourceDeployment.Azdata.DownloadAndInstallingSigningKey', "downloading and installing the signing key for azdata …"),
command: 'wget -qO- https://packages.microsoft.com/keys/microsoft.asc | apt-key add -'
},
{
sudo: true,
comment: localize('resourceDeployment.Azdata.AddingAzdataRepositoryInformation', "adding the azdata repository information …"),
command: `add-apt-repository "$(wget -qO- ${this.azdataInstallLocation})"`
},
{
sudo: true,
comment: localize('resourceDeployment.Azdata.AptGetUpdate', "updating repository information …"),
command: 'apt-get update'
},
{
sudo: true,
comment: localize('resourceDeployment.Azdata.InstallingAzdata', "installing azdata …"),
command: 'apt-get install -y azdata-cli'
}
];
}
}

View File

@@ -7,7 +7,6 @@ import { DockerTool } from './tools/dockerTool';
import { AzCliTool } from './tools/azCliTool';
import { KubeCtlTool } from './tools/kubeCtlTool';
import { IPlatformService } from './platformService';
import { AzdataTool } from './tools/azdataTool';
export interface IToolsService {
getToolByName(toolName: string): ITool | undefined;
@@ -23,7 +22,6 @@ export class ToolsService implements IToolsService {
[
new DockerTool(this._platformService),
new AzCliTool(this._platformService),
new AzdataTool(this._platformService),
new KubeCtlTool(this._platformService)
].map<[string, ITool]>((tool: ITool) => [tool.name, tool])
);

View File

@@ -1,57 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'mocha';
import * as TypeMoq from 'typemoq';
import * as should from 'should';
import { IPlatformService, CommandOptions } from '../../services/platformService';
import { AzdataService } from '../../services/azdataService';
import { BdcDeploymentType } from '../../interfaces';
describe('azdata service Tests', function (): void {
it('azdata service handles deployment types properly', async () => {
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
const azdataService = new AzdataService(mockPlatformService.object);
mockPlatformService.setup((service) => service.runCommand(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns((command: string, options: CommandOptions | undefined) => {
return new Promise<string>((resolve) => {
resolve('{"result":[]}');
});
});
azdataService.getDeploymentProfiles(BdcDeploymentType.ExistingAKS);
azdataService.getDeploymentProfiles(BdcDeploymentType.ExistingARO);
azdataService.getDeploymentProfiles(BdcDeploymentType.ExistingKubeAdm);
azdataService.getDeploymentProfiles(BdcDeploymentType.ExistingOpenShift);
azdataService.getDeploymentProfiles(BdcDeploymentType.NewAKS);
should(azdataService.getDeploymentProfiles(<BdcDeploymentType>'no-such-type')).rejected();
mockPlatformService.verify((service) => service.runCommand(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.exactly(5));
});
it('azdata service returns correct deployment profiles', async () => {
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
const azdataService = new AzdataService(mockPlatformService.object);
mockPlatformService.setup((service => service.storagePath())).returns(() => {
return '';
});
mockPlatformService.setup((service => service.readTextFile(TypeMoq.It.isAnyString()))).returns((path: string) => {
return new Promise<string>((resolve) => {
resolve('{}');
});
});
mockPlatformService.setup((service) => service.runCommand(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns((command: string, options: CommandOptions | undefined) => {
if (command === 'azdata bdc config list -o json') {
return Promise.resolve('{"result":["aks-1","profile-2"]}');
} else if (command.startsWith('azdata bdc config init')) {
return Promise.resolve('');
}
else {
return Promise.reject(`unexpected command: ${command}`);
}
});
const profiles = await azdataService.getDeploymentProfiles(BdcDeploymentType.NewAKS);
should(profiles.length).be.exactly(1);
});
});

View File

@@ -24,13 +24,13 @@ describe('Resource Type Service Tests', function (): void {
// index 0: platform name, index 1: expected resource types
const platforms: { platform: string; resourceTypes: string[] }[] = [
{
platform: 'win32', resourceTypes: ['sql-image', 'sql-bdc', 'sql-windows-setup']
platform: 'win32', resourceTypes: ['sql-image', 'sql-windows-setup']
},
{
platform: 'darwin', resourceTypes: ['sql-image', 'sql-bdc']
platform: 'darwin', resourceTypes: ['sql-image']
},
{
platform: 'linux', resourceTypes: ['sql-image', 'sql-bdc']
platform: 'linux', resourceTypes: ['sql-image']
}
];
platforms.forEach(platformInfo => {

View File

@@ -9,14 +9,12 @@ import * as TypeMoq from 'typemoq';
import { ToolsService } from '../../services/toolsService';
import { ITool, ToolType } from '../../interfaces';
import { IPlatformService } from '../../services/platformService';
import { AzdataToolName } from '../../services/tools/azdataTool';
const tools: { name: string; type: ToolType }[] = [
{ name: 'azure-cli', type: ToolType.AzCli },
{ name: 'docker', type: ToolType.Docker },
{ name: 'kubectl', type: ToolType.KubeCtl },
{ name: AzdataToolName, type: ToolType.Azdata }
{ name: 'kubectl', type: ToolType.KubeCtl }
];
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
const toolsService = new ToolsService(mockPlatformService.object);

View File

@@ -1,73 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export const DeploymentProfile_VariableName = 'AZDATA_NB_VAR_BDC_DEPLOYMENT_PROFILE';
export const ClusterName_VariableName = 'AZDATA_NB_VAR_BDC_CLUSTER_NAME';
export const AdminUserName_VariableName = 'AZDATA_NB_VAR_BDC_CONTROLLER_USERNAME';
export const AdminPassword_VariableName = 'AZDATA_NB_VAR_BDC_ADMIN_PASSWORD';
export const AuthenticationMode_VariableName = 'AZDATA_NB_VAR_BDC_AUTHENTICATION_MODE';
export const 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 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_BDC_AD_APP_OWNERS';
export const AppReaders_VariableName = 'AZDATA_NB_VAR_AD_BDC_AD_APP_READERS';
export const Subdomain_VariableName = 'AZDATA_NB_VAR_BDC_AD_SUBDOMAIN';
export const AccountPrefix_VariableName = 'AZDATA_NB_VAR_BDC_AD_ACCOUNTPREFIX';
export const SubscriptionId_VariableName = 'AZDATA_NB_VAR_BDC_AZURE_SUBSCRIPTION';
export const ResourceGroup_VariableName = 'AZDATA_NB_VAR_BDC_RESOURCEGROUP_NAME';
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';
export const KubeConfigPath_VariableName = 'AZDATA_NB_VAR_BDC_KUBECONFIG_PATH';
export const ClusterContext_VariableName = 'AZDATA_NB_VAR_BDC_CLUSTER_CONTEXT';
export const SQLServerScale_VariableName = 'AZDATA_NB_VAR_BDC_SQLSERVER_SCALE';
export const HDFSPoolScale_VariableName = 'AZDATA_NB_VAR_BDC_HDFSPOOL_SCALE';
export const HDFSNameNodeScale_VariableName = 'AZDATA_NB_VAR_BDC_NAMENODE_SCALE';
export const ZooKeeperScale_VariableName = 'AZDATA_NB_VAR_BDC_ZOOKEEPER_SCALE';
export const SparkHeadScale_VariableName = 'AZDATA_NB_VAR_BDC_SPARKHEAD_SCALE';
export const IncludeSpark_VariableName = 'AZDATA_NB_VAR_BDC_INCLUDESPARK';
export const ComputePoolScale_VariableName = 'AZDATA_NB_VAR_BDC_COMPUTEPOOL_SCALE';
export const DataPoolScale_VariableName = 'AZDATA_NB_VAR_BDC_DATAPOOL_SCALE';
export const SparkPoolScale_VariableName = 'AZDATA_NB_VAR_BDC_SPARKPOOL_SCALE';
export const ControllerDataStorageClassName_VariableName = 'AZDATA_NB_VAR_BDC_CONTROLLER_DATA_STORAGE_CLASS';
export const ControllerDataStorageSize_VariableName = 'AZDATA_NB_VAR_BDC_CONTROLLER_DATA_STORAGE_SIZE';
export const ControllerLogsStorageClassName_VariableName = 'AZDATA_NB_VAR_BDC_CONTROLLER_LOGS_STORAGE_CLASS';
export const ControllerLogsStorageSize_VariableName = 'AZDATA_NB_VAR_BDC_CONTROLLER_LOGS_STORAGE_SIZE';
export const DataPoolDataStorageClassName_VariableName = 'AZDATA_NB_VAR_BDC_DATA_DATA_STORAGE_CLASS';
export const DataPoolDataStorageSize_VariableName = 'AZDATA_NB_VAR_BDC_DATA_DATA_STORAGE_SIZE';
export const DataPoolLogsStorageClassName_VariableName = 'AZDATA_NB_VAR_BDC_DATA_LOGS_STORAGE_CLASS';
export const DataPoolLogsStorageSize_VariableName = 'AZDATA_NB_VAR_BDC_DATA_LOGS_STORAGE_SIZE';
export const HDFSDataStorageClassName_VariableName = 'AZDATA_NB_VAR_BDC_HDFS_DATA_STORAGE_CLASS';
export const HDFSDataStorageSize_VariableName = 'AZDATA_NB_VAR_BDC_HDFS_DATA_STORAGE_SIZE';
export const HDFSLogsStorageClassName_VariableName = 'AZDATA_NB_VAR_BDC_HDFS_LOGS_STORAGE_CLASS';
export const HDFSLogsStorageSize_VariableName = 'AZDATA_NB_VAR_BDC_HDFS_LOGS_STORAGE_SIZE';
export const SQLServerDataStorageClassName_VariableName = 'AZDATA_NB_VAR_BDC_SQL_DATA_STORAGE_CLASS';
export const SQLServerDataStorageSize_VariableName = 'AZDATA_NB_VAR_BDC_SQL_DATA_STORAGE_SIZE';
export const SQLServerLogsStorageClassName_VariableName = 'AZDATA_NB_VAR_BDC_SQL_LOGS_STORAGE_CLASS';
export const SQLServerLogsStorageSize_VariableName = 'AZDATA_NB_VAR_BDC_SQL_LOGS_STORAGE_SIZE';
export const ControllerDNSName_VariableName = 'AZDATA_NB_VAR_BDC_CONTROLLER_DNS';
export const ControllerPort_VariableName = 'AZDATA_NB_VAR_BDC_CONTROLLER_PORT';
export const SQLServerDNSName_VariableName = 'AZDATA_NB_VAR_BDC_SQL_DNS';
export const SQLServerPort_VariableName = 'AZDATA_NB_VAR_BDC_SQL_PORT';
export const GatewayDNSName_VariableName = 'AZDATA_NB_VAR_BDC_GATEWAY_DNS';
export const GateWayPort_VariableName = 'AZDATA_NB_VAR_BDC_GATEWAY_PORT';
export const ReadableSecondaryDNSName_VariableName = 'AZDATA_NB_VAR_BDC_READABLE_SECONDARY_DNS';
export const ReadableSecondaryPort_VariableName = 'AZDATA_NB_VAR_BDC_READABLE_SECONDARY_PORT';
export const 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';

View File

@@ -1,356 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { delimiter, join } from 'path';
import * as fs from 'fs';
import * as os from 'os';
import { BdcDeploymentType, BdcWizardDeploymentProvider, ITool } from '../../interfaces';
import { BigDataClusterDeploymentProfile, DataResource, HdfsResource, SqlServerMasterResource } from '../../services/bigDataClusterDeploymentProfile';
import { KubeCtlToolName } from '../../services/tools/kubeCtlTool';
import { getErrorMessage, getRuntimeBinaryPathEnvironmentVariableName, setEnvironmentVariablesForInstallPaths } from '../../common/utils';
import { ToolsInstallPath } from '../../constants';
import * as VariableNames from './constants';
import { ResourceTypeWizard } from '../resourceTypeWizard';
import * as nls from 'vscode-nls';
import { InputComponents } from '../modelViewUtils';
import { INotebookService } from '../../services/notebookService';
import { IAzdataService } from '../../services/azdataService';
import { IKubeService } from '../../services/kubeService';
import { DeploymentProfilePage } from './pages/deploymentProfilePage';
import { AzureSettingsPage } from './pages/azureSettingsPage';
import { ClusterSettingsPage } from './pages/clusterSettingsPage';
import { ServiceSettingsPage } from './pages/serviceSettingsPage';
import { SummaryPage } from './pages/summaryPage';
import { TargetClusterContextPage } from './pages/targetClusterPage';
import { IToolsService } from '../../services/toolsService';
import { ResourceTypeModel } from '../resourceTypeModel';
import { ResourceTypePage } from '../resourceTypePage';
const localize = nls.loadMessageBundle();
export class DeployClusterWizardModel extends ResourceTypeModel {
private _inputComponents: InputComponents = {};
private _kubeService: IKubeService;
private _azdataService: IAzdataService;
private _notebookService: INotebookService;
private toolsService: IToolsService;
private _saveConfigButton: azdata.window.Button;
public get kubeService(): IKubeService {
return this._kubeService;
}
public get azdataService(): IAzdataService {
return this._azdataService;
}
public get notebookService(): INotebookService {
return this._notebookService;
}
public get inputComponents(): InputComponents {
return this._inputComponents;
}
public showCustomButtons(): void {
this._saveConfigButton.hidden = false;
}
public hideCustomButtons(): void {
this._saveConfigButton.hidden = true;
}
public get deploymentType(): BdcDeploymentType {
return this.bdcProvider.bdcWizard.type;
}
initialize(): void {
this.wizard.setPages(this.getPages());
this.wizard.wizardObject.generateScriptButton.hidden = true;
this.wizard.wizardObject.doneButton.label = localize('deployCluster.ScriptToNotebook', "Script to Notebook");
}
async onOk(): Promise<void> {
await this.scriptToNotebook();
}
constructor(public bdcProvider: BdcWizardDeploymentProvider, wizard: ResourceTypeWizard) {
super(bdcProvider, wizard);
this._kubeService = this.wizard._kubeService;
this._azdataService = this.wizard.azdataService;
this._notebookService = this.wizard.notebookService;
this.toolsService = this.wizard.toolsService;
this.wizard.wizardObject.title = this.getTitle(this.deploymentType);
this._saveConfigButton = azdata.window.createButton(localize('deployCluster.SaveConfigFiles', "Save config files"), 'left');
this._saveConfigButton.hidden = true;
this.wizard.addButton(this._saveConfigButton);
this.wizard.registerDisposable(this._saveConfigButton.onClick(() => this.saveConfigFiles()));
}
public adAuthSupported: boolean = false;
public get authenticationMode(): string | undefined {
return this.getStringValue(VariableNames.AuthenticationMode_VariableName);
}
public set authenticationMode(value: string | undefined) {
this.setPropertyValue(VariableNames.AuthenticationMode_VariableName, value);
}
public getStorageSettingValue(propertyName: string, defaultValuePropertyName: string): string | undefined {
const value = this.getStringValue(propertyName);
return (value === undefined || value === '') ? this.getStringValue(defaultValuePropertyName) : value;
}
private setStorageSettingValue(propertyName: string, defaultValuePropertyName: string): void {
const value = this.getStringValue(propertyName);
if (value === undefined || value === '') {
this.setPropertyValue(propertyName, this.getStringValue(defaultValuePropertyName));
}
}
private setStorageSettingValues(): void {
this.setStorageSettingValue(VariableNames.DataPoolDataStorageClassName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName);
this.setStorageSettingValue(VariableNames.DataPoolDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName);
this.setStorageSettingValue(VariableNames.DataPoolLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName);
this.setStorageSettingValue(VariableNames.DataPoolLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName);
this.setStorageSettingValue(VariableNames.HDFSDataStorageClassName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName);
this.setStorageSettingValue(VariableNames.HDFSDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName);
this.setStorageSettingValue(VariableNames.HDFSLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName);
this.setStorageSettingValue(VariableNames.HDFSLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName);
this.setStorageSettingValue(VariableNames.SQLServerDataStorageClassName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName);
this.setStorageSettingValue(VariableNames.SQLServerDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName);
this.setStorageSettingValue(VariableNames.SQLServerLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName);
this.setStorageSettingValue(VariableNames.SQLServerLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName);
}
public override setEnvironmentVariables(): void {
this.setStorageSettingValues();
}
public selectedProfile: BigDataClusterDeploymentProfile | undefined;
public createTargetProfile(): BigDataClusterDeploymentProfile {
// create a copy of the source files to avoid changing the source profile values
const sourceBdcJson = Object.assign({}, this.selectedProfile!.bdcConfig);
const sourceControlJson = Object.assign({}, this.selectedProfile!.controlConfig);
const targetDeploymentProfile = new BigDataClusterDeploymentProfile('', sourceBdcJson, sourceControlJson);
// 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
targetDeploymentProfile.controllerDataStorageClass = this.getStringValue(VariableNames.ControllerDataStorageClassName_VariableName)!;
targetDeploymentProfile.controllerDataStorageSize = this.getIntegerValue(VariableNames.ControllerDataStorageSize_VariableName)!;
targetDeploymentProfile.controllerLogsStorageClass = this.getStringValue(VariableNames.ControllerLogsStorageClassName_VariableName)!;
targetDeploymentProfile.controllerLogsStorageSize = this.getIntegerValue(VariableNames.ControllerLogsStorageSize_VariableName)!;
targetDeploymentProfile.setResourceStorage(DataResource,
this.getStorageSettingValue(VariableNames.DataPoolDataStorageClassName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName)!,
Number.parseInt(this.getStorageSettingValue(VariableNames.DataPoolDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName)!),
this.getStorageSettingValue(VariableNames.DataPoolLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName)!,
Number.parseInt(this.getStorageSettingValue(VariableNames.DataPoolLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName)!)
);
targetDeploymentProfile.setResourceStorage(SqlServerMasterResource,
this.getStorageSettingValue(VariableNames.SQLServerDataStorageClassName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName)!,
Number.parseInt(this.getStorageSettingValue(VariableNames.SQLServerDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName)!),
this.getStorageSettingValue(VariableNames.SQLServerLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName)!,
Number.parseInt(this.getStorageSettingValue(VariableNames.SQLServerLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName)!)
);
targetDeploymentProfile.setResourceStorage(HdfsResource,
this.getStorageSettingValue(VariableNames.HDFSDataStorageClassName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName)!,
Number.parseInt(this.getStorageSettingValue(VariableNames.HDFSDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName)!),
this.getStorageSettingValue(VariableNames.HDFSLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName)!,
Number.parseInt(this.getStorageSettingValue(VariableNames.HDFSLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName)!)
);
// scale settings
targetDeploymentProfile.dataReplicas = this.getIntegerValue(VariableNames.DataPoolScale_VariableName);
targetDeploymentProfile.computeReplicas = this.getIntegerValue(VariableNames.ComputePoolScale_VariableName);
targetDeploymentProfile.hdfsReplicas = this.getIntegerValue(VariableNames.HDFSPoolScale_VariableName);
targetDeploymentProfile.sqlServerReplicas = this.getIntegerValue(VariableNames.SQLServerScale_VariableName);
targetDeploymentProfile.hdfsNameNodeReplicas = this.getIntegerValue(VariableNames.HDFSNameNodeScale_VariableName);
targetDeploymentProfile.sparkHeadReplicas = this.getIntegerValue(VariableNames.SparkHeadScale_VariableName);
targetDeploymentProfile.zooKeeperReplicas = this.getIntegerValue(VariableNames.ZooKeeperScale_VariableName);
const sparkScale = this.getIntegerValue(VariableNames.SparkPoolScale_VariableName);
if (sparkScale > 0) {
targetDeploymentProfile.addSparkResource(sparkScale);
}
targetDeploymentProfile.includeSpark = this.getBooleanValue(VariableNames.IncludeSpark_VariableName);
// 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)!,
realm: this.getStringValue(VariableNames.Realm_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),
subdomain: this.getStringValue(VariableNames.Subdomain_VariableName),
accountPrefix: this.getStringValue(VariableNames.AccountPrefix_VariableName)
});
}
return targetDeploymentProfile;
}
public override getCodeCellContentForNotebook(tools: ITool[]): string[] {
const profile = this.createTargetProfile();
const statements: string[] = [];
if (this.deploymentType === BdcDeploymentType.NewAKS) {
statements.push(`azure_subscription_id = '${this.getStringValue(VariableNames.SubscriptionId_VariableName, '')}'`);
statements.push(`azure_region = '${this.getStringValue(VariableNames.Location_VariableName)}'`);
statements.push(`azure_resource_group = '${this.getStringValue(VariableNames.ResourceGroup_VariableName)}'`);
statements.push(`azure_vm_size = '${this.getStringValue(VariableNames.VMSize_VariableName)}'`);
statements.push(`azure_vm_count = '${this.getStringValue(VariableNames.VMCount_VariableName)}'`);
statements.push(`aks_cluster_name = '${this.getStringValue(VariableNames.AksName_VariableName)}'`);
} else if (this.deploymentType === BdcDeploymentType.ExistingAKS
|| this.deploymentType === BdcDeploymentType.ExistingKubeAdm
|| this.deploymentType === BdcDeploymentType.ExistingARO
|| this.deploymentType === BdcDeploymentType.ExistingOpenShift) {
statements.push(`mssql_kube_config_path = '${this.escapeForNotebookCodeCell(this.getStringValue(VariableNames.KubeConfigPath_VariableName)!)}'`);
statements.push(`mssql_cluster_context = '${this.getStringValue(VariableNames.ClusterContext_VariableName)}'`);
statements.push('os.environ["KUBECONFIG"] = mssql_kube_config_path');
}
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_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}"]`);
}
const kubeCtlEnvVarName: string = getRuntimeBinaryPathEnvironmentVariableName(KubeCtlToolName);
const env: NodeJS.ProcessEnv = {};
setEnvironmentVariablesForInstallPaths(tools, env);
statements.push(`os.environ["${kubeCtlEnvVarName}"] = "${this.escapeForNotebookCodeCell(env[kubeCtlEnvVarName]!)}"`);
statements.push(`os.environ["PATH"] = os.environ["PATH"] + "${delimiter}" + "${this.escapeForNotebookCodeCell(env[ToolsInstallPath]!)}"`);
statements.push(`print('Variables have been set successfully.')`);
return statements.map(line => line + os.EOL);
}
private async saveConfigFiles(): Promise<void> {
const options: vscode.OpenDialogOptions = {
defaultUri: vscode.Uri.file(os.homedir()),
canSelectFiles: false,
canSelectFolders: true,
canSelectMany: false,
openLabel: localize('deployCluster.SelectConfigFileFolder', "Save config files")
};
const pathArray = await vscode.window.showOpenDialog(options);
if (pathArray && pathArray[0]) {
const targetFolder = pathArray[0].fsPath;
try {
const profile = this.createTargetProfile();
await fs.promises.writeFile(join(targetFolder, 'bdc.json'), profile.getBdcJson());
await fs.promises.writeFile(join(targetFolder, 'control.json'), profile.getControlJson());
this.wizard.wizardObject.message = {
text: localize('deployCluster.SaveConfigFileSucceeded', "Config files saved to {0}", targetFolder),
level: azdata.window.MessageLevel.Information
};
}
catch (error) {
this.wizard.wizardObject.message = {
text: error.message,
level: azdata.window.MessageLevel.Error
};
}
}
}
private getPages(): ResourceTypePage[] {
const pages: ResourceTypePage[] = [];
switch (this.deploymentType) {
case BdcDeploymentType.NewAKS:
pages.push(
new DeploymentProfilePage(this),
new AzureSettingsPage(this),
new ClusterSettingsPage(this),
new ServiceSettingsPage(this),
new SummaryPage(this));
break;
case BdcDeploymentType.ExistingAKS:
case BdcDeploymentType.ExistingKubeAdm:
case BdcDeploymentType.ExistingARO:
case BdcDeploymentType.ExistingOpenShift:
pages.push(
new DeploymentProfilePage(this),
new TargetClusterContextPage(this),
new ClusterSettingsPage(this),
new ServiceSettingsPage(this),
new SummaryPage(this));
break;
default:
throw new Error(`Unknown deployment type: ${this.deploymentType}`);
}
return pages;
}
private async scriptToNotebook(): Promise<void> {
this.setNotebookEnvironmentVariables(process.env);
const variableValueStatements = this.getCodeCellContentForNotebook(this.toolsService.toolsForCurrentProvider);
const insertionPosition = 5; // Cell number 5 is the position where the python variable setting statements need to be inserted in this.wizardInfo.notebook.
try {
await this.notebookService.openNotebookWithEdits(this.bdcProvider.bdcWizard.notebook, variableValueStatements, insertionPosition);
} catch (error) {
vscode.window.showErrorMessage(getErrorMessage(error));
}
}
private setNotebookEnvironmentVariables(env: NodeJS.ProcessEnv): void {
env[VariableNames.AdminPassword_VariableName] = this.getStringValue(VariableNames.AdminPassword_VariableName);
env[VariableNames.DockerPassword_VariableName] = this.getStringValue(VariableNames.DockerPassword_VariableName);
if (this.authenticationMode === AuthenticationMode.ActiveDirectory) {
env[VariableNames.DomainServiceAccountPassword_VariableName] = this.getStringValue(VariableNames.DomainServiceAccountPassword_VariableName);
}
}
private getTitle(type: BdcDeploymentType): string {
switch (type) {
case BdcDeploymentType.NewAKS:
return localize('deployCluster.NewAKSWizardTitle', "Deploy SQL Server 2019 Big Data Cluster on a new AKS cluster");
case BdcDeploymentType.ExistingAKS:
return localize('deployCluster.ExistingAKSWizardTitle', "Deploy SQL Server 2019 Big Data Cluster on an existing AKS cluster");
case BdcDeploymentType.ExistingKubeAdm:
return localize('deployCluster.ExistingKubeAdm', "Deploy SQL Server 2019 Big Data Cluster on an existing kubeadm cluster");
case BdcDeploymentType.ExistingARO:
return localize('deployCluster.ExistingARO', "Deploy SQL Server 2019 Big Data Cluster on an existing Azure Red Hat OpenShift cluster");
case BdcDeploymentType.ExistingOpenShift:
return localize('deployCluster.ExistingOpenShift', "Deploy SQL Server 2019 Big Data Cluster on an existing OpenShift cluster");
default:
throw new Error(`Unknown deployment type: ${type}`);
}
}
}
export enum AuthenticationMode {
ActiveDirectory = 'ad',
Basic = 'basic'
}

View File

@@ -1,186 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { FieldType, LabelPosition, SectionInfo } from '../../../interfaces';
import { createSection, getDropdownComponent, InputComponent, InputComponentInfo, InputComponents, setModelValues, Validator } from '../../modelViewUtils';
import { AksName_VariableName, Location_VariableName, ResourceGroup_VariableName, SubscriptionId_VariableName, VMCount_VariableName, VMSize_VariableName } from '../constants';
import { AzureRegion } from 'azurecore';
import { DeployClusterWizardModel } from '../deployClusterWizardModel';
import { ResourceTypePage } from '../../resourceTypePage';
const localize = nls.loadMessageBundle();
const MissingRequiredInformationErrorMessage = localize('deployCluster.MissingRequiredInfoError', "Please fill out the required fields marked with red asterisks.");
export class AzureSettingsPage extends ResourceTypePage {
private inputComponents: InputComponents = {};
constructor(private _model: DeployClusterWizardModel) {
super(localize('deployCluster.AzureSettingsPageTitle', "Azure settings"),
localize('deployCluster.AzureSettingsPageDescription', "Configure the settings to create an Azure Kubernetes Service cluster"), _model.wizard);
}
public initialize(): void {
const self = this;
const azureSection: SectionInfo = {
title: '',
labelPosition: LabelPosition.Left,
spaceBetweenFields: '5px',
rows: [{
items: [{
type: FieldType.Text,
label: localize('deployCluster.SubscriptionField', "Subscription id"),
required: false,
variableName: SubscriptionId_VariableName,
placeHolder: localize('deployCluster.SubscriptionPlaceholder', "Use my default Azure subscription"),
description: localize('deployCluster.SubscriptionDescription', "The default subscription will be used if you leave this field blank.")
}, {
type: FieldType.ReadonlyText,
label: '{0}',
links: [
{
text: localize('deployCluster.SubscriptionHelpLink', "View available Azure subscriptions"),
url: 'https://portal.azure.com/#blade/Microsoft_Azure_Billing/SubscriptionsBlade'
}
]
}]
}, {
items: [{
type: FieldType.DateTimeText,
label: localize('deployCluster.ResourceGroupName', "New resource group name"),
required: true,
variableName: ResourceGroup_VariableName,
defaultValue: 'mssql-'
}]
}, {
items: [{
type: FieldType.Options,
label: localize('deployCluster.Location', "Location"),
required: true,
variableName: Location_VariableName,
defaultValue: AzureRegion.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: [
AzureRegion.centralus,
AzureRegion.eastus,
AzureRegion.eastus2,
AzureRegion.northcentralus,
AzureRegion.southcentralus,
AzureRegion.westus,
AzureRegion.westus2,
AzureRegion.canadacentral,
AzureRegion.canadaeast
]
}, {
type: FieldType.ReadonlyText,
label: '{0}',
links: [
{
text: localize('deployCluster.AzureLocationHelpLink', "View available Azure locations"),
url: 'https://azure.microsoft.com/global-infrastructure/services/?products=kubernetes-service'
}
]
}]
}, {
items: [{
type: FieldType.DateTimeText,
label: localize('deployCluster.AksName', "AKS cluster name"),
required: true,
variableName: AksName_VariableName,
defaultValue: 'mssql-',
}]
}, {
items: [
{
type: FieldType.Number,
label: localize('deployCluster.VMCount', "VM count"),
required: true,
variableName: VMCount_VariableName,
defaultValue: '5',
min: 1,
max: 999
}
]
}, {
items: [{
type: FieldType.Text,
label: localize('deployCluster.VMSize', "VM size"),
required: true,
variableName: VMSize_VariableName,
defaultValue: 'Standard_E8s_v3'
}, {
type: FieldType.ReadonlyText,
label: '{0}',
links: [
{
text: localize('deployCluster.VMSizeHelpLink', "View available VM sizes"),
url: 'https://docs.microsoft.com/azure/virtual-machines/linux/sizes'
}
]
}]
}]
};
this.pageObject.registerContent(async (view: azdata.ModelView) => {
const azureGroup = await createSection({
sectionInfo: azureSection,
view: view,
onNewDisposableCreated: (disposable: vscode.Disposable): void => {
self.wizard.registerDisposable(disposable);
},
onNewInputComponentCreated: (name: string, inputComponentInfo: InputComponentInfo<InputComponent>): void => {
self.inputComponents[name] = inputComponentInfo;
self._model.inputComponents[name] = inputComponentInfo;
},
onNewValidatorCreated: (validator: Validator): void => {
self.validators.push(validator);
},
container: this.wizard.wizardObject,
inputComponents: this._model.inputComponents,
toolsService: this.wizard.toolsService
});
const formBuilder = view.modelBuilder.formContainer().withFormItems(
[{
title: '',
component: azureGroup
}],
{
horizontal: false,
componentWidth: '100%'
}
);
const form = formBuilder.withLayout({ width: '100%' }).component();
return view.initializeModel(form);
});
}
public override async onEnter(): Promise<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 override async onLeave(): Promise<void> {
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
return true;
});
await setModelValues(this.inputComponents, this.wizard.model);
}
}

View File

@@ -1,367 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import { EOL } from 'os';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { FieldType, LabelPosition, SectionInfo } from '../../../interfaces';
import * as localizedConstants from '../../../localizedConstants';
import { createSection, getInputBoxComponent, getInvalidSQLPasswordMessage, getPasswordMismatchMessage, InputComponent, InputComponentInfo, InputComponents, isValidSQLPassword, setModelValues, Validator } from '../../modelViewUtils';
import { ResourceTypePage } from '../../resourceTypePage';
import { ValidationType } from '../../validation/validations';
import * as VariableNames from '../constants';
import { AuthenticationMode, DeployClusterWizardModel } from '../deployClusterWizardModel';
const localize = nls.loadMessageBundle();
const ConfirmPasswordName = 'ConfirmPassword';
const clusterNameFieldDescription = localize('deployCluster.ClusterNameDescription', "The cluster name must consist only of alphanumeric lowercase characters or '-' and must start and end with an alphanumeric character.");
export class ClusterSettingsPage extends ResourceTypePage {
private inputComponents: InputComponents = {};
private activeDirectorySection!: azdata.FormComponent;
private formBuilder!: azdata.FormBuilder;
constructor(private _model: DeployClusterWizardModel) {
super(localize('deployCluster.ClusterSettingsPageTitle', "Cluster settings"),
localize('deployCluster.ClusterSettingsPageDescription', "Configure the SQL Server Big Data Cluster settings"), _model.wizard);
}
public initialize(): void {
const self = this;
const basicSection: SectionInfo = {
labelPosition: LabelPosition.Left,
title: '',
fields: [
{
type: FieldType.Text,
label: localize('deployCluster.ClusterName', "Cluster name"),
required: true,
variableName: VariableNames.ClusterName_VariableName,
defaultValue: 'mssql-cluster',
validations: [{
type: ValidationType.Regex,
regex: new RegExp('^[a-z0-9]$|^[a-z0-9][a-z0-9-]*[a-z0-9]$'),
description: clusterNameFieldDescription
}],
description: clusterNameFieldDescription
}, {
type: FieldType.Text,
label: localize('deployCluster.AdminUsername', "Admin username"),
required: true,
variableName: VariableNames.AdminUserName_VariableName,
defaultValue: 'admin',
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"),
required: true,
variableName: VariableNames.AdminPassword_VariableName,
defaultValue: '',
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"),
required: true,
variableName: ConfirmPasswordName,
defaultValue: ''
}, {
type: FieldType.Options,
label: localize('deployCluster.AuthenticationMode', "Authentication mode"),
variableName: VariableNames.AuthenticationMode_VariableName,
defaultValue: AuthenticationMode.Basic,
options: [
{
name: AuthenticationMode.Basic,
displayName: localize('deployCluster.AuthenticationMode.Basic', "Basic")
},
{
name: AuthenticationMode.ActiveDirectory,
displayName: localize('deployCluster.AuthenticationMode.ActiveDirectory', "Active Directory")
}
]
}
]
};
const 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.Password,
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.OuDistinguishedName', "Organizational unit"),
required: true,
variableName: VariableNames.OrganizationalUnitDistinguishedName_VariableName,
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,
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,
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
}, {
type: FieldType.Text,
label: localizedConstants.realm,
required: false,
variableName: VariableNames.Realm_VariableName,
description: localize('deployCluster.RealmDescription', "If not provided, the domain DNS name will be used as the default value.")
}, {
type: FieldType.Text,
label: localize('deployCluster.ClusterAdmins', "Cluster admin group"),
required: true,
variableName: VariableNames.ClusterAdmins_VariableName,
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,
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,
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
}, {
type: FieldType.Text,
label: localize('deployCluster.AppOwners', "App owners"),
required: false,
variableName: VariableNames.AppOwners_VariableName,
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.AppReaders', "App readers"),
required: false,
variableName: VariableNames.AppReaders_VariableName,
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.")
}, {
type: FieldType.Text,
label: localize('deployCluster.Subdomain', "Subdomain"),
required: false,
variableName: VariableNames.Subdomain_VariableName,
description: localize('deployCluster.SubdomainDescription', "A unique DNS subdomain to use for this SQL Server Big Data Cluster. If not provided, the cluster name will be used as the default value.")
}, {
type: FieldType.Text,
label: localize('deployCluster.AccountPrefix', "Account prefix"),
required: false,
variableName: VariableNames.AccountPrefix_VariableName,
description: localize('deployCluster.AccountPrefixDescription', "A unique prefix for AD accounts SQL Server Big Data Cluster will generate. If not provided, the subdomain name will be used as the default value. If a subdomain is not provided, the cluster name will be used as the default value.")
}
]
};
this.pageObject.registerContent(async (view: azdata.ModelView) => {
const basicSettingsGroup = await createSection({
view: view,
container: self.wizard.wizardObject,
inputComponents: this._model.inputComponents,
sectionInfo: basicSection,
onNewDisposableCreated: (disposable: vscode.Disposable): void => {
self.wizard.registerDisposable(disposable);
},
onNewInputComponentCreated: (name: string, inputComponentInfo: InputComponentInfo<InputComponent>): void => {
self.inputComponents[name] = inputComponentInfo;
self._model.inputComponents[name] = inputComponentInfo;
},
onNewValidatorCreated: (validator: Validator): void => {
self.validators.push(validator);
},
toolsService: this.wizard.toolsService
});
const activeDirectorySettingsGroup = await createSection({
view: view,
container: self.wizard.wizardObject,
inputComponents: this._model.inputComponents,
sectionInfo: activeDirectorySection,
onNewDisposableCreated: (disposable: vscode.Disposable): void => {
self.wizard.registerDisposable(disposable);
},
onNewInputComponentCreated: (name: string, inputComponentInfo: InputComponentInfo<InputComponent>): void => {
self.inputComponents[name] = inputComponentInfo;
self._model.inputComponents[name] = inputComponentInfo;
},
onNewValidatorCreated: (validator: Validator): void => {
self.validators.push(validator);
},
toolsService: this.wizard.toolsService
});
const dockerSettingsGroup = await createSection({
view: view,
container: self.wizard.wizardObject,
inputComponents: this._model.inputComponents,
sectionInfo: dockerSection,
onNewDisposableCreated: (disposable: vscode.Disposable): void => {
self.wizard.registerDisposable(disposable);
},
onNewInputComponentCreated: (name: string, inputComponentInfo: InputComponentInfo<InputComponent>): void => {
self.inputComponents[name] = inputComponentInfo;
self._model.inputComponents[name] = inputComponentInfo;
},
onNewValidatorCreated: (validator: Validator): void => {
self.validators.push(validator);
},
toolsService: this.wizard.toolsService
});
const basicSettingsFormItem = { title: '', component: basicSettingsGroup };
const dockerSettingsFormItem = { title: '', component: dockerSettingsGroup };
this.activeDirectorySection = { title: '', component: activeDirectorySettingsGroup };
const authModeDropdown = <azdata.DropDownComponent>this.inputComponents[VariableNames.AuthenticationMode_VariableName].component;
this.formBuilder = view.modelBuilder.formContainer().withFormItems(
[basicSettingsFormItem, dockerSettingsFormItem],
{
horizontal: false,
componentWidth: '100%'
}
);
this.wizard.registerDisposable(authModeDropdown.onValueChanged(() => {
const isBasicAuthMode = (<azdata.CategoryValue>authModeDropdown.value).name === 'basic';
getInputBoxComponent(VariableNames.OrganizationalUnitDistinguishedName_VariableName, this.inputComponents).required = !isBasicAuthMode;
getInputBoxComponent(VariableNames.DomainControllerFQDNs_VariableName, this.inputComponents).required = !isBasicAuthMode;
getInputBoxComponent(VariableNames.DomainDNSIPAddresses_VariableName, this.inputComponents).required = !isBasicAuthMode;
getInputBoxComponent(VariableNames.DomainDNSName_VariableName, this.inputComponents).required = !isBasicAuthMode;
getInputBoxComponent(VariableNames.ClusterAdmins_VariableName, this.inputComponents).required = !isBasicAuthMode;
getInputBoxComponent(VariableNames.ClusterUsers_VariableName, this.inputComponents).required = !isBasicAuthMode;
getInputBoxComponent(VariableNames.DomainServiceAccountUserName_VariableName, this.inputComponents).required = !isBasicAuthMode;
getInputBoxComponent(VariableNames.DomainServiceAccountPassword_VariableName, this.inputComponents).required = !isBasicAuthMode;
if (isBasicAuthMode) {
this.formBuilder.removeFormItem(this.activeDirectorySection);
} else {
this.formBuilder.insertFormItem(this.activeDirectorySection);
}
}));
const form = this.formBuilder.withLayout({ width: '100%' }).component();
return view.initializeModel(form);
});
}
public override async onLeave(): Promise<void> {
await setModelValues(this.inputComponents, this.wizard.model);
if (this._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';
const subdomain = this.wizard.model.getStringValue(VariableNames.Subdomain_VariableName) || this.wizard.model.getStringValue(VariableNames.ClusterName_VariableName);
Object.keys(variableDNSPrefixMapping).forEach((variableName: string) => {
this.wizard.model.setPropertyValue(variableName, `${variableDNSPrefixMapping[variableName]}.${subdomain}.${this.wizard.model.getStringValue(VariableNames.DomainDNSName_VariableName)}`);
});
}
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
return true;
});
}
public override async onEnter(): Promise<void> {
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].component;
if (authModeDropdown) {
authModeDropdown.enabled = this._model.adAuthSupported;
const adAuthSelected = (<azdata.CategoryValue>authModeDropdown.value).name === 'ad';
if (!this._model.adAuthSupported && adAuthSelected) {
this.formBuilder.removeFormItem(this.activeDirectorySection);
authModeDropdown.value = {
name: AuthenticationMode.Basic,
displayName: localize('deployCluster.AuthenticationMode.Basic', "Basic")
};
}
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
this.wizard.wizardObject.message = { text: '' };
if (pcInfo.newPage > pcInfo.lastPage) {
const messages: string[] = [];
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")));
}
this.validators.forEach(validator => {
const result = validator();
if (!result.valid) {
messages.push(result.message);
}
});
if (messages.length > 0) {
this._model.wizard.wizardObject.message = {
text: messages.length === 1 ? messages[0] : localizedConstants.multipleValidationErrors,
description: messages.length === 1 ? undefined : messages.join(EOL),
level: azdata.window.MessageLevel.Error
};
}
return messages.length === 0;
}
return true;
});
}
}
}

View File

@@ -1,257 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as nls from 'vscode-nls';
import { BdcDeploymentType } from '../../../interfaces';
import { BigDataClusterDeploymentProfile } from '../../../services/bigDataClusterDeploymentProfile';
import { createFlexContainer, createLabel } from '../../modelViewUtils';
import { ResourceTypePage } from '../../resourceTypePage';
import * as VariableNames from '../constants';
import { DeployClusterWizardModel } from '../deployClusterWizardModel';
const localize = nls.loadMessageBundle();
const serviceScaleTableTitle = localize('deployCluster.serviceScaleTableTitle', "Service scale settings (Instances)");
const storageTableTitle = localize('deployCluster.storageTableTitle', "Service storage settings (GB per Instance)");
const featureTableTitle = localize('deployCluster.featureTableTitle', "Features");
const YesText = localize('deployCluster.yesText', "Yes");
const NoText = localize('deployCluster.noText', "No");
export class DeploymentProfilePage extends ResourceTypePage {
private _loadingComponent: azdata.LoadingComponent | undefined;
private _container: azdata.FlexContainer | undefined;
constructor(private _model: DeployClusterWizardModel) {
super(localize('deployCluster.summaryPageTitle', "Deployment configuration profile"),
localize('deployCluster.summaryPageDescription', "Select the target configuration profile"), _model.wizard);
}
public initialize(): void {
this.pageObject.registerContent(async (view: azdata.ModelView): Promise<void> => {
this._container = view.modelBuilder.flexContainer().withLayout({ flexFlow: 'column' }).component();
const hintText = view.modelBuilder.text().withProps({
value: localize('deployCluster.ProfileHintText', "Note: The settings of the deployment profile can be customized in later steps.")
}).component();
const container = createFlexContainer(view, [this._container, hintText], false);
this._loadingComponent = view.modelBuilder.loadingComponent().withItem(container).withProps({
loading: true,
loadingText: localize('deployCluster.loadingProfiles', "Loading profiles"),
loadingCompletedText: localize('deployCluster.loadingProfilesCompleted', "Loading profiles completed"),
showText: true
}).component();
let formBuilder = view.modelBuilder.formContainer().withFormItems(
[
{
title: '',
component: this._loadingComponent
}
],
{
horizontal: false
}
).withLayout({ width: '100%', height: '100%' });
const form = formBuilder.withLayout({ width: '100%' }).component();
await view.initializeModel(form);
await this.loadProfiles(view);
});
}
private setModelValuesByProfile(selectedProfile: BigDataClusterDeploymentProfile): void {
this._model.setPropertyValue(VariableNames.DeploymentProfile_VariableName, selectedProfile.profileName);
this._model.setPropertyValue(VariableNames.SparkPoolScale_VariableName, selectedProfile.sparkReplicas);
this._model.setPropertyValue(VariableNames.DataPoolScale_VariableName, selectedProfile.dataReplicas);
this._model.setPropertyValue(VariableNames.HDFSPoolScale_VariableName, selectedProfile.hdfsReplicas);
this._model.setPropertyValue(VariableNames.ComputePoolScale_VariableName, selectedProfile.computeReplicas);
this._model.setPropertyValue(VariableNames.HDFSNameNodeScale_VariableName, selectedProfile.hdfsNameNodeReplicas);
this._model.setPropertyValue(VariableNames.SQLServerScale_VariableName, selectedProfile.sqlServerReplicas);
this._model.setPropertyValue(VariableNames.SparkHeadScale_VariableName, selectedProfile.sparkHeadReplicas);
this._model.setPropertyValue(VariableNames.ZooKeeperScale_VariableName, selectedProfile.zooKeeperReplicas);
this._model.setPropertyValue(VariableNames.ControllerDataStorageSize_VariableName, selectedProfile.controllerDataStorageSize);
this._model.setPropertyValue(VariableNames.ControllerLogsStorageSize_VariableName, selectedProfile.controllerLogsStorageSize);
this._model.setPropertyValue(VariableNames.SQLServerPort_VariableName, selectedProfile.sqlServerPort);
this._model.setPropertyValue(VariableNames.GateWayPort_VariableName, selectedProfile.gatewayPort);
this._model.setPropertyValue(VariableNames.ControllerPort_VariableName, selectedProfile.controllerPort);
this._model.setPropertyValue(VariableNames.ServiceProxyPort_VariableName, selectedProfile.serviceProxyPort);
this._model.setPropertyValue(VariableNames.AppServiceProxyPort_VariableName, selectedProfile.appServiceProxyPort);
this._model.setPropertyValue(VariableNames.IncludeSpark_VariableName, selectedProfile.includeSpark);
this._model.setPropertyValue(VariableNames.ControllerDataStorageClassName_VariableName, selectedProfile.controllerDataStorageClass);
this._model.setPropertyValue(VariableNames.ControllerLogsStorageClassName_VariableName, selectedProfile.controllerLogsStorageClass);
this._model.setPropertyValue(VariableNames.ReadableSecondaryPort_VariableName, selectedProfile.sqlServerReadableSecondaryPort);
this._model.setPropertyValue(VariableNames.DockerRegistry_VariableName, selectedProfile.registry);
this._model.setPropertyValue(VariableNames.DockerRepository_VariableName, selectedProfile.repository);
this._model.setPropertyValue(VariableNames.DockerImageTag_VariableName, selectedProfile.imageTag);
this._model.adAuthSupported = selectedProfile.activeDirectorySupported;
this._model.selectedProfile = selectedProfile;
}
private async loadProfiles(view: azdata.ModelView): Promise<void> {
try {
const profiles = await this.wizard.azdataService.getDeploymentProfiles(this._model.deploymentType);
const radioButtonGroup = this.createRadioButtonGroup(view, profiles);
const serviceScaleTable = this.createServiceScaleTable(view, profiles);
const storageTable = this.createStorageTable(view, profiles);
const featuresTable = this.createFeaturesTable(view, profiles);
this._container!.addItem(createLabel(view, { text: localize('deployCluster.profileRadioGroupLabel', "Deployment configuration profile") }), {
CSSStyles: { 'margin-bottom': '5px' }
});
this._container!.addItem(radioButtonGroup, {
CSSStyles: { 'margin-bottom': '20px' }
});
this._container!.addItems([
this.createTableGroup(view, serviceScaleTableTitle, serviceScaleTable),
this.createTableGroup(view, storageTableTitle, storageTable),
this.createTableGroup(view, featureTableTitle, featuresTable)
], {
CSSStyles: { 'margin-bottom': '10px' }
});
this._loadingComponent!.loading = false;
} catch (error) {
this.wizard.wizardObject.message = {
level: azdata.window.MessageLevel.Error,
text: localize('deployCluster.loadProfileFailed', "Failed to load the deployment profiles: {0}", error.message)
};
this._loadingComponent!.loading = false;
}
}
private createRadioButtonGroup(view: azdata.ModelView, profiles: BigDataClusterDeploymentProfile[]): azdata.FlexContainer {
const defaultProfile: string = this.getDefaultProfile();
const groupName = 'profileGroup';
const radioButtons = profiles.map(profile => {
const checked = profile.profileName === defaultProfile;
const radioButton = view.modelBuilder.radioButton().withProps({
label: profile.profileName,
checked: checked,
name: groupName
}).component();
if (checked) {
this.setModelValuesByProfile(profile);
radioButton.focus();
}
this.wizard.registerDisposable(radioButton.onDidClick(() => {
this.wizard.wizardObject.message = { text: '' };
this.setModelValuesByProfile(profile);
}));
return radioButton;
});
return view.modelBuilder.flexContainer().withLayout({ flexFlow: 'row' }).withItems(radioButtons, { flex: '0 0 auto', CSSStyles: { 'margin-right': '20px' } }).component();
}
private createServiceScaleTable(view: azdata.ModelView, profiles: BigDataClusterDeploymentProfile[]): azdata.TableComponent {
const data = [
[localize('deployCluster.masterPoolLabel', "SQL Server Master"), ...profiles.map(profile => profile.sqlServerReplicas.toString())],
[localize('deployCluster.computePoolLable', "Compute"), ...profiles.map(profile => profile.computeReplicas.toString())],
[localize('deployCluster.dataPoolLabel', "Data"), ...profiles.map(profile => profile.dataReplicas.toString())],
[localize('deployCluster.hdfsLabel', "HDFS + Spark"), ...profiles.map(profile => profile.hdfsReplicas.toString())]
];
return view.modelBuilder.table().withProps({
columns: [this.createDescriptionColumn(localize('deployCluster.ServiceName', "Service")), ...this.createProfileColumns(profiles)],
data: data,
title: serviceScaleTableTitle,
ariaLabel: serviceScaleTableTitle,
height: 140,
width: 200 + 150 * profiles.length
}).component();
}
private createStorageTable(view: azdata.ModelView, profiles: BigDataClusterDeploymentProfile[]): azdata.TableComponent {
const data = [
[localize('deployCluster.dataStorageType', "Data"), ...profiles.map(profile => profile.controllerDataStorageSize.toString())],
[localize('deployCluster.logsStorageType', "Logs"), ...profiles.map(profile => profile.controllerLogsStorageSize.toString())]
];
return view.modelBuilder.table().withProps({
columns: [this.createDescriptionColumn(localize('deployCluster.StorageType', "Storage type")), ...this.createProfileColumns(profiles)],
data: data,
title: storageTableTitle,
ariaLabel: storageTableTitle,
height: 80,
width: 200 + 150 * profiles.length
}).component();
}
private createFeaturesTable(view: azdata.ModelView, profiles: BigDataClusterDeploymentProfile[]): azdata.TableComponent {
const data = [
[localize('deployCluster.basicAuthentication', "Basic authentication"), ...profiles.map(profile => YesText)],
];
if (profiles.findIndex(profile => profile.activeDirectorySupported) !== -1) {
data.push([localize('deployCluster.activeDirectoryAuthentication', "Active Directory authentication"), ...profiles.map(profile => profile.activeDirectorySupported ? YesText : NoText)]);
}
if (profiles.findIndex(profile => profile.sqlServerReplicas > 1) !== -1) {
data.push([localize('deployCluster.hadr', "High Availability"), ...profiles.map(profile => profile.sqlServerReplicas > 1 ? YesText : NoText)]);
}
return view.modelBuilder.table().withProps({
columns: [this.createDescriptionColumn(localize('deployCluster.featureText', "Feature")), ...this.createProfileColumns(profiles)],
data: data,
title: featureTableTitle,
ariaLabel: featureTableTitle,
height: 30 + data.length * 25,
width: 200 + 150 * profiles.length
}).component();
}
private createDescriptionColumn(header: string): azdata.TableColumn {
return {
value: header,
width: 150
};
}
private createProfileColumns(profiles: BigDataClusterDeploymentProfile[]): azdata.TableColumn[] {
return profiles.map(profile => {
return {
value: profile.profileName,
width: 100
};
});
}
private createTableGroup(view: azdata.ModelView, title: string, table: azdata.TableComponent): azdata.FlexContainer {
return view.modelBuilder.flexContainer()
.withItems([createLabel(view, { text: title }), table], { CSSStyles: { 'margin-bottom': '5px' } })
.withLayout({ flexFlow: 'column' })
.component();
}
public override async onEnter(): Promise<void> {
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
this.wizard.wizardObject.message = { text: '' };
if (pcInfo.newPage > pcInfo.lastPage) {
const isValid = this.wizard.model.getStringValue(VariableNames.DeploymentProfile_VariableName) !== undefined;
if (!isValid) {
this.wizard.wizardObject.message = {
text: localize('deployCluster.ProfileNotSelectedError', "Please select a deployment profile."),
level: azdata.window.MessageLevel.Error
};
}
return isValid;
}
return true;
});
}
public override async onLeave(): Promise<void> {
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
return true;
});
}
private getDefaultProfile(): string {
switch (this._model.deploymentType) {
case BdcDeploymentType.NewAKS:
case BdcDeploymentType.ExistingAKS:
return 'aks-dev-test';
case BdcDeploymentType.ExistingKubeAdm:
return 'kubeadm-dev-test';
case BdcDeploymentType.ExistingARO:
return 'aro-dev-test';
case BdcDeploymentType.ExistingOpenShift:
return 'openshift-dev-test';
default:
throw new Error(`Unknown deployment type: ${this._model.deploymentType}`);
}
}
}

View File

@@ -1,448 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { FieldType, SectionInfo } from '../../../interfaces';
import { createFlexContainer, createGroupContainer, createLabel, createNumberInputBoxInputInfo, createSection, createInputBoxInputInfo, getCheckboxComponent, getDropdownComponent, getInputBoxComponent, InputComponentInfo, InputComponents, setModelValues, Validator, InputComponent } from '../../modelViewUtils';
import { ResourceTypePage } from '../../resourceTypePage';
import * as VariableNames from '../constants';
import { AuthenticationMode, DeployClusterWizardModel } from '../deployClusterWizardModel';
const localize = nls.loadMessageBundle();
const NumberInputWidth = '100px';
const inputWidth = '180px';
const labelWidth = '200px';
export class ServiceSettingsPage extends ResourceTypePage {
private inputComponents: InputComponents = {};
private endpointHeaderRow!: azdata.FlexContainer;
private dnsColumnHeader!: azdata.TextComponent;
private portColumnHeader!: azdata.TextComponent;
private controllerDNSInput!: azdata.InputBoxComponent;
private controllerPortInput!: azdata.InputBoxComponent;
private controllerEndpointRow!: azdata.FlexContainer;
private sqlServerDNSInput!: azdata.InputBoxComponent;
private sqlServerEndpointRow!: azdata.FlexContainer;
private sqlServerPortInput!: azdata.InputBoxComponent;
private gatewayDNSInput!: azdata.InputBoxComponent;
private gatewayPortInput!: azdata.InputBoxComponent;
private gatewayEndpointRow!: azdata.FlexContainer;
private 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;
private endpointNameColumnHeader!: azdata.TextComponent;
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(private _model: DeployClusterWizardModel) {
super(localize('deployCluster.ServiceSettingsPageTitle', "Service settings"), '', _model.wizard);
}
public initialize(): void {
const self = this;
const scaleSectionInfo: SectionInfo = {
title: localize('deployCluster.scaleSectionTitle', "Scale settings"),
labelWidth: labelWidth,
inputWidth: NumberInputWidth,
spaceBetweenFields: '40px',
rows: [{
items: [{
type: FieldType.Options,
label: localize('deployCluster.MasterSqlServerInstances', "SQL Server master instances"),
options: ['1', '3', '4', '5', '6', '7', '8', '9'],
defaultValue: '1',
variableName: VariableNames.SQLServerScale_VariableName,
}, {
type: FieldType.Number,
label: localize('deployCluster.ComputePoolInstances', "Compute pool instances"),
min: 1,
max: 100,
defaultValue: '1',
required: true,
variableName: VariableNames.ComputePoolScale_VariableName,
}]
}, {
items: [{
type: FieldType.Number,
label: localize('deployCluster.DataPoolInstances', "Data pool instances"),
min: 1,
max: 100,
defaultValue: '1',
required: true,
variableName: VariableNames.DataPoolScale_VariableName,
}, {
type: FieldType.Number,
label: localize('deployCluster.SparkPoolInstances', "Spark pool instances"),
min: 0,
max: 100,
defaultValue: '0',
required: true,
variableName: VariableNames.SparkPoolScale_VariableName
}]
}, {
items: [
{
type: FieldType.Number,
label: localize('deployCluster.StoragePoolInstances', "Storage pool (HDFS) instances"),
min: 1,
max: 100,
defaultValue: '1',
required: true,
variableName: VariableNames.HDFSPoolScale_VariableName
}, {
type: FieldType.Checkbox,
label: localize('deployCluster.IncludeSparkInStoragePool', "Include Spark in storage pool"),
defaultValue: 'true',
variableName: VariableNames.IncludeSpark_VariableName,
required: false
}
]
}
]
};
this.pageObject.registerContent(async (view: azdata.ModelView) => {
const createSectionFunc = async (sectionInfo: SectionInfo): Promise<azdata.GroupContainer> => {
return await createSection({
view: view,
container: this.wizard.wizardObject,
inputComponents: this._model.inputComponents,
sectionInfo: sectionInfo,
onNewDisposableCreated: (disposable: vscode.Disposable): void => {
self.wizard.registerDisposable(disposable);
},
onNewInputComponentCreated: (name: string, inputComponentInfo: InputComponentInfo<InputComponent>): void => {
self.onNewInputComponentCreated(name, inputComponentInfo);
},
onNewValidatorCreated: (validator: Validator): void => {
},
toolsService: this.wizard.toolsService
});
};
const scaleSection = await createSectionFunc(scaleSectionInfo);
this.endpointSection = this.createEndpointSection(view);
const storageSection = this.createStorageSection(view);
this.handleSparkSettingEvents();
const form = view.modelBuilder.formContainer().withFormItems([
{
title: '',
component: scaleSection
}, {
title: '',
component: this.endpointSection
}, {
title: '',
component: storageSection
}
]).withLayout({ width: '100%' }).component();
return view.initializeModel(form);
});
}
private onNewInputComponentCreated(name: string, inputComponentInfo: InputComponentInfo<InputComponent>) {
this.inputComponents[name] = inputComponentInfo;
this._model.inputComponents[name] = inputComponentInfo;
}
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: NumberInputWidth });
this.endpointHeaderRow = createFlexContainer(view, [this.endpointNameColumnHeader, this.dnsColumnHeader, this.portColumnHeader]);
this.controllerNameLabel = createLabel(view, { text: localize('deployCluster.ControllerText', "Controller"), width: labelWidth, required: true });
const controllerDNSInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.ControllerDNSName', "Controller DNS name"), required: false, width: inputWidth });
this.controllerDNSInput = controllerDNSInput.component;
const controllerPortInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.ControllerPortName', "Controller port"), required: true, width: NumberInputWidth, min: 1 });
this.controllerPortInput = controllerPortInput.component;
this.controllerEndpointRow = createFlexContainer(view, [this.controllerNameLabel, this.controllerDNSInput, this.controllerPortInput]);
this.onNewInputComponentCreated(VariableNames.ControllerDNSName_VariableName, controllerDNSInput);
this.onNewInputComponentCreated(VariableNames.ControllerPort_VariableName, controllerPortInput);
this.SqlServerNameLabel = createLabel(view, { text: localize('deployCluster.MasterSqlText', "SQL Server Master"), width: labelWidth, required: true });
const sqlServerDNSInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.MasterSQLServerDNSName', "SQL Server Master DNS name"), required: false, width: inputWidth });
this.sqlServerDNSInput = sqlServerDNSInput.component;
const sqlServerPortInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.MasterSQLServerPortName', "SQL Server Master port"), required: true, width: NumberInputWidth, min: 1 });
this.sqlServerPortInput = sqlServerPortInput.component;
this.sqlServerEndpointRow = createFlexContainer(view, [this.SqlServerNameLabel, this.sqlServerDNSInput, this.sqlServerPortInput]);
this.onNewInputComponentCreated(VariableNames.SQLServerDNSName_VariableName, sqlServerDNSInput);
this.onNewInputComponentCreated(VariableNames.SQLServerPort_VariableName, sqlServerPortInput);
this.gatewayNameLabel = createLabel(view, { text: localize('deployCluster.GatewayText', "Gateway"), width: labelWidth, required: true });
const gatewayDNSInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.GatewayDNSName', "Gateway DNS name"), required: false, width: inputWidth });
this.gatewayDNSInput = gatewayDNSInput.component;
const gatewayPortInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.GatewayPortName', "Gateway port"), required: true, width: NumberInputWidth, min: 1 });
this.gatewayPortInput = gatewayPortInput.component;
this.gatewayEndpointRow = createFlexContainer(view, [this.gatewayNameLabel, this.gatewayDNSInput, this.gatewayPortInput]);
this.onNewInputComponentCreated(VariableNames.GatewayDNSName_VariableName, gatewayDNSInput);
this.onNewInputComponentCreated(VariableNames.GateWayPort_VariableName, gatewayPortInput);
this.serviceProxyNameLabel = createLabel(view, { text: localize('deployCluster.ServiceProxyText', "Management proxy"), width: labelWidth, required: true });
const serviceProxyDNSInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.ServiceProxyDNSName', "Management proxy DNS name"), required: false, width: inputWidth });
this.serviceProxyDNSInput = serviceProxyDNSInput.component;
const serviceProxyPortInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.ServiceProxyPortName', "Management proxy port"), required: true, width: NumberInputWidth, min: 1 });
this.serviceProxyPortInput = serviceProxyPortInput.component;
this.serviceProxyEndpointRow = createFlexContainer(view, [this.serviceProxyNameLabel, this.serviceProxyDNSInput, this.serviceProxyPortInput]);
this.onNewInputComponentCreated(VariableNames.ServiceProxyDNSName_VariableName, serviceProxyDNSInput);
this.onNewInputComponentCreated(VariableNames.ServiceProxyPort_VariableName, serviceProxyPortInput);
this.appServiceProxyNameLabel = createLabel(view, { text: localize('deployCluster.AppServiceProxyText', "Application proxy"), width: labelWidth, required: true });
const appServiceProxyDNSInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.AppServiceProxyDNSName', "Application proxy DNS name"), required: false, width: inputWidth });
this.appServiceProxyDNSInput = appServiceProxyDNSInput.component;
const appServiceProxyPortInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.AppServiceProxyPortName', "Application proxy port"), required: true, width: NumberInputWidth, min: 1 });
this.appServiceProxyPortInput = appServiceProxyPortInput.component;
this.appServiceProxyEndpointRow = createFlexContainer(view, [this.appServiceProxyNameLabel, this.appServiceProxyDNSInput, this.appServiceProxyPortInput]);
this.onNewInputComponentCreated(VariableNames.AppServiceProxyDNSName_VariableName, appServiceProxyDNSInput);
this.onNewInputComponentCreated(VariableNames.AppServiceProxyPort_VariableName, appServiceProxyPortInput);
this.readableSecondaryNameLabel = createLabel(view, { text: localize('deployCluster.ReadableSecondaryText', "Readable secondary"), width: labelWidth, required: true });
const readableSecondaryDNSInput = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.ReadableSecondaryDNSName', "Readable secondary DNS name"), required: false, width: inputWidth });
this.readableSecondaryDNSInput = readableSecondaryDNSInput.component;
const readableSecondaryPortInput = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.ReadableSecondaryPortName', "Readable secondary port"), required: false, width: NumberInputWidth, min: 1 });
this.readableSecondaryPortInput = readableSecondaryPortInput.component;
this.readableSecondaryEndpointRow = createFlexContainer(view, [this.readableSecondaryNameLabel, this.readableSecondaryDNSInput, this.readableSecondaryPortInput]);
this.onNewInputComponentCreated(VariableNames.ReadableSecondaryDNSName_VariableName, readableSecondaryDNSInput);
this.onNewInputComponentCreated(VariableNames.ReadableSecondaryPort_VariableName, readableSecondaryPortInput);
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
});
}
private createStorageSection(view: azdata.ModelView): azdata.GroupContainer {
const hintTextForStorageFields = localize('deployCluster.storageFieldTooltip', "Use controller settings");
const controllerLabel = createLabel(view,
{
text: localize('deployCluster.ControllerText', "Controller"),
width: inputWidth,
required: true,
description: localize('deployCluster.AdvancedStorageDescription', "By default Controller storage settings will be applied to other services as well, you can expand the advanced storage settings to configure storage for other services.")
});
const controllerDataStorageClassInputInfo = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.controllerDataStorageClass', "Controller's data storage class"), width: inputWidth, required: true });
const controllerDataStorageClaimSizeInputInfo = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.controllerDataStorageClaimSize', "Controller's data storage claim size (Gigabytes)"), width: inputWidth, required: true, min: 1 });
const controllerLogsStorageClassInputInfo = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.controllerLogsStorageClass', "Controller's logs storage class"), width: inputWidth, required: true });
const controllerLogsStorageClaimSizeInputInfo = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.controllerLogsStorageClaimSize', "Controller's logs storage claim size (Gigabytes)"), width: inputWidth, required: true, min: 1 });
const storagePoolLabel = createLabel(view,
{
text: localize('deployCluster.StoragePool', "Storage pool (HDFS)"),
width: inputWidth,
required: false
});
const storagePoolDataStorageClassInputInfo = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.storagePoolDataStorageClass', "Storage pool's data storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields });
const storagePoolDataStorageClaimSizeInputInfo = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.storagePoolDataStorageClaimSize', "Storage pool's data storage claim size (Gigabytes)"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields });
const storagePoolLogsStorageClassInputInfo = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.storagePoolLogsStorageClass', "Storage pool's logs storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields });
const storagePoolLogsStorageClaimSizeInputInfo = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.storagePoolLogsStorageClaimSize', "Storage pool's logs storage claim size (Gigabytes)"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields });
const dataPoolLabel = createLabel(view,
{
text: localize('deployCluster.DataPool', "Data pool"),
width: inputWidth,
required: false
});
const dataPoolDataStorageClassInputInfo = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.dataPoolDataStorageClass', "Data pool's data storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields });
const dataPoolDataStorageClaimSizeInputInfo = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.dataPoolDataStorageClaimSize', "Data pool's data storage claim size (Gigabytes)"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields });
const dataPoolLogsStorageClassInputInfo = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.dataPoolLogsStorageClass', "Data pool's logs storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields });
const dataPoolLogsStorageClaimSizeInputInfo = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.dataPoolLogsStorageClaimSize', "Data pool's logs storage claim size (Gigabytes)"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields });
const sqlServerMasterLabel = createLabel(view,
{
text: localize('deployCluster.MasterSqlText', "SQL Server Master"),
width: inputWidth,
required: false
});
const sqlServerMasterDataStorageClassInputInfo = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.sqlServerMasterDataStorageClass', "SQL Server master's data storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields });
const sqlServerMasterDataStorageClaimSizeInputInfo = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.sqlServerMasterDataStorageClaimSize', "SQL Server master's data storage claim size (Gigabytes)"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields });
const sqlServerMasterLogsStorageClassInputInfo = createInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.sqlServerMasterLogsStorageClass', "SQL Server master's logs storage class"), width: inputWidth, required: false, placeHolder: hintTextForStorageFields });
const sqlServerMasterLogsStorageClaimSizeInputInfo = createNumberInputBoxInputInfo(view, { ariaLabel: localize('deployCluster.sqlServerMasterLogsStorageClaimSize', "SQL Server master's logs storage claim size (Gigabytes)"), width: inputWidth, required: false, min: 1, placeHolder: hintTextForStorageFields });
this.onNewInputComponentCreated(VariableNames.ControllerDataStorageClassName_VariableName, controllerDataStorageClassInputInfo);
this.onNewInputComponentCreated(VariableNames.ControllerDataStorageSize_VariableName, controllerDataStorageClaimSizeInputInfo);
this.onNewInputComponentCreated(VariableNames.ControllerLogsStorageClassName_VariableName, controllerLogsStorageClassInputInfo);
this.onNewInputComponentCreated(VariableNames.ControllerLogsStorageSize_VariableName, controllerLogsStorageClaimSizeInputInfo);
this.onNewInputComponentCreated(VariableNames.HDFSDataStorageClassName_VariableName, storagePoolDataStorageClassInputInfo);
this.onNewInputComponentCreated(VariableNames.HDFSDataStorageSize_VariableName, storagePoolDataStorageClaimSizeInputInfo);
this.onNewInputComponentCreated(VariableNames.HDFSLogsStorageClassName_VariableName, storagePoolLogsStorageClassInputInfo);
this.onNewInputComponentCreated(VariableNames.HDFSLogsStorageSize_VariableName, storagePoolLogsStorageClaimSizeInputInfo);
this.onNewInputComponentCreated(VariableNames.DataPoolDataStorageClassName_VariableName, dataPoolDataStorageClassInputInfo);
this.onNewInputComponentCreated(VariableNames.DataPoolDataStorageSize_VariableName, dataPoolDataStorageClaimSizeInputInfo);
this.onNewInputComponentCreated(VariableNames.DataPoolLogsStorageClassName_VariableName, dataPoolLogsStorageClassInputInfo);
this.onNewInputComponentCreated(VariableNames.DataPoolLogsStorageSize_VariableName, dataPoolLogsStorageClaimSizeInputInfo);
this.onNewInputComponentCreated(VariableNames.SQLServerDataStorageClassName_VariableName, sqlServerMasterDataStorageClassInputInfo);
this.onNewInputComponentCreated(VariableNames.SQLServerDataStorageSize_VariableName, sqlServerMasterDataStorageClaimSizeInputInfo);
this.onNewInputComponentCreated(VariableNames.SQLServerLogsStorageClassName_VariableName, sqlServerMasterLogsStorageClassInputInfo);
this.onNewInputComponentCreated(VariableNames.SQLServerLogsStorageSize_VariableName, sqlServerMasterLogsStorageClaimSizeInputInfo);
const storageSettingTable = view.modelBuilder.declarativeTable()
.withProps(
{
columns: [
this.createStorageSettingColumn(localize('deployCluster.ServiceName', "Service name"), false),
this.createStorageSettingColumn(localize('deployCluster.DataStorageClassName', "Storage class for data")),
this.createStorageSettingColumn(localize('deployCluster.DataClaimSize', "Claim size for data (GB)")),
this.createStorageSettingColumn(localize('deployCluster.LogStorageClassName', "Storage class for logs")),
this.createStorageSettingColumn(localize('deployCluster.LogsClaimSize', "Claim size for logs (GB)"))
],
dataValues: [
[{ value: controllerLabel }, { value: controllerDataStorageClassInputInfo.component }, { value: controllerDataStorageClaimSizeInputInfo.component }, { value: controllerLogsStorageClassInputInfo.component }, { value: controllerLogsStorageClaimSizeInputInfo.component }],
[{ value: storagePoolLabel }, { value: storagePoolDataStorageClassInputInfo.component }, { value: storagePoolDataStorageClaimSizeInputInfo.component }, { value: storagePoolLogsStorageClassInputInfo.component }, { value: storagePoolLogsStorageClaimSizeInputInfo.component }],
[{ value: dataPoolLabel }, { value: dataPoolDataStorageClassInputInfo.component }, { value: dataPoolDataStorageClaimSizeInputInfo.component }, { value: dataPoolLogsStorageClassInputInfo.component }, { value: dataPoolLogsStorageClaimSizeInputInfo.component }],
[{ value: sqlServerMasterLabel }, { value: sqlServerMasterDataStorageClassInputInfo.component }, { value: sqlServerMasterDataStorageClaimSizeInputInfo.component }, { value: sqlServerMasterLogsStorageClassInputInfo.component }, { value: sqlServerMasterLogsStorageClaimSizeInputInfo.component }]
],
ariaLabel: localize('deployCluster.StorageSettings', "Storage settings")
})
.component();
return createGroupContainer(view, [storageSettingTable], {
header: localize('deployCluster.StorageSectionTitle', "Storage settings"),
collapsible: true,
collapsed: false
});
}
private createStorageSettingColumn(title: string, showText: boolean = true): azdata.DeclarativeTableColumn {
return {
displayName: showText ? title : '',
ariaLabel: title,
valueType: azdata.DeclarativeDataType.component,
isReadOnly: true,
width: inputWidth,
headerCssStyles: {
'border': 'none',
'font-weight': 'inherit'
},
rowCssStyles: {
'border': 'none'
}
};
}
public override async onEnter(): Promise<void> {
this.setInputBoxValue(VariableNames.ComputePoolScale_VariableName);
this.setInputBoxValue(VariableNames.DataPoolScale_VariableName);
this.setInputBoxValue(VariableNames.HDFSPoolScale_VariableName);
this.setInputBoxValue(VariableNames.SparkPoolScale_VariableName);
this.setCheckboxValue(VariableNames.IncludeSpark_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();
const adAuth = this._model.authenticationMode === AuthenticationMode.ActiveDirectory;
const sqlServerScale = this.wizard.model.getIntegerValue(VariableNames.SQLServerScale_VariableName);
this.endpointSection.collapsed = !adAuth;
if (adAuth) {
this.endpointHeaderRow.addItems([this.endpointNameColumnHeader, this.dnsColumnHeader, this.portColumnHeader]);
} else {
this.endpointHeaderRow.addItems([this.endpointNameColumnHeader, this.portColumnHeader]);
}
getInputBoxComponent(VariableNames.ControllerDNSName_VariableName, this.inputComponents).required = adAuth;
getInputBoxComponent(VariableNames.GatewayDNSName_VariableName, this.inputComponents).required = adAuth;
getInputBoxComponent(VariableNames.AppServiceProxyDNSName_VariableName, this.inputComponents).required = adAuth;
getInputBoxComponent(VariableNames.ServiceProxyDNSName_VariableName, this.inputComponents).required = adAuth;
getInputBoxComponent(VariableNames.SQLServerDNSName_VariableName, this.inputComponents).required = adAuth;
getInputBoxComponent(VariableNames.ReadableSecondaryDNSName_VariableName, this.inputComponents).required = adAuth && sqlServerScale > 1;
getInputBoxComponent(VariableNames.ReadableSecondaryPort_VariableName, this.inputComponents).required = sqlServerScale > 1;
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.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);
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 sparkEnabled = Number.parseInt(getInputBoxComponent(VariableNames.SparkPoolScale_VariableName, this.inputComponents).value!) !== 0
|| getCheckboxComponent(VariableNames.IncludeSpark_VariableName, this.inputComponents).checked!;
let errorMessage: string | undefined;
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: errorMessage,
level: azdata.window.MessageLevel.Error
};
}
return sparkEnabled;
}
return true;
});
}
public override async onLeave(): Promise<void> {
await setModelValues(this.inputComponents, this.wizard.model);
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
return true;
});
}
private setInputBoxValue(variableName: string): void {
getInputBoxComponent(variableName, this.inputComponents).value = this.wizard.model.getStringValue(variableName);
}
private setCheckboxValue(variableName: string): void {
getCheckboxComponent(variableName, this.inputComponents).checked = this.wizard.model.getBooleanValue(variableName);
}
private loadEndpointRow(row: azdata.FlexContainer, label: azdata.TextComponent, dnsInput: azdata.InputBoxComponent, portInput: azdata.InputBoxComponent): void {
row.clearItems();
const itemLayout: azdata.FlexItemLayout = { CSSStyles: { 'margin-right': '20px' } };
row.addItem(label);
if (this._model.authenticationMode === AuthenticationMode.ActiveDirectory) {
row.addItem(dnsInput, itemLayout);
}
row.addItem(portInput);
}
}

View File

@@ -1,434 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as nls from 'vscode-nls';
import { SectionInfo, FieldType, LabelPosition, BdcDeploymentType, FontWeight } from '../../../interfaces';
import { createSection, createGroupContainer, createFlexContainer, createLabel } from '../../modelViewUtils';
import * as VariableNames from '../constants';
import { AuthenticationMode, DeployClusterWizardModel } from '../deployClusterWizardModel';
import * as localizedConstants from '../../../localizedConstants';
import { ResourceTypePage } from '../../resourceTypePage';
const localize = nls.loadMessageBundle();
export class SummaryPage extends ResourceTypePage {
private formItems: azdata.FormComponent[] = [];
private form!: azdata.FormBuilder;
private view!: azdata.ModelView;
constructor(private _model: DeployClusterWizardModel) {
super(localize('deployCluster.summaryPageTitle', "Summary"), '', _model.wizard);
}
public initialize(): void {
this.pageObject.registerContent((view: azdata.ModelView) => {
this.view = view;
this.form = view.modelBuilder.formContainer();
return view.initializeModel(this.form!.withLayout({ width: '100%' }).component());
});
}
public override async onEnter(): Promise<void> {
this._model.showCustomButtons();
this.formItems.forEach(item => {
this.form!.removeFormItem(item);
});
this.formItems = [];
const deploymentTargetSectionInfo: SectionInfo = {
labelPosition: LabelPosition.Left,
labelWidth: '150px',
inputWidth: '200px',
title: localize('deployCluster.DeploymentTarget', "Deployment target"),
rows: [
{
items: [
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.Kubeconfig', "Kube config"),
defaultValue: this.wizard.model.getStringValue(VariableNames.KubeConfigPath_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
},
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.ClusterContext', "Cluster context"),
defaultValue: this.wizard.model.getStringValue(VariableNames.ClusterContext_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}]
}
]
};
const clusterSectionInfo: SectionInfo = {
labelPosition: LabelPosition.Left,
labelWidth: '150px',
inputWidth: '200px',
title: localize('deployCluster.ClusterSettings', "Cluster settings"),
rows: [
{
items: [
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.DeploymentProfile', "Deployment profile"),
defaultValue: this.wizard.model.getStringValue(VariableNames.DeploymentProfile_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
},
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.ClusterName', "Cluster name"),
defaultValue: this.wizard.model.getStringValue(VariableNames.ClusterName_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}]
}, {
items: [
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.ControllerUsername', "Controller username"),
defaultValue: this.wizard.model.getStringValue(VariableNames.AdminUserName_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}, {
type: FieldType.ReadonlyText,
label: localize('deployCluster.AuthenticationMode', "Authentication mode"),
defaultValue: this._model.authenticationMode === AuthenticationMode.ActiveDirectory ?
localize('deployCluster.AuthenticationMode.ActiveDirectory', "Active Directory") :
localize('deployCluster.AuthenticationMode.Basic', "Basic"),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}
]
}
]
};
if (this._model.authenticationMode === AuthenticationMode.ActiveDirectory) {
clusterSectionInfo.rows!.push({
items: [
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.OuDistinguishedName', "Organizational unit"),
defaultValue: this._model.getStringValue(VariableNames.OrganizationalUnitDistinguishedName_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
},
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.DomainControllerFQDNs', "Domain controller FQDNs"),
defaultValue: this.wizard.model.getStringValue(VariableNames.DomainControllerFQDNs_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}]
});
clusterSectionInfo.rows!.push({
items: [
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.DomainDNSIPAddresses', "Domain DNS IP addresses"),
defaultValue: this.wizard.model.getStringValue(VariableNames.DomainDNSIPAddresses_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
},
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.DomainDNSName', "Domain DNS name"),
defaultValue: this.wizard.model.getStringValue(VariableNames.DomainDNSName_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}]
});
clusterSectionInfo.rows!.push({
items: [
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.ClusterAdmins', "Cluster admin group"),
defaultValue: this.wizard.model.getStringValue(VariableNames.ClusterAdmins_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
},
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.ClusterUsers', "Cluster users"),
defaultValue: this.wizard.model.getStringValue(VariableNames.ClusterUsers_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}]
});
clusterSectionInfo.rows!.push({
items: [
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.AppOwners', "App owners"),
defaultValue: this.wizard.model.getStringValue(VariableNames.AppOwners_VariableName, ''),
labelCSSStyles: { fontWeight: FontWeight.Bold }
},
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.AppReaders', "App readers"),
defaultValue: this.wizard.model.getStringValue(VariableNames.AppReaders_VariableName, ''),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}]
});
clusterSectionInfo.rows!.push({
items: [
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.Subdomain', "Subdomain"),
defaultValue: this.wizard.model.getStringValue(VariableNames.Subdomain_VariableName, ''),
labelCSSStyles: { fontWeight: FontWeight.Bold }
},
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.AccountPrefix', "Account prefix"),
defaultValue: this.wizard.model.getStringValue(VariableNames.AccountPrefix_VariableName, ''),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}]
});
clusterSectionInfo.rows!.push({
items: [
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.DomainServiceAccountUserName', "Service account username"),
defaultValue: this.wizard.model.getStringValue(VariableNames.DomainServiceAccountUserName_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}, {
type: FieldType.ReadonlyText,
label: localizedConstants.realm,
defaultValue: this.wizard.model.getStringValue(VariableNames.Realm_VariableName, ''),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}]
});
}
const azureSectionInfo: SectionInfo = {
labelPosition: LabelPosition.Left,
labelWidth: '150px',
inputWidth: '200px',
title: localize('deployCluster.AzureSettings', "Azure settings"),
rows: [{
items: [
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.SubscriptionId', "Subscription id"),
defaultValue: this.wizard.model.getStringValue(VariableNames.SubscriptionId_VariableName) || localize('deployCluster.DefaultSubscription', "Default Azure Subscription"),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}, {
type: FieldType.ReadonlyText,
label: localize('deployCluster.ResourceGroup', "Resource group"),
defaultValue: this.wizard.model.getStringValue(VariableNames.ResourceGroup_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}
]
}, {
items: [
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.Location', "Location"),
defaultValue: this.wizard.model.getStringValue(VariableNames.Location_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}, {
type: FieldType.ReadonlyText,
label: localize('deployCluster.AksClusterName', "AKS cluster name"),
defaultValue: this.wizard.model.getStringValue(VariableNames.AksName_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}
]
}, {
items: [
{
type: FieldType.ReadonlyText,
label: localize('deployCluster.VMSize', "VM size"),
defaultValue: this.wizard.model.getStringValue(VariableNames.VMSize_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}, {
type: FieldType.ReadonlyText,
label: localize('deployCluster.VMCount', "VM count"),
defaultValue: this.wizard.model.getStringValue(VariableNames.VMCount_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}
]
}
]
};
const scaleSectionInfo: SectionInfo = {
labelPosition: LabelPosition.Left,
labelWidth: '150px',
inputWidth: '200px',
title: localize('deployCluster.ScaleSettings', "Scale settings"),
rows: [
{
items: [{
type: FieldType.ReadonlyText,
label: localize('deployCluster.MasterSqlServerInstances', "SQL Server master instances"),
defaultValue: this.wizard.model.getStringValue(VariableNames.SQLServerScale_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}, {
type: FieldType.ReadonlyText,
label: localize('deployCluster.ComputePoolInstances', "Compute pool instances"),
defaultValue: this.wizard.model.getStringValue(VariableNames.ComputePoolScale_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}]
}, {
items: [{
type: FieldType.ReadonlyText,
label: localize('deployCluster.DataPoolInstances', "Data pool instances"),
defaultValue: this.wizard.model.getStringValue(VariableNames.DataPoolScale_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}, {
type: FieldType.ReadonlyText,
label: localize('deployCluster.SparkPoolInstances', "Spark pool instances"),
defaultValue: this.wizard.model.getStringValue(VariableNames.SparkPoolScale_VariableName),
labelCSSStyles: { fontWeight: FontWeight.Bold }
}]
}, {
items: [{
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)") : ''}`,
labelCSSStyles: { fontWeight: FontWeight.Bold }
}]
}
]
};
const createSectionFunc = async (sectionInfo: SectionInfo): Promise<azdata.FormComponent> => {
return {
title: '',
component: await createSection({
container: this.wizard.wizardObject,
inputComponents: this._model.inputComponents,
sectionInfo: sectionInfo,
view: this.view,
onNewDisposableCreated: () => { },
onNewInputComponentCreated: () => { },
onNewValidatorCreated: () => { },
toolsService: this.wizard.toolsService
})
};
};
if (this._model.deploymentType === BdcDeploymentType.ExistingAKS || this._model.deploymentType === BdcDeploymentType.ExistingKubeAdm) {
const deploymentTargetSection = await createSectionFunc(deploymentTargetSectionInfo);
this.formItems.push(deploymentTargetSection);
}
const clusterSection = await createSectionFunc(clusterSectionInfo);
const scaleSection = await createSectionFunc(scaleSectionInfo);
const endpointSection = {
title: '',
component: this.createEndpointSection()
};
const storageSection = {
title: '',
component: this.createStorageSection()
};
if (this.wizard.model.getStringValue(VariableNames.AksName_VariableName)) {
const azureSection = await createSectionFunc(azureSectionInfo);
this.formItems.push(azureSection);
}
this.formItems.push(clusterSection, scaleSection, endpointSection, storageSection);
this.form.addFormItems(this.formItems);
}
public override async onLeave(): Promise<void> {
this._model.hideCustomButtons();
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;
}
private createStorageSection(): azdata.GroupContainer {
const serviceNameColumn: azdata.TableColumn = {
value: localize('deployCluster.ServiceName', "Service"),
width: 150
};
const dataStorageClassColumn: azdata.TableColumn = {
value: localize('deployCluster.DataStorageClassName', "Storage class for data"),
width: 180
};
const dataStorageSizeColumn: azdata.TableColumn = {
value: localize('deployCluster.DataClaimSize', "Claim size for data (GB)"),
width: 180
};
const logStorageClassColumn: azdata.TableColumn = {
value: localize('deployCluster.LogStorageClassName', "Storage class for logs"),
width: 180
};
const logStorageSizeColumn: azdata.TableColumn = {
value: localize('deployCluster.LogsClaimSize', "Claim size for logs (GB)"),
width: 180
};
const storageTableTitle = localize('deployCluster.StorageSettings', "Storage settings");
const storageTable = this.view.modelBuilder.table().withProps({
title: storageTableTitle,
ariaLabel: storageTableTitle,
data: [
[
localize('deployCluster.ControllerText', "Controller"),
this.wizard.model.getStringValue(VariableNames.ControllerDataStorageClassName_VariableName),
this.wizard.model.getStringValue(VariableNames.ControllerDataStorageSize_VariableName),
this.wizard.model.getStringValue(VariableNames.ControllerLogsStorageClassName_VariableName),
this.wizard.model.getStringValue(VariableNames.ControllerLogsStorageSize_VariableName)],
[
localize('deployCluster.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),
this.getStorageSettingValue(VariableNames.HDFSLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName)
], [
localize('deployCluster.DataText', "Data"),
this.getStorageSettingValue(VariableNames.DataPoolDataStorageClassName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName),
this.getStorageSettingValue(VariableNames.DataPoolDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName),
this.getStorageSettingValue(VariableNames.DataPoolLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName),
this.getStorageSettingValue(VariableNames.DataPoolLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName)
], [
localize('deployCluster.MasterSqlText', "SQL Server Master"),
this.getStorageSettingValue(VariableNames.SQLServerDataStorageClassName_VariableName, VariableNames.ControllerDataStorageClassName_VariableName),
this.getStorageSettingValue(VariableNames.SQLServerDataStorageSize_VariableName, VariableNames.ControllerDataStorageSize_VariableName),
this.getStorageSettingValue(VariableNames.SQLServerLogsStorageClassName_VariableName, VariableNames.ControllerLogsStorageClassName_VariableName),
this.getStorageSettingValue(VariableNames.SQLServerLogsStorageSize_VariableName, VariableNames.ControllerLogsStorageSize_VariableName)
]
],
columns: [serviceNameColumn, dataStorageClassColumn, dataStorageSizeColumn, logStorageClassColumn, logStorageSizeColumn],
width: '1000px',
height: '140px'
}).component();
return createGroupContainer(this.view, [storageTable], {
header: localize('deployCluster.StorageSettings', "Storage settings"),
collapsible: true
});
}
private createEndpointSection(): azdata.GroupContainer {
const endpointRows = [
this.createEndpointRow(localize('deployCluster.ControllerText', "Controller"), VariableNames.ControllerDNSName_VariableName, VariableNames.ControllerPort_VariableName),
this.createEndpointRow(localize('deployCluster.SqlServerText', "SQL Server Master"), VariableNames.SQLServerDNSName_VariableName, VariableNames.SQLServerPort_VariableName),
this.createEndpointRow(localize('deployCluster.GatewayText', "Gateway"), VariableNames.GatewayDNSName_VariableName, VariableNames.GateWayPort_VariableName),
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.getIntegerValue(VariableNames.SQLServerScale_VariableName) > 1) {
endpointRows.push(
this.createEndpointRow(localize('deployCluster.ReadableSecondaryText', "Readable secondary"), VariableNames.ReadableSecondaryDNSName_VariableName, VariableNames.ReadableSecondaryPort_VariableName)
);
}
return createGroupContainer(this.view, endpointRows, {
header: localize('deployCluster.EndpointSettings', "Endpoint settings"),
collapsible: true
});
}
private createEndpointRow(name: string, dnsVariableName: string, portVariableName: string): azdata.FlexContainer {
const items = [];
items.push(createLabel(this.view, { text: name, width: '150px', cssStyles: { fontWeight: FontWeight.Bold } }));
if (this._model.authenticationMode === AuthenticationMode.ActiveDirectory) {
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'
}));
return createFlexContainer(this.view, items);
}
}

View File

@@ -1,176 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as os from 'os';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { KubeClusterContext } from '../../../services/kubeService';
import { ResourceTypePage } from '../../resourceTypePage';
import { ClusterContext_VariableName, KubeConfigPath_VariableName } from '../constants';
import { DeployClusterWizardModel } from '../deployClusterWizardModel';
const localize = nls.loadMessageBundle();
const ClusterRadioButtonGroupName = 'ClusterRadioGroup';
export class TargetClusterContextPage extends ResourceTypePage {
private existingClusterControl: azdata.FlexContainer | undefined;
private clusterContextsLabel: azdata.TextComponent | undefined;
private errorLoadingClustersLabel: azdata.TextComponent | undefined;
private clusterContextList: azdata.DivContainer | undefined;
private clusterContextLoadingComponent: azdata.LoadingComponent | undefined;
private configFileInput: azdata.InputBoxComponent | undefined;
private browseFileButton: azdata.ButtonComponent | undefined;
private loadDefaultKubeConfigFile: boolean = true;
private view: azdata.ModelView | undefined;
constructor(private _model: DeployClusterWizardModel) {
super(localize('deployCluster.TargetClusterContextPageTitle', "Target cluster context"),
localize('deployCluster.TargetClusterContextPageDescription', "Select the kube config file and then select a cluster context from the list"), _model.wizard);
}
public initialize(): void {
this.pageObject.registerContent((view: azdata.ModelView) => {
this.view = view;
this.initExistingClusterControl();
let formBuilder = view.modelBuilder.formContainer().withFormItems(
[
{
component: this.existingClusterControl!,
title: ''
}
],
{
horizontal: false
}
).withLayout({ width: '100%', height: '100%' });
const form = formBuilder.withLayout({ width: '100%' }).component();
return view.initializeModel(form);
});
}
public override async onEnter(): Promise<void> {
if (this.loadDefaultKubeConfigFile) {
let defaultKubeConfigPath = this._model.kubeService.getDefaultConfigPath();
this.loadClusterContexts(defaultKubeConfigPath);
this.loadDefaultKubeConfigFile = false;
}
this.wizard.wizardObject.registerNavigationValidator((e) => {
if (e.lastPage > e.newPage) {
this.wizard.wizardObject.message = { text: '' };
return true;
}
let clusterSelected = this.wizard.model.getStringValue(ClusterContext_VariableName) !== undefined;
if (!clusterSelected) {
this.wizard.wizardObject.message = {
text: localize('deployCluster.ClusterContextNotSelectedMessage', "Please select a cluster context."),
level: azdata.window.MessageLevel.Error
};
}
return clusterSelected;
});
}
public override async onLeave(): Promise<void> {
this.wizard.wizardObject.registerNavigationValidator((e) => {
return true;
});
}
private initExistingClusterControl(): void {
let self = this;
const labelWidth = '150px';
let configFileLabel = this.view!.modelBuilder.text().withProps({ value: localize('deployCluster.kubeConfigFileLabelText', "Kube config file path") }).component();
configFileLabel.width = labelWidth;
this.configFileInput = this.view!.modelBuilder.inputBox().withProps({ width: '300px' }).component();
this.configFileInput.enabled = false;
this.browseFileButton = this.view!.modelBuilder.button().withProps({ label: localize('deployCluster.browseText', "Browse"), width: '100px', secondary: true }).component();
let configFileContainer = this.view!.modelBuilder.flexContainer()
.withLayout({ flexFlow: 'row', alignItems: 'baseline' })
.withItems([configFileLabel, this.configFileInput, this.browseFileButton], { CSSStyles: { 'margin-right': '10px' } }).component();
this.clusterContextsLabel = this.view!.modelBuilder.text().withProps({ value: localize('deployCluster.clusterContextsLabelText', "Cluster Contexts") }).component();
this.clusterContextsLabel.width = labelWidth;
this.errorLoadingClustersLabel = this.view!.modelBuilder.text().withProps({ value: localize('deployCluster.errorLoadingClustersText', "No cluster information is found in the config file or an error ocurred while loading the config file") }).component();
this.clusterContextList = this.view!.modelBuilder.divContainer().component();
this.clusterContextLoadingComponent = this.view!.modelBuilder.loadingComponent().withItem(this.clusterContextList).component();
this.existingClusterControl = this.view!.modelBuilder.divContainer().withProps({ clickable: false }).component();
let clusterContextContainer = this.view!.modelBuilder.flexContainer().withLayout({ flexFlow: 'row', alignItems: 'start' }).component();
clusterContextContainer.addItem(this.clusterContextsLabel, { flex: '0 0 auto' });
clusterContextContainer.addItem(this.clusterContextLoadingComponent, { flex: '0 0 auto', CSSStyles: { 'width': '400px', 'margin-left': '10px', 'margin-top': '10px' } });
this.existingClusterControl.addItem(configFileContainer, { CSSStyles: { 'margin-top': '0px' } });
this.existingClusterControl.addItem(clusterContextContainer, {
CSSStyles: { 'margin- top': '10px' }
});
this.wizard.registerDisposable(this.browseFileButton.onDidClick(async () => {
let fileUris = await vscode.window.showOpenDialog(
{
canSelectFiles: true,
canSelectFolders: false,
canSelectMany: false,
defaultUri: vscode.Uri.file(os.homedir()),
openLabel: localize('deployCluster.selectKubeConfigFileText', "Select"),
filters: {
'Config Files': ['*'],
}
}
);
if (!fileUris || fileUris.length === 0) {
return;
}
self.clusterContextList!.clearItems();
let fileUri = fileUris[0];
self.loadClusterContexts(fileUri.fsPath);
}));
}
private async loadClusterContexts(configPath: string): Promise<void> {
this.clusterContextLoadingComponent!.loading = true;
this.wizard.model.setPropertyValue(ClusterContext_VariableName, undefined);
this.wizard.wizardObject.message = { text: '' };
let self = this;
this.configFileInput!.value = configPath;
let clusterContexts: KubeClusterContext[] = [];
try {
clusterContexts = await this._model.kubeService.getClusterContexts(configPath);
} catch (error) {
this.wizard.wizardObject.message = {
text: localize('deployCluster.ConfigParseError', "Failed to load the config file"),
description: error.message || error, level: azdata.window.MessageLevel.Error
};
}
if (clusterContexts.length !== 0) {
self.wizard.model.setPropertyValue(KubeConfigPath_VariableName, configPath);
let options = clusterContexts.map(clusterContext => {
let option = this.view!.modelBuilder.radioButton().withProps({
label: clusterContext.name,
checked: clusterContext.isCurrentContext,
name: ClusterRadioButtonGroupName
}).component();
if (clusterContext.isCurrentContext) {
self.wizard.model.setPropertyValue(ClusterContext_VariableName, clusterContext.name);
self.wizard.wizardObject.message = { text: '' };
}
this.wizard.registerDisposable(option.onDidClick(() => {
self.wizard.model.setPropertyValue(ClusterContext_VariableName, clusterContext.name);
self.wizard.wizardObject.message = { text: '' };
}));
return option;
});
self.clusterContextList!.addItems(options);
} else {
self.clusterContextList!.addItem(this.errorLoadingClustersLabel!);
}
this.clusterContextLoadingComponent!.loading = false;
}
}

View File

@@ -8,7 +8,7 @@ import { IToolsService } from '../../services/toolsService';
import { InputComponents, setModelValues } from '../modelViewUtils';
import { ResourceTypeModel } from '../resourceTypeModel';
import { ResourceTypeWizard } from '../resourceTypeWizard';
import { DeploymentType, NotebookWizardDeploymentProvider, NotebookWizardInfo } from '../../interfaces';
import { NotebookWizardDeploymentProvider, NotebookWizardInfo } from '../../interfaces';
import { IPlatformService } from '../../services/platformService';
import { NotebookWizardAutoSummaryPage } from './notebookWizardAutoSummaryPage';
import { NotebookWizardPage } from './notebookWizardPage';
@@ -47,10 +47,6 @@ export class NotebookWizardModel extends ResourceTypeModel {
this.wizard.wizardObject.generateScriptButton.label = this.notebookProvider.notebookWizard.scriptAction?.label || loc.scriptToNotebook;
}
public get deploymentType(): DeploymentType | undefined {
return this.notebookProvider.notebookWizard.type;
}
public initialize(): void {
this.wizard.setPages(this.getPages());
}

View File

@@ -5,12 +5,10 @@
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { DeploymentProvider, InitialVariableValues, instanceOfAzureSQLDBDeploymentProvider, instanceOfAzureSQLVMDeploymentProvider, instanceOfNotebookWizardDeploymentProvider, instanceOfWizardDeploymentProvider, ResourceType, ResourceTypeOptionValue } from '../interfaces';
import { DeployClusterWizardModel } from './deployClusterWizard/deployClusterWizardModel';
import { DeploymentProvider, InitialVariableValues, instanceOfAzureSQLDBDeploymentProvider, instanceOfAzureSQLVMDeploymentProvider, instanceOfNotebookWizardDeploymentProvider, ResourceType, ResourceTypeOptionValue } from '../interfaces';
import { DeployAzureSQLVMWizardModel } from './deployAzureSQLVMWizard/deployAzureSQLVMWizardModel';
import { WizardPageInfo } from './wizardPageInfo';
import { IKubeService } from '../services/kubeService';
import { IAzdataService } from '../services/azdataService';
import { INotebookService } from '../services/notebookService';
import { IToolsService } from '../services/toolsService';
import { IPlatformService } from '../services/platformService';
@@ -55,7 +53,6 @@ export class ResourceTypeWizard {
constructor(
public resourceType: ResourceType,
public _kubeService: IKubeService,
public azdataService: IAzdataService,
public notebookService: INotebookService,
public toolsService: IToolsService,
public platformService: IPlatformService,
@@ -124,9 +121,7 @@ export class ResourceTypeWizard {
private getResourceProviderModel(): ResourceTypeModel {
if (instanceOfWizardDeploymentProvider(this.provider)) {
return new DeployClusterWizardModel(this.provider, this);
} else if (instanceOfAzureSQLVMDeploymentProvider(this.provider)) {
if (instanceOfAzureSQLVMDeploymentProvider(this.provider)) {
return new DeployAzureSQLVMWizardModel(this.provider, this);
} else if (instanceOfNotebookWizardDeploymentProvider(this.provider)) {
return new NotebookWizardModel(this.provider, this);