Fix #6477 controller login + fix dashboard layout (#6478)

* Fix #6477 controller login + fix dashboard layout
- Service endpoints shoudl be on own column, cut off smaller screen
- Controller login not working due to 404 error
This is due to a breaking API change
We have requested fixes to help mitigate need for cluster name,
but for now have a default value for this

Finally, modified code so it's easier to update swagger API
and also added instructions on how to update in future
This commit is contained in:
Kevin Cunnane
2019-07-23 19:14:18 -07:00
committed by GitHub
parent a92b2e0691
commit a1a67b1a86
9 changed files with 1157 additions and 1186 deletions

View File

@@ -3,10 +3,37 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { EndpointRouterApi } from './apiGenerated';
import * as request from 'request';
import { ClusterRouterApi, Authentication } from './apiGenerated';
class AuthConfiguration implements Authentication {
public username: string = '';
public password: string = '';
constructor(private _ignoreSslVerification: boolean) {
}
applyToRequest(requestOptions: request.Options): void {
requestOptions['agentOptions'] = {
rejectUnauthorized: !this._ignoreSslVerification
};
}
}
class ClusterApiWrapper extends ClusterRouterApi {
constructor(basePathOrUsername: string, password?: string, basePath?: string, ignoreSslVerification?: boolean) {
super(basePathOrUsername, password, basePath);
this.authentications.default = new AuthConfiguration(!!ignoreSslVerification);
}
}
export async function getEndPoints(
url: string, username: string, password: string, ignoreSslVerification?: boolean
clusterName: string,
url: string,
username: string,
password: string,
ignoreSslVerification?: boolean
): Promise<IEndPointsResponse> {
if (!url || !username || !password) {
@@ -14,8 +41,7 @@ export async function getEndPoints(
}
url = adjustUrl(url);
let endPointApi = new EndpointRouterApi(username, password, url);
endPointApi.ignoreSslVerification = !!ignoreSslVerification;
let endPointApi = new ClusterApiWrapper(username, password, url, !!ignoreSslVerification);
let controllerResponse: IEndPointsResponse = undefined;
let controllerError: IControllerError = undefined;
@@ -27,7 +53,7 @@ export async function getEndPoints(
};
try {
let result = await endPointApi.endpointsGet();
let result = await endPointApi.endpointsGet(clusterName);
controllerResponse = <IEndPointsResponse>{
response: result.response as IHttpResponse,
endPoints: result.body as IEndPoint[],

View File

@@ -19,25 +19,27 @@ export class AddControllerDialogModel {
constructor(
public treeDataProvider: ControllerTreeDataProvider,
public node?: TreeNode,
public prefilledClusterName?: string,
public prefilledUrl?: string,
public prefilledUsername?: string,
public prefilledPassword?: string,
public prefilledRememberPassword?: boolean
) {
this.prefilledClusterName = prefilledClusterName || (node && node['clusterName']);
this.prefilledUrl = prefilledUrl || (node && node['url']);
this.prefilledUsername = prefilledUsername || (node && node['username']);
this.prefilledPassword = prefilledPassword || (node && node['password']);
this.prefilledRememberPassword = prefilledRememberPassword || (node && node['rememberPassword']);
}
public async onComplete(url: string, username: string, password: string, rememberPassword: boolean): Promise<void> {
let response = await getEndPoints(url, username, password, true);
public async onComplete(clusterName: string, url: string, username: string, password: string, rememberPassword: boolean): Promise<void> {
let response = await getEndPoints(clusterName, url, username, password, true);
if (response && response.endPoints) {
let masterInstance: IEndPoint = undefined;
if (response.endPoints) {
masterInstance = response.endPoints.find(e => e.name && e.name === 'sql-server-master');
}
this.treeDataProvider.addController(url, username, password, rememberPassword, masterInstance);
this.treeDataProvider.addController(clusterName, url, username, password, rememberPassword, masterInstance);
await this.treeDataProvider.saveControllers();
}
}
@@ -58,6 +60,7 @@ export class AddControllerDialog {
private dialog: azdata.window.Dialog;
private uiModelBuilder: azdata.ModelBuilder;
private clusterNameInputBox: azdata.InputBoxComponent;
private urlInputBox: azdata.InputBoxComponent;
private usernameInputBox: azdata.InputBoxComponent;
private passwordInputBox: azdata.InputBoxComponent;
@@ -76,6 +79,11 @@ export class AddControllerDialog {
this.dialog.registerContent(async view => {
this.uiModelBuilder = view.modelBuilder;
this.clusterNameInputBox = this.uiModelBuilder.inputBox()
.withProperties<azdata.InputBoxProperties>({
placeHolder: localize('textClusterNameLower', 'mssql-cluster'),
value: this.model.prefilledUrl || 'mssql-cluster'
}).component();
this.urlInputBox = this.uiModelBuilder.inputBox()
.withProperties<azdata.InputBoxProperties>({
placeHolder: localize('textUrlLower', 'url'),
@@ -101,22 +109,27 @@ export class AddControllerDialog {
let formModel = this.uiModelBuilder.formContainer()
.withFormItems([{
components: [{
component: this.urlInputBox,
title: localize('textUrlCapital', 'URL'),
required: true
}, {
component: this.usernameInputBox,
title: localize('textUsernameCapital', 'Username'),
required: true
}, {
component: this.passwordInputBox,
title: localize('textPasswordCapital', 'Password'),
required: true
}, {
component: this.rememberPwCheckBox,
title: ''
}
components: [
{
component: this.clusterNameInputBox,
title: localize('textClusterNameCapital', 'Cluster Name'),
required: true
}, {
component: this.urlInputBox,
title: localize('textUrlCapital', 'URL'),
required: true
}, {
component: this.usernameInputBox,
title: localize('textUsernameCapital', 'Username'),
required: true
}, {
component: this.passwordInputBox,
title: localize('textPasswordCapital', 'Password'),
required: true
}, {
component: this.rememberPwCheckBox,
title: ''
}
],
title: ''
}]).withLayout({ width: '100%' }).component();
@@ -131,13 +144,14 @@ export class AddControllerDialog {
}
private async validate(): Promise<boolean> {
let clusterName = this.clusterNameInputBox && this.clusterNameInputBox.value;
let url = this.urlInputBox && this.urlInputBox.value;
let username = this.usernameInputBox && this.usernameInputBox.value;
let password = this.passwordInputBox && this.passwordInputBox.value;
let rememberPassword = this.passwordInputBox && !!this.rememberPwCheckBox.checked;
try {
await this.model.onComplete(url, username, password, rememberPassword);
await this.model.onComplete(clusterName, url, username, password, rememberPassword);
return true;
} catch (error) {
showErrorMessage(error);

View File

@@ -18,6 +18,7 @@ import { LoadingControllerNode } from './loadingControllerNode';
const CredentialNamespace = 'clusterControllerCredentials';
interface IControllerInfoSlim {
clusterName: string;
url: string;
username: string;
password?: string;
@@ -57,6 +58,7 @@ export class ControllerTreeDataProvider implements vscode.TreeDataProvider<TreeN
}
public addController(
clusterName: string,
url: string,
username: string,
password: string,
@@ -64,7 +66,7 @@ export class ControllerTreeDataProvider implements vscode.TreeDataProvider<TreeN
masterInstance?: IEndPoint
): void {
this.removeNonControllerNodes();
this.root.addControllerNode(url, username, password, rememberPassword, masterInstance);
this.root.addControllerNode(clusterName, url, username, password, rememberPassword, masterInstance);
this.notifyNodeChanged();
}
@@ -118,7 +120,7 @@ export class ControllerTreeDataProvider implements vscode.TreeDataProvider<TreeN
password = await this.getPassword(c.url, c.username);
}
this.root.addChild(new ControllerNode(
c.url, c.username, password, c.rememberPassword,
c.clusterName, c.url, c.username, password, c.rememberPassword,
undefined, this.root, this, undefined
));
}
@@ -136,6 +138,7 @@ export class ControllerTreeDataProvider implements vscode.TreeDataProvider<TreeN
let controllers = this.root.children.map(e => {
let controller = e as ControllerNode;
return <IControllerInfoSlim>{
clusterName: controller.clusterName,
url: controller.url,
username: controller.username,
password: controller.password,
@@ -145,6 +148,7 @@ export class ControllerTreeDataProvider implements vscode.TreeDataProvider<TreeN
let controllersWithoutPassword = controllers.map(e => {
return <IControllerInfoSlim>{
clusterName: e.clusterName,
url: e.url,
username: e.username,
rememberPassword: e.rememberPassword

View File

@@ -113,14 +113,20 @@ export class ControllerRootNode extends ControllerTreeNode {
return this.children as ControllerNode[];
}
public addControllerNode(url: string, username: string, password: string, rememberPassword: boolean, masterInstance?: IEndPoint): void {
public addControllerNode(clusterName: string,
url: string,
username: string,
password: string,
rememberPassword: boolean,
masterInstance?: IEndPoint
): void {
let controllerNode = this.getExistingControllerNode(url, username);
if (controllerNode) {
controllerNode.password = password;
controllerNode.rememberPassword = rememberPassword;
controllerNode.clearChildren();
} else {
controllerNode = new ControllerNode(url, username, password, rememberPassword, undefined, this, this.treeChangeHandler, undefined);
controllerNode = new ControllerNode(clusterName, url, username, password, rememberPassword, undefined, this, this.treeChangeHandler, undefined);
this.addChild(controllerNode);
}
@@ -158,6 +164,7 @@ export class ControllerRootNode extends ControllerTreeNode {
export class ControllerNode extends ControllerTreeNode {
constructor(
private _clusterName: string,
private _url: string,
private _username: string,
private _password: string,
@@ -184,7 +191,7 @@ export class ControllerNode extends ControllerTreeNode {
}
try {
let response = await getEndPoints(this._url, this._username, this._password, true);
let response = await getEndPoints(this._clusterName, this._url, this._username, this._password, true);
if (response && response.endPoints) {
let master = response.endPoints.find(e => e.name && e.name === 'sql-server-master');
this.addSqlMasterNode(master.endpoint, master.description);
@@ -226,6 +233,14 @@ export class ControllerNode extends ControllerTreeNode {
return item;
}
public get clusterName() {
return this._clusterName;
}
public set clusterName(clusterName: string) {
this._clusterName = clusterName;
}
public get url() {
return this._url;
}