Mount HDFS Dialog: basic support (#7580)

Implemented in this PR

- New base dialog for anything needing to work with the controller. This is important since going from SQL -> Controller we "should" have the right permissions but aren't guaranteed
- Support for Mount HDFS via a dialog. Includes basic polling for success/failure, but have to give up after 2.5min as mounting could take hours. By then it's assumed to be successful since server-side has 2min timeout built in.


Not implemented in this PR

- Script as Notebook button. This should convert the inputs to a set of cells in a notebook so users can run things themselves
- Updates based on PM / UX reviews. I think we'll need a round of feedback before completing this work.
This commit is contained in:
Kevin Cunnane
2019-10-11 11:06:40 -07:00
committed by GitHub
parent 9a3f72591e
commit 92e1f83046
9 changed files with 588 additions and 6 deletions

View File

@@ -4,8 +4,9 @@
*--------------------------------------------------------------------------------------------*/
import * as request from 'request';
import { authenticateKerberos, getHostAndPortFromEndpoint } from '../auth';
import { BdcRouterApi, Authentication, EndpointModel, BdcStatusModel } from './apiGenerated';
import { BdcRouterApi, Authentication, EndpointModel, BdcStatusModel, DefaultApi } from './apiGenerated';
import { TokenRouterApi } from './clusterApiGenerated2';
import { AuthType } from '../constants';
import * as nls from 'vscode-nls';
@@ -73,6 +74,16 @@ class BdcApiWrapper extends BdcRouterApi {
this.authentications.default = auth;
}
}
class DefaultApiWrapper extends DefaultApi {
constructor(basePathOrUsername: string, password: string, basePath: string, auth: Authentication) {
if (password) {
super(basePathOrUsername, password, basePath);
} else {
super(basePath, undefined, undefined);
}
this.authentications.default = auth;
}
}
export class ClusterController {
@@ -170,6 +181,39 @@ export class ClusterController {
throw new ControllerError(error, localize('bdc.error.getBdcStatus', "Error retrieving BDC status from {0}", this._url));
}
}
public async mountHdfs(mountPath: string, remoteUri: string, credentials: {}): Promise<MountResponse> {
let auth = await this.authPromise;
const api = new DefaultApiWrapper(this.username, this.password, this._url, auth);
try {
const mountStatus = await api.createMount('', '', remoteUri, mountPath, credentials);
return {
response: mountStatus.response,
status: mountStatus.body
};
} catch (error) {
// TODO handle 401 by reauthenticating
throw new ControllerError(error, localize('bdc.error.mountHdfs', "Error creating mount"));
}
}
public async getMountStatus(mountPath?: string): Promise<MountStatusResponse> {
let auth = await this.authPromise;
const api = new DefaultApiWrapper(this.username, this.password, this._url, auth);
try {
const mountStatus = await api.listMounts('', '', mountPath);
return {
response: mountStatus.response,
mount: mountStatus.body ? JSON.parse(mountStatus.body) : undefined
};
} catch (error) {
// TODO handle 401 by reauthenticating
throw new ControllerError(error, localize('bdc.error.mountHdfs', "Error creating mount"));
}
}
}
/**
* Fixes missing protocol and wrong character for port entered by user
@@ -203,6 +247,28 @@ export interface IBdcStatusResponse {
bdcStatus: BdcStatusModel;
}
export enum MountState {
Creating = 'Creating',
Ready = 'Ready',
Error = 'Error'
}
export interface MountInfo {
mount: string;
remote: string;
state: MountState;
error?: string;
}
export interface MountResponse {
response: IHttpResponse;
status: any;
}
export interface MountStatusResponse {
response: IHttpResponse;
mount: MountInfo[];
}
export interface IHttpResponse {
method?: string;
url?: string;