diff --git a/README.md b/README.md index 32abd3e9dc..1cdeba5a02 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,16 @@ Versioning conventions for Zowe CLI and Plug-ins| [Versioning Guidelines](./docs ## **Building Zowe CLI From Source** Zowe CLI requires NPM version 8 and Cargo version 1.72.0 (or newer) to build from source. Before proceeding, check your NPM version with `npm --version` and if it's older than 8.x, update with `npm install -g npm`. To check your version of Cargo, run `cargo --version`. Cargo can be installed using rustup: [https://rustup.rs/](https://rustup.rs/). To update Cargo, run the `rustup update` command. +For developers using Linux, the following packages are required to build Zowe CLI from source: + +- Debian/Ubuntu: + - `sudo apt install build-essential libsecret-1-dev` +- Red Hat-based: + - `sudo dnf group install "Development Tools"` + - `sudo dnf install libsecret-devel` +- Arch Linux: + - `sudo pacman -S base-devel libsecret` + The first time that you download Zowe CLI from the GitHub repository, issue the following command to install the required Zowe CLI dependencies and several development tools: ``` diff --git a/__tests__/__packages__/cli-test-utils/package.json b/__tests__/__packages__/cli-test-utils/package.json index 564ecb1857..b69c7a6c55 100644 --- a/__tests__/__packages__/cli-test-utils/package.json +++ b/__tests__/__packages__/cli-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli-test-utils", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "description": "Test utilities package for Zowe CLI plug-ins", "author": "Zowe", "license": "EPL-2.0", @@ -43,7 +43,7 @@ "devDependencies": { "@types/js-yaml": "^4.0.0", "@types/uuid": "^8.3.0", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/imperative": "^8.0.0-next" diff --git a/jest.config.js b/jest.config.js index 609eccaf7c..cd74c44fab 100644 --- a/jest.config.js +++ b/jest.config.js @@ -150,5 +150,7 @@ module.exports = { "!**/node_modules/**", "!**/lib/**" ], - "maxWorkers": "67%", // You may need to specify maxWorkers if you run out of RAM + // You may need to specify maxWorkers if you run out of RAM + // GHA should use 75% due to high ram, low core count, end user systems ~67% + "maxWorkers": process.env.GITHUB_ACTIONS != null ? "75%" : "67%", } diff --git a/lerna.json b/lerna.json index dee6432a15..044cd0678d 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "command": { "publish": { "ignoreChanges": [ diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index c702113a2d..2e4508fa06 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -51,7 +51,7 @@ }, "__tests__/__packages__/cli-test-utils": { "name": "@zowe/cli-test-utils", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "license": "EPL-2.0", "dependencies": { "find-up": "^5.0.0", @@ -62,7 +62,7 @@ "devDependencies": { "@types/js-yaml": "^4.0.0", "@types/uuid": "^8.3.0", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/imperative": "^8.0.0-next" @@ -7350,8 +7350,6 @@ }, "node_modules/buildcheck": { "version": "0.0.6", - "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz", - "integrity": "sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==", "optional": true, "engines": { "node": ">=10.0.0" @@ -8826,8 +8824,6 @@ }, "node_modules/cpu-features": { "version": "0.0.9", - "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.9.tgz", - "integrity": "sha512-AKjgn2rP2yJyfbepsmLfiYcmtNn/2eUvocUyM/09yB0YDiz39HteK/5/T4Onf0pmdYDMgkBoGvRLvEguzyL7wQ==", "hasInstallScript": true, "optional": true, "dependencies": { @@ -15333,8 +15329,7 @@ }, "node_modules/nan": { "version": "2.18.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", - "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", + "license": "MIT", "optional": true }, "node_modules/nanoid": { @@ -19339,8 +19334,6 @@ }, "node_modules/ssh2": { "version": "1.15.0", - "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.15.0.tgz", - "integrity": "sha512-C0PHgX4h6lBxYx7hcXwu3QWdh4tg6tZZsTfXcdvc5caW/EMxaB4H9dWsl7qk+F7LAW762hp8VbXOX7x4xUYvEw==", "hasInstallScript": true, "dependencies": { "asn1": "^0.2.6", @@ -21291,21 +21284,21 @@ }, "packages/cli": { "name": "@zowe/cli", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "hasInstallScript": true, "license": "EPL-2.0", "dependencies": { - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548", - "@zowe/provisioning-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/zos-console-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/zos-files-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/zos-jobs-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/zos-logs-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/zos-tso-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/zos-uss-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/zos-workflows-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/zosmf-for-zowe-sdk": "8.1.0-next.202401191548", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202", + "@zowe/provisioning-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/zos-console-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/zos-jobs-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/zos-logs-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/zos-tso-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/zos-uss-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/zos-workflows-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/zosmf-for-zowe-sdk": "8.0.0-next.202401162202", "find-process": "1.4.7", "get-stream": "6.0.1", "lodash": "4.17.21", @@ -21319,7 +21312,7 @@ "@types/diff": "^5.0.2", "@types/lodash": "^4.14.175", "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "8.1.0-next.202401191548", + "@zowe/cli-test-utils": "8.0.0-next.202401162202", "comment-json": "^4.1.1", "strip-ansi": "^6.0.1", "which": "^2.0.2" @@ -21328,7 +21321,7 @@ "node": ">=14.0.0" }, "optionalDependencies": { - "@zowe/secrets-for-zowe-sdk": "8.1.0-next.202401191548" + "@zowe/secrets-for-zowe-sdk": "8.0.0-next.202401162202" } }, "packages/cli/node_modules/brace-expansion": { @@ -21350,15 +21343,15 @@ }, "packages/core": { "name": "@zowe/core-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "license": "EPL-2.0", "dependencies": { "comment-json": "^4.1.1", "string-width": "^4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/imperative": "^8.0.0-next" @@ -21366,7 +21359,7 @@ }, "packages/imperative": { "name": "@zowe/imperative", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "license": "EPL-2.0", "dependencies": { "@types/yargs": "^13.0.4", @@ -21422,7 +21415,7 @@ "@types/readline-sync": "^1.4.3", "@types/rimraf": "^3.0.2", "@types/stack-trace": "^0.0.29", - "@zowe/secrets-for-zowe-sdk": "8.1.0-next.202401191548", + "@zowe/secrets-for-zowe-sdk": "8.0.0-next.202401162202", "concurrently": "^7.5.0", "cowsay": "^1.2.1", "deep-diff": "^0.3.8", @@ -21689,16 +21682,16 @@ }, "packages/provisioning": { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "license": "EPL-2.0", "dependencies": { "js-yaml": "^4.1.0" }, "devDependencies": { "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", @@ -21707,7 +21700,7 @@ }, "packages/secrets": { "name": "@zowe/secrets-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "hasInstallScript": true, "license": "EPL-2.0", "devDependencies": { @@ -21720,15 +21713,15 @@ }, "packages/workflows": { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.1.0-next.202401191548" + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202401162202" }, "devDependencies": { - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", @@ -21737,12 +21730,12 @@ }, "packages/zosconsole": { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", @@ -21751,17 +21744,17 @@ }, "packages/zosfiles": { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "license": "EPL-2.0", "dependencies": { "get-stream": "^6.0.1", "minimatch": "^5.0.1" }, "devDependencies": { - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548", - "@zowe/zos-uss-for-zowe-sdk": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202", + "@zowe/zos-uss-for-zowe-sdk": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", @@ -21787,15 +21780,15 @@ }, "packages/zosjobs": { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.1.0-next.202401191548" + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202401162202" }, "devDependencies": { - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", @@ -21804,12 +21797,12 @@ }, "packages/zoslogs": { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", @@ -21818,12 +21811,12 @@ }, "packages/zosmf": { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", @@ -21832,15 +21825,15 @@ }, "packages/zostso": { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "license": "EPL-2.0", "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "8.1.0-next.202401191548" + "@zowe/zosmf-for-zowe-sdk": "8.0.0-next.202401162202" }, "devDependencies": { - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", @@ -21849,15 +21842,15 @@ }, "packages/zosuss": { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "license": "EPL-2.0", "dependencies": { "ssh2": "^1.15.0" }, "devDependencies": { "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/imperative": "^8.0.0-next" diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index cb4258b76d..502906e152 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Zowe CLI package will be documented in this file. -## `8.1.0-next.202401191548` +## Recent Changes - LTS Breaking: Removed all 'profiles' commands, since they only worked with now-obsolete V1 profiles. - BugFix: Properly construct workflow error messages to display properly with V3 error formatting. @@ -15,10 +15,6 @@ All notable changes to the Zowe CLI package will be documented in this file. - Enhancement: Revised help text for consistency [#1756](https://github.com/zowe/zowe-cli/issues/1756) -## `8.0.0-next.202401022112` - -- BugFix: Add missing npm-shrinkwrap - ## `8.0.0-next.202311291643` - LTS Breaking: Replaced the `ZOWE_EDITOR` environment variable with `ZOWE_OPT_EDITOR` and `--editor` option on commands [#1867](https://github.com/zowe/zowe-cli/issues/1867) @@ -36,6 +32,24 @@ All notable changes to the Zowe CLI package will be documented in this file. - Major: First major version bump for V3 +## `7.22.0` + +- Enhancement: Hid the progress bar if `CI` environment variable is set, or if `FORCE_COLOR` environment variable is set to `0`. [#1845](https://github.com/zowe/zowe-cli/issues/1845) + +## `7.21.2` + +- BugFix: Correct extra character being displayed at the end of lines when issuing `zowe files compare` on Windows. [#1992](https://github.com/zowe/zowe-cli/issues/1992) +- BugFix: Correct the online help description for `zowe files compare uss`. [#1754](https://github.com/zowe/zowe-cli/issues/1754) +- BugFix: Fixed typo in command help for `zowe zos-workflows create` commands. + +## `7.20.1` + +- BugFix: Add missing npm-shrinkwrap + +## `7.20.0` + +- Deprecated: `getDataSet` in the `zosfiles` command group utility functions, use `zosfiles` SDK's `ZosFilesUtils.getDataSetFromName` instead. [#1696](https://github.com/zowe/zowe-cli/issues/1696) + ## `7.18.10` - BugFix: Added missing z/OSMF connection options to the z/OS Logs command group. diff --git a/packages/cli/__tests__/auth/__integration__/__snapshots__/cli.auth.apiml.integration.test.ts.snap b/packages/cli/__tests__/auth/__integration__/__snapshots__/cli.auth.apiml.integration.test.ts.snap index adec432955..14dc8baae8 100644 --- a/packages/cli/__tests__/auth/__integration__/__snapshots__/cli.auth.apiml.integration.test.ts.snap +++ b/packages/cli/__tests__/auth/__integration__/__snapshots__/cli.auth.apiml.integration.test.ts.snap @@ -61,7 +61,10 @@ exports[`auth login/logout apiml help should display the login help 1`] = ` --cert-file (local file path) - The file path to a certificate file to use for authentication + The file path to a certificate file to use for authentication. + + Note: The CLI does not support certificate files that require a password. For + more information, search Troubleshooting PEM Certificates in Zowe Docs. --cert-key-file (local file path) @@ -110,9 +113,9 @@ exports[`auth login/logout apiml help should display the login help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: apiml.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n apiml\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Log in to Zowe API Mediation Layer authentication service and obtain or update a\\\\n token.\\\\n\\\\n The token provides authentication to services that support the API ML SSO\\\\n (Single Sign-On) capability. When you log in, the token is stored in your\\\\n default base profile until it expires. Base profiles store connection\\\\n information shared by multiple services (e.g., z/OSMF), and are used if you do\\\\n not supply connection information in a service profile. To take advantage of the\\\\n API ML SSO capability, you should omit username and password in service profiles\\\\n so that the token in the base profile is used.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe auth login apiml [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --show-token | --st (boolean)\\\\n\\\\n Show the token when login is successful. If specified, does not save the token\\\\n to a profile.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n Host name of service on the mainframe.\\\\n\\\\n --port | -P (number)\\\\n\\\\n Port number of service on the mainframe.\\\\n\\\\n --user | -u (string)\\\\n\\\\n User name to authenticate to service on the mainframe.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Password to authenticate to service on the mainframe.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Log in to an API ML instance to obtain or update the token\\\\n stored in your base profile:\\\\n\\\\n $ zowe auth login apiml\\\\n\\\\n - Log in to an API ML instance to obtain a token without\\\\n storing it in a profile:\\\\n\\\\n $ zowe auth login apiml --show-token\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n apiml\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Log in to Zowe API Mediation Layer authentication service and obtain or update a\\\\n token.\\\\n\\\\n The token provides authentication to services that support the API ML SSO\\\\n (Single Sign-On) capability. When you log in, the token is stored in your\\\\n default base profile until it expires. Base profiles store connection\\\\n information shared by multiple services (e.g., z/OSMF), and are used if you do\\\\n not supply connection information in a service profile. To take advantage of the\\\\n API ML SSO capability, you should omit username and password in service profiles\\\\n so that the token in the base profile is used.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe auth login apiml [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --show-token | --st (boolean)\\\\n\\\\n Show the token when login is successful. If specified, does not save the token\\\\n to a profile.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n Host name of service on the mainframe.\\\\n\\\\n --port | -P (number)\\\\n\\\\n Port number of service on the mainframe.\\\\n\\\\n --user | -u (string)\\\\n\\\\n User name to authenticate to service on the mainframe.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Password to authenticate to service on the mainframe.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication.\\\\n\\\\n Note: The CLI does not support certificate files that require a password. For\\\\n more information, search Troubleshooting PEM Certificates in Zowe Docs.\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Log in to an API ML instance to obtain or update the token\\\\n stored in your base profile:\\\\n\\\\n $ zowe auth login apiml\\\\n\\\\n - Log in to an API ML instance to obtain a token without\\\\n storing it in a profile:\\\\n\\\\n $ zowe auth login apiml --show-token\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n apiml\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Log in to Zowe API Mediation Layer authentication service and obtain or update a\\\\n token.\\\\n\\\\n The token provides authentication to services that support the API ML SSO\\\\n (Single Sign-On) capability. When you log in, the token is stored in your\\\\n default base profile until it expires. Base profiles store connection\\\\n information shared by multiple services (e.g., z/OSMF), and are used if you do\\\\n not supply connection information in a service profile. To take advantage of the\\\\n API ML SSO capability, you should omit username and password in service profiles\\\\n so that the token in the base profile is used.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe auth login apiml [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --show-token | --st (boolean)\\\\n\\\\n Show the token when login is successful. If specified, does not save the token\\\\n to a profile.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n Host name of service on the mainframe.\\\\n\\\\n --port | -P (number)\\\\n\\\\n Port number of service on the mainframe.\\\\n\\\\n --user | -u (string)\\\\n\\\\n User name to authenticate to service on the mainframe.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Password to authenticate to service on the mainframe.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Log in to an API ML instance to obtain or update the token\\\\n stored in your base profile:\\\\n\\\\n $ zowe auth login apiml\\\\n\\\\n - Log in to an API ML instance to obtain a token without\\\\n storing it in a profile:\\\\n\\\\n $ zowe auth login apiml --show-token\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n apiml\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Log in to Zowe API Mediation Layer authentication service and obtain or update a\\\\n token.\\\\n\\\\n The token provides authentication to services that support the API ML SSO\\\\n (Single Sign-On) capability. When you log in, the token is stored in your\\\\n default base profile until it expires. Base profiles store connection\\\\n information shared by multiple services (e.g., z/OSMF), and are used if you do\\\\n not supply connection information in a service profile. To take advantage of the\\\\n API ML SSO capability, you should omit username and password in service profiles\\\\n so that the token in the base profile is used.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe auth login apiml [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --show-token | --st (boolean)\\\\n\\\\n Show the token when login is successful. If specified, does not save the token\\\\n to a profile.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n Host name of service on the mainframe.\\\\n\\\\n --port | -P (number)\\\\n\\\\n Port number of service on the mainframe.\\\\n\\\\n --user | -u (string)\\\\n\\\\n User name to authenticate to service on the mainframe.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Password to authenticate to service on the mainframe.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication.\\\\n\\\\n Note: The CLI does not support certificate files that require a password. For\\\\n more information, search Troubleshooting PEM Certificates in Zowe Docs.\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Log in to an API ML instance to obtain or update the token\\\\n stored in your base profile:\\\\n\\\\n $ zowe auth login apiml\\\\n\\\\n - Log in to an API ML instance to obtain a token without\\\\n storing it in a profile:\\\\n\\\\n $ zowe auth login apiml --show-token\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__unit__/compare/ds/Dataset.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/compare/ds/Dataset.handler.unit.test.ts index fbaef2113f..74d90159a8 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/compare/ds/Dataset.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/compare/ds/Dataset.handler.unit.test.ts @@ -178,6 +178,38 @@ describe("Compare data set handler", () => { expect(getDiffStringSpy).toHaveBeenCalledWith("compared", "compared", options); }); + it("should compare two data sets containing carriage returns in terminal with --seqnum specified", async () => { + const processArgCopy: any = { + ...processArguments, + arguments:{ + ...processArguments.arguments, + seqnum: false, + } + }; + + //overwrite ds(strings 1 & 2) to include seqnums to chop off in LocalFileDatasetHandler + getDataSetSpy.mockImplementation(jest.fn(async (session) => { + fakeSession = session; + return Buffer.from("compared12345678\r\n"); + })); + + try { + // Invoke the handler with a full set of mocked arguments and response functions + await handler.process(processArgCopy); + } catch (e) { + error = e; + } + + expect(error).toBeUndefined(); + expect(getDataSetSpy).toHaveBeenCalledTimes(2); + expect(getDiffStringSpy).toHaveBeenCalledTimes(1); + expect(apiMessage).toEqual(""); + expect(logMessage).toEqual("compared string"); + expect(getDataSetSpy).toHaveBeenCalledWith(fakeSession as any, dataSetName1, { task: dsTask }); + expect(jsonObj).toMatchObject({commandResponse: "compared string", success: true}); + expect(getDiffStringSpy).toHaveBeenCalledWith("compared\n", "compared\n", options); + }); + it("should compare two data sets in browser", async () => { openDiffInbrowserSpy.mockImplementation(jest.fn()); processArguments.arguments.browserView = true ; diff --git a/packages/cli/__tests__/zosuss/__integration__/issue/__snapshots__/cli.zos-uss.issue.ssh.integration.test.ts.snap b/packages/cli/__tests__/zosuss/__integration__/issue/__snapshots__/cli.zos-uss.issue.ssh.integration.test.ts.snap index 42bd40b90b..26bc94f6ef 100644 --- a/packages/cli/__tests__/zosuss/__integration__/issue/__snapshots__/cli.zos-uss.issue.ssh.integration.test.ts.snap +++ b/packages/cli/__tests__/zosuss/__integration__/issue/__snapshots__/cli.zos-uss.issue.ssh.integration.test.ts.snap @@ -100,7 +100,10 @@ exports[`zos-uss issue ssh command should display the help 1`] = ` --cert-file (local file path) - The file path to a certificate file to use for authentication + The file path to a certificate file to use for authentication. + + Note: The CLI does not support certificate files that require a password. For + more information, search Troubleshooting PEM Certificates in Zowe Docs. --cert-key-file (local file path) @@ -136,8 +139,8 @@ exports[`zos-uss issue ssh command should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: command.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n command | cmd | ssh\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Issue a z/OS USS command\\\\n\\\\n Note: The common CLI 'Base Connection Options' of token-type and token-value are\\\\n not applicable to the ssh command, since the ssh service is not accessible\\\\n through APIML.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-ssh issue command [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n command\\\\t\\\\t (string)\\\\n\\\\n z/OS USS command to issue.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --cwd (string)\\\\n\\\\n Working directory in which to execute the command.\\\\n\\\\n Z/OS SSH CONNECTION OPTIONS\\\\n ---------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OS SSH server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OS SSH server port.\\\\n\\\\n Default value: 22\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe password, which can be the same as your TSO password.\\\\n\\\\n --privateKey | --key | --pk (string)\\\\n\\\\n Path to a file containing your private key, that must match a public key stored\\\\n in the server for authentication\\\\n\\\\n --keyPassphrase | --passphrase | --kp (string)\\\\n\\\\n Private key passphrase, which unlocks the private key.\\\\n\\\\n --handshakeTimeout | --timeout | --to (number)\\\\n\\\\n How long in milliseconds to wait for the SSH handshake to complete.\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --ssh-profile | --ssh-p (string)\\\\n\\\\n The name of a (ssh) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Issue a simple command, giving the working directory:\\\\n\\\\n $ zowe zos-ssh issue command \\\\\\"npm install express\\\\\\" --cwd /u/cicprov/mnt/CICPY01I/bundles/myapp \\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n command | cmd | ssh\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Issue a z/OS USS command\\\\n\\\\n Note: The common CLI 'Base Connection Options' of token-type and token-value are\\\\n not applicable to the ssh command, since the ssh service is not accessible\\\\n through APIML.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-ssh issue command [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n command\\\\t\\\\t (string)\\\\n\\\\n z/OS USS command to issue.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --cwd (string)\\\\n\\\\n Working directory in which to execute the command.\\\\n\\\\n Z/OS SSH CONNECTION OPTIONS\\\\n ---------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OS SSH server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OS SSH server port.\\\\n\\\\n Default value: 22\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe password, which can be the same as your TSO password.\\\\n\\\\n --privateKey | --key | --pk (string)\\\\n\\\\n Path to a file containing your private key, that must match a public key stored\\\\n in the server for authentication\\\\n\\\\n --keyPassphrase | --passphrase | --kp (string)\\\\n\\\\n Private key passphrase, which unlocks the private key.\\\\n\\\\n --handshakeTimeout | --timeout | --to (number)\\\\n\\\\n How long in milliseconds to wait for the SSH handshake to complete.\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --ssh-profile | --ssh-p (string)\\\\n\\\\n The name of a (ssh) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication.\\\\n\\\\n Note: The CLI does not support certificate files that require a password. For\\\\n more information, search Troubleshooting PEM Certificates in Zowe Docs.\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Issue a simple command, giving the working directory:\\\\n\\\\n $ zowe zos-ssh issue command \\\\\\"npm install express\\\\\\" --cwd /u/cicprov/mnt/CICPY01I/bundles/myapp \\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n command | cmd | ssh\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Issue a z/OS USS command\\\\n\\\\n Note: The common CLI 'Base Connection Options' of token-type and token-value are\\\\n not applicable to the ssh command, since the ssh service is not accessible\\\\n through APIML.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-ssh issue command [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n command\\\\t\\\\t (string)\\\\n\\\\n z/OS USS command to issue.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --cwd (string)\\\\n\\\\n Working directory in which to execute the command.\\\\n\\\\n Z/OS SSH CONNECTION OPTIONS\\\\n ---------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OS SSH server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OS SSH server port.\\\\n\\\\n Default value: 22\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe password, which can be the same as your TSO password.\\\\n\\\\n --privateKey | --key | --pk (string)\\\\n\\\\n Path to a file containing your private key, that must match a public key stored\\\\n in the server for authentication\\\\n\\\\n --keyPassphrase | --passphrase | --kp (string)\\\\n\\\\n Private key passphrase, which unlocks the private key.\\\\n\\\\n --handshakeTimeout | --timeout | --to (number)\\\\n\\\\n How long in milliseconds to wait for the SSH handshake to complete.\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --ssh-profile | --ssh-p (string)\\\\n\\\\n The name of a (ssh) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Issue a simple command, giving the working directory:\\\\n\\\\n $ zowe zos-ssh issue command \\\\\\"npm install express\\\\\\" --cwd /u/cicprov/mnt/CICPY01I/bundles/myapp \\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n command | cmd | ssh\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Issue a z/OS USS command\\\\n\\\\n Note: The common CLI 'Base Connection Options' of token-type and token-value are\\\\n not applicable to the ssh command, since the ssh service is not accessible\\\\n through APIML.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-ssh issue command [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n command\\\\t\\\\t (string)\\\\n\\\\n z/OS USS command to issue.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --cwd (string)\\\\n\\\\n Working directory in which to execute the command.\\\\n\\\\n Z/OS SSH CONNECTION OPTIONS\\\\n ---------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OS SSH server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OS SSH server port.\\\\n\\\\n Default value: 22\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe password, which can be the same as your TSO password.\\\\n\\\\n --privateKey | --key | --pk (string)\\\\n\\\\n Path to a file containing your private key, that must match a public key stored\\\\n in the server for authentication\\\\n\\\\n --keyPassphrase | --passphrase | --kp (string)\\\\n\\\\n Private key passphrase, which unlocks the private key.\\\\n\\\\n --handshakeTimeout | --timeout | --to (number)\\\\n\\\\n How long in milliseconds to wait for the SSH handshake to complete.\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --ssh-profile | --ssh-p (string)\\\\n\\\\n The name of a (ssh) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication.\\\\n\\\\n Note: The CLI does not support certificate files that require a password. For\\\\n more information, search Troubleshooting PEM Certificates in Zowe Docs.\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Issue a simple command, giving the working directory:\\\\n\\\\n $ zowe zos-ssh issue command \\\\\\"npm install express\\\\\\" --cwd /u/cicprov/mnt/CICPY01I/bundles/myapp \\\\n\\\\n\\" }" `; diff --git a/packages/cli/package.json b/packages/cli/package.json index 5bc9d8180f..842da65ed6 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "description": "Zowe CLI is a command line interface (CLI) that provides a simple and streamlined way to interact with IBM z/OS.", "author": "Zowe", "license": "EPL-2.0", @@ -57,17 +57,17 @@ "preshrinkwrap": "node ../../scripts/rewriteShrinkwrap.js" }, "dependencies": { - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548", - "@zowe/provisioning-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/zos-console-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/zos-files-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/zos-jobs-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/zos-logs-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/zos-tso-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/zos-uss-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/zos-workflows-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/zosmf-for-zowe-sdk": "8.1.0-next.202401191548", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202", + "@zowe/provisioning-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/zos-console-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/zos-jobs-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/zos-logs-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/zos-tso-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/zos-uss-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/zos-workflows-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/zosmf-for-zowe-sdk": "8.0.0-next.202401162202", "find-process": "1.4.7", "get-stream": "6.0.1", "lodash": "4.17.21", @@ -78,13 +78,13 @@ "@types/diff": "^5.0.2", "@types/lodash": "^4.14.175", "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "8.1.0-next.202401191548", + "@zowe/cli-test-utils": "8.0.0-next.202401162202", "comment-json": "^4.1.1", "strip-ansi": "^6.0.1", "which": "^2.0.2" }, "optionalDependencies": { - "@zowe/secrets-for-zowe-sdk": "8.1.0-next.202401191548" + "@zowe/secrets-for-zowe-sdk": "8.0.0-next.202401162202" }, "engines": { "node": ">=14.0.0" diff --git a/packages/cli/src/zosfiles/compare/CompareBaseHelper.ts b/packages/cli/src/zosfiles/compare/CompareBaseHelper.ts index 379654cb59..be2ef09872 100644 --- a/packages/cli/src/zosfiles/compare/CompareBaseHelper.ts +++ b/packages/cli/src/zosfiles/compare/CompareBaseHelper.ts @@ -164,7 +164,11 @@ export class CompareBaseHelper { public prepareContent(content: string | Buffer): string { let contentString = content.toString(); if(this.seqnum === false) { - const seqnumlen = 8; + let seqnumlen = 8; + /* If Windows format file, account for the carriage return */ + if(content.toString().endsWith("\r\n")){ + seqnumlen++; + } contentString = content.toString().split("\n").map((line) => line.slice(0, -seqnumlen)).join("\n"); } return contentString; diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 8b0c5cf277..146ba9a0ca 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Zowe core SDK package will be documented in this file. -## `8.1.0-next.202401191548` +## Recent Changes - LTS Breaking: Removed all 'profiles' commands, since they only worked with now-obsolete V1 profiles. - BugFix: Include text from a REST response's causeErrors.message property in error messages. @@ -15,6 +15,10 @@ All notable changes to the Zowe core SDK package will be documented in this file - Major: First major version bump for V3 +## `7.21.2` + +- BugFix: Add information about password-protected certificate file support. [#2006](https://github.com/zowe/zowe-cli/issues/2006) + ## `7.18.0` - Enhancement: Added support for dynamic APIML tokens. [#1734](https://github.com/zowe/zowe-cli/pull/1734) diff --git a/packages/core/package.json b/packages/core/package.json index a5e388f512..4ca44dff3f 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/core-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "description": "Core libraries shared by Zowe SDK packages", "author": "Zowe", "license": "EPL-2.0", @@ -49,8 +49,8 @@ "string-width": "^4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/imperative": "^8.0.0-next" diff --git a/packages/core/src/constants/Core.constants.ts b/packages/core/src/constants/Core.constants.ts index e48ea39ecb..17b427dcdf 100644 --- a/packages/core/src/constants/Core.constants.ts +++ b/packages/core/src/constants/Core.constants.ts @@ -102,7 +102,9 @@ export class ProfileConstants { */ public static readonly BASE_OPTION_CERT_FILE: ICommandOptionDefinition = { name: "cert-file", - description: "The file path to a certificate file to use for authentication", + description: "The file path to a certificate file to use for authentication.\n\nNote: " + + "The CLI does not support certificate files that require a password. " + + "For more information, search Troubleshooting PEM Certificates in Zowe Docs.", type: "existingLocalFile", group: ProfileConstants.BASE_CONNECTION_OPTION_GROUP }; diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index 281ac6f442..373afd5630 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Imperative package will be documented in this file. -## `8.1.0-next.202401191548` +## Recent Changes - LTS Breaking: Removed the following: - All 'profiles' commands, since they only worked with now-obsolete V1 profiles. @@ -50,6 +50,19 @@ All notable changes to the Imperative package will be documented in this file. - Major: First major version bump for V3 +## `5.21.0` + +- Enhancement: Hid the progress bar if `CI` environment variable is set, or if `FORCE_COLOR` environment variable is set to `0`. [#1845](https://github.com/zowe/zowe-cli/issues/1845) +- BugFix: Fixed issue where secure property names could be returned for the wrong profile. [zowe-explorer#2633](https://github.com/zowe/vscode-extension-for-zowe/issues/2633) + +## `5.20.2` + +- BugFix: Fixed issue when a property is not found in `ProfileInfo.updateProperty({forceUpdate: true})`. [zowe-explorer#2493](https://github.com/zowe/vscode-extension-for-zowe/issues/2493) + +## `5.20.1` + +- BugFix: Fixed error message shown for null option definition to include details about which command caused the error. [#2002](https://github.com/zowe/zowe-cli/issues/2002) + ## `5.19.0` - Enhancement: Deprecated function AbstractCommandYargs.getBrightYargsResponse in favor of AbstractCommandYargs.getZoweYargsResponse @@ -383,6 +396,10 @@ that would be used if a command were executed. - BugFix: Fixed incorrect description for untyped profiles in team config files. [zowe/zowe-cli#1303](https://github.com/zowe/zowe-cli/issues/1303) - **Next Breaking**: Schema files created or updated with the above changes are not backward compatible with older versions of Imperative. +## `5.20.0` + +- Enhancement: Added the ability to `forceUpdate` a property using the `ProfileInfo.updateProperty` method. [zowe-explorer#2493](https://github.com/zowe/vscode-extension-for-zowe/issues/2493) + ## `5.0.0-next.202203222132` - BugFix: Reverted unintentional breaking change that prevented `DefaultCredentialManager` from finding Keytar outside of calling CLI's node_modules folder. diff --git a/packages/imperative/package.json b/packages/imperative/package.json index 9df72bf96f..c4cc6b0c6e 100644 --- a/packages/imperative/package.json +++ b/packages/imperative/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/imperative", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "description": "framework for building configurable CLIs", "author": "Zowe", "license": "EPL-2.0", @@ -96,7 +96,7 @@ "@types/readline-sync": "^1.4.3", "@types/rimraf": "^3.0.2", "@types/stack-trace": "^0.0.29", - "@zowe/secrets-for-zowe-sdk": "8.1.0-next.202401191548", + "@zowe/secrets-for-zowe-sdk": "8.0.0-next.202401162202", "concurrently": "^7.5.0", "cowsay": "^1.2.1", "deep-diff": "^0.3.8", diff --git a/packages/imperative/src/cmd/__tests__/response/CommandResponse.unit.test.ts b/packages/imperative/src/cmd/__tests__/response/CommandResponse.unit.test.ts index 02f0af5fd0..001d0861ed 100644 --- a/packages/imperative/src/cmd/__tests__/response/CommandResponse.unit.test.ts +++ b/packages/imperative/src/cmd/__tests__/response/CommandResponse.unit.test.ts @@ -18,7 +18,7 @@ import { inspect } from "util"; import { TestLogger } from "../../../../__tests__/src/TestLogger"; import { IO } from "../../../io"; import { OUTPUT_FORMAT } from "../.."; -import { CliUtils, IDaemonResponse } from "../../../utilities"; +import { CliUtils, IDaemonResponse, TextUtils } from "../../../utilities"; const beforeForceColor = process.env.FORCE_COLOR; @@ -88,6 +88,9 @@ chalk.red = jest.fn((str: string) => { const ORIGINAL_STDOUT_WRITE = process.stdout.write; const ORIGINAL_STDERR_WRITE = process.stderr.write; +let originalCI: any; +let originalForceColor: any; + describe("Command Response", () => { beforeEach(() => { @@ -107,17 +110,29 @@ describe("Command Response", () => { beforeAll(() => { IO.createDirsSyncFromFilePath(testFile); stream = require("fs").createWriteStream(testFile); + originalCI = process.env.CI; + originalForceColor = process.env.FORCE_COLOR; + delete process.env.CI; + delete process.env.FORCE_COLOR; }); afterAll(() => { if (stream != null) { stream.end(); } require("rimraf").sync(testFile); + process.env.CI = originalCI; + process.env.FORCE_COLOR = originalForceColor; + }); + afterEach(() => { + delete process.env.FORCE_COLOR; + delete process.env.CI; + jest.restoreAllMocks(); }); it("If we create a progress bar, an interval should be set to update the bar. " + "If we finish the bar, the interval should be stopped and no longer stored" + "in the command response. ", (done) => { // eslint-disable-line jest/no-done-callback + process.env.FORCE_COLOR = "1"; const response = new CommandResponse({ silent: false, responseFormat: "default" }); const status: ITaskWithStatus = { statusMessage: "Making a bar", @@ -147,6 +162,7 @@ describe("Command Response", () => { }); it("should allow the progress bar to write directly to a socket stream", (done) => { // eslint-disable-line jest/no-done-callback + process.env.FORCE_COLOR = "1"; const response = new CommandResponse({ silent: false, responseFormat: "default", stream }); const status: ITaskWithStatus = { statusMessage: "Making a bar", @@ -180,6 +196,7 @@ describe("Command Response", () => { it("If we create a progress bar, then set the bar to be complete, " + "the progress bar should automatically end ", (done) => { // eslint-disable-line jest/no-done-callback + process.env.FORCE_COLOR = "1"; const response = new CommandResponse({ silent: false, responseFormat: "default" }); const status: ITaskWithStatus = { statusMessage: "Making a bar", @@ -215,6 +232,7 @@ describe("Command Response", () => { it("If our response object is in silent mode, which is caused for example by " + "the user specifying that they want a JSON response, a progress bar should" + " not be created", () => { + process.env.FORCE_COLOR = "1"; const response = new CommandResponse({ silent: true, responseFormat: "json" }); const status: ITaskWithStatus = { statusMessage: "No bar should be made", @@ -233,6 +251,7 @@ describe("Command Response", () => { it("should not duplicate output when calling endBar", () => { + process.env.FORCE_COLOR = "1"; let stdoutMsg: string = ""; let stderrMsg: string = ""; const response = new CommandResponse({responseFormat: "default"}); @@ -271,6 +290,43 @@ describe("Command Response", () => { expect(response.buildJsonResponse().stderr.toString()).toEqual(beforeMessage + "\n" + duringMessage + "\n" + afterMessage + "\n"); }); + it("should not show a progress bar if FORCE_COLOR is set to 0", () => { + process.env.FORCE_COLOR = "0"; + const response = new CommandResponse({ silent: false, responseFormat: "default", stream }); + const status: ITaskWithStatus = { + statusMessage: "Making a bar", + percentComplete: 10, + stageName: TaskStage.IN_PROGRESS + }; + response.progress.startBar( + { + task: status, + stream + }); + expect((response as any).mProgressBar).not.toBeDefined(); // access private fields + expect((response.progress as any).mProgressBarInterval).not.toBeDefined(); + }); + + it("should not show a progress bar if CI is set", () => { + process.env.CI = "true"; + jest.spyOn(TextUtils, "chalk").mockImplementation(() => { + return {level: 1, enabled: true}; + }); + const response = new CommandResponse({ silent: false, responseFormat: "default", stream }); + const status: ITaskWithStatus = { + statusMessage: "Making a bar", + percentComplete: 10, + stageName: TaskStage.IN_PROGRESS + }; + response.progress.startBar( + { + task: status, + stream + }); + expect((response as any).mProgressBar).not.toBeDefined(); // access private fields + expect((response.progress as any).mProgressBarInterval).not.toBeDefined(); + }); + it("should allow us to create an instance", () => { let caughtError; try { diff --git a/packages/imperative/src/cmd/src/CommandProcessor.ts b/packages/imperative/src/cmd/src/CommandProcessor.ts index 9a0166f37e..c546049eb8 100644 --- a/packages/imperative/src/cmd/src/CommandProcessor.ts +++ b/packages/imperative/src/cmd/src/CommandProcessor.ts @@ -43,7 +43,7 @@ import { CliUtils } from "../../utilities/src/CliUtils"; import { WebHelpManager } from "./help/WebHelpManager"; import { ICommandProfile } from "./doc/profiles/definition/ICommandProfile"; import { Config } from "../../config/src/Config"; -import { getActiveProfileName } from "../../config/src/ConfigUtils"; +import { ConfigUtils } from "../../config/src/ConfigUtils"; import { ConfigConstants } from "../../config/src/ConfigConstants"; import { IDaemonContext } from "../../imperative/src/doc/IDaemonContext"; import { IHandlerResponseApi } from "../.."; @@ -820,7 +820,7 @@ export class CommandProcessor { const combinedProfiles = [ ...showInputsOnly.requiredProfiles ?? [], ...showInputsOnly.optionalProfiles ?? [] ]; combinedProfiles.forEach((profile) => { - const name = getActiveProfileName(profile, commandParameters.arguments); // get profile name + const name = ConfigUtils.getActiveProfileName(profile, commandParameters.arguments); // get profile name const props = this.mConfig.api.secure.securePropsForProfile(name); // get secure props configSecureProps.push(...props); // add to list }); diff --git a/packages/imperative/src/cmd/src/response/CommandResponse.ts b/packages/imperative/src/cmd/src/response/CommandResponse.ts index 7351f925fb..2c25263ec6 100644 --- a/packages/imperative/src/cmd/src/response/CommandResponse.ts +++ b/packages/imperative/src/cmd/src/response/CommandResponse.ts @@ -724,7 +724,8 @@ export class CommandResponse implements ICommandResponseApi { `Please call progress.endBar() before starting a new one.` }); } - if (!outer.silent && outer.mResponseFormat !== "json") { + if (!outer.silent && outer.mResponseFormat !== "json" && + !(TextUtils.chalk.level === 0 || !TextUtils.chalk.enabled || process.env.CI != null)) { // Persist the task specifications and determine the stream to use for the progress bar this.mProgressBarStdoutStartIndex = outer.mStdout.length; diff --git a/packages/imperative/src/config/__tests__/Config.secure.unit.test.ts b/packages/imperative/src/config/__tests__/Config.secure.unit.test.ts index 44500f6737..b189683cf7 100644 --- a/packages/imperative/src/config/__tests__/Config.secure.unit.test.ts +++ b/packages/imperative/src/config/__tests__/Config.secure.unit.test.ts @@ -161,7 +161,10 @@ describe("Config secure tests", () => { .mockReturnValueOnce(false); // Global layer jest.spyOn(fs, "readFileSync"); const config = await Config.load(MY_APP); - expect(config.api.secure.secureFields()).toEqual(["profiles.fruit.properties.secret"]); + expect(config.api.secure.secureFields()).toEqual([ + "profiles.fruit.properties.secret", + "profiles.fruit.profiles.grape.properties.secret2" + ]); }); it("should list all secure fields for a profile", async () => { @@ -176,6 +179,19 @@ describe("Config secure tests", () => { expect(config.api.secure.securePropsForProfile("fruit.apple")).toEqual(["secret"]); }); + it("should not list secure fields for a profile with partial name match", async () => { + jest.spyOn(Config, "search").mockReturnValue(projectConfigPath); + jest.spyOn(fs, "existsSync") + .mockReturnValueOnce(false) // Project user layer + .mockReturnValueOnce(true) // Project layer + .mockReturnValueOnce(false) // User layer + .mockReturnValueOnce(false); // Global layer + jest.spyOn(fs, "readFileSync"); + const config = await Config.load(MY_APP); + expect(config.api.secure.securePropsForProfile("fruit.grape")).toEqual(["secret", "secret2"]); + expect(config.api.secure.securePropsForProfile("fruit.grapefruit")).toEqual(["secret"]); + }); + describe("secureInfoForProp", () => { const configProperties: IConfig = { profiles: { diff --git a/packages/imperative/src/config/__tests__/ConfigUtils.unit.test.ts b/packages/imperative/src/config/__tests__/ConfigUtils.unit.test.ts index c909303d13..7a7abae614 100644 --- a/packages/imperative/src/config/__tests__/ConfigUtils.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ConfigUtils.unit.test.ts @@ -9,7 +9,7 @@ * */ -import * as ConfigUtils from "../../config/src/ConfigUtils"; +import { ConfigUtils } from "../../config/src/ConfigUtils"; import { CredentialManagerFactory } from "../../security"; import { ImperativeConfig } from "../../utilities"; diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index 1042b5a537..44a4374eb0 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -25,6 +25,8 @@ import { AbstractSession, SessConstants } from "../../rest"; import { ConfigAutoStore } from "../src/ConfigAutoStore"; import { ImperativeConfig } from "../../utilities/src/ImperativeConfig"; import { ImperativeError } from "../../error"; +import { IProfInfoUpdatePropOpts } from "../src/doc/IProfInfoUpdatePropOpts"; +import { ConfigUtils } from "../src/ConfigUtils"; const testAppNm = "ProfInfoApp"; const testEnvPrefix = testAppNm.toUpperCase(); @@ -1009,6 +1011,63 @@ describe("TeamConfig ProfileInfo tests", () => { expect(updateKnownPropertySpy).toHaveBeenCalledWith({ ...profileOptions, mergedArgs: {}, osLocInfo: undefined }); }); + it("should succeed forceUpdating a property even if the jsonLoc points somewhere else", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk(); + const mergedArgs = { + knownArgs: [{ + argName: "rejectUnauthorized", + argLoc: { jsonLoc: "profiles.base_glob.properties.rejectUnauthorized" } + }] + }; + jest.spyOn(profInfo as any, "mergeArgsForProfile").mockReturnValue(mergedArgs); + const updateKnownPropertySpy = jest.spyOn(profInfo as any, "updateKnownProperty").mockResolvedValue(true); + const jsonPathMatchesSpy = jest.spyOn(ConfigUtils, "jsonPathMatches"); + const profileOptions: IProfInfoUpdatePropOpts = { + profileName: "LPAR4", + profileType: "dummy", + property: "rejectUnauthorized", + value: true, + forceUpdate: true + }; + let caughtError; + try { + await profInfo.updateProperty(profileOptions); + } catch (error) { + caughtError = error; + } + expect(caughtError).toBeUndefined(); + expect(mergedArgs.knownArgs[0].argLoc.jsonLoc).toEqual("profiles.LPAR4.properties.rejectUnauthorized"); + const osLocInfo = { global: false, user: false, name: "LPAR4", path: path.join(teamProjDir, `${testAppNm}.config.json`) }; + expect(updateKnownPropertySpy).toHaveBeenCalledWith({ ...profileOptions, mergedArgs, osLocInfo }); + expect(jsonPathMatchesSpy).toHaveBeenCalledTimes(1); // Verify that profile names are matched correctly + }); + + it("should succeed forceUpdating a property even if the property doesn't exist", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk(); + const storeSpy = jest.spyOn(ConfigAutoStore, "_storeSessCfgProps").mockImplementation(jest.fn()); + const profileOptions: IProfInfoUpdatePropOpts = { + profileName: "LPAR4", + profileType: "dummy", + property: "DOES_NOT_EXIST", + value: true, + forceUpdate: true + }; + let caughtError; + try { + await profInfo.updateProperty(profileOptions); + } catch (error) { + caughtError = error; + } + expect(caughtError).toBeUndefined(); + expect(storeSpy).toHaveBeenCalledWith({ + config: profInfo.getTeamConfig(), profileName: "LPAR4", profileType: "dummy", + defaultBaseProfileName: "base_glob", + propsToStore: [ "DOES_NOT_EXIST" ], sessCfg: { "DOES_NOT_EXIST": true }, setSecure : undefined, + }); + }); + it("should attempt to store session config properties without adding profile types to the loadedConfig", async () => { const profInfo = createNewProfInfo(teamProjDir); await profInfo.readProfilesFromDisk(); @@ -1105,6 +1164,7 @@ describe("TeamConfig ProfileInfo tests", () => { it("should update the given property and return true", async () => { const profInfo = createNewProfInfo(teamProjDir); await profInfo.readProfilesFromDisk(); + const jsonPathMatchesSpy = jest.spyOn(ConfigUtils, "jsonPathMatches"); const prof = profInfo.mergeArgsForProfile(profInfo.getAllProfiles("dummy")[0]); const ret = await profInfo.updateKnownProperty({ mergedArgs: prof, property: "host", value: "example.com" }); @@ -1112,6 +1172,7 @@ describe("TeamConfig ProfileInfo tests", () => { expect(newHost).toEqual("example.com"); expect(ret).toBe(true); + expect(jsonPathMatchesSpy).toHaveBeenCalled(); // Verify that profile names are matched correctly }); it("should remove the given property if the value specified if undefined", async () => { @@ -1153,11 +1214,11 @@ describe("TeamConfig ProfileInfo tests", () => { await profInfo.readProfilesFromDisk(); const prof = profInfo.mergeArgsForProfile(profInfo.getAllProfiles("dummy")[0]); - await profInfo.updateProperty({profileName: 'LPAR4', property: "someProperty", value: "example.com", profileType: "dummy"}); + await profInfo.updateProperty({ profileName: 'LPAR4', property: "someProperty", value: "example.com", profileType: "dummy" }); const afterUpdate = profInfo.mergeArgsForProfile(profInfo.getAllProfiles("dummy")[0]); expect(afterUpdate.knownArgs.find(v => v.argName === 'someProperty')?.argValue).toBe('example.com'); - await profInfo.removeKnownProperty({mergedArgs: afterUpdate, property: 'someProperty'}); + await profInfo.removeKnownProperty({ mergedArgs: afterUpdate, property: 'someProperty' }); const afterRemove = profInfo.mergeArgsForProfile(profInfo.getAllProfiles("dummy")[0]); expect(afterRemove.knownArgs.find(v => v.argName === 'someProperty')).toBeUndefined(); diff --git a/packages/imperative/src/config/__tests__/__resources__/project.config.json b/packages/imperative/src/config/__tests__/__resources__/project.config.json index 5a69cd0ddf..c2a1b3be7f 100644 --- a/packages/imperative/src/config/__tests__/__resources__/project.config.json +++ b/packages/imperative/src/config/__tests__/__resources__/project.config.json @@ -16,6 +16,21 @@ "properties": { "color": "orange" } + }, + "grape": { + "type": "fruit", + "properties": { + "color": "red" + }, + "secure": [ + "secret2" + ] + }, + "grapefruit": { + "type": "fruit", + "properties": { + "color": "pink" + } } }, "secure": [ diff --git a/packages/imperative/src/config/__tests__/__snapshots__/Config.unit.test.ts.snap b/packages/imperative/src/config/__tests__/__snapshots__/Config.unit.test.ts.snap index 5c9a0e7e47..eca30feba2 100644 --- a/packages/imperative/src/config/__tests__/__snapshots__/Config.unit.test.ts.snap +++ b/packages/imperative/src/config/__tests__/__snapshots__/Config.unit.test.ts.snap @@ -67,6 +67,21 @@ Object { }, "type": "fruit", }, + "grape": Object { + "properties": Object { + "color": "red", + }, + "secure": Array [ + "secret2", + ], + "type": "fruit", + }, + "grapefruit": Object { + "properties": Object { + "color": "pink", + }, + "type": "fruit", + }, "orange": Object { "properties": Object { "color": "orange", @@ -183,6 +198,21 @@ Object { }, "type": "fruit", }, + "grape": Object { + "properties": Object { + "color": "red", + }, + "secure": Array [ + "secret2", + ], + "type": "fruit", + }, + "grapefruit": Object { + "properties": Object { + "color": "pink", + }, + "type": "fruit", + }, "orange": Object { "properties": Object { "color": "orange", diff --git a/packages/imperative/src/config/index.ts b/packages/imperative/src/config/index.ts index da606bb9d4..0a02bfc2b3 100644 --- a/packages/imperative/src/config/index.ts +++ b/packages/imperative/src/config/index.ts @@ -14,7 +14,7 @@ export * from "./src/ConfigAutoStore"; export * from "./src/ConfigConstants"; export * from "./src/ConfigSchema"; export * from "./src/ConfigBuilder"; -export * as ConfigUtils from "./src/ConfigUtils"; +export * from "./src/ConfigUtils"; export * from "./src/ProfileCredentials"; export * from "./src/ProfileInfo"; export * from "./src/ProfInfoErr"; diff --git a/packages/imperative/src/config/src/Config.ts b/packages/imperative/src/config/src/Config.ts index 18db6e345e..7f9a211590 100644 --- a/packages/imperative/src/config/src/Config.ts +++ b/packages/imperative/src/config/src/Config.ts @@ -27,7 +27,7 @@ import { IConfigOpts } from "./doc/IConfigOpts"; import { IConfigSecure } from "./doc/IConfigSecure"; import { IConfigVault } from "./doc/IConfigVault"; import { ConfigLayers, ConfigPlugins, ConfigProfiles, ConfigSecure } from "./api"; -import { coercePropValue } from "./ConfigUtils"; +import { ConfigUtils } from "./ConfigUtils"; import { IConfigSchemaInfo } from "./doc/IConfigSchema"; import { JsUtils } from "../../utilities/src/JsUtils"; import { IConfigMergeOpts } from "./doc/IConfigMergeOpts"; @@ -443,7 +443,7 @@ export class Config { obj = obj[segment]; } else if (segments.indexOf(segment) === segments.length - 1) { if (opts?.parseString) { - value = coercePropValue(value); + value = ConfigUtils.coercePropValue(value); } if (opts?.parseString && Array.isArray(obj[segment])) { diff --git a/packages/imperative/src/config/src/ConfigAutoStore.ts b/packages/imperative/src/config/src/ConfigAutoStore.ts index a36a921fe1..7c6fae155a 100644 --- a/packages/imperative/src/config/src/ConfigAutoStore.ts +++ b/packages/imperative/src/config/src/ConfigAutoStore.ts @@ -13,7 +13,7 @@ import * as lodash from "lodash"; import { ICommandArguments, IHandlerParameters } from "../../cmd"; import { ICommandHandlerRequire } from "../../cmd/src/doc/handler/ICommandHandlerRequire"; import { ICommandProfileAuthConfig } from "../../cmd/src/doc/profiles/definition/ICommandProfileAuthConfig"; -import * as ConfigUtils from "./ConfigUtils"; +import { ConfigUtils } from "./ConfigUtils"; import { AbstractAuthHandler } from "../../imperative/src/auth/handlers/AbstractAuthHandler"; import { ImperativeConfig } from "../../utilities"; import { ISession } from "../../rest/src/session/doc/ISession"; diff --git a/packages/imperative/src/config/src/ConfigUtils.ts b/packages/imperative/src/config/src/ConfigUtils.ts index 48c95465e1..6a1540fe7a 100644 --- a/packages/imperative/src/config/src/ConfigUtils.ts +++ b/packages/imperative/src/config/src/ConfigUtils.ts @@ -14,59 +14,70 @@ import { ICommandArguments } from "../../cmd"; import { ImperativeConfig } from "../../utilities"; import { ImperativeError } from "../../error"; -/** - * Coeerces string property value to a boolean or number type. - * @param value String value - * @param type Property type defined in the schema - * @returns Boolean, number, or string - */ -export function coercePropValue(value: any, type?: string) { - if (type === "boolean" || type === "number") { - // For boolean or number, parse the string and throw on failure - return JSON.parse(value); - } else if (type == null) { - // For unknown type, try to parse the string and ignore failure - try { +export class ConfigUtils { + /** + * Coeerces string property value to a boolean or number type. + * @param value String value + * @param type Property type defined in the schema + * @returns Boolean, number, or string + */ + public static coercePropValue(value: any, type?: string) { + if (type === "boolean" || type === "number") { + // For boolean or number, parse the string and throw on failure return JSON.parse(value); - } catch { - return value; + } else if (type == null) { + // For unknown type, try to parse the string and ignore failure + try { + return JSON.parse(value); + } catch { + return value; + } + } else { + // For string or other type, don't do any parsing + return value.toString(); } - } else { - // For string or other type, don't do any parsing - return value.toString(); } -} -/** - * Retrieves the name of the active profile for the given type. If no such - * profile exists, returns the default name which can be used to create a new profile. - * @param profileType The type of CLI profile - * @param cmdArguments CLI arguments which may specify a profile - * @param defaultProfileName Name to fall back to if profile doesn't exist. If - * not specified, the profile type will be used. - * @returns The profile name - */ -export function getActiveProfileName(profileType: string, cmdArguments?: ICommandArguments, defaultProfileName?: string): string { - // Look for profile name first in command line arguments, second in - // default profiles defined in config, and finally fall back to using - // the profile type as the profile name. - return cmdArguments?.[`${profileType}-profile`] || - ImperativeConfig.instance.config?.properties.defaults[profileType] || - defaultProfileName || profileType; -} + /** + * Retrieves the name of the active profile for the given type. If no such + * profile exists, returns the default name which can be used to create a new profile. + * @param profileType The type of CLI profile + * @param cmdArguments CLI arguments which may specify a profile + * @param defaultProfileName Name to fall back to if profile doesn't exist. If + * not specified, the profile type will be used. + * @returns The profile name + */ + public static getActiveProfileName(profileType: string, cmdArguments?: ICommandArguments, defaultProfileName?: string): string { + // Look for profile name first in command line arguments, second in + // default profiles defined in config, and finally fall back to using + // the profile type as the profile name. + return cmdArguments?.[`${profileType}-profile`] || + ImperativeConfig.instance.config?.properties.defaults[profileType] || + defaultProfileName || profileType; + } -/** - * Form an error message for failures to securely save a value. - * @param solution Text that our caller can supply for a solution. - * @returns ImperativeError to be thrown - */ -export function secureSaveError(solution?: string): ImperativeError { - let details = CredentialManagerFactory.manager.secureErrorDetails(); - if (solution != null) { - details = (details != null) ? (details + `\n - ${solution}`) : solution; + /** + * Checks if partial path is equal to or nested inside full path + * @param fullPath JSON path to profile 1 + * @param partialPath JSON path to profile 2 + */ + public static jsonPathMatches(fullPath: string, partialPath: string): boolean { + return fullPath === partialPath || fullPath.startsWith(partialPath + ".profiles."); + } + + /** + * Form an error message for failures to securely save a value. + * @param solution Text that our caller can supply for a solution. + * @returns ImperativeError to be thrown + */ + public static secureSaveError(solution?: string): ImperativeError { + let details = CredentialManagerFactory.manager.secureErrorDetails(); + if (solution != null) { + details = (details != null) ? (details + `\n - ${solution}`) : solution; + } + return new ImperativeError({ + msg: "Unable to securely save credentials.", + additionalDetails: details + }); } - return new ImperativeError({ - msg: "Unable to securely save credentials.", - additionalDetails: details - }); } diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index 65d6dadc92..63509f3ce5 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -51,6 +51,7 @@ import { ConfigAutoStore } from "./ConfigAutoStore"; import { IGetAllProfilesOptions } from "./doc/IProfInfoProps"; import { IConfig } from "./doc/IConfig"; import { IProfInfoRemoveKnownPropOpts } from "./doc/IProfInfoRemoveKnownPropOpts"; +import { ConfigUtils } from "./ConfigUtils"; /** * This class provides functions to retrieve profile-related information. @@ -201,6 +202,15 @@ export class ProfileInfo { } const mergedArgs = this.mergeArgsForProfile(desiredProfile, { getSecureVals: false }); + if (options.forceUpdate && this.usingTeamConfig) { + const knownProperty = mergedArgs.knownArgs.find((v => v.argName === options.property)); + if (knownProperty != null) { + const profPath = this.getTeamConfig().api.profiles.getProfilePathFromName(options.profileName); + if (!ConfigUtils.jsonPathMatches(knownProperty.argLoc.jsonLoc, profPath)) { + knownProperty.argLoc.jsonLoc = `${profPath}.properties.${options.property}`; + } + } + } if (!(await this.updateKnownProperty({ ...options, mergedArgs, osLocInfo: this.getOsLocInfo(desiredProfile)?.[0] }))) { if (this.usingTeamConfig) { // Check to see if loadedConfig already contains the schema for the specified profile type @@ -284,7 +294,7 @@ export class ProfileInfo { let oldLayer: IProfLocOsLocLayer; const layer = this.getTeamConfig().layerActive(); const osLoc = options.osLocInfo ?? this.getOsLocInfo( - this.getAllProfiles().find(p => toUpdate.argLoc.jsonLoc.startsWith(p.profLoc.jsonLoc)))?.[0]; + this.getAllProfiles().find(p => ConfigUtils.jsonPathMatches(toUpdate.argLoc.jsonLoc, p.profLoc.jsonLoc)))?.[0]; if (osLoc && (layer.user !== osLoc.user || layer.global !== osLoc.global)) { oldLayer = { user: layer.user, global: layer.global }; this.getTeamConfig().api.layers.activate(osLoc.user, osLoc.global); diff --git a/packages/imperative/src/config/src/api/ConfigSecure.ts b/packages/imperative/src/config/src/api/ConfigSecure.ts index 3251e880a9..be89ddc39b 100644 --- a/packages/imperative/src/config/src/api/ConfigSecure.ts +++ b/packages/imperative/src/config/src/api/ConfigSecure.ts @@ -19,6 +19,7 @@ import { IConfigSecureProperties } from "../doc/IConfigSecure"; import { ConfigConstants } from "../ConfigConstants"; import { IConfigProfile } from "../doc/IConfigProfile"; import { CredentialManagerFactory } from "../../../security"; +import { ConfigUtils } from "../ConfigUtils"; /** * API Class for manipulating config layers. @@ -200,17 +201,18 @@ export class ConfigSecure extends ConfigApi { * @param profileName Profile name to search for * @returns Array of secure property names */ - public securePropsForProfile(profileName: string) { + public securePropsForProfile(profileName: string): string[] { const profilePath = this.mConfig.api.profiles.getProfilePathFromName(profileName); - const secureProps = []; + const secureProps = new Set(); for (const propPath of this.secureFields()) { const pathSegments = propPath.split("."); // profiles.XXX.properties.YYY // eslint-disable-next-line @typescript-eslint/no-magic-numbers - if (profilePath.startsWith(pathSegments.slice(0, -2).join("."))) { - secureProps.push(pathSegments.pop()); + const propProfilePath = pathSegments.slice(0, -2).join("."); + if (ConfigUtils.jsonPathMatches(profilePath, propProfilePath)) { + secureProps.add(pathSegments.pop()); } } - return secureProps; + return [...secureProps]; } /** diff --git a/packages/imperative/src/config/src/doc/IProfInfoUpdatePropOpts.ts b/packages/imperative/src/config/src/doc/IProfInfoUpdatePropOpts.ts index 1c39c7b381..17f3f7f332 100644 --- a/packages/imperative/src/config/src/doc/IProfInfoUpdatePropOpts.ts +++ b/packages/imperative/src/config/src/doc/IProfInfoUpdatePropOpts.ts @@ -26,6 +26,16 @@ export interface IProfInfoUpdatePropOpts extends IProfInfoUpdatePropCommonOpts { * Name of the active profile */ profileName: string; + + /** + * Force the update to the profile specified even if the property comes from somehwere else + * @example Token Value could be in the base profile (not in the service profile specified) + * and the programmer has the intention of storing the token in the service profile + * @default false When the property is not specified, the updateProperty method follows current + * procedure of updating the property in the known jsonLoc (e.g. base profile). Otherwise, + * the updateProperty method updates the specified profile name-type combination. + */ + forceUpdate?: boolean } /** diff --git a/packages/imperative/src/imperative/src/auth/handlers/BaseAuthHandler.ts b/packages/imperative/src/imperative/src/auth/handlers/BaseAuthHandler.ts index 6a99f418bb..1d90405b21 100644 --- a/packages/imperative/src/imperative/src/auth/handlers/BaseAuthHandler.ts +++ b/packages/imperative/src/imperative/src/auth/handlers/BaseAuthHandler.ts @@ -22,7 +22,7 @@ import { Imperative } from "../../Imperative"; import { IImperativeError, ImperativeError } from "../../../../error"; import { ISaveProfileFromCliArgs } from "../../../../profiles"; import { ImperativeConfig } from "../../../../utilities"; -import { getActiveProfileName, secureSaveError } from "../../../../config/src/ConfigUtils"; +import { ConfigUtils } from "../../../../config/src/ConfigUtils"; import { AbstractAuthHandler } from "./AbstractAuthHandler"; import { IAuthHandlerApi } from "../doc/IAuthHandlerApi"; @@ -102,7 +102,8 @@ export abstract class BaseAuthHandler extends AbstractAuthHandler { // process login for old school profiles await this.processLoginOld(params, tokenValue); } else if (ImperativeConfig.instance.config.api.secure.loadFailed) { - throw secureSaveError(`Instead of secure storage, rerun this command with the "--show-token" flag to print the token to console. ` + + throw ConfigUtils.secureSaveError(`Instead of secure storage, ` + + `rerun this command with the "--show-token" flag to print the token to console. ` + `Store the token in an environment variable ${ImperativeConfig.instance.loadedConfig.envVariablePrefix}_OPT_TOKEN_VALUE to use it ` + `in future commands.`); } else { @@ -161,7 +162,7 @@ export abstract class BaseAuthHandler extends AbstractAuthHandler { } private getBaseProfileName(params: IHandlerParameters): string { - return getActiveProfileName(this.mProfileType, params.arguments, `${this.mProfileType}_${params.positionals[2]}`); + return ConfigUtils.getActiveProfileName(this.mProfileType, params.arguments, `${this.mProfileType}_${params.positionals[2]}`); } private async promptForBaseProfile(params: IHandlerParameters, profileName: string): Promise { diff --git a/packages/imperative/src/imperative/src/config/cmd/init/init.handler.ts b/packages/imperative/src/imperative/src/config/cmd/init/init.handler.ts index 66e876b65f..b43f58329c 100644 --- a/packages/imperative/src/imperative/src/config/cmd/init/init.handler.ts +++ b/packages/imperative/src/imperative/src/config/cmd/init/init.handler.ts @@ -15,7 +15,7 @@ import { Config, ConfigConstants, ConfigSchema, IConfig } from "../../../../../c import { IProfileProperty } from "../../../../../profiles"; import { ConfigBuilder } from "../../../../../config/src/ConfigBuilder"; import { IConfigBuilderOpts } from "../../../../../config/src/doc/IConfigBuilderOpts"; -import { coercePropValue, secureSaveError } from "../../../../../config/src/ConfigUtils"; +import { ConfigUtils } from "../../../../../config/src/ConfigUtils"; import { OverridesLoader } from "../../../OverridesLoader"; import * as JSONC from "comment-json"; import * as lodash from "lodash"; @@ -102,7 +102,7 @@ export default class InitHandler implements ICommandHandler { await this.initWithSchema(config, params.arguments.userConfig, params.arguments.overwrite && params.arguments.forSure); if (params.arguments.prompt !== false && config.api.secure.loadFailed && config.api.secure.secureFields().length > 0) { - const warning = secureSaveError(); + const warning = ConfigUtils.secureSaveError(); params.response.console.log(TextUtils.chalk.yellow("Warning:\n") + `${warning.message} Skipped prompting for credentials.\n\n${warning.additionalDetails}\n`); } @@ -193,7 +193,7 @@ export default class InitHandler implements ICommandHandler { // coerce to correct type if (propValue && propValue.trim().length > 0) { - return coercePropValue(propValue); + return ConfigUtils.coercePropValue(propValue); } return propValue || null; diff --git a/packages/imperative/src/imperative/src/config/cmd/secure/secure.handler.ts b/packages/imperative/src/imperative/src/config/cmd/secure/secure.handler.ts index 3c88d79197..9398585097 100644 --- a/packages/imperative/src/imperative/src/config/cmd/secure/secure.handler.ts +++ b/packages/imperative/src/imperative/src/config/cmd/secure/secure.handler.ts @@ -11,7 +11,7 @@ import { ICommandArguments, ICommandHandler, IHandlerParameters } from "../../../../../cmd"; import { Config, ConfigAutoStore, ConfigConstants, ConfigSchema } from "../../../../../config"; -import { coercePropValue, secureSaveError } from "../../../../../config/src/ConfigUtils"; +import { ConfigUtils } from "../../../../../config/src/ConfigUtils"; import { ImperativeError } from "../../../../../error"; import { Logger } from "../../../../../logger"; import { ConnectionPropsForSessCfg, ISession, Session } from "../../../../../rest"; @@ -36,7 +36,7 @@ export default class SecureHandler implements ICommandHandler { // Setup the credential vault API for the config if (config.api.secure.loadFailed) { - throw secureSaveError(); + throw ConfigUtils.secureSaveError(); } if (params.arguments.prune) { @@ -74,7 +74,7 @@ export default class SecureHandler implements ICommandHandler { // Save the value in the config securely if (propValue) { - propValue = coercePropValue(propValue, ConfigSchema.findPropertyType(propName, config.properties)); + propValue = ConfigUtils.coercePropValue(propValue, ConfigSchema.findPropertyType(propName, config.properties)); config.set(propName, propValue, { secure: true }); } } diff --git a/packages/imperative/src/imperative/src/config/cmd/set/set.handler.ts b/packages/imperative/src/imperative/src/config/cmd/set/set.handler.ts index 67b9795bc3..9b5fb96324 100644 --- a/packages/imperative/src/imperative/src/config/cmd/set/set.handler.ts +++ b/packages/imperative/src/imperative/src/config/cmd/set/set.handler.ts @@ -12,7 +12,7 @@ import * as JSONC from "comment-json"; import { ICommandHandler, IHandlerParameters } from "../../../../../cmd"; import { ConfigSchema } from "../../../../../config"; -import { coercePropValue, secureSaveError } from "../../../../../config/src/ConfigUtils"; +import { ConfigUtils } from "../../../../../config/src/ConfigUtils"; import { ImperativeError } from "../../../../../error"; import { ImperativeConfig } from "../../../../../utilities"; @@ -39,7 +39,7 @@ export default class SetHandler implements ICommandHandler { // Setup the credential vault API for the config if (secure && config.api.secure.loadFailed) { - throw secureSaveError(); + throw ConfigUtils.secureSaveError(); } // Get the value to set @@ -57,7 +57,7 @@ export default class SetHandler implements ICommandHandler { throw new ImperativeError({ msg: `could not parse JSON value: ${e.message}` }); } } else { - value = coercePropValue(value, ConfigSchema.findPropertyType(params.arguments.property, config.properties)); + value = ConfigUtils.coercePropValue(value, ConfigSchema.findPropertyType(params.arguments.property, config.properties)); } // Set the value in the config, save the secure values, write the config layer diff --git a/packages/imperative/src/rest/src/session/ConnectionPropsForSessCfg.ts b/packages/imperative/src/rest/src/session/ConnectionPropsForSessCfg.ts index 1d319ece26..5bb3ad2888 100644 --- a/packages/imperative/src/rest/src/session/ConnectionPropsForSessCfg.ts +++ b/packages/imperative/src/rest/src/session/ConnectionPropsForSessCfg.ts @@ -19,7 +19,7 @@ import { IPromptOptions } from "../../../cmd/src/doc/response/api/handler/IPromp import { ISession } from "./doc/ISession"; import { IProfileProperty } from "../../../profiles"; import { ConfigAutoStore } from "../../../config/src/ConfigAutoStore"; -import * as ConfigUtils from "../../../config/src/ConfigUtils"; +import { ConfigUtils } from "../../../config/src/ConfigUtils"; /** * Extend options for IPromptOptions for internal wrapper method diff --git a/packages/imperative/src/utilities/src/TextUtils.ts b/packages/imperative/src/utilities/src/TextUtils.ts index 858074015c..91af27f12f 100644 --- a/packages/imperative/src/utilities/src/TextUtils.ts +++ b/packages/imperative/src/utilities/src/TextUtils.ts @@ -300,7 +300,8 @@ export class TextUtils { const mChalk = require("chalk"); // chalk is supposed to handle this, but I think it only does so the first time it is loaded // so we need to check ourselves in case we've changed the environmental variables - mChalk.enabled = process.env.FORCE_COLOR !== "0" && process.env.MARKDOWN_GEN == null; + if (process.env.FORCE_COLOR != null && ["1", "2", "3", "true"].includes(process.env.FORCE_COLOR)) { mChalk.enabled = true; } + if (process.env.MARKDOWN_GEN != null || process.env.FORCE_COLOR == "0") { mChalk.enabled = false; } if (!mChalk.enabled) { mChalk.level = 0; } else if (process.env.FORCE_COLOR != null) { const parsedInt = parseInt(process.env.FORCE_COLOR); diff --git a/packages/provisioning/package.json b/packages/provisioning/package.json index d35aef7e4b..23051f21f5 100644 --- a/packages/provisioning/package.json +++ b/packages/provisioning/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "description": "Zowe SDK to interact with the z/OS provisioning APIs", "author": "Zowe", "license": "EPL-2.0", @@ -49,9 +49,9 @@ }, "devDependencies": { "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", diff --git a/packages/secrets/package.json b/packages/secrets/package.json index 90eb8732c5..fca1c48c8e 100644 --- a/packages/secrets/package.json +++ b/packages/secrets/package.json @@ -3,7 +3,7 @@ "description": "Credential management facilities for Imperative, Zowe CLI, and extenders.", "repository": "https://github.com/zowe/zowe-cli.git", "author": "Zowe", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "homepage": "https://github.com/zowe/zowe-cli/tree/master/packages/secrets#readme", "bugs": { "url": "https://github.com/zowe/zowe-cli/issues" diff --git a/packages/workflows/package.json b/packages/workflows/package.json index de80c4d41c..23ae6f6c5f 100644 --- a/packages/workflows/package.json +++ b/packages/workflows/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "description": "Zowe SDK to interact with the z/OS workflows APIs", "author": "Zowe", "license": "EPL-2.0", @@ -45,12 +45,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.1.0-next.202401191548" + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202401162202" }, "devDependencies": { - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", diff --git a/packages/zosconsole/package.json b/packages/zosconsole/package.json index 77557cc8dc..fb6c5cac7e 100644 --- a/packages/zosconsole/package.json +++ b/packages/zosconsole/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "description": "Zowe SDK to interact with the z/OS console", "author": "Zowe", "license": "EPL-2.0", @@ -45,9 +45,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", diff --git a/packages/zosfiles/CHANGELOG.md b/packages/zosfiles/CHANGELOG.md index dad6ac045b..70684afb2c 100644 --- a/packages/zosfiles/CHANGELOG.md +++ b/packages/zosfiles/CHANGELOG.md @@ -5,12 +5,19 @@ All notable changes to the Zowe z/OS files SDK package will be documented in thi ## `8.0.0-next.202311282012` - LTS Breaking: Unpinned dependency versions to allow for patch/minor version updates for dependencies [#1968](https://github.com/zowe/zowe-cli/issues/1968) -- Enhancement: Added `ZosFilesUtils.getDataSetFromName` to create an IDataSet from a dataset name [#1696](https://github.com/zowe/zowe-cli/issues/1696) ## `8.0.0-next.202311132045` - Major: First major version bump for V3 +## `7.21.3` + +- BugFix: Corrects the behavior of `Create.dataSetLike` so that the new data set is always defined with the correct block size [#2610](https://github.com/zowe/vscode-extension-for-zowe/issues/2610) + +## `7.20.0` + +- Enhancement: Adds `ZosFilesUtils.getDataSetFromName` to create an IDataSet from a dataset name [#1696](https://github.com/zowe/zowe-cli/issues/1696) + ## `7.18.9` - BugFix: Fix behavior where a specified directory was being lowercased on non-PDS datasets when downloading all datasets [#1722](https://github.com/zowe/zowe-cli/issues/1722) diff --git a/packages/zosfiles/__tests__/__unit__/methods/create/Create.unit.test.ts b/packages/zosfiles/__tests__/__unit__/methods/create/Create.unit.test.ts index af4c4281e5..731bdc5004 100644 --- a/packages/zosfiles/__tests__/__unit__/methods/create/Create.unit.test.ts +++ b/packages/zosfiles/__tests__/__unit__/methods/create/Create.unit.test.ts @@ -10,7 +10,7 @@ */ import { ImperativeError, TextUtils } from "@zowe/imperative"; -import { Create, CreateDataSetTypeEnum, ZosFilesConstants, CreateDefaults, Invoke, ICreateVsamOptions } from "../../../../src"; +import { Create, CreateDataSetTypeEnum, ZosFilesConstants, CreateDefaults, Invoke, ICreateVsamOptions, List } from "../../../../src"; import { ZosmfHeaders, ZosmfRestClient } from "@zowe/core-for-zowe-sdk"; import { ZosFilesMessages } from "../../../../src/constants/ZosFiles.messages"; import { IZosFilesOptions } from "../../../../src/doc/IZosFilesOptions"; @@ -19,17 +19,29 @@ describe("Create data set", () => { const dummySession: any = {}; const dataSetName = "testing"; const dsOptions: any = {alcunit: "CYL"}; + const likePsDataSetName = "TEST.PS.DATA.SET"; const endpoint = ZosFilesConstants.RESOURCE + ZosFilesConstants.RES_DS_FILES + "/" + dataSetName; let mySpy: any; + let listDatasetSpy: any; + + const dataSetPS = { + dsname: likePsDataSetName, + dsorg: "PS", + spacu: "TRK", + blksz: "800" + }; beforeEach(() => { mySpy = jest.spyOn(ZosmfRestClient, "postExpectString").mockResolvedValue(""); + listDatasetSpy = jest.spyOn(List, "dataSet"); }); afterEach(() => { - mySpy.mockReset(); + mySpy.mockClear(); mySpy.mockRestore(); + listDatasetSpy.mockClear(); + listDatasetSpy.mockResolvedValue({} as any); }); describe("Success scenarios", () => { @@ -179,28 +191,48 @@ describe("Create data set", () => { }); it("should be able to allocate like from a sequential data set", async () => { - const response = await Create.dataSetLike(dummySession, dataSetName, "testing2"); + listDatasetSpy.mockImplementation(async (): Promise => { + return { + apiResponse: { + returnedRows: 1, + items: [dataSetPS] + } + }; + }); + const response = await Create.dataSetLike(dummySession, dataSetName, likePsDataSetName); expect(response.success).toBe(true); expect(response.commandResponse).toContain("created successfully"); + expect(listDatasetSpy).toHaveBeenCalledTimes(1); expect(mySpy).toHaveBeenCalledWith( dummySession, endpoint, [ZosmfHeaders.ACCEPT_ENCODING], JSON.stringify({ ...{ - like: "testing2" + like: likePsDataSetName, + blksize: 800 } }) ); }); it("should be able to create a dataSetLike with responseTimeout", async () => { - dsOptions.dsntype = "PDS"; + dsOptions.alcunit = undefined; + dsOptions.dsntype = undefined; + dsOptions.recfm = undefined; dsOptions.responseTimeout = 5; - await Create.dataSet(dummySession, CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, dataSetName, dsOptions); - const response2 = await Create.dataSetLike(dummySession, dataSetName, "testing2", dsOptions); + listDatasetSpy.mockImplementation(async (): Promise => { + return { + apiResponse: { + returnedRows: 1, + items: [dataSetPS] + } + }; + }); + + const response2 = await Create.dataSetLike(dummySession, dataSetName, likePsDataSetName, dsOptions); expect(response2.success).toBe(true); expect(response2.commandResponse).toContain("created successfully"); @@ -209,10 +241,10 @@ describe("Create data set", () => { endpoint, [ZosmfHeaders.ACCEPT_ENCODING, { [ZosmfHeaders.X_IBM_RESPONSE_TIMEOUT]: "5" }], JSON.stringify({ - ...CreateDefaults.DATA_SET.SEQUENTIAL, - ...dsOptions, ...{ - secondary: 1 + like: likePsDataSetName, + responseTimeout: 5, + blksize: 800 } }) ); @@ -410,6 +442,8 @@ describe("Create data set", () => { }); it("should be able to create a classic data set", async () => { + dsOptions.alcunit = "CYL"; + dsOptions.recfm = "FB"; const response = await Create.dataSet(dummySession, CreateDataSetTypeEnum.DATA_SET_CLASSIC, dataSetName, dsOptions); expect(response.success).toBe(true); @@ -522,6 +556,8 @@ describe("Create data set", () => { }); it("should be able to create a C data set", async () => { + dsOptions.alcunit = "CYL"; + dsOptions.recfm = "VB"; const response = await Create.dataSet(dummySession, CreateDataSetTypeEnum.DATA_SET_C, dataSetName, dsOptions); expect(response.success).toBe(true); @@ -633,6 +669,8 @@ describe("Create data set", () => { }); it("should be able to create a binary data set", async () => { + dsOptions.alcunit = "CYL"; + dsOptions.recfm = "U"; const response = await Create.dataSet(dummySession, CreateDataSetTypeEnum.DATA_SET_BINARY, dataSetName, dsOptions); expect(response.success).toBe(true); @@ -934,6 +972,8 @@ describe("Create data set", () => { let error; try { + dsOptions.alcunit = "CYL"; + dsOptions.recfm = "FB"; await Create.dataSet(dummySession, CreateDataSetTypeEnum.DATA_SET_PARTITIONED, dataSetName, dsOptions); } catch (err) { error = err.message; diff --git a/packages/zosfiles/__tests__/__unit__/utils/__snapshots__/ZosFilesUtils.unit.test.ts.snap b/packages/zosfiles/__tests__/__unit__/utils/__snapshots__/ZosFilesUtils.unit.test.ts.snap index 169c04a6a8..3dcce8f4cf 100644 --- a/packages/zosfiles/__tests__/__unit__/utils/__snapshots__/ZosFilesUtils.unit.test.ts.snap +++ b/packages/zosfiles/__tests__/__unit__/utils/__snapshots__/ZosFilesUtils.unit.test.ts.snap @@ -81,6 +81,9 @@ Object { "dataSetsMatchedPattern": Object { "message": "%d data set(s) were found matching pattern.", }, + "datasetAllocateLikeNotFound": Object { + "message": "Data set allocation aborted. The \\"allocate like\\" data set was not found.", + }, "datasetCopiedAborted": Object { "message": "Data set copied aborted. The existing target data set was not overwritten.", }, diff --git a/packages/zosfiles/package.json b/packages/zosfiles/package.json index 789355d89c..30d2bd9936 100644 --- a/packages/zosfiles/package.json +++ b/packages/zosfiles/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "description": "Zowe SDK to interact with files and data sets on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -50,10 +50,10 @@ "minimatch": "^5.0.1" }, "devDependencies": { - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548", - "@zowe/zos-uss-for-zowe-sdk": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202", + "@zowe/zos-uss-for-zowe-sdk": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", diff --git a/packages/zosfiles/src/constants/ZosFiles.messages.ts b/packages/zosfiles/src/constants/ZosFiles.messages.ts index 728850e609..0aae6fb6ab 100644 --- a/packages/zosfiles/src/constants/ZosFiles.messages.ts +++ b/packages/zosfiles/src/constants/ZosFiles.messages.ts @@ -688,6 +688,14 @@ export const ZosFilesMessages: { [key: string]: IMessageDefinition } = { message: "Data set copied aborted. Copying to a PDS without a member name is not supported when using the 'dsclp' option." }, + /** + * Message indicating that the data set allocation was aborted + * @type {IMessageDefinition} + */ + datasetAllocateLikeNotFound: { + message: "Data set allocation aborted. The \"allocate like\" data set was not found." + }, + /** * Message indicating that the following members failed to properly download * @type {IMessageDefinition} diff --git a/packages/zosfiles/src/methods/create/Create.ts b/packages/zosfiles/src/methods/create/Create.ts index 4e3bf03aa5..c93b96509d 100644 --- a/packages/zosfiles/src/methods/create/Create.ts +++ b/packages/zosfiles/src/methods/create/Create.ts @@ -22,6 +22,8 @@ import { ICreateVsamOptions } from "./doc/ICreateVsamOptions"; import { ICreateZfsOptions } from "./doc/ICreateZfsOptions"; import * as path from "path"; import { IZosFilesOptions } from "../../doc/IZosFilesOptions"; +import { List } from "../list"; +import { IZosmfListResponse } from "../list/doc/IZosmfListResponse"; // Do not use import in anticipation of some internationalization work to be done later. // const strings = (require("../../../../../packages/cli/zosfiles/src/-strings-/en").default as typeof i18nTypings); @@ -150,8 +152,36 @@ export class Create { if (options && options.responseTimeout != null) { headers.push({[ZosmfHeaders.X_IBM_RESPONSE_TIMEOUT]: options.responseTimeout.toString()}); } + const tempOptions = JSON.parse(JSON.stringify({ like: likeDataSetName, ...(options || {}) })); Create.dataSetValidateOptions(tempOptions); + + /* + * This is a fix for issue https://github.com/zowe/vscode-extension-for-zowe/issues/2610. + * + * If no block size is passed, then retrieve the attributes of the "Like" dataset and + * set the block size, as the zosmf Rest API does not set the block size properly in + * some instances. + * + */ + if (tempOptions.blksize === null || tempOptions.blksize === undefined) { + let likeDataSetObj: IZosmfListResponse; + const likeDataSetList = await List.dataSet(session, likeDataSetName, { + attributes: true, maxLength: 1, + start: likeDataSetName, + recall: "wait" + }); + + const dsnameIndex = likeDataSetList.apiResponse.returnedRows === 0 ? -1 : + likeDataSetList.apiResponse.items.findIndex((ds: any) => ds.dsname.toUpperCase() === likeDataSetName.toUpperCase()); + if (dsnameIndex !== -1) { + likeDataSetObj = likeDataSetList.apiResponse.items[dsnameIndex]; + tempOptions.blksize = parseInt(likeDataSetObj.blksz); + } + else { + throw new ImperativeError({ msg: ZosFilesMessages.datasetAllocateLikeNotFound.message }); + } + } await ZosmfRestClient.postExpectString(session, endpoint, headers, JSON.stringify(tempOptions)); return { success: true, diff --git a/packages/zosjobs/package.json b/packages/zosjobs/package.json index 80ab5c15f3..ce71a4ba16 100644 --- a/packages/zosjobs/package.json +++ b/packages/zosjobs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "description": "Zowe SDK to interact with jobs on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -46,12 +46,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.1.0-next.202401191548" + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202401162202" }, "devDependencies": { - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", diff --git a/packages/zoslogs/package.json b/packages/zoslogs/package.json index 1f6f573a3a..300eaa34c4 100644 --- a/packages/zoslogs/package.json +++ b/packages/zoslogs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "description": "Zowe SDK to interact with the z/OS logs", "author": "Zowe", "license": "EPL-2.0", @@ -45,9 +45,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", diff --git a/packages/zosmf/package.json b/packages/zosmf/package.json index 0752aede6c..2f59f306a1 100644 --- a/packages/zosmf/package.json +++ b/packages/zosmf/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "description": "Zowe SDK to interact with the z/OS Management Facility", "author": "Zowe", "license": "EPL-2.0", @@ -44,9 +44,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", diff --git a/packages/zostso/package.json b/packages/zostso/package.json index 8bc8a2f20d..aea2c3e0cf 100644 --- a/packages/zostso/package.json +++ b/packages/zostso/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "description": "Zowe SDK to interact with TSO on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -45,12 +45,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "8.1.0-next.202401191548" + "@zowe/zosmf-for-zowe-sdk": "8.0.0-next.202401162202" }, "devDependencies": { - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/core-for-zowe-sdk": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", diff --git a/packages/zosuss/CHANGELOG.md b/packages/zosuss/CHANGELOG.md index 074f72ca17..955db6a484 100644 --- a/packages/zosuss/CHANGELOG.md +++ b/packages/zosuss/CHANGELOG.md @@ -2,10 +2,6 @@ All notable changes to the Zowe z/OS USS SDK package will be documented in this file. -## `8.0.0-next.202401022112` - -- BugFix: Updated `ssh2` package to resolve technical currency - ## `8.0.0-next.202311282012` - LTS Breaking: Unpinned dependency versions to allow for patch/minor version updates for dependencies [#1968](https://github.com/zowe/zowe-cli/issues/1968) @@ -14,6 +10,10 @@ All notable changes to the Zowe z/OS USS SDK package will be documented in this - Major: First major version bump for V3 +## `7.21.1` + +- BugFix: Updated `ssh2` package to resolve technical currency + ## `7.18.2` - BugFix: Updated `zowe zos-ssh issue cmd` to return just the command output in `stdout` instead of both the command and its output. [#1724](https://github.com/zowe/zowe-cli/issues/1724) diff --git a/packages/zosuss/package.json b/packages/zosuss/package.json index b99404da3d..a403489be1 100644 --- a/packages/zosuss/package.json +++ b/packages/zosuss/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "8.1.0-next.202401191548", + "version": "8.0.0-next.202401162202", "description": "Zowe SDK to interact with USS on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -49,8 +49,8 @@ }, "devDependencies": { "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "8.1.0-next.202401191548", - "@zowe/imperative": "8.1.0-next.202401191548" + "@zowe/cli-test-utils": "8.0.0-next.202401162202", + "@zowe/imperative": "8.0.0-next.202401162202" }, "peerDependencies": { "@zowe/imperative": "^8.0.0-next" diff --git a/release.config.js b/release.config.js index 22a6621662..250b85e810 100644 --- a/release.config.js +++ b/release.config.js @@ -18,7 +18,7 @@ module.exports = { "displayNames": { "cli": "Zowe CLI", "core": "Core SDK", - "imperative": "imperative", + "imperative": "Imperative", "zosconsole": "z/OS Console SDK", "zosfiles": "z/OS Files SDK", "zosjobs": "z/OS Jobs SDK",