diff --git a/__tests__/__packages__/cli-test-utils/package.json b/__tests__/__packages__/cli-test-utils/package.json index 5fba6d49c1..0ea4d5a3f4 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.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "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.9", "@types/uuid": "^9.0.8", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/imperative": "8.0.0-next.202403132009" }, "peerDependencies": { "@zowe/imperative": "^8.0.0-next" diff --git a/lerna.json b/lerna.json index 1e68d73eea..e53c7d10d2 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "command": { "publish": { "ignoreChanges": [ diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 5467ad0a01..5200a03d15 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.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "license": "EPL-2.0", "dependencies": { "find-up": "^5.0.0", @@ -62,7 +62,7 @@ "devDependencies": { "@types/js-yaml": "^4.0.9", "@types/uuid": "^9.0.8", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/imperative": "8.0.0-next.202403132009" }, "peerDependencies": { "@zowe/imperative": "^8.0.0-next" @@ -17365,21 +17365,21 @@ }, "packages/cli": { "name": "@zowe/cli", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "hasInstallScript": true, "license": "EPL-2.0", "dependencies": { - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702", - "@zowe/provisioning-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/zos-console-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/zos-jobs-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/zos-logs-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/zos-tso-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/zos-uss-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/zos-workflows-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/zosmf-for-zowe-sdk": "8.0.0-next.202403131702", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009", + "@zowe/provisioning-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/zos-console-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/zos-jobs-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/zos-logs-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/zos-tso-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/zos-uss-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/zos-workflows-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/zosmf-for-zowe-sdk": "8.0.0-next.202403132009", "find-process": "1.4.7", "lodash": "4.17.21", "minimatch": "9.0.3", @@ -17392,7 +17392,7 @@ "@types/diff": "^5.0.9", "@types/lodash": "^4.14.202", "@types/tar": "^6.1.11", - "@zowe/cli-test-utils": "8.0.0-next.202403131702", + "@zowe/cli-test-utils": "8.0.0-next.202403132009", "comment-json": "^4.2.3", "strip-ansi": "^6.0.1", "which": "^4.0.0" @@ -17401,7 +17401,7 @@ "node": ">=18.12.0" }, "optionalDependencies": { - "@zowe/secrets-for-zowe-sdk": "8.0.0-next.202403131702" + "@zowe/secrets-for-zowe-sdk": "8.0.0-next.202403132009" } }, "packages/cli/node_modules/brace-expansion": { @@ -17448,15 +17448,15 @@ }, "packages/core": { "name": "@zowe/core-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "license": "EPL-2.0", "dependencies": { "comment-json": "~4.2.3", "string-width": "^4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "engines": { "node": ">=18.12.0" @@ -17467,7 +17467,7 @@ }, "packages/imperative": { "name": "@zowe/imperative", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "license": "EPL-2.0", "dependencies": { "@types/yargs": "^17.0.32", @@ -17519,7 +17519,7 @@ "@types/pacote": "^11.1.8", "@types/progress": "^2.0.7", "@types/stack-trace": "^0.0.29", - "@zowe/secrets-for-zowe-sdk": "8.0.0-next.202403131702", + "@zowe/secrets-for-zowe-sdk": "8.0.0-next.202403132009", "concurrently": "^8.0.0", "cowsay": "^1.6.0", "deep-diff": "^1.0.0", @@ -17688,16 +17688,16 @@ }, "packages/provisioning": { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "license": "EPL-2.0", "dependencies": { "js-yaml": "^4.1.0" }, "devDependencies": { "@types/js-yaml": "^4.0.9", - "@zowe/cli-test-utils": "8.0.0-next.202403131702", - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "engines": { "node": ">=18.12.0" @@ -17709,7 +17709,7 @@ }, "packages/secrets": { "name": "@zowe/secrets-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "hasInstallScript": true, "license": "EPL-2.0", "devDependencies": { @@ -17722,15 +17722,15 @@ }, "packages/workflows": { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202403131702" + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202403132009" }, "devDependencies": { - "@zowe/cli-test-utils": "8.0.0-next.202403131702", - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "engines": { "node": ">=18.12.0" @@ -17742,12 +17742,12 @@ }, "packages/zosconsole": { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "8.0.0-next.202403131702", - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "engines": { "node": ">=18.12.0" @@ -17759,16 +17759,16 @@ }, "packages/zosfiles": { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "license": "EPL-2.0", "dependencies": { "minimatch": "^9.0.3" }, "devDependencies": { - "@zowe/cli-test-utils": "8.0.0-next.202403131702", - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702", - "@zowe/zos-uss-for-zowe-sdk": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009", + "@zowe/zos-uss-for-zowe-sdk": "8.0.0-next.202403132009" }, "engines": { "node": ">=18.12.0" @@ -17800,15 +17800,15 @@ }, "packages/zosjobs": { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202403131702" + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202403132009" }, "devDependencies": { - "@zowe/cli-test-utils": "8.0.0-next.202403131702", - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "engines": { "node": ">=18.12.0" @@ -17820,12 +17820,12 @@ }, "packages/zoslogs": { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "8.0.0-next.202403131702", - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "engines": { "node": ">=18.12.0" @@ -17837,12 +17837,12 @@ }, "packages/zosmf": { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "8.0.0-next.202403131702", - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "engines": { "node": ">=18.12.0" @@ -17854,15 +17854,15 @@ }, "packages/zostso": { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "license": "EPL-2.0", "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "8.0.0-next.202403131702" + "@zowe/zosmf-for-zowe-sdk": "8.0.0-next.202403132009" }, "devDependencies": { - "@zowe/cli-test-utils": "8.0.0-next.202403131702", - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "engines": { "node": ">=18.12.0" @@ -17874,15 +17874,15 @@ }, "packages/zosuss": { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "license": "EPL-2.0", "dependencies": { "ssh2": "^1.15.0" }, "devDependencies": { "@types/ssh2": "^1.11.19", - "@zowe/cli-test-utils": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "engines": { "node": ">=18.12.0" diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 13c399dc1e..f9637fa740 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -6,6 +6,10 @@ All notable changes to the Zowe CLI package will be documented in this file. - Enhancement: Changed references in command output from 'Team Configuration' to 'Zowe client configuration' [#2019](https://github.com/zowe/zowe-cli/issues/2019). +## `8.0.0-next.202403132009` + +- Enhancement: Prompt for user/password on SSH commands when a token is stored in the config. [#2081](https://github.com/zowe/zowe-cli/pull/2081) + ## `8.0.0-next.202403131702` - BugFix: Removing stack trace for zosjobs errors. [#2078](https://github.com/zowe/zowe-cli/pull/2078) diff --git a/packages/cli/__tests__/zosuss/__integration__/issue/cli.zos-uss.issue.ssh.integration.test.ts b/packages/cli/__tests__/zosuss/__integration__/issue/cli.zos-uss.issue.ssh.integration.test.ts index 32a5978676..162b1e9c10 100644 --- a/packages/cli/__tests__/zosuss/__integration__/issue/cli.zos-uss.issue.ssh.integration.test.ts +++ b/packages/cli/__tests__/zosuss/__integration__/issue/cli.zos-uss.issue.ssh.integration.test.ts @@ -45,5 +45,4 @@ describe("zos-uss issue ssh command", () => { expect(response.stderr.toString()).toContain('Command entered: "zos-uss issue ss"'); expect(response.stderr.toString()).toContain('Use "zowe --help" to view groups, commands, and options.'); }); - }); diff --git a/packages/cli/__tests__/zosuss/__system__/issue/cli.issue.ssh.system.test.ts b/packages/cli/__tests__/zosuss/__system__/issue/cli.issue.ssh.system.test.ts index 3626dac9f1..fce953a4e2 100644 --- a/packages/cli/__tests__/zosuss/__system__/issue/cli.issue.ssh.system.test.ts +++ b/packages/cli/__tests__/zosuss/__system__/issue/cli.issue.ssh.system.test.ts @@ -272,4 +272,16 @@ describe("zowe uss issue ssh passwords and passkeys", () => { [command, "--ssh-p", invalidPrivateKey]); expect(response.stderr.toString()).toMatch("no such file or directory, open 'bogusKey'"); }); + + it("should fail command execution without trace when improper user credentials", async () => { + // create a temporary zowe profile with an invalid user + const user = "bogusUser"; + const invalidCreds = await TempTestProfiles.createV2Profile(TEST_ENVIRONMENT, "ssh", + { host, port, user, password }); + + const command = "echo test"; + const response = await runCliScript(__dirname + "/__scripts__/issue_ssh_no_cwd.sh", TEST_ENVIRONMENT, + [command, "--ssh-p", invalidCreds]); + expect(response.stderr.toString()).toMatch("All configured authentication methods failed"); + }); }); diff --git a/packages/cli/package.json b/packages/cli/package.json index a09a106fe0..c7fd0d98bb 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "zoweVersion": "V3", "description": "Zowe CLI is a command line interface (CLI) that provides a simple and streamlined way to interact with IBM z/OS.", "author": "Zowe", @@ -58,17 +58,17 @@ "preshrinkwrap": "node ../../scripts/rewriteShrinkwrap.js" }, "dependencies": { - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702", - "@zowe/provisioning-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/zos-console-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/zos-jobs-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/zos-logs-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/zos-tso-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/zos-uss-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/zos-workflows-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/zosmf-for-zowe-sdk": "8.0.0-next.202403131702", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009", + "@zowe/provisioning-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/zos-console-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/zos-jobs-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/zos-logs-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/zos-tso-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/zos-uss-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/zos-workflows-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/zosmf-for-zowe-sdk": "8.0.0-next.202403132009", "find-process": "1.4.7", "lodash": "4.17.21", "minimatch": "9.0.3", @@ -78,13 +78,13 @@ "@types/diff": "^5.0.9", "@types/lodash": "^4.14.202", "@types/tar": "^6.1.11", - "@zowe/cli-test-utils": "8.0.0-next.202403131702", + "@zowe/cli-test-utils": "8.0.0-next.202403132009", "comment-json": "^4.2.3", "strip-ansi": "^6.0.1", "which": "^4.0.0" }, "optionalDependencies": { - "@zowe/secrets-for-zowe-sdk": "8.0.0-next.202403131702" + "@zowe/secrets-for-zowe-sdk": "8.0.0-next.202403132009" }, "engines": { "node": ">=18.12.0" diff --git a/packages/cli/src/zosuss/issue/ssh/Ssh.handler.ts b/packages/cli/src/zosuss/issue/ssh/Ssh.handler.ts index 83c9b53a81..0702c4567c 100644 --- a/packages/cli/src/zosuss/issue/ssh/Ssh.handler.ts +++ b/packages/cli/src/zosuss/issue/ssh/Ssh.handler.ts @@ -37,4 +37,4 @@ export default class Handler extends SshBaseHandler { public handleStdout(data: string) { this.parameters.response.console.log(Buffer.from(data)); } -} +} \ No newline at end of file diff --git a/packages/core/package.json b/packages/core/package.json index b1c8157597..356e28451b 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/core-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "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.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "peerDependencies": { "@zowe/imperative": "^8.0.0-next" diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index 604d7c5675..70f947e338 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -19,6 +19,10 @@ All notable changes to the Imperative package will be documented in this file. - Removed deprecated function ProcessUtils.execAndCheckOutput - Use ExecUtils.spawnAndGetOutput +## `8.0.0-next.202403132009` + +- Enhancement: Prompt for user/password on SSH commands when a token is stored in the config. [#2081](https://github.com/zowe/zowe-cli/pull/2081) + ## `8.0.0-next.202403061549` - V3 Breaking: Changed prompting logic to prompt for port if port provided is 0 [#2075](https://github.com/zowe/zowe-cli/issues/2075) diff --git a/packages/imperative/package.json b/packages/imperative/package.json index cfa6eeb35a..340cd53911 100644 --- a/packages/imperative/package.json +++ b/packages/imperative/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/imperative", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "description": "framework for building configurable CLIs", "author": "Zowe", "license": "EPL-2.0", @@ -92,7 +92,7 @@ "@types/pacote": "^11.1.8", "@types/progress": "^2.0.7", "@types/stack-trace": "^0.0.29", - "@zowe/secrets-for-zowe-sdk": "8.0.0-next.202403131702", + "@zowe/secrets-for-zowe-sdk": "8.0.0-next.202403132009", "concurrently": "^8.0.0", "cowsay": "^1.6.0", "deep-diff": "^1.0.0", diff --git a/packages/imperative/src/rest/__tests__/session/ConnectionPropsForSessCfg.unit.test.ts b/packages/imperative/src/rest/__tests__/session/ConnectionPropsForSessCfg.unit.test.ts index d1f3fd2cce..9943614d70 100644 --- a/packages/imperative/src/rest/__tests__/session/ConnectionPropsForSessCfg.unit.test.ts +++ b/packages/imperative/src/rest/__tests__/session/ConnectionPropsForSessCfg.unit.test.ts @@ -186,6 +186,34 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.tokenValue).toBeUndefined(); }); + it("ignore token and cert if unsupported auth types and authenticate with user and pass", async() => { + const initialSessCfg = { + hostname: "SomeHost", + port: 11, + rejectUnauthorized: true + }; + const args = { + $0: "zowe", + _: [""], + cert: "fakeCert", + certKey: "fakeCertKey", + tokenType: SessConstants.TOKEN_TYPE_JWT, + tokenValue: "fakeToken" + }; + const fakePromptFn = jest.fn().mockReturnValue({ + "user": "FakeUser", + "password": "FakePassword" + }); + const sessCfgWithConnProps = await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, args, {getValuesBack: fakePromptFn, supportedAuthTypes: ["basic"]} + ); + expect(fakePromptFn).toHaveBeenCalledWith(["user", "password"]); + expect(sessCfgWithConnProps.hostname).toBe("SomeHost"); + expect(sessCfgWithConnProps.user).toBe("FakeUser"); + expect(sessCfgWithConnProps.password).toBe("FakePassword"); + expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_BASIC); + }); + it("not set tokenValue if user and pass are defined", async() => { const initialSessCfg = { hostname: "SomeHost", diff --git a/packages/imperative/src/rest/src/session/ConnectionPropsForSessCfg.ts b/packages/imperative/src/rest/src/session/ConnectionPropsForSessCfg.ts index ed9acb4b77..360fc214f4 100644 --- a/packages/imperative/src/rest/src/session/ConnectionPropsForSessCfg.ts +++ b/packages/imperative/src/rest/src/session/ConnectionPropsForSessCfg.ts @@ -144,8 +144,11 @@ export class ConnectionPropsForSessCfg { promptForValues.push("port"); } - if (ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.tokenValue) === false && - ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.cert) === false) { + const isTokenIrrelevant = ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.tokenValue) === false || + (connOpts.supportedAuthTypes && !connOpts.supportedAuthTypes.includes(SessConstants.AUTH_TYPE_TOKEN)); + const isCertIrrelevant = ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.cert) === false || + (connOpts.supportedAuthTypes && !connOpts.supportedAuthTypes.includes(SessConstants.AUTH_TYPE_CERT_PEM)); + if (isTokenIrrelevant && isCertIrrelevant) { if (ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.user) === false && !doNotPromptForValues.includes("user")) { promptForValues.push("user"); } @@ -269,7 +272,11 @@ export class ConnectionPropsForSessCfg { // } } - if (ConnectionPropsForSessCfg.propHasValue(sessCfg.tokenValue)) { + const isTokenUsed = ConnectionPropsForSessCfg.propHasValue(sessCfg.tokenValue) && + (connOpts.supportedAuthTypes == null || connOpts.supportedAuthTypes.includes(SessConstants.AUTH_TYPE_TOKEN)); + const isCertUsed = ConnectionPropsForSessCfg.propHasValue(sessCfg.cert) && + (connOpts.supportedAuthTypes == null || connOpts.supportedAuthTypes.includes(SessConstants.AUTH_TYPE_CERT_PEM)); + if (isTokenUsed) { // when tokenValue is set at this point, we are definitely using the token. impLogger.debug("Using token authentication"); @@ -285,7 +292,7 @@ export class ConnectionPropsForSessCfg { // When no tokenType supplied, user wants bearer sessCfg.type = SessConstants.AUTH_TYPE_BEARER; } - } else if (ConnectionPropsForSessCfg.propHasValue(sessCfg.cert)) { + } else if (isCertUsed) { // when cert property is set at this point, we will use the certificate if (ConnectionPropsForSessCfg.propHasValue(sessCfg.certKey)) { impLogger.debug("Using PEM Certificate authentication"); diff --git a/packages/imperative/src/rest/src/session/doc/IOptionsForAddConnProps.ts b/packages/imperative/src/rest/src/session/doc/IOptionsForAddConnProps.ts index ac50b7f30d..706e40a11a 100644 --- a/packages/imperative/src/rest/src/session/doc/IOptionsForAddConnProps.ts +++ b/packages/imperative/src/rest/src/session/doc/IOptionsForAddConnProps.ts @@ -11,6 +11,7 @@ import { SessConstants } from "../../.."; import { IHandlerParameters } from "../../../../cmd"; +import { AUTH_TYPE_CHOICES } from "../SessConstants"; import { IOverridePromptConnProps } from "./IOverridePromptConnProps"; /** @@ -82,4 +83,10 @@ export interface IOptionsForAddConnProps { * exists. */ autoStore?: boolean; + + /** + * Specifies list of authentication types that are supported for your + * service. Defaults to allow all authentication types. + */ + supportedAuthTypes?: AUTH_TYPE_CHOICES[]; } diff --git a/packages/provisioning/package.json b/packages/provisioning/package.json index 776d2a7600..ec4afc2df7 100644 --- a/packages/provisioning/package.json +++ b/packages/provisioning/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "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.9", - "@zowe/cli-test-utils": "8.0.0-next.202403131702", - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", diff --git a/packages/secrets/package.json b/packages/secrets/package.json index a3f7488e7a..37617fa406 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.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "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 0727b63c79..5d55922bef 100644 --- a/packages/workflows/package.json +++ b/packages/workflows/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "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.0.0-next.202403131702" + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202403132009" }, "devDependencies": { - "@zowe/cli-test-utils": "8.0.0-next.202403131702", - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", diff --git a/packages/zosconsole/package.json b/packages/zosconsole/package.json index a0268c07a5..8a1cb60509 100644 --- a/packages/zosconsole/package.json +++ b/packages/zosconsole/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "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.0.0-next.202403131702", - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", diff --git a/packages/zosfiles/CHANGELOG.md b/packages/zosfiles/CHANGELOG.md index 05d088b17c..7617ebc49c 100644 --- a/packages/zosfiles/CHANGELOG.md +++ b/packages/zosfiles/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to the Zowe z/OS files SDK package will be documented in this file. +## `8.0.0-next.202403132009` + +- LTS Breaking: Changed return type of `Upload.bufferToUssFile` to return `IZosFilesResponse` object instead of string. [#2089](https://github.com/zowe/zowe-cli/pull/2089) +- BugFix: Fixed `Upload.bufferToUssFile` not normalizing new lines when uploading plain text. [#2089](https://github.com/zowe/zowe-cli/pull/2089) + ## `8.0.0-next.202403041352` - BugFix: Updated engine to Node 18.12.0. [#2074](https://github.com/zowe/zowe-cli/pull/2074) diff --git a/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts b/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts index d8ce8b49a0..b755d19f2f 100644 --- a/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts +++ b/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts @@ -121,7 +121,7 @@ describe("z/OS Files - Upload", () => { expect(error.causeErrors).toBe(rootError); }); - it("return with proper response", async () => { + it("should return with proper response", async () => { const testReturn = {}; const testPath = "test/path"; lstatSpy.mockImplementationOnce((somePath, callback: any) => { @@ -141,7 +141,7 @@ describe("z/OS Files - Upload", () => { expect(dataSetSpy).toHaveBeenCalledTimes(1); expect(dataSetSpy).toHaveBeenLastCalledWith(dummySession, testPath, dsName, {}); }); - it("return with proper response with responseTimeout", async () => { + it("should return with proper response with responseTimeout", async () => { const testReturn = {}; const testPath = "test/path"; lstatSpy.mockImplementationOnce((somePath, callback: any) => { @@ -227,7 +227,7 @@ describe("z/OS Files - Upload", () => { expect(error.causeErrors).toBe(rootError); }); - it("return with proper message when path is pointing to a file", async () => { + it("should return with proper message when path is pointing to a file", async () => { lstatSpy.mockImplementationOnce((somePath, callback: any) => { callback(null, {isFile: () => false}); }); @@ -244,7 +244,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeDefined(); expect(error.message).toContain(ZosFilesMessages.missingInputDir.message); }); - it("return with proper response", async () => { + it("should return with proper response", async () => { const testReturn = {}; const testPath = "test/path"; isDirSpy.mockReturnValueOnce(true); @@ -264,7 +264,7 @@ describe("z/OS Files - Upload", () => { expect(dataSetSpy).toHaveBeenCalledTimes(1); expect(dataSetSpy).toHaveBeenLastCalledWith(dummySession, testPath, dsName, {}); }); - it("return with proper response with responseTimeout", async () => { + it("should return with proper response with responseTimeout", async () => { const testReturn = {}; const testPath = "test/path"; isDirSpy.mockReturnValueOnce(true); @@ -284,7 +284,7 @@ describe("z/OS Files - Upload", () => { expect(dataSetSpy).toHaveBeenCalledTimes(1); expect(dataSetSpy).toHaveBeenLastCalledWith(dummySession, testPath, dsName, {responseTimeout: 5}); }); - it("return with proper response with encoding", async () => { + it("should return with proper response with encoding", async () => { const encoding = "1048"; const testReturn = {}; const testPath = "test/path"; @@ -346,7 +346,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeDefined(); expect(error.message).toContain(ZosFilesMessages.missingDatasetName.message); }); - it("return error that throw by the ZosmfRestClient", async () => { + it("should return error that is thrown by the ZosmfRestClient", async () => { const buffer: Buffer = Buffer.from("testing"); const testError = new ImperativeError({ msg: "test error" @@ -364,7 +364,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeDefined(); expect(error).toBe(testError); }); - it("return with proper response when upload buffer to a data set", async () => { + it("should return with proper response when upload buffer to a data set", async () => { const buffer: Buffer = Buffer.from("testing"); const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsName); const reqHeaders = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.ACCEPT_ENCODING]; @@ -383,7 +383,7 @@ describe("z/OS Files - Upload", () => { reqHeaders, writeData: buffer}); }); - it("return with proper response when upload buffer to a PDS member", async () => { + it("should return with proper response when upload buffer to a PDS member", async () => { const buffer: Buffer = Buffer.from("testing"); const testDsName = `${dsName}(member)`; const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, testDsName); @@ -403,6 +403,27 @@ describe("z/OS Files - Upload", () => { reqHeaders, writeData: buffer}); }); + it("should normalize new lines when upload buffer to a data set", async () => { + const buffer: Buffer = Buffer.from("testing\r\ntesting2"); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsName); + const reqHeaders = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.ACCEPT_ENCODING]; + + try { + response = await Upload.bufferToDataSet(dummySession, buffer, dsName); + } catch (err) { + error = err; + } + + expect(error).toBeUndefined(); + expect(response).toBeDefined(); + + const normalizedData = ZosFilesUtils.normalizeNewline(buffer); + expect(buffer.length).not.toBe(normalizedData.length); + expect(zosmfPutFullSpy).toHaveBeenCalledTimes(1); + expect(zosmfPutFullSpy).toHaveBeenCalledWith(dummySession, {resource: endpoint, + reqHeaders, + writeData: normalizedData}); + }); describe("Using optional parameters", () => { let buffer: Buffer; let uploadOptions: IUploadOptions; @@ -517,7 +538,7 @@ describe("z/OS Files - Upload", () => { reqHeaders, writeData: buffer}); }); - it("return with proper response when uploading with 'recall nowait' option", async () => { + it("should return with proper response when uploading with 'recall nowait' option", async () => { // Unit test for no wait option uploadOptions.recall = "nowait"; reqHeaders.push(ZosmfHeaders.X_IBM_MIGRATED_RECALL_NO_WAIT); @@ -536,7 +557,7 @@ describe("z/OS Files - Upload", () => { reqHeaders, writeData: buffer}); }); - it("return with proper response when uploading with 'recall error' option", async () => { + it("should return with proper response when uploading with 'recall error' option", async () => { // Unit test for no error option uploadOptions.recall = "error"; reqHeaders.push(ZosmfHeaders.X_IBM_MIGRATED_RECALL_ERROR); @@ -555,7 +576,7 @@ describe("z/OS Files - Upload", () => { reqHeaders, writeData: buffer}); }); - it("return with proper response when uploading with non-exiting recall option", async () => { + it("should return with proper response when uploading with non-exiting recall option", async () => { // Unit test default value uploadOptions.recall = "non-existing"; reqHeaders.push(ZosmfHeaders.X_IBM_MIGRATED_RECALL_NO_WAIT); @@ -574,7 +595,7 @@ describe("z/OS Files - Upload", () => { reqHeaders, writeData: buffer}); }); - it("return with proper response when uploading with pass 'etag' option", async () => { + it("should return with proper response when uploading with pass 'etag' option", async () => { // Unit test for pass etag option uploadOptions.etag = etagValue; reqHeaders.push({"If-Match" : uploadOptions.etag}); @@ -593,7 +614,7 @@ describe("z/OS Files - Upload", () => { reqHeaders, writeData: buffer}); }); - it("return with proper response when uploading with return 'etag' option", async () => { + it("should return with proper response when uploading with return 'etag' option", async () => { zosmfPutFullSpy.mockImplementationOnce(async () => fakeResponseWithEtag); // Unit test for return etag option reqHeaders.push(ZosmfHeaders.X_IBM_RETURN_ETAG); @@ -613,7 +634,7 @@ describe("z/OS Files - Upload", () => { writeData: buffer, dataToReturn: [CLIENT_PROPERTY.response]}); }); - it("return with proper response when uploading with responseTimeout option", async () => { + it("should return with proper response when uploading with responseTimeout option", async () => { uploadOptions.responseTimeout = 5; reqHeaders.push({[ZosmfHeaders.X_IBM_RESPONSE_TIMEOUT]: "5"}); @@ -632,7 +653,7 @@ describe("z/OS Files - Upload", () => { writeData: buffer}); }); }); - it("return with proper response when upload dataset with specify volume option", async () => { + it("should return with proper response when upload dataset with specify volume option", async () => { const buffer: Buffer = Buffer.from("testing"); const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, `-(TEST)`, dsName); const reqHeaders = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.ACCEPT_ENCODING]; @@ -683,7 +704,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeDefined(); expect(error.message).toContain(ZosFilesMessages.missingDatasetName.message); }); - it("return error that throw by the ZosmfRestClient", async () => { + it("should return error that throw by the ZosmfRestClient", async () => { const testError = new ImperativeError({ msg: "test error" }); @@ -700,7 +721,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeDefined(); expect(error).toBe(testError); }); - it("return with proper response when upload stream to a data set", async () => { + it("should return with proper response when upload stream to a data set", async () => { const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsName); const reqHeaders = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.ACCEPT_ENCODING]; @@ -719,7 +740,7 @@ describe("z/OS Files - Upload", () => { reqHeaders, requestStream: inputStream}); }); - it("return with proper response when upload stream to a PDS member", async () => { + it("should return with proper response when upload stream to a PDS member", async () => { const testDsName = `${dsName}(member)`; const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, testDsName); const reqHeaders = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.ACCEPT_ENCODING]; @@ -739,7 +760,7 @@ describe("z/OS Files - Upload", () => { reqHeaders, requestStream: inputStream}); }); - it("return with proper response when upload stream to a data set with optional parameters 1", async () => { + it("should return with proper response when upload stream to a data set with optional parameters 1", async () => { const uploadOptions: IUploadOptions = { binary: true }; @@ -928,7 +949,7 @@ describe("z/OS Files - Upload", () => { requestStream: inputStream, dataToReturn: [CLIENT_PROPERTY.response]}); }); - it("return with proper response when upload stream to a data set with optional parameters 2", async () => { + it("should return with proper response when upload stream to a data set with optional parameters 2", async () => { const uploadOptions: IUploadOptions = { record: true }; @@ -1101,7 +1122,7 @@ describe("z/OS Files - Upload", () => { requestStream: inputStream, dataToReturn: [CLIENT_PROPERTY.response]}); }); - it("return with proper response when upload dataset with specify volume option", async () => { + it("should return with proper response when upload dataset with specify volume option", async () => { const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, `-(TEST)`, dsName); const reqHeaders = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.ACCEPT_ENCODING]; const uploadOptions: IUploadOptions = { @@ -1528,8 +1549,12 @@ describe("z/OS Files - Upload", () => { }); describe("bufferToUssFile", () => { - const zosmfExpectSpy = jest.spyOn(ZosmfRestClient, "putExpectString"); - let USSresponse: string; + const zosmfExpectSpy = jest.spyOn(ZosmfRestClient, "putExpectFullResponse"); + const fakeResponseWithEtag = { + data: Buffer.from(dsName), + response: { headers: { etag: etagValue } } + }; + let USSresponse: IZosFilesResponse; beforeEach(() => { USSresponse = undefined; error = undefined; @@ -1548,7 +1573,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeDefined(); expect(error.message).toContain(ZosFilesMessages.missingUSSFileName.message); }); - it("return error that throw by the ZosmfRestClient", async () => { + it("should return error that is thrown by the ZosmfRestClient", async () => { const testError = new ImperativeError({ msg: "test error" }); @@ -1565,7 +1590,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeDefined(); expect(error).toBe(testError); }); - it("return error that thrown when the 'record' option is specified", async () => { + it("should return error that is thrown when the 'record' option is specified", async () => { const record = true; try { @@ -1578,7 +1603,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeDefined(); expect(error.message).toContain(ZosFilesMessages.unsupportedDataType.message); }); - it("return with proper response when upload USS file", async () => { + it("should return with proper response when upload USS file", async () => { const data: Buffer = Buffer.from("testing"); const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, dsName); const headers = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.TEXT_PLAIN, ZosmfHeaders.ACCEPT_ENCODING]; @@ -1593,9 +1618,9 @@ describe("z/OS Files - Upload", () => { expect(USSresponse).toBeDefined(); expect(zosmfExpectSpy).toHaveBeenCalledTimes(1); - expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, endpoint, headers, data); + expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, { reqHeaders: headers, resource: endpoint, writeData: data }); }); - it("return with proper response when upload USS file with responseTimeout", async () => { + it("should return with proper response when upload USS file with responseTimeout", async () => { const data: Buffer = Buffer.from("testing"); const responseTimeout = 5; const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, dsName); @@ -1618,9 +1643,9 @@ describe("z/OS Files - Upload", () => { expect(USSresponse).toBeDefined(); expect(zosmfExpectSpy).toHaveBeenCalledTimes(1); - expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, endpoint, headers, data); + expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, { reqHeaders: headers, resource: endpoint, writeData: data }); }); - it("return with proper response when upload USS file in binary", async () => { + it("should return with proper response when upload USS file in binary", async () => { const data: Buffer = Buffer.from("testing"); const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, dsName); const headers = [ZosmfHeaders.OCTET_STREAM, ZosmfHeaders.X_IBM_BINARY, ZosmfHeaders.ACCEPT_ENCODING]; @@ -1635,9 +1660,9 @@ describe("z/OS Files - Upload", () => { expect(USSresponse).toBeDefined(); expect(zosmfExpectSpy).toHaveBeenCalledTimes(1); - expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, endpoint, headers, data); + expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, { reqHeaders: headers, resource: endpoint, writeData: data }); }); - it("return with proper response when upload USS file with Etag", async () => { + it("should return with proper response when upload USS file with Etag", async () => { const data: Buffer = Buffer.from("testing"); const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, dsName); const headers = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.TEXT_PLAIN, ZosmfHeaders.ACCEPT_ENCODING, {"If-Match": etagValue}]; @@ -1656,7 +1681,28 @@ describe("z/OS Files - Upload", () => { expect(USSresponse).toBeDefined(); expect(zosmfExpectSpy).toHaveBeenCalledTimes(1); - expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, endpoint, headers, data); + expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, { reqHeaders: headers, resource: endpoint, writeData: data }); + }); + it("should return with proper response when upload USS file and request Etag back", async () => { + const data: Buffer = Buffer.from("testing"); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, dsName); + const headers = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.TEXT_PLAIN, ZosmfHeaders.ACCEPT_ENCODING, ZosmfHeaders.X_IBM_RETURN_ETAG]; + zosmfExpectSpy.mockImplementationOnce(async () => fakeResponseWithEtag); + try { + USSresponse = await Upload.bufferToUssFile(dummySession, dsName, data, {returnEtag: true}); + } catch (err) { + error = err; + } + + expect(error).toBeUndefined(); + expect(USSresponse).toBeDefined(); + expect(USSresponse.success).toBeTruthy(); + expect(USSresponse.apiResponse.etag).toBeDefined(); + expect(USSresponse.apiResponse.etag).toEqual(etagValue); + + expect(zosmfExpectSpy).toHaveBeenCalledTimes(1); + expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, { reqHeaders: headers, resource: endpoint, writeData: data, + dataToReturn: [CLIENT_PROPERTY.response] }); }); it("should set local encoding if specified", async () => { const data: Buffer = Buffer.from("testing"); @@ -1676,7 +1722,26 @@ describe("z/OS Files - Upload", () => { expect(USSresponse).toBeDefined(); expect(zosmfExpectSpy).toHaveBeenCalledTimes(1); - expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, endpoint, headers, data); + expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, { reqHeaders: headers, resource: endpoint, writeData: data }); + }); + it("should normalize new lines when upload USS file", async () => { + const data: Buffer = Buffer.from("testing\r\ntesting2"); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, dsName); + const headers = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.TEXT_PLAIN, ZosmfHeaders.ACCEPT_ENCODING]; + + try { + USSresponse = await Upload.bufferToUssFile(dummySession, dsName, data); + } catch (err) { + error = err; + } + + expect(error).toBeUndefined(); + expect(USSresponse).toBeDefined(); + + const normalizedData = ZosFilesUtils.normalizeNewline(data); + expect(data.length).not.toBe(normalizedData.length); + expect(zosmfExpectSpy).toHaveBeenCalledTimes(1); + expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, { reqHeaders: headers, resource: endpoint, writeData: normalizedData }); }); }); @@ -1718,7 +1783,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeDefined(); expect(error.message).toContain(ZosFilesMessages.missingUSSFileName.message); }); - it("return error that is thrown by the ZosmfRestClient", async () => { + it("should return error that is thrown by the ZosmfRestClient", async () => { const testError = new ImperativeError({ msg: "test error" }); @@ -1735,7 +1800,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeDefined(); expect(error).toBe(testError); }); - it("return with proper response when upload USS file", async () => { + it("should return with proper response when upload USS file", async () => { const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, dsName); const reqHeaders = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.TEXT_PLAIN, ZosmfHeaders.ACCEPT_ENCODING]; @@ -1756,7 +1821,7 @@ describe("z/OS Files - Upload", () => { normalizeRequestNewLines: true}); expect(chtagSpy).toHaveBeenCalledTimes(0); }); - it("return with proper response when upload USS file with responseTimeout", async () => { + it("should return with proper response when upload USS file with responseTimeout", async () => { const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, dsName); const reqHeaders = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.TEXT_PLAIN, ZosmfHeaders.ACCEPT_ENCODING, {[ZosmfHeaders.X_IBM_RESPONSE_TIMEOUT]: "5"}]; @@ -1778,7 +1843,7 @@ describe("z/OS Files - Upload", () => { normalizeRequestNewLines: true}); expect(chtagSpy).toHaveBeenCalledTimes(0); }); - it("return with proper response when upload USS file in binary", async () => { + it("should return with proper response when upload USS file in binary", async () => { const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, dsName); const reqHeaders = [ZosmfHeaders.OCTET_STREAM, ZosmfHeaders.X_IBM_BINARY, ZosmfHeaders.ACCEPT_ENCODING]; @@ -1801,7 +1866,7 @@ describe("z/OS Files - Upload", () => { expect(chtagSpy).toHaveBeenCalledTimes(1); expect(chtagSpy).toHaveBeenCalledWith(dummySession, dsName, Tag.BINARY); }); - it("return with proper response when upload USS file with Etag", async () => { + it("should return with proper response when upload USS file with Etag", async () => { const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, dsName); const reqHeaders = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.TEXT_PLAIN, ZosmfHeaders.ACCEPT_ENCODING, {"If-Match": etagValue}]; @@ -1823,7 +1888,7 @@ describe("z/OS Files - Upload", () => { normalizeRequestNewLines: true}); expect(chtagSpy).toHaveBeenCalledTimes(0); }); - it("return with proper response when upload USS file and request Etag back", async () => { + it("should return with proper response when upload USS file and request Etag back", async () => { const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, dsName); const reqHeaders = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.TEXT_PLAIN, ZosmfHeaders.ACCEPT_ENCODING, ZosmfHeaders.X_IBM_RETURN_ETAG]; zosmfExpectFullSpy.mockImplementationOnce(async () => fakeResponseWithEtag); @@ -1976,7 +2041,7 @@ describe("z/OS Files - Upload", () => { expect(error.additionalDetails).toEqual(rootError.toString()); expect(error.causeErrors).toBe(rootError); }); - it("return with proper response when upload USS file", async () => { + it("should return with proper response when upload USS file", async () => { try { USSresponse = await Upload.fileToUssFile(dummySession, inputFile, "file"); } catch (err) { @@ -1992,7 +2057,7 @@ describe("z/OS Files - Upload", () => { expect(streamToUssFileSpy).toHaveBeenCalledTimes(1); expect(streamToUssFileSpy).toHaveBeenCalledWith(dummySession, "file", null, {}); }); - it("return with proper response when upload USS file with responseTimeout", async () => { + it("should return with proper response when upload USS file with responseTimeout", async () => { try { USSresponse = await Upload.fileToUssFile(dummySession, inputFile, "file", {responseTimeout: 5}); } catch (err) { @@ -2008,7 +2073,7 @@ describe("z/OS Files - Upload", () => { expect(streamToUssFileSpy).toHaveBeenCalledTimes(1); expect(streamToUssFileSpy).toHaveBeenCalledWith(dummySession, "file", null, {responseTimeout: 5}); }); - it("return with proper response when upload USS file including Etag", async () => { + it("should return with proper response when upload USS file including Etag", async () => { const streamResponse: IZosFilesResponse = { success: true, commandResponse: undefined as any, diff --git a/packages/zosfiles/package.json b/packages/zosfiles/package.json index 825aa01ab2..91eecb1fb9 100644 --- a/packages/zosfiles/package.json +++ b/packages/zosfiles/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "description": "Zowe SDK to interact with files and data sets on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -49,10 +49,10 @@ "minimatch": "^9.0.3" }, "devDependencies": { - "@zowe/cli-test-utils": "8.0.0-next.202403131702", - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702", - "@zowe/zos-uss-for-zowe-sdk": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009", + "@zowe/zos-uss-for-zowe-sdk": "8.0.0-next.202403132009" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", diff --git a/packages/zosfiles/src/methods/upload/Upload.ts b/packages/zosfiles/src/methods/upload/Upload.ts index 5c90d5c31c..570796a722 100644 --- a/packages/zosfiles/src/methods/upload/Upload.ts +++ b/packages/zosfiles/src/methods/upload/Upload.ts @@ -447,33 +447,62 @@ export class Upload { * Upload content to USS file * @param {AbstractSession} session - z/OS connection info * @param {string} ussname - Name of the USS file to write to - * @param {Buffer} buffer - Data to be written + * @param {Buffer} fileBuffer - Data to be written * @param {IUploadOptions} [options={}] - Uploading options - * @returns {Promise} + * @returns {Promise} */ public static async bufferToUssFile(session: AbstractSession, ussname: string, - buffer: Buffer, - options: IUploadOptions = {}) { + fileBuffer: Buffer, + options: IUploadOptions = {}): Promise { ImperativeExpect.toNotBeEqual(options.record, true, ZosFilesMessages.unsupportedDataType.message); options.binary = options.binary ? options.binary : false; ImperativeExpect.toNotBeNullOrUndefined(ussname, ZosFilesMessages.missingUSSFileName.message); ussname = ZosFilesUtils.sanitizeUssPathForRestCall(ussname); - const parameters: string = ZosFilesConstants.RES_USS_FILES + "/" + ussname; - const headers: IHeaderContent[] = this.generateHeadersBasedOnOptions(options, "buffer"); - return ZosmfRestClient.putExpectString(session, ZosFilesConstants.RESOURCE + parameters, headers, buffer); + const endpoint = ZosFilesConstants.RESOURCE + ZosFilesConstants.RES_USS_FILES + "/" + ussname; + const reqHeaders: IHeaderContent[] = this.generateHeadersBasedOnOptions(options, "buffer"); + + if (!options.binary) { + fileBuffer = ZosFilesUtils.normalizeNewline(fileBuffer); + } + + // Options to use the buffer to write a file + const requestOptions: IOptionsFullResponse = { + resource: endpoint, + reqHeaders, + writeData: fileBuffer + }; + + // If requestor needs etag, add header + get "response" back + if (options.returnEtag) { + requestOptions.dataToReturn = [CLIENT_PROPERTY.response]; + } + const uploadRequest: IRestClientResponse = await ZosmfRestClient.putExpectFullResponse(session, requestOptions); + + // By default, apiResponse is empty when uploading + const apiResponse: any = {}; + + // Return Etag in apiResponse, if requested + if (options.returnEtag) { + apiResponse.etag = uploadRequest.response.headers.etag; + } + + return { + success: true, + commandResponse: ZosFilesMessages.dataSetUploadedSuccessfully.message, + apiResponse + }; } /** * Upload content to USS file * @param {AbstractSession} session - z/OS connection info * @param {string} ussname - Name of the USS file to write to - * @param {Buffer} uploadStream - Data to be written + * @param {Stream} uploadStream - Data to be written * @param {IUploadOptions} [options={}] - Uploading options * @returns {Promise} - A response indicating the outcome */ - public static async streamToUssFile(session: AbstractSession, ussname: string, uploadStream: Readable, diff --git a/packages/zosjobs/package.json b/packages/zosjobs/package.json index 74ae95bf62..bddb536ca0 100644 --- a/packages/zosjobs/package.json +++ b/packages/zosjobs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "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.0.0-next.202403131702" + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202403132009" }, "devDependencies": { - "@zowe/cli-test-utils": "8.0.0-next.202403131702", - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", diff --git a/packages/zoslogs/package.json b/packages/zoslogs/package.json index f4480e9d1c..46c7396343 100644 --- a/packages/zoslogs/package.json +++ b/packages/zoslogs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "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.0.0-next.202403131702", - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", diff --git a/packages/zosmf/package.json b/packages/zosmf/package.json index c5273dfe5a..0b1c41b83d 100644 --- a/packages/zosmf/package.json +++ b/packages/zosmf/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "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.0.0-next.202403131702", - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", diff --git a/packages/zostso/package.json b/packages/zostso/package.json index fbb3258092..dd2b25cabc 100644 --- a/packages/zostso/package.json +++ b/packages/zostso/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "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.0.0-next.202403131702" + "@zowe/zosmf-for-zowe-sdk": "8.0.0-next.202403132009" }, "devDependencies": { - "@zowe/cli-test-utils": "8.0.0-next.202403131702", - "@zowe/core-for-zowe-sdk": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0-next", diff --git a/packages/zosuss/CHANGELOG.md b/packages/zosuss/CHANGELOG.md index aa7e4833f2..0c8bc5e813 100644 --- a/packages/zosuss/CHANGELOG.md +++ b/packages/zosuss/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to the Zowe z/OS USS SDK package will be documented in this file. +## `8.0.0-next.202403132009` + +- Enhancement: Provide more legible errors to user when they are missing user/password credentials while +running `zowe zos-uss issue ssh` commands. [#2081](https://github.com/zowe/zowe-cli/pull/2081) + ## `8.0.0-next.202403041352` - BugFix: Updated engine to Node 18.12.0. [#2074](https://github.com/zowe/zowe-cli/pull/2074) diff --git a/packages/zosuss/package.json b/packages/zosuss/package.json index 9dbac99c18..a7bd9a50b0 100644 --- a/packages/zosuss/package.json +++ b/packages/zosuss/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "8.0.0-next.202403131702", + "version": "8.0.0-next.202403132009", "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.19", - "@zowe/cli-test-utils": "8.0.0-next.202403131702", - "@zowe/imperative": "8.0.0-next.202403131702" + "@zowe/cli-test-utils": "8.0.0-next.202403132009", + "@zowe/imperative": "8.0.0-next.202403132009" }, "peerDependencies": { "@zowe/imperative": "^8.0.0-next" diff --git a/packages/zosuss/src/SshBaseHandler.ts b/packages/zosuss/src/SshBaseHandler.ts index 156af231b1..cf76092a5f 100644 --- a/packages/zosuss/src/SshBaseHandler.ts +++ b/packages/zosuss/src/SshBaseHandler.ts @@ -21,12 +21,12 @@ import { IHandlerProgressApi, IImperativeError, ImperativeError, - ConnectionPropsForSessCfg + ConnectionPropsForSessCfg, + SessConstants } from "@zowe/imperative"; import { SshSession } from "./SshSession"; import { ISshSession } from "./doc/ISshSession"; - /** * This class is used by the various handlers in the project as the base class for their implementation. */ @@ -64,7 +64,11 @@ export abstract class SshBaseHandler implements ICommandHandler { }]; const sshSessCfg: ISshSession = SshSession.createSshSessCfgFromArgs(commandParameters.arguments); const sshSessCfgWithCreds = await ConnectionPropsForSessCfg.addPropsOrPrompt( - sshSessCfg, commandParameters.arguments, {parms: commandParameters, propertyOverrides: sshSessCfgOverride} + sshSessCfg, commandParameters.arguments, { + parms: commandParameters, + propertyOverrides: sshSessCfgOverride, + supportedAuthTypes: [SessConstants.AUTH_TYPE_BASIC] + } ); this.mSession = new SshSession(sshSessCfgWithCreds);