Skip to content

Commit

Permalink
wip: Prompt for creds when opening DS
Browse files Browse the repository at this point in the history
Signed-off-by: Trae Yelovich <trae.yelovich@broadcom.com>
  • Loading branch information
traeok committed Oct 16, 2024
1 parent 5186e84 commit 53e9518
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 46 deletions.
60 changes: 34 additions & 26 deletions packages/zowe-explorer-api/src/utils/ErrorCorrelator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@ export interface ErrorCorrelation {
tips?: string[];
}

interface NetworkErrorInfo extends Omit<ErrorCorrelation, "matches"> {
/**
* The full error details sent by the server.
* @type {string}
*/
fullError?: string;
export interface NetworkErrorProps {
errorCode?: string;
correlation?: ErrorCorrelation;
error?: ImperativeError | string;
}

export interface CorrelateErrorOpts {
profileType?: string;
templateArgs?: Record<string, string>;
}

/**
Expand All @@ -57,8 +60,8 @@ interface NetworkErrorInfo extends Omit<ErrorCorrelation, "matches"> {
* Used to cache the error info such as tips, the match that was encountered and the full error message.
*/
export class NetworkError extends ImperativeError {
public constructor(public info: NetworkErrorInfo) {
super({ msg: info.summary });
public constructor(public properties: NetworkErrorProps) {
super(properties?.error instanceof ImperativeError ? properties.error.mDetails : { msg: properties.error });
}
}

Expand Down Expand Up @@ -204,29 +207,32 @@ export class ErrorCorrelator extends Singleton {
* @param errorDetails The full error details (usually `error.message`)
* @returns A matching `NetworkError`, or a generic `NetworkError` with the full error details as the summary
*/
public correlateError(api: ZoweExplorerApiType, profileType: string, errorDetails: string, templateArgs?: Record<string, string>): NetworkError {
public correlateError(api: ZoweExplorerApiType, error: ImperativeError | string, opts?: CorrelateErrorOpts): NetworkError {
const errorDetails = error instanceof ImperativeError ? error.message : error;
if (!this.errorMatches.has(api)) {
return new NetworkError({ summary: errorDetails });
return new NetworkError({ error });
}

for (const apiError of [
...(this.errorMatches.get(api)?.[profileType] ?? []),
...(opts?.profileType ? this.errorMatches.get(api)?.[opts.profileType] ?? [] : []),
...(this.errorMatches.get(api)?.any ?? []),
...this.errorMatches.get(ZoweExplorerApiType.All).any,
]) {
for (const match of Array.isArray(apiError.matches) ? apiError.matches : [apiError.matches]) {
if (errorDetails.match(match)) {
return new NetworkError({
errorCode: apiError.errorCode,
fullError: errorDetails,
summary: templateArgs ? Mustache.render(apiError.summary, templateArgs) : apiError.summary,
tips: apiError?.tips,
error,
correlation: {
...apiError,
summary: opts?.templateArgs ? Mustache.render(apiError.summary, opts.templateArgs) : apiError.summary,
},
});
}
}
}

return new NetworkError({ summary: errorDetails });
return new NetworkError({ error });
}

/**
Expand All @@ -239,26 +245,29 @@ export class ErrorCorrelator extends Singleton {
* @param allowRetry Whether to allow retrying the action
* @returns The user selection ("Retry" [if enabled] or "Troubleshoot")
*/
public async displayCorrelatedError(error: NetworkError, opts?: { allowRetry?: boolean; stackTrace?: string }): Promise<string | undefined> {
const errorCodeStr = error.info?.errorCode ? `(Error Code ${error.info.errorCode})` : "";
public async displayCorrelatedError(error: NetworkError, opts?: { allowRetry?: boolean }): Promise<string | undefined> {
const errorCodeStr = error.properties.errorCode ? `(Error Code ${error.properties.errorCode})` : "";
const userSelection = await Gui.errorMessage(`${error.mDetails.msg.trim()} ${errorCodeStr}`.trim(), {
items: [opts?.allowRetry ? "Retry" : undefined, "More info"].filter(Boolean),
});

// If the user selected "More info", show the full error details in a dialog,
// containing "Show log" and "Troubleshoot" dialog options
if (userSelection === "More info" && error.info?.fullError) {
const secondDialogSelection = await Gui.errorMessage(error.info.fullError, {
items: ["Show log", "Troubleshoot"],
});
if (userSelection === "More info" && error.properties?.error) {
const secondDialogSelection = await Gui.errorMessage(
error.properties.error instanceof ImperativeError ? error.properties.error.message : error.properties.error,
{
items: ["Show log", "Troubleshoot"],
}
);

switch (secondDialogSelection) {
// Reveal the output channel when the "Show log" option is selected
case "Show log":
return commands.executeCommand("zowe.revealOutputChannel");
// Show the troubleshooting webview when the "Troubleshoot" option is selected
case "Troubleshoot":
return commands.executeCommand("zowe.troubleshootError", error, opts?.stackTrace);
return commands.executeCommand("zowe.troubleshootError", error, error.stack);
default:
return;
}
Expand All @@ -279,11 +288,10 @@ export class ErrorCorrelator extends Singleton {
*/
public async displayError(
api: ZoweExplorerApiType,
profileType: string,
errorDetails: string,
opts?: { allowRetry?: boolean; stackTrace?: string }
errorDetails: string | ImperativeError,
opts?: { allowRetry?: boolean; profileType: string; stackTrace?: string }
): Promise<string | undefined> {
const error = this.correlateError(api, profileType, errorDetails);
const error = this.correlateError(api, errorDetails, { profileType: opts.profileType });
return this.displayCorrelatedError(error, opts);
}
}
29 changes: 20 additions & 9 deletions packages/zowe-explorer/src/trees/dataset/DatasetFSProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { ZoweExplorerApiRegister } from "../../extending/ZoweExplorerApiRegister
import { ZoweLogger } from "../../tools/ZoweLogger";
import * as dayjs from "dayjs";
import { DatasetUtils } from "./DatasetUtils";
import { AuthUtils } from "../../utils/AuthUtils";

export class DatasetFSProvider extends BaseProvider implements vscode.FileSystemProvider {
private static _instance: DatasetFSProvider;
Expand Down Expand Up @@ -338,13 +339,24 @@ export class DatasetFSProvider extends BaseProvider implements vscode.FileSystem
const bufBuilder = new BufferBuilder();
const metadata = file.metadata ?? this._getInfoFromUri(uri);
const profileEncoding = file.encoding ? null : file.metadata.profile.profile?.encoding;
const resp = await ZoweExplorerApiRegister.getMvsApi(metadata.profile).getContents(metadata.dsName, {
binary: file.encoding?.kind === "binary",
encoding: file.encoding?.kind === "other" ? file.encoding.codepage : profileEncoding,
responseTimeout: metadata.profile.profile?.responseTimeout,
returnEtag: true,
stream: bufBuilder,
});

let resp;
try {
resp = await ZoweExplorerApiRegister.getMvsApi(metadata.profile).getContents(metadata.dsName, {
binary: file.encoding?.kind === "binary",
encoding: file.encoding?.kind === "other" ? file.encoding.codepage : profileEncoding,
responseTimeout: metadata.profile.profile?.responseTimeout,
returnEtag: true,
stream: bufBuilder,
});
} catch (err) {
const credsUpdated = await AuthUtils.errorHandling(err, {
profile: metadata.profile
});
if (credsUpdated) {
return this.fetchDatasetAtUri(uri, options);
}
}
const data: Uint8Array = bufBuilder.read() ?? new Uint8Array();

if (options?.isConflict) {
Expand Down Expand Up @@ -447,9 +459,8 @@ export class DatasetFSProvider extends BaseProvider implements vscode.FileSystem
ZoweLogger.error(err.message);
const userSelection = await ErrorCorrelator.getInstance().displayError(
ZoweExplorerApiType.Mvs,
entry.metadata.profile.type,
err.message,
{ allowRetry: true, stackTrace: err.stack }
{ allowRetry: true, profileType: entry.metadata.profile.type, stackTrace: err.stack }
);

switch (userSelection) {
Expand Down
3 changes: 1 addition & 2 deletions packages/zowe-explorer/src/trees/uss/UssFSProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,8 @@ export class UssFSProvider extends BaseProvider implements vscode.FileSystemProv
ZoweLogger.error(err.message);
const userSelection = await ErrorCorrelator.getInstance().displayError(
ZoweExplorerApiType.Uss,
entry.metadata.profile.type,
err.message,
{ allowRetry: true, stackTrace: err.stack }
{ allowRetry: true, profileType: entry.metadata.profile.type, stackTrace: err.stack }
);

switch (userSelection) {
Expand Down
5 changes: 2 additions & 3 deletions packages/zowe-explorer/src/utils/AuthUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,9 @@ export class AuthUtils {
const profile = typeof moreInfo.profile === "string" ? Constants.PROFILES_CACHE.loadNamedProfile(moreInfo.profile) : moreInfo?.profile;
const correlation = ErrorCorrelator.getInstance().correlateError(
moreInfo?.apiType ?? ZoweExplorerApiType.All,
profile?.type,
typeof errorDetails === "string" ? errorDetails : errorDetails.message,
{
profileName: profile?.name,
profileType: profile?.type,
...Object.keys(moreInfo).reduce((all, k) => (typeof moreInfo[k] === "string" ? { ...all, [k]: moreInfo[k] } : all), {}),
}
);
Expand All @@ -108,7 +107,7 @@ export class AuthUtils {
return false;
}

ErrorCorrelator.getInstance().displayCorrelatedError(correlation);
await ErrorCorrelator.getInstance().displayCorrelatedError(correlation);
return false;
}

Expand Down
4 changes: 2 additions & 2 deletions packages/zowe-explorer/src/utils/TroubleshootError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ export class TroubleshootError extends WebView {
case "copy":
await env.clipboard.writeText(
this.errorData.error.stack
? `Error details:\n${this.errorData.error.info.fullError}\nStack trace:\n${this.errorData.error.stack.replace(/(.+?)\n/, "")}`
: `Error details:\n${this.errorData.error.info.fullError}`
? `Error details:\n${this.errorData.error.message}\nStack trace:\n${this.errorData.error.stack.replace(/(.+?)\n/, "")}`
: `Error details:\n${this.errorData.error.message}`
);
break;
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ export const ErrorInfo = ({ error, stackTrace }: ErrorInfoProps) => {
<h2>Error details</h2>
<p>
<span style={{ fontWeight: "bold" }}>Code: </span>
{error.info.errorCode ?? "Not available"}
{error.errorCode ?? "Not available"}
</p>
<p>
<span style={{ fontWeight: "bold" }}>
Description: <br />
</span>
{error.info.summary}
{error.properties.correlation?.summary}
</p>
<details style={{ marginBottom: "0.5rem" }}>
<summary
Expand Down Expand Up @@ -58,14 +58,14 @@ export const ErrorInfo = ({ error, stackTrace }: ErrorInfoProps) => {
</span>
</summary>
<VSCodeTextArea
value={stackTrace ?? error.info.fullError}
value={stackTrace ?? error.message}
resize="vertical"
rows={10}
style={{ height: "fit-content", marginTop: "0.5rem", width: "100%" }}
/>
</details>
<VSCodeDivider />
{error.info.tips ? <TipList tips={error.info.tips} /> : null}
{error.properties.correlation?.tips ? <TipList tips={error.properties.correlation.tips} /> : null}
<VSCodeDivider />
<h2>Additional resources</h2>
<ul>
Expand Down

0 comments on commit 53e9518

Please sign in to comment.