diff --git a/extensions/mssql/src/main.ts b/extensions/mssql/src/main.ts index cfebb419db..67538d2bda 100644 --- a/extensions/mssql/src/main.ts +++ b/extensions/mssql/src/main.ts @@ -107,7 +107,7 @@ export async function activate(context: vscode.ExtensionContext): Promise { this.client.readdir(path, (error, files) => { if (error) { - reject(error.message); + reject(error); } else { let hdfsFiles: IFile[] = files.map(file => { let hdfsFile = file; diff --git a/extensions/mssql/src/objectExplorerNodeProvider/hdfsProvider.ts b/extensions/mssql/src/objectExplorerNodeProvider/hdfsProvider.ts index b4e3dc3037..a4ce114356 100644 --- a/extensions/mssql/src/objectExplorerNodeProvider/hdfsProvider.ts +++ b/extensions/mssql/src/objectExplorerNodeProvider/hdfsProvider.ts @@ -136,7 +136,7 @@ export class FolderNode extends HdfsFileSourceNode { }); } } catch (error) { - this.children = [ErrorNode.create(localize('errorExpanding', 'Error: {0}', utils.getErrorMessage(error)), this)]; + this.children = [ErrorNode.create(localize('errorExpanding', 'Error: {0}', utils.getErrorMessage(error)), this, error.statusCode)]; } } return this.children; @@ -342,9 +342,12 @@ export class ErrorNode extends TreeNode { super(); } - public static create(message: string, parent: TreeNode): ErrorNode { + public static create(message: string, parent: TreeNode, errorCode?: number): ErrorNode { let node = new ErrorNode(message); node.parent = parent; + if(errorCode){ + node.errorStatusCode = errorCode; + } return node; } diff --git a/extensions/mssql/src/objectExplorerNodeProvider/objectExplorerNodeProvider.ts b/extensions/mssql/src/objectExplorerNodeProvider/objectExplorerNodeProvider.ts index b1307f3ed6..730f8f9174 100644 --- a/extensions/mssql/src/objectExplorerNodeProvider/objectExplorerNodeProvider.ts +++ b/extensions/mssql/src/objectExplorerNodeProvider/objectExplorerNodeProvider.ts @@ -20,6 +20,7 @@ import { AppContext } from '../appContext'; import * as constants from '../constants'; import * as SqlClusterLookUp from '../sqlClusterLookUp'; import { ICommandObjectExplorerContext } from './command'; +import { IPrompter, IQuestion, QuestionTypes } from '../prompts/question'; export const mssqlOutputChannel = vscode.window.createOutputChannel(constants.providerId); @@ -28,7 +29,7 @@ export class MssqlObjectExplorerNodeProvider extends ProviderBase implements azd private sessionMap: Map; private expandCompleteEmitter = new vscode.EventEmitter(); - constructor(private appContext: AppContext) { + constructor(private prompter: IPrompter, private appContext: AppContext) { super(); this.sessionMap = new Map(); this.appContext.registerService(constants.ObjectExplorerService, this); @@ -95,6 +96,13 @@ export class MssqlObjectExplorerNodeProvider extends ProviderBase implements azd return true; } + private hasExpansionError(children: TreeNode[]): boolean { + if(children.find(c => c.errorStatusCode > 0)){ + return true; + } + return false; + } + private async startExpansion(session: SqlClusterSession, nodeInfo: azdata.ExpandNodeInfo, isRefresh: boolean = false): Promise { let expandResult: azdata.ObjectExplorerExpandInfo = { sessionId: session.sessionId, @@ -107,16 +115,26 @@ export class MssqlObjectExplorerNodeProvider extends ProviderBase implements azd if (node) { expandResult.errorMessage = node.getNodeInfo().errorMessage; let children = await node.getChildren(true); - if (children) { - expandResult.nodes = children.map(c => c.getNodeInfo()); - // There is only child returned when failure happens - if (children.length === 1) { - let child = children[0].getNodeInfo(); - if (child && child.nodeType === constants.MssqlClusterItems.Error) { - expandResult.errorMessage = child.label; - expandResult.nodes = []; + if (children && children.length > 0) { + // Only child returned when failure happens : When failed with 'Unauthorized' error, prompt for password. + if (children.length === 1 && this.hasExpansionError(children)) { + if (children[0].errorStatusCode === 401) { + //Prompt for password + let password: string = await this.promptPassword(localize('prmptPwd', 'Please provide the password to connect to HDFS:')); + if (password && password.length > 0) { + session.sqlClusterConnection.updatePassword(password); + node.updateFileSource(session.sqlClusterConnection); + children = await node.getChildren(true); + } } } + + expandResult.nodes = children.map(c => c.getNodeInfo()); + if (children.length === 1 && this.hasExpansionError(children)) { + let child = children[0].getNodeInfo(); + expandResult.errorMessage = child ? child.label : 'Unknown Error'; + expandResult.nodes = []; + } } } } catch (error) { @@ -125,6 +143,15 @@ export class MssqlObjectExplorerNodeProvider extends ProviderBase implements azd this.expandCompleteEmitter.fire(expandResult); } + private async promptPassword(promptMsg: string): Promise { + return await this.prompter.promptSingle({ + type: QuestionTypes.password, + name: 'passwordPrompt', + message: promptMsg, + default: '' + }).then(confirmed => confirmed); + } + refreshNode(nodeInfo: azdata.ExpandNodeInfo): Thenable { // TODO #3815 implement properly return this.expandNode(nodeInfo, true); diff --git a/extensions/mssql/src/objectExplorerNodeProvider/treeNodes.ts b/extensions/mssql/src/objectExplorerNodeProvider/treeNodes.ts index eecf411e2c..25d8f55ef3 100644 --- a/extensions/mssql/src/objectExplorerNodeProvider/treeNodes.ts +++ b/extensions/mssql/src/objectExplorerNodeProvider/treeNodes.ts @@ -8,11 +8,15 @@ import * as azdata from 'azdata'; import * as vscode from 'vscode'; import { ITreeNode } from './types'; +import { IFileSource } from './fileSources'; +import { SqlClusterConnection } from './connection'; type TreeNodePredicate = (node: TreeNode) => boolean; export abstract class TreeNode implements ITreeNode { private _parent: TreeNode = undefined; + protected fileSource: IFileSource; + private _errorStatusCode: number; public get parent(): TreeNode { return this._parent; @@ -22,6 +26,14 @@ export abstract class TreeNode implements ITreeNode { this._parent = node; } + public get errorStatusCode(): number { + return this._errorStatusCode; + } + + public set errorStatusCode(error: number) { + this._errorStatusCode = error; + } + public generateNodePath(): string { let path = undefined; if (this.parent) { @@ -66,6 +78,9 @@ export abstract class TreeNode implements ITreeNode { return undefined; } + public updateFileSource(connection: SqlClusterConnection): void{ + this.fileSource = connection.createHdfsFileSource(); + } /** * The value to use for this node in the node path */