Allow non-admin BDC connections to see BDC features (#12663)

* Add handling for non-admin BDC users

* Bump STS

* Fix HDFS root node commands

* remove nested awaits

* colon
This commit is contained in:
Charles Gagnon
2020-09-29 14:02:01 -07:00
committed by GitHub
parent a2552c1cc1
commit a91b965a33
17 changed files with 230 additions and 151 deletions

View File

@@ -17,6 +17,7 @@ import { TreeNode } from './treeNodes';
import * as utils from '../utils';
import { IFileNode } from './types';
import { MountStatus } from '../hdfs/mount';
import { SqlClusterSession } from './objectExplorerNodeProvider';
export interface ITreeChangeHandler {
notifyNodeChanged(node: TreeNode): void;
@@ -29,8 +30,8 @@ export class TreeDataContext {
}
export abstract class HdfsFileSourceNode extends TreeNode {
constructor(protected context: TreeDataContext, protected _path: string, public readonly fileSource: IFileSource, protected mountStatus?: MountStatus) {
super();
constructor(protected context: TreeDataContext, protected _path: string, fileSource: IFileSource | undefined, protected mountStatus?: MountStatus) {
super(fileSource);
}
public get hdfsPath(): string {
@@ -51,7 +52,8 @@ export abstract class HdfsFileSourceNode extends TreeNode {
}
public async delete(recursive: boolean = false): Promise<void> {
await this.fileSource.delete(this.hdfsPath, recursive);
const fileSource = await this.getFileSource();
await fileSource.delete(this.hdfsPath, recursive);
// Notify parent should be updated. If at top, will return undefined which will refresh whole tree
(<HdfsFileSourceNode>this.parent).onChildRemoved();
this.context.changeHandler.notifyNodeChanged(this.parent);
@@ -60,34 +62,28 @@ export abstract class HdfsFileSourceNode extends TreeNode {
}
export class FolderNode extends HdfsFileSourceNode {
private children: TreeNode[];
private children: TreeNode[] = [];
protected _nodeType: string;
constructor(context: TreeDataContext, path: string, fileSource: IFileSource, nodeType?: string, mountStatus?: MountStatus) {
constructor(context: TreeDataContext, path: string, fileSource: IFileSource | undefined, nodeType?: string, mountStatus?: MountStatus) {
super(context, path, fileSource, mountStatus);
this._nodeType = nodeType ? nodeType : Constants.MssqlClusterItems.Folder;
}
private ensureChildrenExist(): void {
if (!this.children) {
this.children = [];
}
}
public onChildRemoved(): void {
this.children = undefined;
}
async getChildren(refreshChildren: boolean): Promise<TreeNode[]> {
if (refreshChildren || !this.children) {
this.ensureChildrenExist();
try {
let files: IFile[] = await this.fileSource.enumerateFiles(this._path);
const fileSource = await this.getFileSource();
let files: IFile[] = await fileSource.enumerateFiles(this._path);
if (files) {
// Note: for now, assuming HDFS-provided sorting is sufficient
this.children = files.map((file) => {
let node: TreeNode = file.fileType === FileType.File ?
new FileNode(this.context, file.path, this.fileSource, this.getChildMountStatus(file)) :
new FolderNode(this.context, file.path, this.fileSource, Constants.MssqlClusterItems.Folder, this.getChildMountStatus(file));
new FileNode(this.context, file.path, fileSource, this.getChildMountStatus(file)) :
new FolderNode(this.context, file.path, fileSource, Constants.MssqlClusterItems.Folder, this.getChildMountStatus(file));
node.parent = this;
return node;
});
@@ -153,8 +149,9 @@ export class FolderNode extends HdfsFileSourceNode {
}
private async writeFileAsync(localFile: IFile): Promise<FileNode> {
await this.fileSource.writeFile(localFile, this._path);
let fileNode = new FileNode(this.context, File.createPath(this._path, File.getBasename(localFile)), this.fileSource);
const fileSource = await this.getFileSource();
await fileSource.writeFile(localFile, this._path);
let fileNode = new FileNode(this.context, File.createPath(this._path, File.getBasename(localFile)), fileSource);
return fileNode;
}
@@ -163,8 +160,9 @@ export class FolderNode extends HdfsFileSourceNode {
}
private async mkdirAsync(name: string): Promise<FolderNode> {
await this.fileSource.mkdir(name, this._path);
let subDir = new FolderNode(this.context, File.createPath(this._path, name), this.fileSource);
const fileSource = await this.getFileSource();
await fileSource.mkdir(name, this._path);
let subDir = new FolderNode(this.context, File.createPath(this._path, name), fileSource);
return subDir;
}
@@ -186,8 +184,8 @@ export class FolderNode extends HdfsFileSourceNode {
export class ConnectionNode extends FolderNode {
constructor(context: TreeDataContext, private displayName: string, fileSource: IFileSource) {
super(context, '/', fileSource, Constants.MssqlClusterItems.Connection);
constructor(context: TreeDataContext, private displayName: string, private clusterSession: SqlClusterSession) {
super(context, '/', undefined, Constants.MssqlClusterItems.Connection);
}
getDisplayName(): string {
@@ -204,6 +202,16 @@ export class ConnectionNode extends FolderNode {
return item;
}
public async getFileSource(): Promise<IFileSource | undefined> {
// The node is initially created without a filesource and then one is created only once an action is
// taken that requires a connection
const fileSource = await super.getFileSource();
if (!fileSource) {
await this.updateFileSource(await this.clusterSession.getSqlClusterConnection());
}
return super.getFileSource();
}
getNodeInfo(): azdata.NodeInfo {
// TODO handle error message case by returning it in the OE API
// TODO support better mapping of node type
@@ -264,18 +272,21 @@ export class FileNode extends HdfsFileSourceNode implements IFileNode {
}
public async getFileContentsAsString(maxBytes?: number): Promise<string> {
let contents: Buffer = await this.fileSource.readFile(this.hdfsPath, maxBytes);
const fileSource = await this.getFileSource();
let contents: Buffer = await fileSource.readFile(this.hdfsPath, maxBytes);
return contents ? contents.toString('utf8') : '';
}
public async getFileLinesAsString(maxLines: number): Promise<string> {
let contents: Buffer = await this.fileSource.readFileLines(this.hdfsPath, maxLines);
const fileSource = await this.getFileSource();
let contents: Buffer = await fileSource.readFileLines(this.hdfsPath, maxLines);
return contents ? contents.toString('utf8') : '';
}
public writeFileContentsToDisk(localPath: string, cancelToken?: vscode.CancellationTokenSource): Promise<vscode.Uri> {
public async writeFileContentsToDisk(localPath: string, cancelToken?: vscode.CancellationTokenSource): Promise<vscode.Uri> {
const fileSource = await this.getFileSource();
return new Promise((resolve, reject) => {
let readStream: fs.ReadStream = this.fileSource.createReadStream(this.hdfsPath);
let readStream: fs.ReadStream = fileSource.createReadStream(this.hdfsPath);
readStream.on('error', (err) => {
reject(err);
});
@@ -320,7 +331,7 @@ class ErrorNode extends TreeNode {
private _nodePathValue: string;
constructor(private message: string) {
super();
super(undefined);
}
public static create(message: string, parent: TreeNode, errorCode?: number): ErrorNode {