Add Storage Class params to MIAA deploy (#11993)

This commit is contained in:
Charles Gagnon
2020-08-27 18:19:31 -07:00
committed by GitHub
parent 57ce9fae6f
commit 100072cabd
21 changed files with 148 additions and 32 deletions

View File

@@ -95,6 +95,16 @@
" mssql_password = os.environ[\"AZDATA_NB_VAR_SQL_PASSWORD\"]\n", " mssql_password = os.environ[\"AZDATA_NB_VAR_SQL_PASSWORD\"]\n",
"else:\n", "else:\n",
" sys.exit(f'environment variable: AZDATA_NB_VAR_SQL_PASSWORD was not defined. Exiting\\n') \n", " sys.exit(f'environment variable: AZDATA_NB_VAR_SQL_PASSWORD was not defined. Exiting\\n') \n",
"env_var = \"AZDATA_NB_VAR_SQL_STORAGE_CLASS_DATA\" in os.environ\n",
"if env_var:\n",
" mssql_storage_class_data = os.environ[\"AZDATA_NB_VAR_SQL_STORAGE_CLASS_DATA\"]\n",
"else:\n",
" sys.exit(f'environment variable: AZDATA_NB_VAR_SQL_STORAGE_CLASS_DATA was not defined. Exiting\\n') \n",
"env_var = \"AZDATA_NB_VAR_SQL_STORAGE_CLASS_LOGS\" in os.environ\n",
"if env_var:\n",
" mssql_storage_class_logs = os.environ[\"AZDATA_NB_VAR_SQL_STORAGE_CLASS_LOGS\"]\n",
"else:\n",
" sys.exit(f'environment variable: AZDATA_NB_VAR_SQL_STORAGE_CLASS_LOGS was not defined. Exiting\\n') \n",
"" ""
], ],
"metadata": { "metadata": {
@@ -119,7 +129,7 @@
"print (f'Creating Managed SQL Server instance on Azure Arc')\n", "print (f'Creating Managed SQL Server instance on Azure Arc')\n",
"\n", "\n",
"os.environ[\"AZDATA_PASSWORD\"] = mssql_password\n", "os.environ[\"AZDATA_PASSWORD\"] = mssql_password\n",
"cmd = f'azdata arc sql mi create -n {mssql_instance_name}'\n", "cmd = f'azdata arc sql mi create -n {mssql_instance_name} -scd {mssql_storage_class_data} -scl {mssql_storage_class_logs}'\n",
"out=run_command()" "out=run_command()"
], ],
"metadata": { "metadata": {

View File

@@ -603,6 +603,20 @@
"confirmationLabel": "%arc.confirm.password%", "confirmationLabel": "%arc.confirm.password%",
"defaultValue": "", "defaultValue": "",
"required": true "required": true
},
{
"label": "%arc.sql.storage-class.data.label%",
"description": "%arc.sql.storage-class.data.description%",
"variableName": "AZDATA_NB_VAR_SQL_STORAGE_CLASS_DATA",
"type": "kube_storage_class",
"required": true
},
{
"label": "%arc.sql.storage-class.logs.label%",
"description": "%arc.sql.storage-class.logs.description%",
"variableName": "AZDATA_NB_VAR_SQL_STORAGE_CLASS_LOGS",
"type": "kube_storage_class",
"required": true
} }
] ]
} }

View File

@@ -80,6 +80,10 @@
"arc.azure.section.title": "Azure information", "arc.azure.section.title": "Azure information",
"arc.sql.instance.name": "Instance name (lower case letters and digits only)", "arc.sql.instance.name": "Instance name (lower case letters and digits only)",
"arc.sql.username": "Username", "arc.sql.username": "Username",
"arc.sql.storage-class.data.label": "Storage Class (Data)",
"arc.sql.storage-class.data.description": "The storage classes to be used for data (.mdf)",
"arc.sql.storage-class.logs.label": "Storage Class (Logs)",
"arc.sql.storage-class.logs.description": "The storage classes to be used for logs (/var/log)",
"arc.password": "Password", "arc.password": "Password",
"arc.confirm.password": "Confirm password", "arc.confirm.password": "Confirm password",
"arc.azure.account": "Azure account", "arc.azure.account": "Azure account",

