diff --git a/packages/zowe-explorer-api/CHANGELOG.md b/packages/zowe-explorer-api/CHANGELOG.md index 0eb1e421fc..eeb9c2f192 100644 --- a/packages/zowe-explorer-api/CHANGELOG.md +++ b/packages/zowe-explorer-api/CHANGELOG.md @@ -6,16 +6,15 @@ All notable changes to the "zowe-explorer-api" extension will be documented in t ### New features and enhancements +- - Update Zowe SDKs to `8.8.2` to get the latest enhancements from Imperative. [#3296](https://github.com/zowe/zowe-explorer-vscode/pull/3296) +- Added support for extenders to obtain an updated Session that will includes VS Code proxy settings values if set, `getProfileSessionWithVscProxy`. [#3010](https://github.com/zowe/zowe-explorer-vscode/issues/3010) +- Added support for VS Code proxy settings with zosmf profile types. [#3010](https://github.com/zowe/zowe-explorer-vscode/issues/3010) - Added optional `getLocalStorage` function to the `IApiExplorerExtender` interface to expose local storage access to Zowe Explorer extenders. [#3180](https://github.com/zowe/zowe-explorer-vscode/issues/3180) ### Bug fixes ## `3.0.3` -### New features and enhancements - -- Update Zowe SDKs to `8.8.2` to get the latest enhancements from Imperative. [#3296](https://github.com/zowe/zowe-explorer-vscode/pull/3296) - ### Bug fixes - Fixed an issue to review inconsistent capitalization across translation strings. [#2935](https://github.com/zowe/zowe-explorer-vscode/issues/2935) diff --git a/packages/zowe-explorer-api/__mocks__/vscode.ts b/packages/zowe-explorer-api/__mocks__/vscode.ts index 839decdfa3..532f340e5d 100644 --- a/packages/zowe-explorer-api/__mocks__/vscode.ts +++ b/packages/zowe-explorer-api/__mocks__/vscode.ts @@ -1096,7 +1096,7 @@ export class FileSystemError extends Error { */ export namespace workspace { export const textDocuments: TextDocument[] = []; - export function getConfiguration(_configuration: string): { update: () => void; inspect: () => void } { + export function getConfiguration(_configuration: string) { return { update: () => { return; @@ -1104,6 +1104,7 @@ export namespace workspace { inspect: () => { return {}; }, + get: () => {}, }; } diff --git a/packages/zowe-explorer-api/__tests__/__unit__/profiles/ProfilesCache.unit.test.ts b/packages/zowe-explorer-api/__tests__/__unit__/profiles/ProfilesCache.unit.test.ts index fcb8af9e33..7d69a86871 100644 --- a/packages/zowe-explorer-api/__tests__/__unit__/profiles/ProfilesCache.unit.test.ts +++ b/packages/zowe-explorer-api/__tests__/__unit__/profiles/ProfilesCache.unit.test.ts @@ -15,6 +15,7 @@ import * as imperative from "@zowe/imperative"; import { ProfilesCache } from "../../../src/profiles/ProfilesCache"; import { FileManagement, Types } from "../../../src"; import { mocked } from "../../../__mocks__/mockUtils"; +import { VscSettings } from "../../../src/vscode/doc/VscSettings"; jest.mock("fs"); @@ -544,6 +545,27 @@ describe("ProfilesCache", () => { }); }); + describe("getProfileSessionWithVscProxy", () => { + it("should return same session if no VSC proxy values", () => { + const fakeSession = imperative.Session.createFromUrl(new URL("https://example.com")); + jest.spyOn(VscSettings, "getVsCodeProxySettings").mockReturnValue(undefined as any); + expect(ProfilesCache.getProfileSessionWithVscProxy(fakeSession)).toEqual(fakeSession); + }); + it("should return updated session if VSC proxy values", () => { + const fakeSession = imperative.Session.createFromUrl(new URL("https://example.com")); + const proxyValues = { + http_proxy: "fake.com", + https_proxy: "fake.com", + no_proxy: ["zowe.com"], + proxy_authorization: null, + proxy_strict_ssl: true, + }; + fakeSession.ISession.proxy = proxyValues as any; + jest.spyOn(VscSettings, "getVsCodeProxySettings").mockReturnValue(proxyValues as any); + expect(ProfilesCache.getProfileSessionWithVscProxy(fakeSession)).toEqual(fakeSession); + }); + }); + it("getProfileFromConfig should return profile attributes for given name", async () => { const profCache = new ProfilesCache(fakeLogger as unknown as imperative.Logger); jest.spyOn(profCache, "getProfileInfo").mockResolvedValue(createProfInfoMock([{ name: "lpar1", type: "zosmf" }])); diff --git a/packages/zowe-explorer-api/__tests__/__unit__/profiles/ZoweExplorerZosmfApi.unit.test.ts b/packages/zowe-explorer-api/__tests__/__unit__/profiles/ZoweExplorerZosmfApi.unit.test.ts index 6882b75541..d5850f0904 100644 --- a/packages/zowe-explorer-api/__tests__/__unit__/profiles/ZoweExplorerZosmfApi.unit.test.ts +++ b/packages/zowe-explorer-api/__tests__/__unit__/profiles/ZoweExplorerZosmfApi.unit.test.ts @@ -20,6 +20,7 @@ import * as zosmf from "@zowe/zosmf-for-zowe-sdk"; import { ZoweExplorerZosmf } from "../../../src/profiles/ZoweExplorerZosmfApi"; import { FileManagement } from "../../../src/utils/FileManagement"; import { MainframeInteraction } from "../../../src/extend"; +import { ProfilesCache } from "../../../src/profiles/ProfilesCache"; type ParametersWithProfileArgs = F extends (...args: infer P) => any ? [...Parameters, profileProperties?: object] : never; @@ -104,6 +105,10 @@ describe("ZosmfUssApi", () => { ...fakeProperties, }, } as imperative.IProfileLoaded; + const exampleSession = imperative.Session.createFromUrl(new URL("http://localhost")); + exampleSession.ISession.password = exampleProfile.profile?.password; + exampleSession.ISession.user = exampleProfile.profile?.user; + jest.spyOn(ProfilesCache, "getProfileSessionWithVscProxy").mockReturnValueOnce(exampleSession as any); it("should include profile properties in the built session object", () => { const api = new ZoweExplorerZosmf.UssApi(loadedProfile); @@ -208,161 +213,174 @@ describe("ZosmfUssApi", () => { }); }); - it("uploads a file from buffer", async () => { - const uploadFileSpy = jest.spyOn(zosfiles.Upload, "bufferToUssFile").mockImplementation(); - const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); - const buf = Buffer.from("123abc"); - await zosmfApi.uploadFromBuffer(buf, "/some/uss/path"); - expect(uploadFileSpy).toHaveBeenCalledWith(zosmfApi.getSession(), "/some/uss/path", buf, fakeProperties); - }); - - it("constants should be unchanged", () => { - const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); - expect(zosmfApi.getProfileTypeName()).toMatchSnapshot(); - expect(zosmfApi.getTokenTypeName()).toMatchSnapshot(); - }); - - it("getSessionFromCommandArgument should build session from arguments", () => { - const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); - const session = zosmfApi.getSessionFromCommandArgument(fakeProfile as unknown as imperative.ICommandArguments); - expect(session).toBeDefined(); - const sessCfg: imperative.ISession = { - ...fakeProfile, - hostname: fakeProfile.host, - type: imperative.SessConstants.AUTH_TYPE_BASIC, - }; - delete sessCfg["host"]; - delete sessCfg["responseTimeout"]; - expect(session.ISession).toMatchObject(sessCfg); - }); + describe("misc", () => { + fakeSession.ISession.user = fakeProfile.user; + fakeSession.ISession.password = fakeProfile.password; + fakeSession.ISession.basePath = fakeProfile.basePath; + jest.spyOn(ProfilesCache, "getProfileSessionWithVscProxy").mockReturnValue(fakeSession as any); + + it("uploads a file from buffer", async () => { + const uploadFileSpy = jest.spyOn(zosfiles.Upload, "bufferToUssFile").mockImplementation(); + const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); + const buf = Buffer.from("123abc"); + await zosmfApi.uploadFromBuffer(buf, "/some/uss/path"); + expect(uploadFileSpy).toHaveBeenCalledWith(zosmfApi.getSession(), "/some/uss/path", buf, fakeProperties); + }); - it("getSession should build session from profile with user and password", () => { - const zosmfApi = new ZoweExplorerZosmf.UssApi({ - profile: fakeProfile, - } as unknown as imperative.IProfileLoaded); - const session = zosmfApi.getSession(); - expect(session).toBeDefined(); - const sessCfg: Partial & { hostname: string; type: string } = { - ...fakeProfile, - hostname: fakeProfile.host, - type: imperative.SessConstants.AUTH_TYPE_BASIC, - }; - delete sessCfg.host; - delete sessCfg["responseTimeout"]; - expect(session.ISession).toMatchObject(sessCfg); - }); + it("constants should be unchanged", () => { + const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); + expect(zosmfApi.getProfileTypeName()).toMatchSnapshot(); + expect(zosmfApi.getTokenTypeName()).toMatchSnapshot(); + }); - it("getSession should build session from profile with token", () => { - const fakeProfileWithToken: imperative.IProfile = { - ...fakeProfile, - tokenType: imperative.SessConstants.TOKEN_TYPE_JWT, - tokenValue: "fakeToken", - }; - delete fakeProfileWithToken.user; - delete fakeProfileWithToken.password; - const zosmfApi = new ZoweExplorerZosmf.UssApi({ - profile: fakeProfileWithToken, - } as unknown as imperative.IProfileLoaded); - const session = zosmfApi.getSession(); - expect(session).toBeDefined(); - const sessCfg: Partial & { hostname: string; type: string } = { - ...fakeProfileWithToken, - hostname: fakeProfileWithToken.host, - type: imperative.SessConstants.AUTH_TYPE_TOKEN, - }; - delete sessCfg.host; - delete sessCfg["responseTimeout"]; - expect(session.ISession).toMatchObject(sessCfg); - }); + it("getSessionFromCommandArgument should build session from arguments", () => { + const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); + const session = zosmfApi.getSessionFromCommandArgument(fakeProfile as unknown as imperative.ICommandArguments); + expect(session).toBeDefined(); + const sessCfg: imperative.ISession = { + ...fakeProfile, + hostname: fakeProfile.host, + type: imperative.SessConstants.AUTH_TYPE_BASIC, + }; + delete sessCfg["host"]; + delete sessCfg["responseTimeout"]; + expect(session.ISession).toMatchObject(sessCfg); + }); - it("getSession should log error when it fails", () => { - const zosmfApi = new ZoweExplorerZosmf.UssApi({} as unknown as imperative.IProfileLoaded); - const loggerSpy = jest.spyOn(imperative.Logger.prototype, "error").mockReturnValue(""); - const session = zosmfApi.getSession(); - expect(session).toBeUndefined(); - expect(loggerSpy).toHaveBeenCalledTimes(1); - }); + it("getSession should build session from profile with user and password", () => { + const zosmfApi = new ZoweExplorerZosmf.UssApi({ + profile: fakeProfile, + } as unknown as imperative.IProfileLoaded); + const session = zosmfApi.getSession(); + expect(session).toBeDefined(); + const sessCfg: Partial & { hostname: string; type: string } = { + ...fakeProfile, + hostname: fakeProfile.host, + type: imperative.SessConstants.AUTH_TYPE_BASIC, + }; + delete sessCfg.host; + delete sessCfg["responseTimeout"]; + expect(session.ISession).toMatchObject(sessCfg); + }); - it("getStatus should validate active profile", async () => { - const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); - const checkStatusSpy = jest.spyOn(zosmf.CheckStatus, "getZosmfInfo").mockResolvedValue({}); - const status = await zosmfApi.getStatus({ profile: fakeProfile } as unknown as imperative.IProfileLoaded, "zosmf"); - expect(status).toBe("active"); - expect(checkStatusSpy).toHaveBeenCalledTimes(1); - }); + it("getSession should build session from profile with token", () => { + const fakeProfileWithToken: imperative.IProfile = { + ...fakeProfile, + tokenType: imperative.SessConstants.TOKEN_TYPE_JWT, + tokenValue: "fakeToken", + }; + delete fakeProfileWithToken.user; + delete fakeProfileWithToken.password; + fakeSession.ISession.tokenType = imperative.SessConstants.TOKEN_TYPE_JWT; + fakeSession.ISession.tokenValue = "fakeToken"; + fakeSession.ISession.type = "token"; + delete fakeSession.ISession.user; + delete fakeSession.ISession.password; + const zosmfApi = new ZoweExplorerZosmf.UssApi({ + profile: fakeProfileWithToken, + } as unknown as imperative.IProfileLoaded); + const session = zosmfApi.getSession(); + expect(session).toBeDefined(); + const sessCfg: Partial & { hostname: string; type: string } = { + ...fakeProfileWithToken, + hostname: fakeProfileWithToken.host, + type: imperative.SessConstants.AUTH_TYPE_TOKEN, + }; + delete sessCfg.host; + delete sessCfg["responseTimeout"]; + expect(session.ISession).toMatchObject(sessCfg); + }); - it("getStatus should validate inactive profile", async () => { - const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); - const checkStatusSpy = jest.spyOn(zosmf.CheckStatus, "getZosmfInfo").mockResolvedValue(undefined as unknown as zosmf.IZosmfInfoResponse); - const status = await zosmfApi.getStatus({ profile: fakeProfile } as unknown as imperative.IProfileLoaded, "zosmf"); - expect(status).toBe("inactive"); - expect(checkStatusSpy).toHaveBeenCalledTimes(1); - }); + it("getSession should log error when it fails", () => { + jest.resetAllMocks(); + const zosmfApi = new ZoweExplorerZosmf.UssApi({} as unknown as imperative.IProfileLoaded); + const loggerSpy = jest.spyOn(imperative.Logger.prototype, "error").mockReturnValue(""); + const session = zosmfApi.getSession(); + expect(session).toBeUndefined(); + expect(loggerSpy).toHaveBeenCalledTimes(1); + }); - it("should test that copy calls zowe.Utilities.putUSSPayload", async () => { - const api = new ZoweExplorerZosmf.UssApi(loadedProfile); - api.getSession = jest.fn(); - const response = Buffer.from("hello world!"); + it("getStatus should validate active profile", async () => { + const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); + const checkStatusSpy = jest.spyOn(zosmf.CheckStatus, "getZosmfInfo").mockResolvedValue({}); + const status = await zosmfApi.getStatus({ profile: fakeProfile } as unknown as imperative.IProfileLoaded, "zosmf"); + expect(status).toBe("active"); + expect(checkStatusSpy).toHaveBeenCalledTimes(1); + }); - Object.defineProperty(zosfiles.Utilities, "putUSSPayload", { - value: jest.fn().mockResolvedValue(response), - configurable: true, + it("getStatus should validate inactive profile", async () => { + const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); + const checkStatusSpy = jest.spyOn(zosmf.CheckStatus, "getZosmfInfo").mockResolvedValue(undefined as unknown as zosmf.IZosmfInfoResponse); + const status = await zosmfApi.getStatus({ profile: fakeProfile } as unknown as imperative.IProfileLoaded, "zosmf"); + expect(status).toBe("inactive"); + expect(checkStatusSpy).toHaveBeenCalledTimes(1); }); - await expect(api.copy("/")).resolves.toEqual(response); - }); + it("should test that copy calls zowe.Utilities.putUSSPayload", async () => { + const api = new ZoweExplorerZosmf.UssApi(loadedProfile); + api.getSession = jest.fn(); + const response = Buffer.from("hello world!"); - it("getStatus should validate unverified profile", async () => { - const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); - const status = await zosmfApi.getStatus({ profile: fakeProfile } as unknown as imperative.IProfileLoaded, "sample"); - expect(status).toBe("unverified"); - }); + Object.defineProperty(zosfiles.Utilities, "putUSSPayload", { + value: jest.fn().mockResolvedValue(response), + configurable: true, + }); - it("login and logout should call APIML endpoints", async () => { - const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); - const loginSpy = jest.spyOn(Login, "apimlLogin").mockResolvedValue(""); - const logoutSpy = jest.spyOn(Logout, "apimlLogout").mockResolvedValue(); + await expect(api.copy("/")).resolves.toEqual(response); + }); + + it("getStatus should validate unverified profile", async () => { + const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); + const status = await zosmfApi.getStatus({ profile: fakeProfile } as unknown as imperative.IProfileLoaded, "sample"); + expect(status).toBe("unverified"); + }); - await zosmfApi.login(fakeSession); - expect(loginSpy).toHaveBeenCalledWith(fakeSession); + it("login and logout should call APIML endpoints", async () => { + const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); + const loginSpy = jest.spyOn(Login, "apimlLogin").mockResolvedValue(""); + const logoutSpy = jest.spyOn(Logout, "apimlLogout").mockResolvedValue(); - await zosmfApi.logout(fakeSession); - expect(logoutSpy).toHaveBeenCalledWith(fakeSession); - }); + await zosmfApi.login(fakeSession); + expect(loginSpy).toHaveBeenCalledWith(fakeSession); - it("should retrieve the tag of a file", async () => { - const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); - jest.spyOn(JSON, "parse").mockReturnValue({ - stdout: ["-t UTF-8 tesfile.txt"], + await zosmfApi.logout(fakeSession); + expect(logoutSpy).toHaveBeenCalledWith(fakeSession); }); - Object.defineProperty(zosfiles.Utilities, "putUSSPayload", { - value: () => Buffer.from(""), - configurable: true, + it("should retrieve the tag of a file", async () => { + const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); + jest.spyOn(JSON, "parse").mockReturnValue({ + stdout: ["-t UTF-8 tesfile.txt"], + }); + + Object.defineProperty(zosfiles.Utilities, "putUSSPayload", { + value: () => Buffer.from(""), + configurable: true, + }); + await expect(zosmfApi.getTag("testfile.txt")).resolves.toEqual("UTF-8"); }); - await expect(zosmfApi.getTag("testfile.txt")).resolves.toEqual("UTF-8"); - }); - it("should update the tag attribute when passed in", async () => { - const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); - const changeTagSpy = jest.fn(); - Object.defineProperty(zosfiles.Utilities, "putUSSPayload", { - value: changeTagSpy, - configurable: true, + it("should update the tag attribute when passed in", async () => { + const zosmfApi = new ZoweExplorerZosmf.UssApi(loadedProfile); + const changeTagSpy = jest.fn(); + Object.defineProperty(zosfiles.Utilities, "putUSSPayload", { + value: changeTagSpy, + configurable: true, + }); + await expect(zosmfApi.updateAttributes("/test/path", { tag: "utf-8" })).resolves.not.toThrow(); + expect(changeTagSpy).toHaveBeenCalledTimes(1); }); - await expect(zosmfApi.updateAttributes("/test/path", { tag: "utf-8" })).resolves.not.toThrow(); - expect(changeTagSpy).toHaveBeenCalledTimes(1); - }); - it("calls putUSSPayload to move a directory from old path to new path", async () => { - const api = new ZoweExplorerZosmf.UssApi(loadedProfile); - const putUssPayloadSpy = jest.fn(); - Object.defineProperty(zosfiles.Utilities, "putUSSPayload", { - value: putUssPayloadSpy, - configurable: true, + it("calls putUSSPayload to move a directory from old path to new path", async () => { + const api = new ZoweExplorerZosmf.UssApi(loadedProfile); + const putUssPayloadSpy = jest.fn(); + Object.defineProperty(zosfiles.Utilities, "putUSSPayload", { + value: putUssPayloadSpy, + configurable: true, + }); + await expect(api.move("/old/path", "/new/path")).resolves.not.toThrow(); + expect(putUssPayloadSpy).toHaveBeenCalledWith(api.getSession(), "/new/path", { request: "move", from: "/old/path" }); }); - await expect(api.move("/old/path", "/new/path")).resolves.not.toThrow(); - expect(putUssPayloadSpy).toHaveBeenCalledWith(api.getSession(), "/new/path", { request: "move", from: "/old/path" }); }); const ussApis: ITestApi[] = [ diff --git a/packages/zowe-explorer-api/__tests__/__unit__/profiles/__snapshots__/ZoweExplorerZosmfApi.unit.test.ts.snap b/packages/zowe-explorer-api/__tests__/__unit__/profiles/__snapshots__/ZoweExplorerZosmfApi.unit.test.ts.snap index 54a29025af..ed5e893386 100644 --- a/packages/zowe-explorer-api/__tests__/__unit__/profiles/__snapshots__/ZoweExplorerZosmfApi.unit.test.ts.snap +++ b/packages/zowe-explorer-api/__tests__/__unit__/profiles/__snapshots__/ZoweExplorerZosmfApi.unit.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ZosmfUssApi constants should be unchanged 1`] = `"zosmf"`; +exports[`ZosmfUssApi misc constants should be unchanged 1`] = `"zosmf"`; -exports[`ZosmfUssApi constants should be unchanged 2`] = `"apimlAuthenticationToken"`; +exports[`ZosmfUssApi misc constants should be unchanged 2`] = `"apimlAuthenticationToken"`; diff --git a/packages/zowe-explorer-api/__tests__/__unit__/vscode/doc/VscSettings.unit.test.ts b/packages/zowe-explorer-api/__tests__/__unit__/vscode/doc/VscSettings.unit.test.ts new file mode 100644 index 0000000000..c0d88837f7 --- /dev/null +++ b/packages/zowe-explorer-api/__tests__/__unit__/vscode/doc/VscSettings.unit.test.ts @@ -0,0 +1,57 @@ +/** + * This program and the accompanying materials are made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Copyright Contributors to the Zowe Project. + * + */ + +import * as vscode from "vscode"; +import { VscSettings } from "../../../../src/vscode/doc/VscSettings"; + +function createGlobalMocks() { + const globalMocks = { + vscConfSpy: jest.spyOn(vscode.workspace, "getConfiguration"), + getConfiguration: jest.fn(), + testProxyVars: { + http_proxy: "host.com", + https_proxy: "host.com", + no_proxy: ["fake.com"], + proxy_authorization: null, + proxy_strict_ssl: true, + }, + }; + globalMocks.getConfiguration = jest.fn().mockReturnValue({ + get: jest.fn(), + }); + globalMocks.vscConfSpy.mockImplementation(globalMocks.getConfiguration); + + return globalMocks; +} + +describe("VscSettings", () => { + describe("getVsCodeProxySettings", () => { + beforeEach(() => { + jest.resetAllMocks(); + }); + it("should return undefined with VSC proxy support off", () => { + const globalMocks = createGlobalMocks(); + globalMocks.getConfiguration().get.mockReturnValueOnce("off"); + const response = VscSettings.getVsCodeProxySettings(); + expect(response).not.toBeDefined(); + }); + it("should return undefined with VSC proxy support off", () => { + const globalMocks = createGlobalMocks(); + globalMocks.getConfiguration().get.mockReturnValueOnce("on"); + globalMocks.getConfiguration().get.mockReturnValueOnce("host.com"); + globalMocks.getConfiguration().get.mockReturnValueOnce(["fake.com"]); + globalMocks.getConfiguration().get.mockReturnValueOnce(true); + globalMocks.getConfiguration().get.mockReturnValueOnce(null); + const response = VscSettings.getVsCodeProxySettings(); + expect(response).toEqual(globalMocks.testProxyVars); + }); + }); +}); diff --git a/packages/zowe-explorer-api/src/profiles/ProfilesCache.ts b/packages/zowe-explorer-api/src/profiles/ProfilesCache.ts index f6a933f2b3..1e2099224f 100644 --- a/packages/zowe-explorer-api/src/profiles/ProfilesCache.ts +++ b/packages/zowe-explorer-api/src/profiles/ProfilesCache.ts @@ -17,6 +17,7 @@ import { ZosmfProfile } from "@zowe/zosmf-for-zowe-sdk"; import { ZosTsoProfile } from "@zowe/zos-tso-for-zowe-sdk"; import { ZosUssProfile } from "@zowe/zos-uss-for-zowe-sdk"; import { Types } from "../Types"; +import { VscSettings } from "../vscode/doc/VscSettings"; export class ProfilesCache { public profilesForValidation: Validation.IValidationProfile[] = []; @@ -388,6 +389,12 @@ export class ProfilesCache { return convertResult; } + public static getProfileSessionWithVscProxy(session: imperative.Session): imperative.Session { + const VsCodeProxySettings = VscSettings.getVsCodeProxySettings(); + session.ISession.proxy = VsCodeProxySettings; + return session; + } + protected getCoreProfileTypes(): imperative.IProfileTypeConfiguration[] { return [ZosmfProfile, ZosTsoProfile, ZosUssProfile]; } diff --git a/packages/zowe-explorer-api/src/profiles/ZoweExplorerZosmfApi.ts b/packages/zowe-explorer-api/src/profiles/ZoweExplorerZosmfApi.ts index 340da8f7b4..a1d70f42da 100644 --- a/packages/zowe-explorer-api/src/profiles/ZoweExplorerZosmfApi.ts +++ b/packages/zowe-explorer-api/src/profiles/ZoweExplorerZosmfApi.ts @@ -20,6 +20,7 @@ import * as zosmf from "@zowe/zosmf-for-zowe-sdk"; import { MainframeInteraction } from "../extend/MainframeInteraction"; import { FileManagement } from "../utils"; import { Types } from "../Types"; +import { ProfilesCache } from "../profiles/ProfilesCache"; /** * Implementations of Zowe Explorer API for z/OSMF profiles @@ -44,7 +45,7 @@ export namespace ZoweExplorerZosmf { const sessCfg = zosmf.ZosmfSession.createSessCfgFromArgs(cmdArgs); imperative.ConnectionPropsForSessCfg.resolveSessCfgProps(sessCfg, cmdArgs); const sessionToUse = new imperative.Session(sessCfg); - return sessionToUse; + return ProfilesCache.getProfileSessionWithVscProxy(sessionToUse); } public getSession(profile?: imperative.IProfileLoaded): imperative.Session { @@ -56,7 +57,7 @@ export namespace ZoweExplorerZosmf { imperative.Logger.getAppLogger().error(error as string); } } - return this.session; + return ProfilesCache.getProfileSessionWithVscProxy(this.session); } private _getSession(serviceProfile: imperative.IProfileLoaded): imperative.Session { diff --git a/packages/zowe-explorer-api/src/vscode/ZoweVsCodeExtension.ts b/packages/zowe-explorer-api/src/vscode/ZoweVsCodeExtension.ts index 8b390e98dc..6d39ddd41b 100644 --- a/packages/zowe-explorer-api/src/vscode/ZoweVsCodeExtension.ts +++ b/packages/zowe-explorer-api/src/vscode/ZoweVsCodeExtension.ts @@ -11,13 +11,13 @@ import * as semver from "semver"; import * as vscode from "vscode"; -import { ProfilesCache } from "../profiles"; +import { ProfilesCache } from "../profiles/ProfilesCache"; import { Login, Logout } from "@zowe/core-for-zowe-sdk"; import * as imperative from "@zowe/imperative"; import { Gui } from "../globals/Gui"; import { PromptCredentialsOptions } from "./doc/PromptCredentials"; import { Types } from "../Types"; -import { BaseProfileAuthOptions } from "./doc"; +import { BaseProfileAuthOptions } from "./doc/BaseProfileAuth"; /** * Collection of utility functions for writing Zowe Explorer VS Code extensions. diff --git a/packages/zowe-explorer-api/src/vscode/doc/VscSettings.ts b/packages/zowe-explorer-api/src/vscode/doc/VscSettings.ts new file mode 100644 index 0000000000..e516e7ea1c --- /dev/null +++ b/packages/zowe-explorer-api/src/vscode/doc/VscSettings.ts @@ -0,0 +1,44 @@ +/** + * This program and the accompanying materials are made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Copyright Contributors to the Zowe Project. + * + */ + +import * as vscode from "vscode"; +import * as imperative from "@zowe/imperative"; + +export class VscSettings { + /** + * Retrieves a generic setting either in user or workspace. + * @param {string} key - The config property that needs retrieving + * @param {T} defaultValue - Default value if config property is undefined + */ + public static getDirectValue(key: string, defaultValue?: T): T { + const [first, ...rest] = key.split("."); + return vscode.workspace.getConfiguration(first).get(rest.join("."), defaultValue); + } + + public static getVsCodeProxySettings(): imperative.ProxyVariables { + const proxySupport = this.getDirectValue("http.proxySupport"); + if (proxySupport !== "on") { + return; + } + const http_proxy: string = this.getDirectValue("http.proxy"); + const no_proxy: string[] = this.getDirectValue("http.noProxy"); + const proxy_strict_ssl: boolean = this.getDirectValue("http.proxyStrictSSL"); + const proxy_authorization: string = this.getDirectValue("http.proxyAuthorization"); + + return { + http_proxy, + https_proxy: http_proxy, + no_proxy, + proxy_authorization, + proxy_strict_ssl, + }; + } +} diff --git a/packages/zowe-explorer/CHANGELOG.md b/packages/zowe-explorer/CHANGELOG.md index 50fea1c71e..2cc2dbc2cc 100644 --- a/packages/zowe-explorer/CHANGELOG.md +++ b/packages/zowe-explorer/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen - Added expired JSON web token detection for profiles in each tree view (Data Sets, USS, Jobs). When a user performs a search on a profile, they are prompted to log in if their token expired. [#3175](https://github.com/zowe/zowe-explorer-vscode/issues/3175) - Add a data set or USS resource to a virtual workspace with the new "Add to Workspace" context menu option. [#3265](https://github.com/zowe/zowe-explorer-vscode/issues/3265) - Power users and developers can now build links to efficiently open mainframe resources in Zowe Explorer. Use the **Copy External Link** option in the context menu to get the URL for a data set or USS resource, or create a link in the format `vscode://Zowe.vscode-extension-for-zowe?`. For more information on building resource URIs, see the [FileSystemProvider wiki article](https://github.com/zowe/zowe-explorer-vscode/wiki/FileSystemProvider#file-paths-vs-uris). [#3271](https://github.com/zowe/zowe-explorer-vscode/pull/3271) +- Adopted support for VS Code proxy settings with zosmf profile types. [#3010](https://github.com/zowe/zowe-explorer-vscode/issues/3010) - Implemented more user-friendly error messages for API or network errors within Zowe Explorer. [#3243](https://github.com/zowe/zowe-explorer-vscode/pull/3243) - Use the "Troubleshoot" option for certain errors to obtain additional context, tips, and resources for how to resolve the errors. [#3243](https://github.com/zowe/zowe-explorer-vscode/pull/3243) - Updated Zowe SDKs to `8.8.2` for technical currency. [#3296](https://github.com/zowe/zowe-explorer-vscode/pull/3296) diff --git a/packages/zowe-explorer/__tests__/__unit__/configuration/Profiles.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/configuration/Profiles.unit.test.ts index 8128ac7fd8..d5906d5266 100644 --- a/packages/zowe-explorer/__tests__/__unit__/configuration/Profiles.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/configuration/Profiles.unit.test.ts @@ -27,7 +27,17 @@ import { createMockNode, } from "../../__mocks__/mockCreators/shared"; import { createDatasetSessionNode, createDatasetTree } from "../../__mocks__/mockCreators/datasets"; -import { imperative, Gui, ZoweTreeNode, ZoweVsCodeExtension, IZoweTree, IZoweTreeNode, Validation, FileManagement } from "@zowe/zowe-explorer-api"; +import { + imperative, + Gui, + ZoweTreeNode, + ZoweVsCodeExtension, + IZoweTree, + IZoweTreeNode, + Validation, + FileManagement, + ProfilesCache, +} from "@zowe/zowe-explorer-api"; import { Profiles } from "../../../src/configuration/Profiles"; import { ZoweExplorerExtender } from "../../../src/extending/ZoweExplorerExtender"; import { ZoweExplorerApiRegister } from "../../../src/extending/ZoweExplorerApiRegister"; @@ -194,6 +204,10 @@ function createGlobalMocks(): { [key: string]: any } { }), configurable: true, }); + Object.defineProperty(ProfilesCache, "getProfileSessionWithVscProxy", { + value: jest.fn().mockReturnValue(newMocks.testSession), + configurable: true, + }); newMocks.testUSSTree = createUSSTree(undefined as any, [createUSSNode(newMocks.testSession, newMocks.testProfile)], createTreeView()); diff --git a/packages/zowe-explorer/__tests__/__unit__/extending/ZoweExplorerZosmfApi.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/extending/ZoweExplorerZosmfApi.unit.test.ts index 1f2b445f09..0c13dcad2c 100644 --- a/packages/zowe-explorer/__tests__/__unit__/extending/ZoweExplorerZosmfApi.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/extending/ZoweExplorerZosmfApi.unit.test.ts @@ -10,7 +10,7 @@ */ import * as zosfiles from "@zowe/zos-files-for-zowe-sdk"; -import { imperative, ZoweExplorerZosmf } from "@zowe/zowe-explorer-api"; +import { imperative, ProfilesCache, ZoweExplorerZosmf } from "@zowe/zowe-explorer-api"; export declare enum TaskStage { IN_PROGRESS = 0, @@ -20,6 +20,10 @@ export declare enum TaskStage { } describe("Zosmf API tests", () => { + Object.defineProperty(ProfilesCache, "getProfileSessionWithVscProxy", { + value: jest.fn(), + configurable: true, + }); it("should test that copy data set uses default options", async () => { const dataSet = jest.fn((_session, _toDataSet, options) => { expect(options).toMatchSnapshot(); diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetActions.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetActions.unit.test.ts index 80f222d3ed..2cc7905171 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetActions.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetActions.unit.test.ts @@ -11,7 +11,7 @@ import * as vscode from "vscode"; import * as zosfiles from "@zowe/zos-files-for-zowe-sdk"; -import { Gui, imperative, Validation, Types, ZoweExplorerApiType } from "@zowe/zowe-explorer-api"; +import { Gui, imperative, Validation, Types, ProfilesCache, ZoweExplorerApiType } from "@zowe/zowe-explorer-api"; import { DatasetFSProvider } from "../../../../src/trees/dataset/DatasetFSProvider"; import { bindMvsApi, createMvsApi } from "../../../__mocks__/mockCreators/api"; import { @@ -133,6 +133,7 @@ const createBlockMocksShared = () => { const mvsApi = createMvsApi(imperativeProfile); const fetchDsAtUri = jest.spyOn(DatasetFSProvider.instance, "fetchDatasetAtUri").mockImplementation(); bindMvsApi(mvsApi); + Object.defineProperty(ProfilesCache, "getProfileSessionWithVscProxy", { value: jest.fn().mockReturnValue(zosmfSession), configurable: true }); return { session, diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetTree.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetTree.unit.test.ts index 25585eb78b..225736ef37 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetTree.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetTree.unit.test.ts @@ -172,6 +172,7 @@ function createGlobalMocks() { Object.defineProperty(ZoweLogger, "warn", { value: jest.fn(), configurable: true }); Object.defineProperty(ZoweLogger, "info", { value: jest.fn(), configurable: true }); Object.defineProperty(ZoweLogger, "trace", { value: jest.fn(), configurable: true }); + Object.defineProperty(ProfilesCache, "getProfileSessionWithVscProxy", { value: jest.fn().mockReturnValue(createISession()), configurable: true }); return globalMocks; } diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/job/JobActions.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/job/JobActions.unit.test.ts index 973fd49613..23afc0a0db 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/job/JobActions.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/job/JobActions.unit.test.ts @@ -13,7 +13,7 @@ import * as vscode from "vscode"; import * as zosconsole from "@zowe/zos-console-for-zowe-sdk"; import * as zosjobs from "@zowe/zos-jobs-for-zowe-sdk"; import * as zosmf from "@zowe/zosmf-for-zowe-sdk"; -import { Gui, IZoweJobTreeNode, Sorting, Validation, ZoweScheme } from "@zowe/zowe-explorer-api"; +import { Gui, IZoweJobTreeNode, ProfilesCache, Sorting, Validation, ZoweScheme } from "@zowe/zowe-explorer-api"; import { createISession, createIProfile, @@ -135,6 +135,10 @@ function createGlobalMocks() { value: jest.fn().mockReturnValue([newMocks.imperativeProfile.name]), configurable: true, }); + Object.defineProperty(ProfilesCache, "getProfileSessionWithVscProxy", { + value: jest.fn().mockReturnValue(newMocks.session), + configurable: true, + }); function settingJobObjects( job: zosjobs.IJob, setjobname: string, diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSTree.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSTree.unit.test.ts index ca1003fb21..ca8fa6d6ee 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSTree.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSTree.unit.test.ts @@ -218,6 +218,10 @@ function createGlobalMocks() { value: jest.fn().mockReturnValue(true), configurable: true, }); + Object.defineProperty(ProfilesCache, "getProfileSessionWithVscProxy", { + value: jest.fn().mockReturnValue(globalMocks.testSession), + configurable: true, + }); jest.spyOn(SharedTreeProviders, "providers", "get").mockReturnValue({ ds: { diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/uss/ZoweUSSNode.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/uss/ZoweUSSNode.unit.test.ts index 5a6da76892..10b8c07e78 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/uss/ZoweUSSNode.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/uss/ZoweUSSNode.unit.test.ts @@ -12,7 +12,7 @@ import * as vscode from "vscode"; import * as zosfiles from "@zowe/zos-files-for-zowe-sdk"; import * as zosmf from "@zowe/zosmf-for-zowe-sdk"; -import { Gui, imperative, UssDirectory, UssFile, Validation, ZoweScheme } from "@zowe/zowe-explorer-api"; +import { Gui, imperative, ProfilesCache, UssDirectory, UssFile, Validation, ZoweScheme } from "@zowe/zowe-explorer-api"; import { ZoweExplorerApiRegister } from "../../../../src/extending/ZoweExplorerApiRegister"; import { Profiles } from "../../../../src/configuration/Profiles"; import { ZoweUSSNode } from "../../../../src/trees/uss/ZoweUSSNode"; @@ -167,6 +167,10 @@ function createGlobalMocks() { }, configurable: true, }); + Object.defineProperty(ProfilesCache, "getProfileSessionWithVscProxy", { + value: jest.fn().mockReturnValue(globalMocks.session), + configurable: true, + }); return globalMocks; }