Replacing all azdata with az (#16502)

* Changed azdata to az in azcli extension and resource-deployment, and some arc. Removed user, pass, url from controller connect blade. Commented out tests. Ported over work from old branch.

* Changed unit tests, all unit tests passing. Changed parameters to new ones, fixed some Controller Connect issues.

* Connect data controller and create dc working.

* Changed az back to azdata in necessary places in resource-deployment.

* Changed notebook values and added namespace to some params.

* Added some changes from PR to this branch

* Changed azdata.ts to az.ts and changed subscription parameter

* Brought over changes from azcli PR into this branch.

* added endpoint, username, password to getIsPassword

* Changed notebooks to use proper az params, hard coded in some values to verify it is working, removed some variableNames from package.json.

* Changed -sc to --storage-class in notebook

* Added namespace to SQL deploy, deleted dc create in api

* Deleted more dc create code and uncommented findAz() with unfinished work on Do Not Ask Again.

* Removed (preview) from extensions/arc and extensions/azcli excluding preview:true in package.json

* Commented out install/update prompts until DoNotAskAgain is implemented

* Fixed bugs: JSON Output errors are now being caught, --infrastructure now has a required UI component with dropdown options, config page loads properly, SQL create flags use full names instead of shortnames.

* Adds validation to pg extensions and bug fixes (#16486)

* Extensions

* Server parameters

* Change locaiton of postgres extensions, pr fixes

* Change location of list

* List spacing

* Commented out Don't Ask Again prompt implementation.

* Uncommented header of a test file.

* Added Azure CLI arcdata extension to Prerequisites

* Reverted package.json and yarn.lock

* Took away casting of stderr and stdout in executeCommand.

* Deleted override function for initializeFields in connectControllerDialog.ts

* Removed fakeAzApi for testing and added back in (Preview)

* Removed en-us from python notebook links.

* Deleted azdata tool from tool tests in resource-deployment

* Deleted another instance of azdata in tool test

* Add back in azdata tooltype

* Remove en-us

* Replaced AzdataTool in typings

* Reverting adding azdata tool back in

* Changed Azdata to AzdataToolOld

* Added back azdata tool type

* Added AzdataToolOld to tool types

* fix test

Co-authored-by: Candice Ye <canye@microsoft.com>
Co-authored-by: nasc17 <nasc@microsoft.com>
Co-authored-by: nasc17 <69922333+nasc17@users.noreply.github.com>
Co-authored-by: chgagnon <chgagnon@microsoft.com>
This commit is contained in:
Candice Ye
2021-08-01 15:12:24 -07:00
committed by GitHub
parent 65cc61fdbd
commit 914fe8fc29
58 changed files with 1623 additions and 2032 deletions

View File

@@ -10,6 +10,8 @@ import { cssStyles } from '../../constants';
import { InitializingComponent } from '../components/initializingComponent';
import { PostgresModel } from '../../models/postgresModel';
export const validExtensions = ['citus', 'pgaudit', 'pgautofailover', 'pg_cron', 'pg_partman', 'plv8', 'postgis', 'postgis_raster', 'postgis_sfcgal', 'postgis_tiger_geocoder', 'tdigest'];
export class AddPGExtensionsDialog extends InitializingComponent {
protected modelBuilder!: azdata.ModelBuilder;
@@ -28,7 +30,7 @@ export class AddPGExtensionsDialog extends InitializingComponent {
this.modelBuilder = view.modelBuilder;
const info = this.modelBuilder.text().withProps({
value: loc.extensionsFunction,
value: loc.extensionsAddFunction(validExtensions.join(', ')),
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px' }
}).component();
@@ -45,7 +47,15 @@ export class AddPGExtensionsDialog extends InitializingComponent {
.withProps({
value: '',
ariaLabel: loc.extensionsAddList,
enabled: true
enabled: true,
validationErrorMessage: loc.extensionsAddErrorrMessage(validExtensions.join(','))
}).withValidation((component) => {
if (!component.value) {
return true;
}
let newExtensions = component.value.split(',');
return newExtensions.every(e => validExtensions.includes(e));
}).component();
let formModel = this.modelBuilder.formContainer()
@@ -56,7 +66,8 @@ export class AddPGExtensionsDialog extends InitializingComponent {
},
{
component: this.extensionsListInputBox,
title: loc.extensionsAddList
title: loc.extensionsAddList,
required: true
}
],
title: ''

View File

@@ -5,7 +5,6 @@
import { ControllerInfo, ResourceInfo } from 'arc';
import * as azdata from 'azdata';
import * as azdataExt from 'azdata-ext';
import { v4 as uuid } from 'uuid';
import * as vscode from 'vscode';
import { Deferred } from '../../common/promise';
@@ -13,12 +12,11 @@ import * as loc from '../../localizedConstants';
import { ControllerModel } from '../../models/controllerModel';
import { InitializingComponent } from '../components/initializingComponent';
import { AzureArcTreeDataProvider } from '../tree/azureArcTreeDataProvider';
import { getErrorMessage } from '../../common/utils';
import { RadioOptionsGroup } from '../components/radioOptionsGroup';
import { getCurrentClusterContext, getDefaultKubeConfigPath, getKubeConfigClusterContexts, KubeClusterContext } from '../../common/kubeUtils';
import { FilePicker } from '../components/filePicker';
export type ConnectToControllerDialogModel = { controllerModel: ControllerModel, password: string };
export type ConnectToControllerDialogModel = { controllerModel: ControllerModel };
abstract class ControllerDialogBase extends InitializingComponent {
protected _toDispose: vscode.Disposable[] = [];
@@ -29,9 +27,6 @@ abstract class ControllerDialogBase extends InitializingComponent {
protected kubeConfigInputBox!: FilePicker;
protected clusterContextRadioGroup!: RadioOptionsGroup;
protected nameInputBox!: azdata.InputBoxComponent;
protected usernameInputBox!: azdata.InputBoxComponent;
protected passwordInputBox!: azdata.InputBoxComponent;
protected urlInputBox!: azdata.InputBoxComponent;
private _kubeClusters: KubeClusterContext[] = [];
@@ -46,13 +41,6 @@ abstract class ControllerDialogBase extends InitializingComponent {
component: this.namespaceInputBox,
title: loc.namespace,
required: true
},
{
component: this.urlInputBox,
title: loc.controllerUrl,
layout: {
info: loc.controllerUrlDescription
}
}, {
component: this.kubeConfigInputBox.component(),
title: loc.controllerKubeConfig,
@@ -68,14 +56,6 @@ abstract class ControllerDialogBase extends InitializingComponent {
layout: {
info: loc.controllerNameDescription
}
}, {
component: this.usernameInputBox,
title: loc.controllerUsername,
required: true
}, {
component: this.passwordInputBox,
title: loc.controllerPassword,
required: true
}
];
}
@@ -83,16 +63,11 @@ abstract class ControllerDialogBase extends InitializingComponent {
protected abstract fieldToFocusOn(): azdata.Component;
protected readonlyFields(): azdata.Component[] { return []; }
protected initializeFields(controllerInfo: ControllerInfo | undefined, password: string | undefined) {
protected initializeFields(controllerInfo: ControllerInfo | undefined) {
this.namespaceInputBox = this.modelBuilder.inputBox()
.withProps({
value: controllerInfo?.namespace,
}).component();
this.urlInputBox = this.modelBuilder.inputBox()
.withProps({
value: controllerInfo?.endpoint,
placeHolder: loc.controllerUrlPlaceholder,
}).component();
this.kubeConfigInputBox = new FilePicker(
this.modelBuilder,
controllerInfo?.kubeConfigFilePath || getDefaultKubeConfigPath(),
@@ -113,15 +88,6 @@ abstract class ControllerDialogBase extends InitializingComponent {
.withProps({
value: controllerInfo?.name
}).component();
this.usernameInputBox = this.modelBuilder.inputBox()
.withProps({
value: controllerInfo?.username
}).component();
this.passwordInputBox = this.modelBuilder.inputBox()
.withProps({
inputType: 'password',
value: password
}).component();
}
protected completionPromise = new Deferred<ConnectToControllerDialogModel | undefined>();
@@ -150,13 +116,13 @@ abstract class ControllerDialogBase extends InitializingComponent {
this.namespaceInputBox.value = currentContext?.namespace;
}
public showDialog(controllerInfo?: ControllerInfo, password: string | undefined = undefined): azdata.window.Dialog {
public showDialog(controllerInfo?: ControllerInfo): azdata.window.Dialog {
this.id = controllerInfo?.id ?? uuid();
this.resources = controllerInfo?.resources ?? [];
this._toDispose.push(this.dialog.cancelButton.onClick(() => this.handleCancel()));
this.dialog.registerContent(async (view) => {
this.modelBuilder = view.modelBuilder;
this.initializeFields(controllerInfo, password);
this.initializeFields(controllerInfo);
let formModel = this.modelBuilder.formContainer()
.withFormItems([{
@@ -192,75 +158,37 @@ abstract class ControllerDialogBase extends InitializingComponent {
return this.completionPromise.promise;
}
protected getControllerInfo(url: string, rememberPassword: boolean = false): ControllerInfo {
protected getControllerInfo(): ControllerInfo {
return {
id: this.id,
endpoint: url || undefined,
namespace: this.namespaceInputBox.value!.trim(),
kubeConfigFilePath: this.kubeConfigInputBox.value!,
kubeClusterContext: this.clusterContextRadioGroup.value!,
name: this.nameInputBox.value ?? '',
username: this.usernameInputBox.value!,
rememberPassword: rememberPassword,
resources: this.resources
};
}
}
export class ConnectToControllerDialog extends ControllerDialogBase {
protected rememberPwCheckBox!: azdata.CheckBoxComponent;
protected fieldToFocusOn() {
return this.namespaceInputBox;
}
protected override getComponents() {
return [
...super.getComponents(),
{
component: this.rememberPwCheckBox,
title: ''
}];
}
protected override initializeFields(controllerInfo: ControllerInfo | undefined, password: string | undefined) {
super.initializeFields(controllerInfo, password);
this.rememberPwCheckBox = this.modelBuilder.checkBox()
.withProps({
label: loc.rememberPassword,
checked: controllerInfo?.rememberPassword
}).component();
}
constructor(treeDataProvider: AzureArcTreeDataProvider) {
super(treeDataProvider, loc.connectToController);
}
public async validate(): Promise<boolean> {
if (!this.namespaceInputBox.value || !this.usernameInputBox.value || !this.passwordInputBox.value) {
if (!this.namespaceInputBox.value) {
return false;
}
let url = this.urlInputBox.value?.trim() || '';
if (url) {
// Only support https connections
if (url.toLowerCase().startsWith('http://')) {
url = url.replace('http', 'https');
}
// Append https if they didn't type it in
if (!url.toLowerCase().startsWith('https://')) {
url = `https://${url}`;
}
// Append default port if one wasn't specified
if (!/.*:\d*$/.test(url)) {
url = `${url}:30080`;
}
}
const controllerInfo: ControllerInfo = this.getControllerInfo(url, !!this.rememberPwCheckBox.checked);
const controllerModel = new ControllerModel(this.treeDataProvider, controllerInfo, this.passwordInputBox.value);
const controllerInfo: ControllerInfo = this.getControllerInfo();
const controllerModel = new ControllerModel(this.treeDataProvider, controllerInfo);
try {
// Validate that we can connect to the controller, this also populates the controllerRegistration from the connection response.
await controllerModel.refresh(false);
await controllerModel.refresh(false, this.namespaceInputBox.value);
// default info.name to the name of the controller instance if the user did not specify their own and to a pre-canned default if for some weird reason controller endpoint returned instanceName is also not a valid value
controllerModel.info.name = controllerModel.info.name || controllerModel.controllerConfig?.metadata.name || loc.defaultControllerName;
} catch (err) {
@@ -270,74 +198,7 @@ export class ConnectToControllerDialog extends ControllerDialogBase {
};
return false;
}
this.completionPromise.resolve({ controllerModel: controllerModel, password: this.passwordInputBox.value });
this.completionPromise.resolve({ controllerModel: controllerModel });
return true;
}
}
export class PasswordToControllerDialog extends ControllerDialogBase {
constructor(treeDataProvider: AzureArcTreeDataProvider) {
super(treeDataProvider, loc.passwordToController);
}
protected fieldToFocusOn() {
return this.passwordInputBox;
}
protected override readonlyFields(): azdata.Component[] {
return [
this.urlInputBox,
...this.kubeConfigInputBox.items,
...this.clusterContextRadioGroup.items,
this.nameInputBox,
this.usernameInputBox
];
}
public async validate(): Promise<boolean> {
if (!this.passwordInputBox.value) {
return false;
}
const controllerInfo: ControllerInfo = this.getControllerInfo(this.urlInputBox.value!, false);
const controllerModel = new ControllerModel(this.treeDataProvider, controllerInfo, this.passwordInputBox.value);
const azdataApi = <azdataExt.IExtension>vscode.extensions.getExtension(azdataExt.extension.name)?.exports;
try {
await azdataApi.azdata.login(
{
endpoint: controllerInfo.endpoint,
namespace: controllerInfo.namespace
},
controllerInfo.username,
this.passwordInputBox.value,
{
'KUBECONFIG': this.kubeConfigInputBox.value!,
'KUBECTL_CONTEXT': this.clusterContextRadioGroup.value!
}
);
} catch (e) {
if (getErrorMessage(e).match(/Wrong username or password/i)) {
this.dialog.message = {
text: loc.loginFailed,
level: azdata.window.MessageLevel.Error
};
return false;
} else {
this.dialog.message = {
text: loc.errorVerifyingPassword(e),
level: azdata.window.MessageLevel.Error
};
return false;
}
}
this.completionPromise.resolve({ controllerModel: controllerModel, password: this.passwordInputBox.value });
return true;
}
public override showDialog(controllerInfo?: ControllerInfo): azdata.window.Dialog {
const dialog = super.showDialog(controllerInfo);
dialog.okButton.label = loc.ok;
return dialog;
}
}