View File

@@ -284,6 +284,7 @@ export enum FieldType {
AzureLocations = 'azure_locations', AzureLocations = 'azure_locations',
FilePicker = 'file_picker', FilePicker = 'file_picker',
KubeClusterContextPicker = 'kube_cluster_context_picker', KubeClusterContextPicker = 'kube_cluster_context_picker',
KubeStorageClass = 'kube_storage_class'
} }
export enum OptionsType { export enum OptionsType {

View File

@@ -70,7 +70,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
} }
}); });
vscode.commands.registerCommand('azdata.openNotebookInputDialog', (dialogInfo: NotebookBasedDialogInfo) => { vscode.commands.registerCommand('azdata.openNotebookInputDialog', (dialogInfo: NotebookBasedDialogInfo) => {
const dialog = new DeploymentInputDialog(notebookService, platformService, dialogInfo); const dialog = new DeploymentInputDialog(notebookService, platformService, toolsService, dialogInfo);
dialog.open(); dialog.open();
}); });
} }

View File

@@ -245,7 +245,7 @@ export class ResourceTypeService implements IResourceTypeService {
const wizard = new NotebookWizard(provider.notebookWizard, this.notebookService, this.platformService, this.toolsService); const wizard = new NotebookWizard(provider.notebookWizard, this.notebookService, this.platformService, this.toolsService);
wizard.open(); wizard.open();
} else if (instanceOfDialogDeploymentProvider(provider)) { } else if (instanceOfDialogDeploymentProvider(provider)) {
const dialog = new DeploymentInputDialog(this.notebookService, this.platformService, provider.dialog); const dialog = new DeploymentInputDialog(this.notebookService, this.platformService, this.toolsService, provider.dialog);
dialog.open(); dialog.open();
} else if (instanceOfNotebookDeploymentProvider(provider)) { } else if (instanceOfNotebookDeploymentProvider(provider)) {
this.notebookService.launchNotebook(provider.notebook); this.notebookService.launchNotebook(provider.notebook);

View File

@@ -37,7 +37,7 @@ export class AzdataTool extends ToolBase {
} }
get displayName(): string { get displayName(): string {
return localize('resourceDeployment.AzdataDisplayName', "azdata"); return localize('resourceDeployment.AzdataDisplayName', "Azure Data CLI");
} }
get homePage(): string { get homePage(): string {

View File

@@ -20,6 +20,27 @@ interface KubeCtlVersion {
}; };
} }
export interface KubeStorageClass {
apiVersion: string, // "storage.k8s.io/v1",
kind: string, // "StorageClass",
metadata: KubeStorageClassMetadata,
provisioner: string, // "kubernetes.io/no-provisioner",
reclaimPolicy: string, // "Delete",
volumeBindingMode: string, // "WaitForFirstConsumer"
}
export interface KubeStorageClassMetadata {
annotations: {
'kubectl.kubernetes.io/last-applied-configuration': string, // "{\"apiVersion\":\"storage.k8s.io/v1\",\"kind\":\"StorageClass\",\"metadata\":{\"annotations\":{},\"name\":\"local-storage\"},\"provisioner\":\"kubernetes.io/no-provisioner\",\"reclaimPolicy\":\"Delete\",\"volumeBindingMode\":\"WaitForFirstConsumer\"}\n",
'storageclass.kubernetes.io/is-default-class': string, // "true"
},
creationTimestamp: string, // "2020-08-17T19:55:23Z",
name: string, // "local-storage",
resourceVersion: string, // "256",
selfLink: string, // "/apis/storage.k8s.io/v1/storageclasses/local-storage",
uid: string, // "262615e9-618b-4052-b0d4-2ddd02794cb4"
}
export class KubeCtlTool extends ToolBase { export class KubeCtlTool extends ToolBase {
constructor(platformService: IPlatformService) { constructor(platformService: IPlatformService) {
super(platformService); super(platformService);
@@ -45,6 +66,14 @@ export class KubeCtlTool extends ToolBase {
return 'https://kubernetes.io/docs/tasks/tools/install-kubectl'; return 'https://kubernetes.io/docs/tasks/tools/install-kubectl';
} }
public async getStorageClasses(): Promise<{ storageClasses: string[], defaultStorageClass: string }> {
const storageClasses: KubeStorageClass[] = JSON.parse(await this.platformService.runCommand('kubectl get sc -o json')).items;
return {
storageClasses: storageClasses.map(sc => sc.metadata.name),
defaultStorageClass: storageClasses.find(sc => sc.metadata.annotations['storageclass.kubernetes.io/is-default-class'] === 'true')?.metadata.name ?? ''
};
}
protected getVersionFromOutput(output: string): SemVer | undefined { protected getVersionFromOutput(output: string): SemVer | undefined {
let version: SemVer | undefined = undefined; let version: SemVer | undefined = undefined;
if (output) { if (output) {

View File

@@ -40,7 +40,7 @@ export const messageByDependencyType: Map<dependencyType, string> = new Map<depe
]); ]);
export abstract class ToolBase implements ITool { export abstract class ToolBase implements ITool {
constructor(private _platformService: IPlatformService) { constructor(protected platformService: IPlatformService) {
this.startVersionAndStatusUpdate(); this.startVersionAndStatusUpdate();
} }
@@ -77,7 +77,7 @@ export abstract class ToolBase implements ITool {
} }
protected logToOutputChannel(data: string | Buffer, header?: string): void { protected logToOutputChannel(data: string | Buffer, header?: string): void {
this._platformService.logToOutputChannel(data, header); // data and header are localized by caller this.platformService.logToOutputChannel(data, header); // data and header are localized by caller
} }
public get onDidUpdateData(): vscode.Event<ITool> { public get onDidUpdateData(): vscode.Event<ITool> {
@@ -101,11 +101,11 @@ export abstract class ToolBase implements ITool {
return this.status === ToolStatus.NotInstalled && this.autoInstallSupported; return this.status === ToolStatus.NotInstalled && this.autoInstallSupported;
} }
public get storagePath(): string { public get storagePath(): string {
return this._platformService.storagePath(); return this.platformService.storagePath();
} }
public get osDistribution(): OsDistribution { public get osDistribution(): OsDistribution {
return this._platformService.osDistribution(); return this.platformService.osDistribution();
} }
protected get version(): SemVer | undefined { protected get version(): SemVer | undefined {
@@ -136,7 +136,7 @@ export abstract class ToolBase implements ITool {
protected async getPip3InstallLocation(packageName: string): Promise<string> { protected async getPip3InstallLocation(packageName: string): Promise<string> {
const command = `pip3 show ${packageName}`; const command = `pip3 show ${packageName}`;
const pip3ShowOutput: string = await this._platformService.runCommand(command, { sudo: false, ignoreError: true }); const pip3ShowOutput: string = await this.platformService.runCommand(command, { sudo: false, ignoreError: true });
const installLocation = /^Location\: (.*)$/gim.exec(pip3ShowOutput); const installLocation = /^Location\: (.*)$/gim.exec(pip3ShowOutput);
let retValue = installLocation && installLocation[1]; let retValue = installLocation && installLocation[1];
if (retValue === undefined || retValue === null) { if (retValue === undefined || retValue === null) {
@@ -150,11 +150,11 @@ export abstract class ToolBase implements ITool {
} }
public get outputChannelName(): string { public get outputChannelName(): string {
return this._platformService.outputChannelName(); return this.platformService.outputChannelName();
} }
public showOutputChannel(preserveFocus?: boolean | undefined): void { public showOutputChannel(preserveFocus?: boolean | undefined): void {
this._platformService.showOutputChannel(preserveFocus); this.platformService.showOutputChannel(preserveFocus);
} }
@@ -197,7 +197,7 @@ export abstract class ToolBase implements ITool {
throw new Error(localize('toolBase.installCore.CannotInstallTool', "Cannot install tool:{0}::{1} as installation commands are unknown for your OS distribution, Please install {0} manually before proceeding", this.displayName, this.description)); throw new Error(localize('toolBase.installCore.CannotInstallTool', "Cannot install tool:{0}::{1} as installation commands are unknown for your OS distribution, Please install {0} manually before proceeding", this.displayName, this.description));
} }
for (let i: number = 0; i < installationCommands.length; i++) { for (let i: number = 0; i < installationCommands.length; i++) {
await this._platformService.runCommand(installationCommands[i].command, await this.platformService.runCommand(installationCommands[i].command,
{ {
workingDirectory: installationCommands[i].workingDirectory || this.downloadPath, workingDirectory: installationCommands[i].workingDirectory || this.downloadPath,
additionalEnvironmentVariables: installationCommands[i].additionalEnvironmentVariables, additionalEnvironmentVariables: installationCommands[i].additionalEnvironmentVariables,
@@ -253,7 +253,7 @@ export abstract class ToolBase implements ITool {
private async updateVersionAndStatus(): Promise<void> { private async updateVersionAndStatus(): Promise<void> {
this._statusDescription = ''; this._statusDescription = '';
await this.addInstallationSearchPathsToSystemPath(); await this.addInstallationSearchPathsToSystemPath();
const commandOutput = await this._platformService.runCommand( const commandOutput = await this.platformService.runCommand(
this.versionCommand.command, this.versionCommand.command,
{ {
workingDirectory: this.versionCommand.workingDirectory, workingDirectory: this.versionCommand.workingDirectory,
@@ -289,7 +289,7 @@ export abstract class ToolBase implements ITool {
} }
protected async setInstallationPath() { protected async setInstallationPath() {
const commandOutput = await this._platformService.runCommand( const commandOutput = await this.platformService.runCommand(
this.discoveryCommand.command, this.discoveryCommand.command,
{ {
workingDirectory: this.discoveryCommand.workingDirectory, workingDirectory: this.discoveryCommand.workingDirectory,

View File

@@ -57,8 +57,8 @@ export class DeployClusterWizard extends WizardBase<DeployClusterWizard, WizardP
this._saveConfigButton.hidden = true; this._saveConfigButton.hidden = true;
} }
constructor(private wizardInfo: BdcWizardInfo, private _kubeService: IKubeService, private _azdataService: IAzdataService, private _notebookService: INotebookService, private _toolsService: IToolsService) { constructor(private wizardInfo: BdcWizardInfo, private _kubeService: IKubeService, private _azdataService: IAzdataService, private _notebookService: INotebookService, toolsService: IToolsService) {
super(DeployClusterWizard.getTitle(wizardInfo.type), new DeployClusterWizardModel(wizardInfo.type)); super(DeployClusterWizard.getTitle(wizardInfo.type), new DeployClusterWizardModel(wizardInfo.type), toolsService);
this._saveConfigButton = azdata.window.createButton(localize('deployCluster.SaveConfigFiles', "Save config files"), 'left'); this._saveConfigButton = azdata.window.createButton(localize('deployCluster.SaveConfigFiles', "Save config files"), 'left');
this._saveConfigButton.hidden = true; this._saveConfigButton.hidden = true;
this.addButton(this._saveConfigButton); this.addButton(this._saveConfigButton);
@@ -141,7 +141,7 @@ export class DeployClusterWizard extends WizardBase<DeployClusterWizard, WizardP
private async scriptToNotebook(): Promise<void> { private async scriptToNotebook(): Promise<void> {
this.setEnvironmentVariables(process.env); this.setEnvironmentVariables(process.env);
const variableValueStatements = this.model.getCodeCellContentForNotebook(this._toolsService.toolsForCurrentProvider); const variableValueStatements = this.model.getCodeCellContentForNotebook(this.toolsService.toolsForCurrentProvider);
const insertionPosition = 5; // Cell number 5 is the position where the python variable setting statements need to be inserted in this.wizardInfo.notebook. const insertionPosition = 5; // Cell number 5 is the position where the python variable setting statements need to be inserted in this.wizardInfo.notebook.
try { try {
await this.notebookService.launchNotebookWithEdits(this.wizardInfo.notebook, variableValueStatements, insertionPosition); await this.notebookService.launchNotebookWithEdits(this.wizardInfo.notebook, variableValueStatements, insertionPosition);

View File

@@ -139,7 +139,8 @@ export class AzureSettingsPage extends WizardPageBase<DeployClusterWizard> {
self.validators.push(validator); self.validators.push(validator);
}, },
container: this.wizard.wizardObject, container: this.wizard.wizardObject,
inputComponents: this.wizard.inputComponents inputComponents: this.wizard.inputComponents,
toolsService: this.wizard.toolsService
}); });
const formBuilder = view.modelBuilder.formContainer().withFormItems( const formBuilder = view.modelBuilder.formContainer().withFormItems(
[{ [{

View File

@@ -222,7 +222,8 @@ export class ClusterSettingsPage extends WizardPageBase<DeployClusterWizard> {
}, },
onNewValidatorCreated: (validator: Validator): void => { onNewValidatorCreated: (validator: Validator): void => {
self.validators.push(validator); self.validators.push(validator);
} },
toolsService: this.wizard.toolsService
}); });
const activeDirectorySettingsGroup = await createSection({ const activeDirectorySettingsGroup = await createSection({
view: view, view: view,
@@ -237,7 +238,8 @@ export class ClusterSettingsPage extends WizardPageBase<DeployClusterWizard> {
}, },
onNewValidatorCreated: (validator: Validator): void => { onNewValidatorCreated: (validator: Validator): void => {
self.validators.push(validator); self.validators.push(validator);
} },
toolsService: this.wizard.toolsService
}); });
const dockerSettingsGroup = await createSection({ const dockerSettingsGroup = await createSection({
view: view, view: view,
@@ -252,7 +254,8 @@ export class ClusterSettingsPage extends WizardPageBase<DeployClusterWizard> {
}, },
onNewValidatorCreated: (validator: Validator): void => { onNewValidatorCreated: (validator: Validator): void => {
self.validators.push(validator); self.validators.push(validator);
} },
toolsService: this.wizard.toolsService
}); });
const basicSettingsFormItem = { title: '', component: basicSettingsGroup }; const basicSettingsFormItem = { title: '', component: basicSettingsGroup };
const dockerSettingsFormItem = { title: '', component: dockerSettingsGroup }; const dockerSettingsFormItem = { title: '', component: dockerSettingsGroup };

View File

@@ -128,7 +128,8 @@ export class ServiceSettingsPage extends WizardPageBase<DeployClusterWizard> {
this.inputComponents[name] = { component: inputComponentInfo.component }; this.inputComponents[name] = { component: inputComponentInfo.component };
}, },
onNewValidatorCreated: (validator: Validator): void => { onNewValidatorCreated: (validator: Validator): void => {
} },
toolsService: this.wizard.toolsService
}); });
}; };
const scaleSection = await createSectionFunc(scaleSectionInfo); const scaleSection = await createSectionFunc(scaleSectionInfo);

View File

@@ -296,7 +296,8 @@ export class SummaryPage extends WizardPageBase<DeployClusterWizard> {
view: this.view, view: this.view,
onNewDisposableCreated: () => { }, onNewDisposableCreated: () => { },
onNewInputComponentCreated: () => { }, onNewInputComponentCreated: () => { },
onNewValidatorCreated: () => { } onNewValidatorCreated: () => { },
toolsService: this.wizard.toolsService
}) })
}; };
}; };

View File

@@ -13,6 +13,7 @@ import { IPlatformService } from '../services/platformService';
import { DialogBase } from './dialogBase'; import { DialogBase } from './dialogBase';
import { Model } from './model'; import { Model } from './model';
import { initializeDialog, InputComponentInfo, InputComponents, setModelValues, Validator } from './modelViewUtils'; import { initializeDialog, InputComponentInfo, InputComponents, setModelValues, Validator } from './modelViewUtils';
import { IToolsService } from '../services/toolsService';
const localize = nls.loadMessageBundle(); const localize = nls.loadMessageBundle();
@@ -22,6 +23,7 @@ export class DeploymentInputDialog extends DialogBase {
constructor(private notebookService: INotebookService, constructor(private notebookService: INotebookService,
private platformService: IPlatformService, private platformService: IPlatformService,
private toolsService: IToolsService,
private dialogInfo: DialogInfo) { private dialogInfo: DialogInfo) {
super(dialogInfo.title, dialogInfo.name, false); super(dialogInfo.title, dialogInfo.name, false);
let okButtonText: string; let okButtonText: string;
@@ -51,7 +53,8 @@ export class DeploymentInputDialog extends DialogBase {
}, },
onNewValidatorCreated: (validator: Validator): void => { onNewValidatorCreated: (validator: Validator): void => {
validators.push(validator); validators.push(validator);
} },
toolsService: this.toolsService
}); });
this._dialogObject.registerCloseValidator(() => { this._dialogObject.registerCloseValidator(() => {
const messages: string[] = []; const messages: string[] = [];

View File

@@ -17,6 +17,8 @@ import { assert, getDateTimeString, getErrorMessage } from '../utils';
import { WizardInfoBase } from './../interfaces'; import { WizardInfoBase } from './../interfaces';
import { Model } from './model'; import { Model } from './model';
import { RadioGroupLoadingComponentBuilder } from './radioGroupLoadingComponentBuilder'; import { RadioGroupLoadingComponentBuilder } from './radioGroupLoadingComponentBuilder';
import { IToolsService } from '../services/toolsService';
import { KubeCtlToolName, KubeCtlTool } from '../services/tools/kubeCtlTool';
const localize = nls.loadMessageBundle(); const localize = nls.loadMessageBundle();
@@ -107,6 +109,7 @@ interface AzureAccountComponents {
interface ContextBase { interface ContextBase {
container: azdata.window.Dialog | azdata.window.Wizard; container: azdata.window.Dialog | azdata.window.Wizard;
toolsService: IToolsService,
inputComponents: InputComponents; inputComponents: InputComponents;
onNewValidatorCreated: (validator: Validator) => void; onNewValidatorCreated: (validator: Validator) => void;
onNewDisposableCreated: (disposable: vscode.Disposable) => void; onNewDisposableCreated: (disposable: vscode.Disposable) => void;
@@ -197,7 +200,8 @@ export function initializeDialog(dialogContext: DialogContext): void {
onNewInputComponentCreated: dialogContext.onNewInputComponentCreated, onNewInputComponentCreated: dialogContext.onNewInputComponentCreated,
onNewValidatorCreated: dialogContext.onNewValidatorCreated, onNewValidatorCreated: dialogContext.onNewValidatorCreated,
container: dialogContext.container, container: dialogContext.container,
inputComponents: dialogContext.inputComponents inputComponents: dialogContext.inputComponents,
toolsService: dialogContext.toolsService
}); });
})); }));
const formBuilder = view.modelBuilder.formContainer().withFormItems( const formBuilder = view.modelBuilder.formContainer().withFormItems(
@@ -229,6 +233,7 @@ export function initializeWizardPage(context: WizardPageContext): void {
return createSection({ return createSection({
view: view, view: view,
container: context.container, container: context.container,
toolsService: context.toolsService,
inputComponents: context.inputComponents, inputComponents: context.inputComponents,
onNewDisposableCreated: context.onNewDisposableCreated, onNewDisposableCreated: context.onNewDisposableCreated,
onNewInputComponentCreated: context.onNewInputComponentCreated, onNewInputComponentCreated: context.onNewInputComponentCreated,
@@ -299,7 +304,8 @@ async function processFields(fieldInfoArray: FieldInfo[], components: azdata.Com
fieldInfo: fieldInfo, fieldInfo: fieldInfo,
container: context.container, container: context.container,
inputComponents: context.inputComponents, inputComponents: context.inputComponents,
components: components components: components,
toolsService: context.toolsService
}); });
if (spaceBetweenFields && i < fieldInfoArray.length - 1) { if (spaceBetweenFields && i < fieldInfoArray.length - 1) {
components.push(context.view.modelBuilder.divContainer().withLayout({ width: spaceBetweenFields }).component()); components.push(context.view.modelBuilder.divContainer().withLayout({ width: spaceBetweenFields }).component());
@@ -380,6 +386,9 @@ async function processField(context: FieldContext): Promise<void> {
case FieldType.KubeClusterContextPicker: case FieldType.KubeClusterContextPicker:
processKubeConfigClusterPickerField(context); processKubeConfigClusterPickerField(context);
break; break;
case FieldType.KubeStorageClass:
await processKubeStorageClassField(context);
break;
default: default:
throw new Error(localize('UnknownFieldTypeError', "Unknown field type: \"{0}\"", context.fieldInfo.type)); throw new Error(localize('UnknownFieldTypeError', "Unknown field type: \"{0}\"", context.fieldInfo.type));
} }
@@ -719,7 +728,8 @@ async function processKubeConfigClusterPickerField(context: KubeClusterContextFi
variableName: kubeConfigFilePathVariableName, variableName: kubeConfigFilePathVariableName,
labelPosition: LabelPosition.Left, labelPosition: LabelPosition.Left,
required: true required: true
} },
toolsService: context.toolsService
}; };
const filePicker = processFilePickerField(filePickerContext); const filePicker = processFilePickerField(filePickerContext);
context.fieldInfo.subFields = context.fieldInfo.subFields || []; context.fieldInfo.subFields = context.fieldInfo.subFields || [];
@@ -840,6 +850,42 @@ async function processAzureAccountField(context: AzureAccountFieldContext): Prom
}, 0); }, 0);
} }
async function processKubeStorageClassField(context: FieldContext): Promise<void> {
const label = createLabel(context.view, {
text: context.fieldInfo.label,
description: context.fieldInfo.description,
required: context.fieldInfo.required,
width: context.fieldInfo.labelWidth,
cssStyles: context.fieldInfo.labelCSSStyles
});
// Try to query for the available storage classes - but if this fails the dropdown is editable
// so users can still enter their own
let storageClasses: string[] = [];
let defaultStorageClass = '';
try {
const kubeCtlTool = context.toolsService.getToolByName(KubeCtlToolName) as KubeCtlTool;
const response = await kubeCtlTool.getStorageClasses();
storageClasses = response.storageClasses;
defaultStorageClass = response.defaultStorageClass;
} catch (err) {
vscode.window.showErrorMessage(localize('resourceDeployment.errorFetchingStorageClasses', "Unexpected error fetching available kubectl storage classes : {0}", err.message ?? err));
}
const storageClassDropdown = createDropdown(context.view, {
width: context.fieldInfo.inputWidth,
editable: true,
required: context.fieldInfo.required,
label: context.fieldInfo.label,
values: storageClasses,
defaultValue: defaultStorageClass
});
storageClassDropdown.fireOnTextChange = true;
context.onNewInputComponentCreated(context.fieldInfo.variableName!, { component: storageClassDropdown });
addLabelInputPairToContainer(context.view, context.components, label, storageClassDropdown, context.fieldInfo);
}
function getAccountDisplayString(account: azdata.Account) { function getAccountDisplayString(account: azdata.Account) {
return `${account.displayInfo.displayName} (${account.displayInfo.userId})`; return `${account.displayInfo.displayName} (${account.displayInfo.userId})`;
} }

View File

@@ -35,8 +35,8 @@ export class NotebookWizard extends WizardBase<NotebookWizard, NotebookWizardPag
return this._inputComponents; return this._inputComponents;
} }
constructor(private _wizardInfo: NotebookWizardInfo, private _notebookService: INotebookService, private _platformService: IPlatformService, private _toolsService: IToolsService) { constructor(private _wizardInfo: NotebookWizardInfo, private _notebookService: INotebookService, private _platformService: IPlatformService, toolsService: IToolsService) {
super(_wizardInfo.title, new Model()); super(_wizardInfo.title, new Model(), toolsService);
if (this._wizardInfo.codeCellInsertionPosition === undefined) { if (this._wizardInfo.codeCellInsertionPosition === undefined) {
this._wizardInfo.codeCellInsertionPosition = 0; this._wizardInfo.codeCellInsertionPosition = 0;
} }
@@ -67,7 +67,7 @@ export class NotebookWizard extends WizardBase<NotebookWizard, NotebookWizardPag
const notebook: Notebook = await this.notebookService.getNotebook(this.wizardInfo.notebook); const notebook: Notebook = await this.notebookService.getNotebook(this.wizardInfo.notebook);
// generate python code statements for all variables captured by the wizard // generate python code statements for all variables captured by the wizard
const statements = this.model.getCodeCellContentForNotebook( const statements = this.model.getCodeCellContentForNotebook(
this._toolsService.toolsForCurrentProvider, this.toolsService.toolsForCurrentProvider,
(varName) => { (varName) => {
const isPassword = !!this.inputComponents[varName]?.isPassword; const isPassword = !!this.inputComponents[varName]?.isPassword;
return !isPassword; return !isPassword;

View File

@@ -79,6 +79,7 @@ export class NotebookWizardAutoSummaryPage extends NotebookWizardPage {
title: pageInfo.title, title: pageInfo.title,
component: await createSection({ component: await createSection({
container: this.wizard.wizardObject, container: this.wizard.wizardObject,
toolsService: this.wizard.toolsService,
inputComponents: this.wizard.inputComponents, inputComponents: this.wizard.inputComponents,
sectionInfo: summarySectionInfo, sectionInfo: summarySectionInfo,
view: this.view, view: this.view,

View File

@@ -53,6 +53,7 @@ export class NotebookWizardPage extends WizardPageBase<NotebookWizard> {
onNewValidatorCreated: (validator: Validator): void => { onNewValidatorCreated: (validator: Validator): void => {
this.validators.push(validator); this.validators.push(validator);
}, },
toolsService: this.wizard.toolsService
}); });
} }

View File

@@ -94,7 +94,7 @@ export class ResourceTypePickerDialog extends DialogBase {
this._agreementContainer = view.modelBuilder.divContainer().component(); this._agreementContainer = view.modelBuilder.divContainer().component();
const toolColumn: azdata.TableColumn = { const toolColumn: azdata.TableColumn = {
value: localize('deploymentDialog.toolNameColumnHeader', "Tool"), value: localize('deploymentDialog.toolNameColumnHeader', "Tool"),
width: 55 width: 80
}; };
const descriptionColumn: azdata.TableColumn = { const descriptionColumn: azdata.TableColumn = {
value: localize('deploymentDialog.toolDescriptionColumnHeader', "Description"), value: localize('deploymentDialog.toolDescriptionColumnHeader', "Description"),

View File

@@ -8,6 +8,7 @@ import * as vscode from 'vscode';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
import { WizardPageBase } from './wizardPageBase'; import { WizardPageBase } from './wizardPageBase';
import { Model } from './model'; import { Model } from './model';
import { IToolsService } from '../services/toolsService';
const localize = nls.loadMessageBundle(); const localize = nls.loadMessageBundle();
export abstract class WizardBase<T, P extends WizardPageBase<T>, M extends Model> { export abstract class WizardBase<T, P extends WizardPageBase<T>, M extends Model> {
@@ -20,7 +21,7 @@ export abstract class WizardBase<T, P extends WizardPageBase<T>, M extends Model
return this._model; return this._model;
} }
constructor(private title: string, private _model: M) { constructor(private title: string, private _model: M, public toolsService: IToolsService) {
this.wizardObject = azdata.window.createWizard(title); this.wizardObject = azdata.window.createWizard(title);
} }