Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into addressSpaceApps
Browse files Browse the repository at this point in the history
i
  • Loading branch information
jace-roell committed Oct 1, 2024
2 parents 75126e6 + b11995e commit 113a983
Show file tree
Hide file tree
Showing 27 changed files with 1,024 additions and 257 deletions.
6 changes: 6 additions & 0 deletions packages/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

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


## Recent Changes

- Enhancement: Added `--stateful` flag to `zos-tso issue cmd` to allow declaring the statefulness of the address space being created. [#2240](https://github.com/zowe/zowe-cli/pull/2240)
- Enhancement: `--suppress-startup-messages` flag default value changed to `true`. [#2240](https://github.com/zowe/zowe-cli/pull/2240)

## `8.0.0`

- MAJOR: v8.0.0 Release
Expand Down
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -e

# Generate console name: 6 characters + "CN"
CONSOLE_NAME=`cat /dev/urandom | tr -dc '[:upper:]' | fold -w 6 | head -n 1`
CONSOLE_NAME=`cat /dev/urandom | LC_CTYPE=C tr -dc '[:upper:]' | fold -w 6 | head -n 1`
CONSOLE_NAME="${CONSOLE_NAME}CN"

# Ensure that console doesn't exist
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -e

# Generate console name: 6 characters + "CN"
CONSOLE_NAME=`cat /dev/urandom | tr -dc '[:upper:]' | fold -w 6 | head -n 1`
CONSOLE_NAME=`cat /dev/urandom | LC_CTYPE=C tr -dc '[:upper:]' | fold -w 6 | head -n 1`
CONSOLE_NAME="${CONSOLE_NAME}CN"

# Ensure that console doesn't exist
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -e

# Generate console name: 6 characters + "CN"
CONSOLE_NAME=`cat /dev/urandom | tr -dc '[:upper:]' | fold -w 6 | head -n 1`
CONSOLE_NAME=`cat /dev/urandom | LC_CTYPE=C tr -dc '[:upper:]' | fold -w 6 | head -n 1`
CONSOLE_NAME="${CONSOLE_NAME}CN"

# Ensure that console doesn't exist
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -e

# Generate console name: 6 characters + "CN"
CONSOLE_NAME=`cat /dev/urandom | tr -dc '[:upper:]' | fold -w 6 | head -n 1`
CONSOLE_NAME=`cat /dev/urandom | LC_CTYPE=C tr -dc '[:upper:]' | fold -w 6 | head -n 1`
CONSOLE_NAME="${CONSOLE_NAME}CN"

# Ensure that console doesn't exist
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*
*/

/* eslint-disable deprecation/deprecation */
jest.mock("../../../../../../zostso/lib/IssueTso");
import { IssueTso } from "@zowe/zos-tso-for-zowe-sdk";
import { IHandlerParameters, ImperativeError } from "@zowe/imperative";
Expand All @@ -24,7 +25,7 @@ const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({
...UNIT_TEST_TSO_PROF_OPTS
},
positionals: ["zos-tso", "issue", "address-space"],
definition: CommandDefinition
definition: CommandDefinition,
});

describe("issue command handler tests", () => {
Expand All @@ -34,24 +35,24 @@ describe("issue command handler tests", () => {
});

it("should issue command", async () => {
IssueTso.issueTsoCommand = jest.fn((session, acc, cmd, prof) => {
expect(prof).toBeDefined();
expect(prof).toMatchSnapshot();
IssueTso.issueTsoCmd = jest.fn((session, cmd) => {
expect(session).toBeDefined();
expect(session.ISession).toMatchSnapshot();
return StartTsoData.SAMPLE_ISSUE_RESPONSE_WITH_MSG;
});
const handler = new Command.default();
const params = Object.assign({}, ...[DEFAULT_PARAMETERS]);
params.arguments.acc = "acc";
params.arguments.cmd = "time";
await handler.process(params);
expect(IssueTso.issueTsoCommand).toHaveBeenCalledTimes(1);
expect(IssueTso.issueTsoCmd).toHaveBeenCalledTimes(1);
});

it("should be able respond with error message", async () => {
const failMessage = "IZUG1126E: z/OSMF cannot correlate the request for key \"ZOSMFAD-SYS2-55-aaakaaac\"\n" +
"with an active z/OS application session.";
let error;
IssueTso.issueTsoCommand = jest.fn((session, servletKey) => {
IssueTso.issueTsoCmd = jest.fn((session, servletKey) => {
throw new ImperativeError({msg: failMessage});
});
const handler = new Command.default();
Expand All @@ -63,7 +64,7 @@ describe("issue command handler tests", () => {
} catch (thrownError) {
error = thrownError;
}
expect(IssueTso.issueTsoCommand).toHaveBeenCalledTimes(1);
expect(IssueTso.issueTsoCmd).toHaveBeenCalledTimes(1);
expect(error).toBeDefined();
expect(error instanceof ImperativeError).toBe(true);
expect(error.message).toMatchSnapshot();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,20 @@ Object {
"aliases": Array [
"ssm",
],
"defaultValue": true,
"description": "Suppress console messages from start of address space.",
"name": "suppress-startup-messages",
"type": "boolean",
},
Object {
"aliases": Array [
"sf",
],
"defaultValue": false,
"description": "Statefulness of address space created for TSO command. This option is not supported when --suppress-startup-messages is set to false.",
"name": "stateful",
"type": "boolean",
},
Object {
"aliases": Array [
"a",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@ with an active z/OS application session."

exports[`issue command handler tests should issue command 1`] = `
Object {
"account": "fake",
"characterSet": undefined,
"codePage": undefined,
"columns": undefined,
"logonProcedure": undefined,
"regionSize": undefined,
"rows": undefined,
"base64EncodedAuth": "c29tZW9uZTpmYWtl",
"basePath": "",
"hostname": "somewhere.com",
"password": "fake",
"port": "43443",
"protocol": "https",
"rejectUnauthorized": true,
"secureProtocol": "SSLv23_method",
"strictSSL": true,
"type": "basic",
"user": "someone",
}
`;

Expand Down
17 changes: 16 additions & 1 deletion packages/cli/src/zostso/issue/command/Command.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,25 @@ export const CommandDefinition: ICommandDefinition = {
],
options: ([
{
// Old API behavior will be utilized upon specifying --ssm to be false,
// otherwise try new API and if it fails, fallback to old API.

// Specifying --ssm to be false makes the value of --stateful have no impact on
// behavior since old API behavior does not utilize statefulness.
name: "suppress-startup-messages",
aliases: ["ssm"],
type: "boolean",
description: "Suppress console messages from start of address space."
description: "Suppress console messages from start of address space.",
defaultValue: true
},
{
// --stateful has no impact if --suppress-startup-messages is set to false.
name: "stateful",
aliases: ["sf"],
type: "boolean",
description:"Statefulness of address space created for TSO command." +
" This option is not supported when --suppress-startup-messages is set to false.",
defaultValue: false
}
] as ICommandOptionDefinition[]).concat(TsoProfileConstants.TSO_PROFILE_OPTIONS),
examples: [
Expand Down
47 changes: 30 additions & 17 deletions packages/cli/src/zostso/issue/command/Command.handler.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,52 @@
/*
* 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.
*
*/
* 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 { IHandlerParameters } from "@zowe/imperative";
import { IIssueResponse, IssueTso, ZosTsoBaseHandler } from "@zowe/zos-tso-for-zowe-sdk";

import {
IIssueResponse,
IssueTso,
ZosTsoBaseHandler,
} from "@zowe/zos-tso-for-zowe-sdk";
import chalk = require("chalk");
/**
* Handler to issue command to TSO address space
* @export
* @class Handler
* @implements {ICommandHandler}
*/
export default class Handler extends ZosTsoBaseHandler {

// Process the command and produce the TSO response
public async processCmd(params: IHandlerParameters) {

// Issue the TSO command
const response: IIssueResponse = await IssueTso.issueTsoCommand(
const response: IIssueResponse = await IssueTso.issueTsoCmd(
this.mSession,
params.arguments.account,
params.arguments.commandText,
this.mTsoStart);
{
isStateful: params.arguments.stateful,
suppressStartupMessages:
params.arguments.suppressStartupMessages,
addressSpaceOptions: this.mTsoStart
}
);

// If requested, suppress the startup
if (!params.arguments.suppressStartupMessages) {
if (
!params.arguments.suppressStartupMessages &&
response.startResponse != null
) {
this.console.log(response.startResponse.messages);
}
if(response. zosmfResponse?.[0]?.servletKey)
this.console.log(`${chalk.yellow("Servlet Key: ")}${response.zosmfResponse[0].servletKey}`);

this.console.log(response.commandResponse);
// Return as an object when using --response-format-json
this.data.setObj(response);
Expand Down
5 changes: 5 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

- Enhancement: Added the ability to specify a profile with the `zowe config secure` command. This allows the user to prompt for the secure values of the specified profile. [#1890] https://github.com/zowe/zowe-cli/issues/1890

## `8.0.1`

- BugFix: Removed Secrets SDK requirement when Imperative is a bundled dependency. [#2276](https://github.com/zowe/zowe-cli/issues/2276)
Expand All @@ -15,6 +19,7 @@ All notable changes to the Imperative package will be documented in this file.
- Update: Final prerelease
- Update: See `5.27.1` for details


## `8.0.0-next.202408301809`

- LTS Breaking: Removed the following obsolete V1 profile classes/functions:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*/

import { Logger } from "../../../../../logger";
import { Config } from "../../../../../config/src/Config";
import { Config } from "../../../../../config";
import { IConfig, IConfigOpts, IConfigProfile } from "../../../../../config";
import { ImperativeConfig } from "../../../../../utilities";
import { IImperativeConfig } from "../../../../src/doc/IImperativeConfig";
Expand Down Expand Up @@ -760,7 +760,7 @@ describe("Configuration Secure command handler", () => {
expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeProjPath, JSON.stringify(compObj, null, 4)); // Config
});

it("should fail to invoke auth handler if it throws an error", async () => {
it("should only prompt for profiles that matched profile param", async () => {
const eco = lodash.cloneDeep(expectedProjConfigObjectWithToken);

readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco));
Expand Down Expand Up @@ -792,5 +792,112 @@ describe("Configuration Secure command handler", () => {
expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(0);
expect(writeFileSyncSpy).toHaveBeenCalledTimes(0);
});
describe("profile param tests", () => {
let handler: SecureHandler;
let params: any;
let myPromptSpy: jest.SpyInstance;

beforeEach(() => {
handler = new SecureHandler();
params = getIHandlerParametersObject();

params.arguments.userConfig = true;
params.arguments.globalConfig = true;

// Mock the console prompt to return an empty string
myPromptSpy = jest.spyOn(params.response.console, "prompt").mockResolvedValue("");

// Reset spies
keytarGetPasswordSpy.mockReturnValue(fakeSecureData);
keytarSetPasswordSpy.mockImplementation();
keytarDeletePasswordSpy.mockImplementation();
readFileSyncSpy = jest.spyOn(fs, "readFileSync");
writeFileSyncSpy = jest.spyOn(fs, "writeFileSync");
existsSyncSpy = jest.spyOn(fs, "existsSync");
writeFileSyncSpy.mockImplementation();
});

const runTest = async (profile: string, secureFields: string[], expectedPromptTimes: number, expectedSecureField: string) => {
params.arguments.profile = profile;

// Mock fs calls
const eco = lodash.cloneDeep(expectedGlobalUserConfigObject);
eco.$schema = "./fakeapp.schema.json";
readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco));
existsSyncSpy.mockReturnValueOnce(false).mockReturnValueOnce(false).mockReturnValueOnce(true).mockReturnValue(false);
searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath);
await setupConfigToLoad(undefined, configOpts);

// Setup mock secure fields
jest.spyOn(ImperativeConfig.instance.config.api.secure, "secureFields").mockReturnValue(secureFields);

let caughtError;
try {
await handler.process(params);
} catch (error) {
caughtError = error;
}

// Verify prompt count and inclusion of expected secure fields
expect(myPromptSpy).toHaveBeenCalledTimes(expectedPromptTimes);
if (expectedPromptTimes > 0) {
expect(myPromptSpy).toHaveBeenCalledWith(expect.stringContaining(expectedSecureField), { "hideText": true });
}
expect(caughtError).toBeUndefined();
};

it("should only prompt for secure values that match the profile passed in through params", async () => {
await runTest(
"GoodProfile",
[
"profiles.noMatchProfile.properties.tokenValue",
"profiles.GoodProfile.properties.tokenValue",
"profiles.abcdefg.properties.tokenValue"
],
1,
"profiles.GoodProfile.properties.tokenValue"
);
});

it("should only prompt for secure values that match the profile passed in through params - nested profile", async () => {
await runTest(
"lpar1.GoodProfile",
[
"profiles.noMatchProfile.properties.tokenValue",
"profiles.lpar1.profiles.GoodProfile.properties.tokenValue",
"profiles.abcdefg.properties.tokenValue"
],
1,
"profiles.lpar1.profiles.GoodProfile.properties.tokenValue"
);
});

it("should only prompt for secure values that match the profile passed in through params - ignore casing", async () => {
await runTest(
"gOODpROFILE",
[
"profiles.noMatchProfile.properties.tokenValue",
"profiles.GoodProfile.properties.tokenValue",
"profiles.abcdefg.properties.tokenValue"
],
1,
"profiles.GoodProfile.properties.tokenValue"
);
});

it("should prompt for all secure values given a profile in which no secure profile value matches", async () => {
await runTest(
"noMatchProfile",
[
"profiles.lpar1.profiles.test.properties.tokenValue",
"profiles.GoodProfile.properties.tokenValue",
"profiles.abcdefg.properties.tokenValue"
],
3,
"profiles.lpar1.profiles.test.properties.tokenValue"
);
});
});

});
});
Loading

0 comments on commit 113a983

Please sign in to comment.