Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update next with changes from master #2210

Merged
merged 20 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions __tests__/__packages__/cli-test-utils/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

All notable changes to the Zowe CLI test utils package will be documented in this file.

## Recent Changes

- Update: See `7.28.2` for details

## `8.0.0-next.202407021516`

- BugFix: Updated dependencies for technical currency [#2188](https://github.com/zowe/zowe-cli/pull/2188)
Expand All @@ -14,6 +18,10 @@ All notable changes to the Zowe CLI test utils package will be documented in thi

- Major: First major version bump for V3

## `7.28.2`

- BugFix: Improved the error message shown on Windows when `runCliScript` method cannot find `sh` executable on PATH. [#2208](https://github.com/zowe/zowe-cli/issues/2208)

## `7.18.11`

- BugFix: Fix types error from an incorrect jstree type during compilation
Expand Down
13 changes: 9 additions & 4 deletions __tests__/__packages__/cli-test-utils/src/TestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*/

import * as fs from "fs";
import { spawnSync, SpawnSyncReturns } from "child_process";
import { spawnSync, SpawnSyncReturns, ExecFileException } from "child_process";
import { ITestEnvironment } from "./environment/doc/response/ITestEnvironment";
import { CommandProfiles, ICommandDefinition, IHandlerParameters } from "@zowe/imperative";

Expand All @@ -37,11 +37,16 @@ export function runCliScript(scriptPath: string, testEnvironment: ITestEnvironme

if (process.platform === "win32") {
// Execute the command synchronously
return spawnSync("sh", [`${scriptPath}`].concat(args), {
const response = spawnSync("sh", [scriptPath].concat(args), {
cwd: testEnvironment.workingDir,
env: childEnv,
encoding: "buffer"
encoding: "buffer",
env: childEnv
});
if ((response.error as ExecFileException)?.code === "ENOENT") {
throw new Error(`"sh" is missing from your PATH. Check that Git Bash is installed with the option to ` +
`"Use Git and Unix Tools from Windows Command Prompt".`);
}
return response;
}

// Check to see if the file is executable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ function mockConfigApi(properties: IConfig | undefined): any {
},
profiles: {
getProfilePathFromName: (name: string) => `profiles.${name}`,
get: jest.fn().mockReturnValue({})
get: jest.fn().mockReturnValue(properties.profiles.base?.properties)
},
secure: {
securePropsForProfile: jest.fn().mockReturnValue([])
securePropsForProfile: jest.fn().mockReturnValue(properties.profiles.base?.secure)
}
},
exists: true,
Expand Down Expand Up @@ -200,21 +200,97 @@ describe("ApimlAutoInitHandler", () => {
expect(response.profiles[baseProfName].properties.tokenValue).toEqual("fakeToken");
});

it("should not have changed - secure fields with existing non-default base profile", async () => {
// NOTE: Token type and token value will be stored, but user and password will still be present in the base profile
const mockCreateZosmfSession = jest.fn();
const mockGetPluginApimlConfigs = jest.fn().mockReturnValue([]);
const mockGetServicesByConfig = jest.fn().mockResolvedValue([]);
jest.spyOn(ConfigUtils, "getActiveProfileName").mockReturnValueOnce("base");
const mockConfigValue: any = {
defaults: {},
profiles: {
"base": {
properties: {
host: "fake",
port: 12345,
user: "fake",
password: "fake"
},
secure: [
"host",
"user",
"password"
],
profiles: {}
}
},
plugins: []
};
const mockConvertApimlProfileInfoToProfileConfig = jest.fn().mockReturnValue(mockConfigValue);
const mockLogin = jest.fn().mockResolvedValue("fakeToken");
jest.spyOn(ImperativeConfig.instance, "config", "get").mockReturnValue(mockConfigApi(mockConfigValue));

ZosmfSession.createSessCfgFromArgs = mockCreateZosmfSession;
Services.getPluginApimlConfigs = mockGetPluginApimlConfigs;
Services.getServicesByConfig = mockGetServicesByConfig;
Services.convertApimlProfileInfoToProfileConfig = mockConvertApimlProfileInfoToProfileConfig;
Login.apimlLogin = mockLogin;

const handler: any = new ApimlAutoInitHandler();
expect(handler.mProfileType).toBe("base");

handler.createSessCfgFromArgs();
expect(mockCreateZosmfSession).toHaveBeenCalledTimes(1);

const response = await handler.doAutoInit(
{
ISession: {
hostname: "fake",
port: 1234,
user: "fake",
password: "fake",
type: SessConstants.AUTH_TYPE_BASIC,
tokenType: undefined
}
}, {
arguments: {
$0: "fake",
_: ["fake"],
"base-profile": "base"
}
});
expect(mockGetPluginApimlConfigs).toHaveBeenCalledTimes(1);
expect(mockGetServicesByConfig).toHaveBeenCalledTimes(1);
expect(mockConvertApimlProfileInfoToProfileConfig).toHaveBeenCalledTimes(1);
expect(mockLogin).toHaveBeenCalledTimes(1);
expect(response.profiles.base.secure).toEqual(["host", "tokenValue"]);
expect(response.profiles.base.properties.tokenType).toBeDefined();
expect(response.profiles.base.properties.tokenValue).toBeDefined();
expect(response.profiles.base.properties.user).toBeUndefined();
expect(response.profiles.base.properties.password).toBeUndefined();
expect(response.defaults.base).toBe("base");
});

it("should not have changed - user & password with existing base profile", async () => {
// NOTE: Token type and token value will be stored, but user and password will still be present in the base profile
const mockCreateZosmfSession = jest.fn();
const mockGetPluginApimlConfigs = jest.fn().mockReturnValue([]);
const mockGetServicesByConfig = jest.fn().mockResolvedValue([]);
jest.spyOn(ConfigUtils, "getActiveProfileName").mockReturnValueOnce("base");
const mockConfigValue: any = {
defaults: { base: "base"},
defaults: { base: "base" },
profiles: {
"base": {
properties: {
host: "fake",
port: 12345
port: 12345,
user: "fake",
password: "fake"
},
secure: [],
secure: [
"user",
"password"
],
profiles: {}
}
},
Expand Down Expand Up @@ -259,6 +335,9 @@ describe("ApimlAutoInitHandler", () => {
expect(response.profiles.base.secure).toContain("tokenValue");
expect(response.profiles.base.properties.tokenType).toBeDefined();
expect(response.profiles.base.properties.tokenValue).toBeDefined();
expect(response.profiles.base.properties.user).toBeUndefined();
expect(response.profiles.base.properties.password).toBeUndefined();
expect(response.defaults.base).toBe("base");
});

it("should not have changed - rejectUnauthorized flag true", async () => {
Expand Down
8 changes: 8 additions & 0 deletions packages/imperative/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

All notable changes to the Imperative package will be documented in this file.

## Recent Changes

- Update: See `5.26.1` for details

## `8.0.0-next.202407232256`

- Enhancement: Allowed boolean value (`false`) to be provided to the Credential Manager related function. [zowe-explorer-vscode#2622](https://github.com/zowe/zowe-explorer-vscode/issues/2622)
Expand Down Expand Up @@ -422,6 +426,10 @@ All notable changes to the Imperative package will be documented in this file.

- Major: First major version bump for V3

## `5.26.1`

- BugFix: Fixed missing export for `Proxy` class in Imperative package. [#2205](https://github.com/zowe/zowe-cli/pull/2205)

## `5.26.0`

- Enhancement: Updated `ProfileInfo.updateProperty` function to support updating properties in typeless profiles. [#2196](https://github.com/zowe/zowe-cli/issues/2196)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import { ImperativeConfig } from "../../utilities/src/ImperativeConfig";
import { setupConfigToLoad } from "../../../__tests__/src/TestUtil";
import { EnvFileUtils } from "../../utilities";
import { join } from "path";
import { Config } from "../../config";
import { LoggerUtils } from "../../logger/src/LoggerUtils";

jest.mock("../src/syntax/SyntaxValidator");
jest.mock("../src/utils/SharedOptions");
Expand Down Expand Up @@ -1479,7 +1481,7 @@ describe("Command Processor", () => {
rootCommandName: SAMPLE_ROOT_COMMAND,
commandLine: "",
promptPhrase: "dummydummy",
config: ImperativeConfig.instance.config
config: ImperativeConfig.instance.config
});

// Mock the profile loader
Expand All @@ -1506,7 +1508,8 @@ describe("Command Processor", () => {
expect(commandResponse.data.optionalProfiles[0]).toBe(`banana`);
expect(commandResponse.data.requiredProfiles).toBeUndefined();
});
it("should mask input value for a secure parm when --show-inputs-only flag is set", async () => {

it("should mask input value for a default secure parm when --show-inputs-only flag is set", async () => {

// values to test
const secretParmKey = `brownSpots`;
Expand Down Expand Up @@ -1589,7 +1592,7 @@ describe("Command Processor", () => {
rootCommandName: SAMPLE_ROOT_COMMAND,
commandLine: "",
promptPhrase: "dummydummy",
config: ImperativeConfig.instance.config
config: ImperativeConfig.instance.config
});

// Mock the profile loader
Expand Down Expand Up @@ -1619,6 +1622,80 @@ describe("Command Processor", () => {
expect(commandResponse.data.requiredProfiles).toBeUndefined();
});

it.each(LoggerUtils.SECURE_PROMPT_OPTIONS)("should mask input value for secure parm %s when --show-inputs-only flag is set", async (propName) => {

// values to test
const parm1Key = CliUtils.getOptionFormat(propName).kebabCase;
const parm1Value = `secret`;
const secure = `(secure value)`;
jest.spyOn(ImperativeConfig, "instance", "get").mockReturnValue({
config: {
api: {
secure: {
securePropsForProfile: jest.fn(() => [propName])
}
},
layers: [{ exists: true, path: "zowe.config.json" }],
properties: Config.empty()
}
} as any);

// Allocate the command processor
const processor: CommandProcessor = new CommandProcessor({
envVariablePrefix: ENV_VAR_PREFIX,
fullDefinition: SAMPLE_COMPLEX_COMMAND, // `group action`
definition: { // `object`
name: "banana",
description: "The banana command",
type: "command",
handler: __dirname + "/__model__/TestCmdHandler",
options: [
{
name: parm1Key,
type: "string",
description: "The first parameter",
}
],
profile: {
optional: ["fruit"]
}
},
helpGenerator: FAKE_HELP_GENERATOR,
rootCommandName: SAMPLE_ROOT_COMMAND,
commandLine: "",
promptPhrase: "dummydummy",
config: ImperativeConfig.instance.config
});

// Mock the profile loader
(CommandProfileLoader.loader as any) = jest.fn((args) => {
return {
loadProfiles: (profArgs: any) => {
return;
}
};
});

// return the "fake" args object with values from profile
CliUtils.getOptValueFromProfiles = jest.fn((cmdProfiles, profileDef, allOpts) => {
return {};
});

const parms: any = {
arguments: {
_: ["check", "for", "banana"],
$0: "",
[parm1Key]: parm1Value,
valid: true,
showInputsOnly: true,
},
silent: true
};
const commandResponse: ICommandResponse = await processor.invoke(parms);
expect(commandResponse.data.commandValues[parm1Key]).toBe(secure);
expect(commandResponse.stderr.toString()).toContain(`Some inputs are not displayed`);
});

it("should not mask input value for a secure parm when --show-inputs-only flag is set with env setting", async () => {

// values to test
Expand Down
1 change: 1 addition & 0 deletions packages/imperative/src/rest/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export * from "./src/client/doc/IRestClientError";
export * from "./src/client/doc/IRestClientResponse";
export * from "./src/client/doc/IRestOptions";
export * from "./src/client/Headers";
export * from "./src/client/Proxy";
export * from "./src/client/AbstractRestClient";
// export * from "./src/client/CompressionUtils";
export * from "./src/client/RestClient";
Expand Down
Loading