From 3e494caf54f6ac5d7486ce44d78a352484ad1799 Mon Sep 17 00:00:00 2001 From: Timothy Johnson Date: Wed, 12 Jan 2022 12:58:42 -0500 Subject: [PATCH 01/14] Fix daemon parsing of double-byte chars Signed-off-by: Timothy Johnson --- packages/cli/CHANGELOG.md | 4 ++ .../daemon/__unit__/DaemonClient.unit.test.ts | 42 +++++++++++-------- .../DaemonClient.unit.test.ts.snap | 14 ++++--- packages/cli/src/daemon/DaemonClient.ts | 7 ++-- 4 files changed, 39 insertions(+), 28 deletions(-) diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index c87660c986..fe8a99eef7 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the Zowe CLI package will be documented in this file. +## Recent Changes + +- BugFix: Fixed stdin data being corrupted when daemon server processes CLI command containing double-byte characters. + ## `7.0.0-next.202201121428` - BugFix: Set executable attribute on zowe executable file on Linux and Mac. diff --git a/packages/cli/__tests__/daemon/__unit__/DaemonClient.unit.test.ts b/packages/cli/__tests__/daemon/__unit__/DaemonClient.unit.test.ts index 339a5012ed..c15ffa90da 100644 --- a/packages/cli/__tests__/daemon/__unit__/DaemonClient.unit.test.ts +++ b/packages/cli/__tests__/daemon/__unit__/DaemonClient.unit.test.ts @@ -50,9 +50,9 @@ describe("DaemonClient tests", () => { const daemonClient = new DaemonClient(client as any, server, "fake"); const daemonResponse: IDaemonResponse = { - argv: ["feed", "dog"], + argv: ["feed", "🐶"], cwd: "fake", - env: {}, + env: { FORCE_COLOR: "0" }, stdinLength: 0, stdin: null, user: Buffer.from("fake").toString('base64') @@ -61,9 +61,10 @@ describe("DaemonClient tests", () => { daemonClient.run(); // force `data` call and verify input is from instantiation of DaemonClient // and is what is passed to mocked Imperative.parse via snapshot - (daemonClient as any).data(JSON.stringify(daemonResponse)); + const stringData = JSON.stringify(daemonResponse); + (daemonClient as any).data(Buffer.from(stringData)); - expect(log).toHaveBeenLastCalledWith('daemon input command: feed dog'); + expect(log).toHaveBeenLastCalledWith('daemon input command: feed 🐶'); expect(log).toHaveBeenCalledTimes(2); expect(parse).toHaveBeenCalled(); }); @@ -99,9 +100,9 @@ describe("DaemonClient tests", () => { }; const daemonClient = new DaemonClient(client as any, server, "fake"); - const stdinData = String.fromCharCode(...Array(256).keys()); + const stdinData = String.fromCharCode(...Array(1024).keys()); const daemonResponse: IDaemonResponse = { - argv: ["feed", "cat"], + argv: ["feed", "🐱"], cwd: "fake", env: {}, stdinLength: stdinData.length, @@ -114,11 +115,11 @@ describe("DaemonClient tests", () => { // force `data` call and verify input is from instantiation of DaemonClient // and is what is passed to mocked Imperative.parse via snapshot const stringData = JSON.stringify(daemonResponse) + "\f" + stdinData; - await (daemonClient as any).data(stringData); + await (daemonClient as any).data(Buffer.from(stringData)); - expect(log).toHaveBeenLastCalledWith('daemon input command: feed cat'); + expect(log).toHaveBeenLastCalledWith('daemon input command: feed 🐱'); expect(log).toHaveBeenCalledTimes(2); - expect(writeToStdinSpy).toHaveBeenCalledWith(stdinData, stdinData.length); + expect(writeToStdinSpy).toHaveBeenCalledWith(Buffer.from(stdinData), stdinData.length); expect(parse).toHaveBeenCalled(); }); @@ -157,7 +158,7 @@ describe("DaemonClient tests", () => { daemonClient.run(); // force `data` call and verify input is from instantiation of DaemonClient // and is what is passed to mocked Imperative.parse via snapshot - (daemonClient as any).data("not json"); + (daemonClient as any).data(Buffer.from("not json")); expect(log).toHaveBeenCalledTimes(3); expect(log).toHaveBeenLastCalledWith("First 1024 bytes of daemon request:\n", "not json"); @@ -200,7 +201,8 @@ describe("DaemonClient tests", () => { // force `data` call and verify input is from instantiation of DaemonClient // and is what is passed to mocked Imperative.parse via snapshot const promptResponse = { stdin: "some answer", user: Buffer.from("fake").toString('base64') }; - (daemonClient as any).data(JSON.stringify(promptResponse)); + const stringData = JSON.stringify(promptResponse); + (daemonClient as any).data(Buffer.from(stringData)); expect(log).toHaveBeenCalledTimes(1); expect(parse).not.toHaveBeenCalled(); @@ -246,7 +248,8 @@ describe("DaemonClient tests", () => { daemonClient.run(); // force `data` call and verify write method is called with termination message const shutdownResponse = { stdin: DaemonClient.CTRL_C_CHAR, user: Buffer.from("fake").toString('base64') }; - (daemonClient as any).data(JSON.stringify(shutdownResponse)); + const stringData = JSON.stringify(shutdownResponse); + (daemonClient as any).data(Buffer.from(stringData)); expect(log).toHaveBeenCalledTimes(2); expect(shutdownSpy).toHaveBeenCalledTimes(1); @@ -339,7 +342,7 @@ describe("DaemonClient tests", () => { const daemonClient = new DaemonClient(client as any, server, "fake"); const daemonResponse: IDaemonResponse = { - argv: ["feed", "dog"], + argv: ["feed", "🐶"], cwd: "fake", env: {}, stdinLength: 0, @@ -350,7 +353,8 @@ describe("DaemonClient tests", () => { daemonClient.run(); // force `data` call and verify input is from instantiation of DaemonClient // and is what is passed to mocked Imperative.parse via snapshot - (daemonClient as any).data(JSON.stringify(daemonResponse)); + const stringData = JSON.stringify(daemonResponse); + (daemonClient as any).data(Buffer.from(stringData)); expect(log).toHaveBeenCalledTimes(2); expect(log).toHaveBeenLastCalledWith("The user 'ekaf' attempted to connect."); @@ -390,7 +394,7 @@ describe("DaemonClient tests", () => { const daemonClient = new DaemonClient(client as any, server, "fake"); const daemonResponse: IDaemonResponse = { - argv: ["feed", "dog"], + argv: ["feed", "🐶"], cwd: "fake", env: {}, stdinLength: 0, @@ -400,7 +404,8 @@ describe("DaemonClient tests", () => { daemonClient.run(); // force `data` call and verify input is from instantiation of DaemonClient // and is what is passed to mocked Imperative.parse via snapshot - (daemonClient as any).data(JSON.stringify(daemonResponse)); + const stringData = JSON.stringify(daemonResponse); + (daemonClient as any).data(Buffer.from(stringData)); expect(log).toHaveBeenCalledTimes(2); expect(log).toHaveBeenLastCalledWith("A connection was attempted without a valid user."); @@ -440,7 +445,7 @@ describe("DaemonClient tests", () => { const daemonClient = new DaemonClient(client as any, server, "fake"); const daemonResponse: IDaemonResponse = { - argv: ["feed", "dog"], + argv: ["feed", "🐶"], cwd: "fake", env: {}, stdinLength: 0, @@ -451,7 +456,8 @@ describe("DaemonClient tests", () => { daemonClient.run(); // force `data` call and verify input is from instantiation of DaemonClient // and is what is passed to mocked Imperative.parse via snapshot - (daemonClient as any).data(JSON.stringify(daemonResponse)); + const stringData = JSON.stringify(daemonResponse); + (daemonClient as any).data(Buffer.from(stringData)); expect(log).toHaveBeenCalledTimes(2); expect(log).toHaveBeenLastCalledWith("The user 'zF�' attempted to connect."); diff --git a/packages/cli/__tests__/daemon/__unit__/__snapshots__/DaemonClient.unit.test.ts.snap b/packages/cli/__tests__/daemon/__unit__/__snapshots__/DaemonClient.unit.test.ts.snap index c21c47ad1e..138d50a6d2 100644 --- a/packages/cli/__tests__/daemon/__unit__/__snapshots__/DaemonClient.unit.test.ts.snap +++ b/packages/cli/__tests__/daemon/__unit__/__snapshots__/DaemonClient.unit.test.ts.snap @@ -3,7 +3,7 @@ exports[`DaemonClient tests should process data when received 1`] = ` Array [ "feed", - "dog", + "🐶", ] `; @@ -12,10 +12,12 @@ Object { "daemonResponse": Object { "argv": Array [ "feed", - "dog", + "🐶", ], "cwd": "fake", - "env": Object {}, + "env": Object { + "FORCE_COLOR": "0", + }, "stdin": null, "stdinLength": 0, "user": "ZmFrZQ==", @@ -60,7 +62,7 @@ Object { exports[`DaemonClient tests should process response with binary stdin data when received 1`] = ` Array [ "feed", - "cat", + "🐱", ] `; @@ -69,12 +71,12 @@ Object { "daemonResponse": Object { "argv": Array [ "feed", - "cat", + "🐱", ], "cwd": "fake", "env": Object {}, "stdin": null, - "stdinLength": 256, + "stdinLength": 1024, "user": "ZmFrZQ==", }, "stream": Object { diff --git a/packages/cli/src/daemon/DaemonClient.ts b/packages/cli/src/daemon/DaemonClient.ts index c89ae87882..0b450410bb 100644 --- a/packages/cli/src/daemon/DaemonClient.ts +++ b/packages/cli/src/daemon/DaemonClient.ts @@ -143,13 +143,12 @@ export class DaemonClient { if (this.pendingStdinLength > 0) return; // Split JSON body and binary data from multipart response - const stringData = data.toString(); - const jsonEndIdx = stringData.indexOf("}" + DaemonRequest.EOW_DELIMITER); + const jsonEndIdx = data.indexOf("}" + DaemonRequest.EOW_DELIMITER); let jsonData: IDaemonResponse; let stdinData: Buffer; try { - jsonData = JSON.parse(jsonEndIdx !== -1 ? stringData.slice(0, jsonEndIdx + 1) : stringData); + jsonData = JSON.parse((jsonEndIdx !== -1 ? data.slice(0, jsonEndIdx + 1) : data).toString()); stdinData = jsonEndIdx !== -1 ? data.slice(jsonEndIdx + 2) : undefined; } catch (error) { Imperative.api.appLogger.logError(new ImperativeError({ @@ -157,7 +156,7 @@ export class DaemonClient { causeErrors: error })); // eslint-disable-next-line @typescript-eslint/no-magic-numbers - Imperative.api.appLogger.trace("First 1024 bytes of daemon request:\n", stringData.slice(0, 1024)); + Imperative.api.appLogger.trace("First 1024 bytes of daemon request:\n", data.slice(0, 1024).toString()); const responsePayload: string = DaemonRequest.create({ stderr: "Failed to parse data received from daemon client:\n" + error.stack, exitCode: 1 From e7957ad9edde8864f70a3159e4b094f4a89d2b67 Mon Sep 17 00:00:00 2001 From: Timothy Johnson Date: Wed, 12 Jan 2022 14:56:15 -0500 Subject: [PATCH 02/14] Clean up Rust code and add watch script Signed-off-by: Timothy Johnson --- package.json | 1 + zowex/src/main.rs | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 8ac5083221..a660c066bc 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "test:system": "cross-env FORCE_COLOR=1 jest \".*__tests__.*\\**\\.system\\.(spec|test)\\.ts\\$\" --coverage false", "test:unit": "cross-env FORCE_COLOR=1 jest \".*__tests__.*\\**\\.unit\\.(spec|test)\\.ts\\$\" --coverage", "watch": "lerna run --parallel watch", + "watch:exe": "cd zowex && cargo install cargo-watch && cargo watch -x build -x test", "watch:test": "jest --watch", "doc:clean": "rimraf docs/CLIReadme.md", "doc:generate": "npm run doc:clean && gulp doc", diff --git a/zowex/src/main.rs b/zowex/src/main.rs index 1afd093beb..c06449b539 100644 --- a/zowex/src/main.rs +++ b/zowex/src/main.rs @@ -94,7 +94,7 @@ struct DaemonResponse { // >> } | Measure-Object -Property TotalSeconds -Average // 3.6393932 and 0.76156812 zowe average over 10 run sample = 2.87782508 sec faster on windows -fn main() -> std::io::Result<()> { +fn main() -> io::Result<()> { // turn args into vector let mut _args: Vec = env::args().collect(); let cmd_result: Result; @@ -261,7 +261,7 @@ fn get_zowe_env() -> HashMap { ).collect() } -fn run_daemon_command(args: &mut Vec) -> std::io::Result<()> { +fn run_daemon_command(args: &mut Vec) -> io::Result<()> { let cwd = env::current_dir()?; let mut stdin = Vec::new(); if !atty::is(Stream::Stdin) { @@ -293,7 +293,7 @@ fn run_daemon_command(args: &mut Vec) -> std::io::Result<()> { * Attempt to make a TCP connection to the daemon. * Iterate to enable a slow system to start the daemon. */ -fn establish_connection(host: String, port: String) -> std::io::Result { +fn establish_connection(host: String, port: String) -> io::Result { const THREE_SEC_DELAY: u64 = 3; const THREE_MIN_OF_RETRIES: i32 = 60; const RETRY_TO_SHOW_DIAG: i32 = 5; From 8c3b39af5624571b36750a637ac62dd73c75848e Mon Sep 17 00:00:00 2001 From: Timothy Johnson Date: Wed, 12 Jan 2022 15:18:31 -0500 Subject: [PATCH 03/14] Lint Rust code with clippy and add a test Signed-off-by: Timothy Johnson --- package.json | 4 +- zowex/src/main.rs | 183 +++++++++++++++++++++------------------------- 2 files changed, 85 insertions(+), 102 deletions(-) diff --git a/package.json b/package.json index a660c066bc..d42fd0c301 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ ], "scripts": { "build": "gulp updateLicense && lerna run build && npm run lint && npm run checkTestsCompile && npm run circularDependencyCheck", - "build:exe": "cd zowex && cargo build && cargo test", + "build:exe": "cd zowex && cargo build && cargo clippy && cargo test", "clean": "lerna run --parallel clean", "clean:exe": "cd zowex && cargo clean", "installWithBuild": "npm install && npm run build", @@ -28,7 +28,7 @@ "test:system": "cross-env FORCE_COLOR=1 jest \".*__tests__.*\\**\\.system\\.(spec|test)\\.ts\\$\" --coverage false", "test:unit": "cross-env FORCE_COLOR=1 jest \".*__tests__.*\\**\\.unit\\.(spec|test)\\.ts\\$\" --coverage", "watch": "lerna run --parallel watch", - "watch:exe": "cd zowex && cargo install cargo-watch && cargo watch -x build -x test", + "watch:exe": "cd zowex && cargo install cargo-watch && cargo watch -x build -x clippy -x test", "watch:test": "jest --watch", "doc:clean": "rimraf docs/CLIReadme.md", "doc:generate": "npm run doc:clean && gulp doc", diff --git a/zowex/src/main.rs b/zowex/src/main.rs index c06449b539..f01e05350f 100644 --- a/zowex/src/main.rs +++ b/zowex/src/main.rs @@ -11,7 +11,7 @@ use std::collections::HashMap; use std::env; -use std::ffi::OsString; + use std::io; use std::io::prelude::*; use std::io::BufReader; @@ -102,11 +102,9 @@ fn main() -> io::Result<()> { _args.drain(..1); // remove first (exe name) // Do we only need to display our version? - if _args.len() >= 1 { - if _args[0] == "--version-exe" { - println!("{}", env!("CARGO_PKG_VERSION")); - std::process::exit(EXIT_CODE_SUCCESS); - } + if !_args.is_empty() && _args[0] == "--version-exe" { + println!("{}", env!("CARGO_PKG_VERSION")); + std::process::exit(EXIT_CODE_SUCCESS); } // daemon commands that overwrite our executable cannot be run by our executable @@ -161,7 +159,7 @@ fn main() -> io::Result<()> { * The user-supplied command line arguments to the zowe command. * Each argument is in its own vector element. */ -fn exit_when_alt_cmd_needed(cmd_line_args: &Vec) { +fn exit_when_alt_cmd_needed(cmd_line_args: &[String]) { // commands other than daemon commands can be run by our exe if cmd_line_args.len() < 2 { return; @@ -192,7 +190,7 @@ fn exit_when_alt_cmd_needed(cmd_line_args: &Vec) { // We use COMSPEC so that the command will work for CMD and PowerShell match env::var("COMSPEC") { Ok(comspec_val) => { - if comspec_val.len() > 0 { + if !comspec_val.is_empty() { if comspec_val.contains(' ') { zowe_cmd_to_show.push('"'); zowe_cmd_to_show.push_str(&comspec_val); @@ -229,7 +227,7 @@ fn exit_when_alt_cmd_needed(cmd_line_args: &Vec) { * @returns * A String containing all of the command line arguments. */ -fn arg_vec_to_string(arg_vec: &Vec) -> String { +fn arg_vec_to_string(arg_vec: &[String]) -> String { let mut arg_string = String::new(); let mut arg_count = 1; for next_arg in arg_vec.iter() { @@ -241,7 +239,7 @@ fn arg_vec_to_string(arg_vec: &Vec) -> String { * enclosed in double quotes when it is placed into a single argument * string. */ - if next_arg.contains(' ') || next_arg.len() == 0 { + if next_arg.contains(' ') || next_arg.is_empty() { arg_string.push('"'); arg_string.push_str(next_arg); arg_string.push('"'); @@ -249,10 +247,10 @@ fn arg_vec_to_string(arg_vec: &Vec) -> String { arg_string.push_str(next_arg); } - arg_count = arg_count + 1; + arg_count += 1; } - return arg_string; + arg_string } fn get_zowe_env() -> HashMap { @@ -286,7 +284,7 @@ fn run_daemon_command(args: &mut Vec) -> io::Result<()> { let port_string = get_port_string(); let mut stream = establish_connection(daemon_host, port_string)?; - Ok(talk(&_resp, &mut stream)?) + talk(&_resp, &mut stream) } /** @@ -314,23 +312,21 @@ fn establish_connection(host: String, port: String) -> io::Result { let daemon_proc_info = is_daemon_running(); // when not running, start it. - if daemon_proc_info.is_running == false { + if !daemon_proc_info.is_running { if conn_retries == 0 { // start the daemon and continue trying to connect let njs_zowe_path = get_nodejs_zowe_path(); we_started_daemon = true; cmd_to_show = start_daemon(&njs_zowe_path); - } else { - if we_started_daemon { - println!("The Zowe daemon that we started is not running on host = {} with port = {}.", - host, port - ); - println!( - "Command used to start the Zowe daemon was:\n {}\nTerminating.", - cmd_to_show - ); - std::process::exit(EXIT_CODE_DAEMON_NOT_RUNNING_AFTER_START); - } + } else if we_started_daemon { + println!("The Zowe daemon that we started is not running on host = {} with port = {}.", + host, port + ); + println!( + "Command used to start the Zowe daemon was:\n {}\nTerminating.", + cmd_to_show + ); + std::process::exit(EXIT_CODE_DAEMON_NOT_RUNNING_AFTER_START); } } @@ -364,7 +360,7 @@ fn establish_connection(host: String, port: String) -> io::Result { if conn_retries > 0 { println!("{} ({} of {})", retry_msg, conn_retries, THREE_MIN_OF_RETRIES); } - conn_retries = conn_retries + 1; + conn_retries += 1; }; Ok(stream) @@ -374,7 +370,7 @@ fn talk(message: &[u8], stream: &mut TcpStream) -> io::Result<()> { /* * Send the command line arguments to the daemon and await responses. */ - stream.write(message).unwrap(); // write it + stream.write_all(message).unwrap(); // write it let mut stream_clone = stream.try_clone().expect("clone failed"); let mut reader = BufReader::new(&*stream); @@ -411,72 +407,54 @@ fn talk(message: &[u8], stream: &mut TcpStream) -> io::Result<()> { } }; - match p.stdout { - Some(s) => { - print!("{}", s); - io::stdout().flush().unwrap(); - } - None => (), // do nothing + if let Some(s) = p.stdout { + print!("{}", s); + io::stdout().flush().unwrap(); } - match p.stderr { - Some(s) => { - eprint!("{}", s); - io::stderr().flush().unwrap(); - } - None => (), // do nothing + if let Some(s) = p.stderr { + eprint!("{}", s); + io::stderr().flush().unwrap(); } - match p.prompt { - Some(s) => { - print!("{}", s); - io::stdout().flush().unwrap(); - let mut reply = String::new(); - io::stdin().read_line(&mut reply).unwrap(); - let response: DaemonResponse = DaemonResponse { - argv: None, - cwd: None, - env: None, - stdinLength: None, - stdin: Some(reply), - user: Some(encode(username())), - }; - let v = serde_json::to_string(&response)?; - - stream_clone.write(v.as_bytes()).unwrap(); - } - None => (), // do nothing + if let Some(s) = p.prompt { + print!("{}", s); + io::stdout().flush().unwrap(); + let mut reply = String::new(); + io::stdin().read_line(&mut reply).unwrap(); + let response: DaemonResponse = DaemonResponse { + argv: None, + cwd: None, + env: None, + stdinLength: None, + stdin: Some(reply), + user: Some(encode(username())), + }; + let v = serde_json::to_string(&response)?; + + stream_clone.write_all(v.as_bytes()).unwrap(); } - match p.securePrompt { - Some(s) => { - print!("{}", s); - io::stdout().flush().unwrap(); - let reply; - reply = read_password().unwrap(); - let response: DaemonResponse = DaemonResponse { - argv: None, - cwd: None, - env: None, - stdinLength: None, - stdin: Some(reply), - user: Some(encode(username())), - }; - let v = serde_json::to_string(&response)?; - stream_clone.write(v.as_bytes()).unwrap(); - } - None => (), // do nothing + if let Some(s) = p.securePrompt { + print!("{}", s); + io::stdout().flush().unwrap(); + let reply; + reply = read_password().unwrap(); + let response: DaemonResponse = DaemonResponse { + argv: None, + cwd: None, + env: None, + stdinLength: None, + stdin: Some(reply), + user: Some(encode(username())), + }; + let v = serde_json::to_string(&response)?; + stream_clone.write_all(v.as_bytes()).unwrap(); } - exit_code = match p.exitCode { - Some(s) => s, - None => 0, // do nothing - }; + exit_code = p.exitCode.unwrap_or(0); - _progress = match p.progress { - Some(s) => s, - None => false, // do nothing - }; + _progress = p.progress.unwrap_or(false); } else { // end of reading break; @@ -510,8 +488,8 @@ fn get_port_string() -> String { Ok(val) => _port = val.parse::().unwrap(), Err(_e) => _port = DEFAULT_PORT, } - let port_string = _port.to_string(); - return port_string; + + _port.to_string() } // Get the file path to the command that runs the NodeJS version of Zowe @@ -541,8 +519,8 @@ fn get_nodejs_zowe_path() -> String { let path_ext = env::var_os("PATHEXT"); for njs_zowe_path_buf in PathSearcher::new( zowe_cmd, - path.as_ref().map(OsString::as_os_str), - path_ext.as_ref().map(OsString::as_os_str), + path.as_deref(), + path_ext.as_deref(), ) { njs_zowe_path = njs_zowe_path_buf.to_string_lossy().to_string(); if njs_zowe_path.to_lowercase().eq(&my_exe_path.to_lowercase()) { @@ -560,7 +538,7 @@ fn get_nodejs_zowe_path() -> String { std::process::exit(EXIT_CODE_NO_NODEJS_ZOWE_ON_PATH); } - return njs_zowe_path; + njs_zowe_path } /** @@ -592,12 +570,12 @@ fn is_daemon_running() -> DaemonProcInfo { }; } } - return DaemonProcInfo { + DaemonProcInfo { is_running: false, name: "no name".to_string(), pid: "no pid".to_string(), cmd: "no cmd".to_string(), - }; + } } /** @@ -618,7 +596,7 @@ fn user_wants_daemon() -> bool { { return false; } - return true; + true } /** @@ -655,7 +633,7 @@ fn run_nodejs_command(cmd_line_args: &mut Vec) -> Result { } }; - return Ok(exit_code); + Ok(exit_code) } /** @@ -726,9 +704,9 @@ fn start_daemon(njs_zowe_path: &str) -> String { // return the command that we run (for display purposes) let mut cmd_to_show: String = njs_zowe_path.to_owned(); - cmd_to_show.push_str(" "); + cmd_to_show.push(' '); cmd_to_show.push_str(daemon_arg); - return cmd_to_show; + cmd_to_show } // @@ -741,11 +719,6 @@ mod tests { // Note this useful idiom: importing names from outer (for mod tests) scope. use super::*; - #[test] - fn test_parse_headers_get_total_length() { - assert_eq!(8, 8); - } - #[test] fn test_get_port_string() { // expect default port with no env @@ -757,4 +730,14 @@ mod tests { let port_string = get_port_string(); assert_eq!("777", port_string); } + + #[test] + fn test_get_zowe_env() { + let env = get_zowe_env(); + assert_eq!(env.keys().len(), 0); + + env::set_var("ZOWE_DAEMON", "777"); + let env = get_zowe_env(); + assert_eq!(env.keys().len(), 1); + } } From 9707e633fe801594a0790f12ae43089d5a8d869f Mon Sep 17 00:00:00 2001 From: Timothy Johnson Date: Wed, 12 Jan 2022 15:23:52 -0500 Subject: [PATCH 04/14] Fix unit test not cleaning up properly Signed-off-by: Timothy Johnson --- zowex/src/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zowex/src/main.rs b/zowex/src/main.rs index f01e05350f..32aaf59592 100644 --- a/zowex/src/main.rs +++ b/zowex/src/main.rs @@ -739,5 +739,7 @@ mod tests { env::set_var("ZOWE_DAEMON", "777"); let env = get_zowe_env(); assert_eq!(env.keys().len(), 1); + + env::remove_var("ZOWE_DAEMON"); } } From bd64b42c6bff23611dfce0f4c7f5bc53d1da8631 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Thu, 13 Jan 2022 17:52:46 -0500 Subject: [PATCH 05/14] Disable kills Linux daemon. Tell user to open new terminal Signed-off-by: Gene Johnston --- .../cli.daemon.disable.integration.test.ts | 18 ++- .../cli.daemon.enable.integration.test.ts | 22 ++-- .../disable/Disable.handler.unit.test.ts | 54 +++++++++ .../enable/Enable.handler.unit.test.ts | 105 +++++++++++++++++- .../cli/src/daemon/disable/Disable.handler.ts | 19 +++- .../cli/src/daemon/enable/Enable.handler.ts | 11 +- 6 files changed, 208 insertions(+), 21 deletions(-) diff --git a/packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.test.ts b/packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.test.ts index 608e530f9b..bf8ab3a307 100644 --- a/packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.test.ts +++ b/packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.test.ts @@ -26,6 +26,8 @@ let testEnvironment: ITestEnvironment; describe("daemon disable", () => { const rimrafSync = require("rimraf").sync; const fakeExeContent = "This is not a real executable"; + const zoweCmdRegEx = "zowe.*[/|\\\\]cli[/|\\\\]lib[/|\\\\]main.js.* --daemon" + "|" + + "[/|\\\\]bin[/|\\\\]zowe.* --daemon"; let exePath: string; let pathToBin: string; @@ -116,6 +118,11 @@ describe("daemon disable", () => { const response = runCliScript(__dirname + "/__scripts__/daemon_disable.sh", testEnvironment); const stdoutStr = response.stdout.toString(); expect(stdoutStr).toContain("Zowe CLI daemon mode is disabled."); + if (ProcessUtils.getBasicSystemInfo().platform === "win32") { + expect(stdoutStr).not.toContain("close this terminal and open a new terminal"); + } else { + expect(stdoutStr).toContain("close this terminal and open a new terminal"); + } expect(response.status).toBe(0); } }); @@ -143,9 +150,8 @@ describe("daemon disable", () => { const procArray = await findProc('name', 'node', true); // match and kill any running Zowe daemon - const zoweCmdRegEx = "@zowe[/|\\\\]cli[/|\\\\]lib[/|\\\\]main.js"; for (const nextProc of procArray) { - if (nextProc.cmd.match(zoweCmdRegEx) && nextProc.cmd.includes("--daemon")) { + if (nextProc.cmd.match(zoweCmdRegEx)) { process.kill(nextProc.pid, "SIGINT"); } } @@ -173,12 +179,14 @@ describe("daemon disable", () => { // match any running Zowe daemon const findProc = require('find-process'); const procArray = await findProc('name', 'node', true); - const zoweCmdRegEx = "@zowe[/|\\\\]cli[/|\\\\]lib[/|\\\\]main.js"; + let weFoundDaemon = false; for (const nextProc of procArray) { - if (nextProc.cmd.match(zoweCmdRegEx) && nextProc.cmd.includes("--daemon")) { - expect("we should not find a daemon").toContain("so the disable command failed."); + if (nextProc.cmd.match(zoweCmdRegEx)) { + weFoundDaemon = true; + break; } } + expect(weFoundDaemon).toBe(false); } }); }); diff --git a/packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.test.ts b/packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.test.ts index 23e634b438..1de6af2242 100644 --- a/packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.test.ts +++ b/packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.test.ts @@ -164,7 +164,7 @@ describe("daemon enable", () => { if (willRunNodeJsZowe()) { const response = runCliScript(__dirname + "/__scripts__/daemon_enable.sh", testEnvironment); const stdoutStr = response.stdout.toString(); - expect(stdoutStr).toContain("Zowe CLI daemon mode enabled"); + expect(stdoutStr).toContain("Zowe CLI daemon mode is enabled"); expect(stdoutStr).toContain("Zowe CLI native executable version ="); expect(IO.existsSync(exePath)).toBe(true); expect(response.status).toBe(0); @@ -176,7 +176,7 @@ describe("daemon enable", () => { fs.mkdirSync(pathToBin, 0o755); const response = runCliScript(__dirname + "/__scripts__/daemon_enable.sh", testEnvironment); const stdoutStr = response.stdout.toString(); - expect(stdoutStr).toContain("Zowe CLI daemon mode enabled"); + expect(stdoutStr).toContain("Zowe CLI daemon mode is enabled"); expect(stdoutStr).toContain("Zowe CLI native executable version ="); expect(IO.existsSync(exePath)).toBe(true); expect(response.status).toBe(0); @@ -191,7 +191,7 @@ describe("daemon enable", () => { const response = runCliScript(__dirname + "/__scripts__/daemon_enable.sh", testEnvironment); const stdoutStr = response.stdout.toString(); - expect(stdoutStr).toContain("Zowe CLI daemon mode enabled"); + expect(stdoutStr).toContain("Zowe CLI daemon mode is enabled"); expect(IO.existsSync(exePath)).toBe(true); // our test tgz file is more than 10 bytes larger than this fake tgz @@ -205,10 +205,11 @@ describe("daemon enable", () => { if (willRunNodeJsZowe()) { const response = runCliScript(__dirname + "/__scripts__/daemon_enable.sh", testEnvironment); const stdoutStr = response.stdout.toString(); - expect(stdoutStr).toContain("Zowe CLI daemon mode enabled"); + expect(stdoutStr).toContain("Zowe CLI daemon mode is enabled"); expect(stdoutStr).toContain("Zowe CLI native executable version ="); expect(stdoutStr).toContain(`Add '${pathToBin}' to your PATH`); expect(stdoutStr).toContain("Otherwise, you will continue to run the classic Zowe CLI interpreter"); + expect(stdoutStr).toContain("close this terminal and open a new terminal"); expect(IO.existsSync(exePath)).toBe(true); expect(response.status).toBe(0); } @@ -222,9 +223,14 @@ describe("daemon enable", () => { testEnvironment.env["PATH"] = pathOrig; const stdoutStr = response.stdout.toString(); - expect(stdoutStr).toContain("Zowe CLI daemon mode enabled"); + expect(stdoutStr).toContain("Zowe CLI daemon mode is enabled"); expect(stdoutStr).toContain("Zowe CLI native executable version ="); expect(stdoutStr).not.toContain(`Add '${pathToBin}' to your PATH`); + if (ProcessUtils.getBasicSystemInfo().platform === "win32") { + expect(stdoutStr).not.toContain("close this terminal and open a new terminal"); + } else { + expect(stdoutStr).toContain("close this terminal and open a new terminal"); + } expect(IO.existsSync(exePath)).toBe(true); expect(response.status).toBe(0); } @@ -237,7 +243,7 @@ describe("daemon enable", () => { delete testEnvironment.env.ZOWE_USE_DAEMON; const stdoutStr = response.stdout.toString(); - expect(stdoutStr).toContain("Zowe CLI daemon mode enabled"); + expect(stdoutStr).toContain("Zowe CLI daemon mode is enabled"); expect(stdoutStr).toContain("Zowe CLI native executable version ="); expect(stdoutStr).toContain("Your ZOWE_USE_DAEMON environment variable is set to 'no'"); expect(stdoutStr).toContain("You must remove it, or set it to 'yes' to use daemon mode"); @@ -251,7 +257,7 @@ describe("daemon enable", () => { delete testEnvironment.env.ZOWE_USE_DAEMON; const response = runCliScript(__dirname + "/__scripts__/daemon_enable.sh", testEnvironment); const stdoutStr = response.stdout.toString(); - expect(stdoutStr).toContain("Zowe CLI daemon mode enabled"); + expect(stdoutStr).toContain("Zowe CLI daemon mode is enabled"); expect(testEnvironment.env["ZOWE_USE_DAEMON"]).toBeFalsy(); expect(stdoutStr).not.toContain("Your ZOWE_USE_DAEMON environment variable is set to"); expect(IO.existsSync(exePath)).toBe(true); @@ -266,7 +272,7 @@ describe("daemon enable", () => { delete testEnvironment.env.ZOWE_USE_DAEMON; const stdoutStr = response.stdout.toString(); - expect(stdoutStr).toContain("Zowe CLI daemon mode enabled"); + expect(stdoutStr).toContain("Zowe CLI daemon mode is enabled"); expect(stdoutStr).not.toContain("Your ZOWE_USE_DAEMON environment variable is set to"); expect(IO.existsSync(exePath)).toBe(true); expect(response.status).toBe(0); diff --git a/packages/cli/__tests__/daemon/__unit__/disable/Disable.handler.unit.test.ts b/packages/cli/__tests__/daemon/__unit__/disable/Disable.handler.unit.test.ts index 2ea26bf97d..0e82996c2c 100644 --- a/packages/cli/__tests__/daemon/__unit__/disable/Disable.handler.unit.test.ts +++ b/packages/cli/__tests__/daemon/__unit__/disable/Disable.handler.unit.test.ts @@ -84,6 +84,60 @@ describe("Disable daemon handler", () => { expect(logMessage).toContain("Zowe CLI daemon mode is disabled."); }); + it("should tell you to open new terminal on Linux", async () => { + const getBasicSystemInfoOrig = ProcessUtils.getBasicSystemInfo; + ProcessUtils.getBasicSystemInfo = jest.fn(() => { + return { + "arch": "ArchNotNeeded", + "platform": "linux" + }; + }); + + // spy on our handler's private disableDaemon() function + disableDaemonSpy = jest.spyOn(DisableDaemonHandler.prototype as any, "disableDaemon"); + disableDaemonSpy.mockImplementation(() => {return;}); + + let error; + try { + // Invoke the handler with a full set of mocked arguments and response functions + await disableHandler.process(cmdParms); + } catch (e) { + error = e; + } + + expect(error).toBeUndefined(); + expect(disableDaemonSpy).toHaveBeenCalledTimes(1); + expect(logMessage).toContain("Zowe CLI daemon mode is disabled."); + expect(logMessage).toContain("close this terminal and open a new terminal"); + }); + + it("should NOT tell you to open new terminal on Windows", async () => { + const getBasicSystemInfoOrig = ProcessUtils.getBasicSystemInfo; + ProcessUtils.getBasicSystemInfo = jest.fn(() => { + return { + "arch": "ArchNotNeeded", + "platform": "win32" + }; + }); + + // spy on our handler's private disableDaemon() function + disableDaemonSpy = jest.spyOn(DisableDaemonHandler.prototype as any, "disableDaemon"); + disableDaemonSpy.mockImplementation(() => {return;}); + + let error; + try { + // Invoke the handler with a full set of mocked arguments and response functions + await disableHandler.process(cmdParms); + } catch (e) { + error = e; + } + + expect(error).toBeUndefined(); + expect(disableDaemonSpy).toHaveBeenCalledTimes(1); + expect(logMessage).toContain("Zowe CLI daemon mode is disabled."); + expect(logMessage).not.toContain("close this terminal and open a new terminal"); + }); + it("should fail when the disableDaemon function fails", async () => { const badStuffMsg = "Some bad exception happened"; diff --git a/packages/cli/__tests__/daemon/__unit__/enable/Enable.handler.unit.test.ts b/packages/cli/__tests__/daemon/__unit__/enable/Enable.handler.unit.test.ts index f28f29807a..57bf33de3c 100644 --- a/packages/cli/__tests__/daemon/__unit__/enable/Enable.handler.unit.test.ts +++ b/packages/cli/__tests__/daemon/__unit__/enable/Enable.handler.unit.test.ts @@ -129,7 +129,7 @@ describe("Handler for daemon enable", () => { expect(error).toBeUndefined(); expect(enableDaemonSpy).toHaveBeenCalledTimes(1); - expect(logMessage).toContain("Zowe CLI daemon mode enabled."); + expect(logMessage).toContain("Zowe CLI daemon mode is enabled."); expect(logMessage).toContain(allOkMsg); }); @@ -369,6 +369,7 @@ describe("Handler for daemon enable", () => { expect(error).toBeUndefined(); expect(unzipTgzSpy).toHaveBeenCalledTimes(1); expect(userInfoMsg).toContain(`Add '${zoweBinDirMock}' to your PATH.`); + expect(userInfoMsg).toContain("close this terminal and open a new terminal"); IO.existsSync = existsSyncOrig; IO.isDir = isDirOrig; @@ -376,6 +377,108 @@ describe("Handler for daemon enable", () => { process.env.PATH = pathOrig; }); + it("should tell you to open new terminal on Linux even when PATH is set", async () => { + // Mock the IO functions to simulate stuff is working + const existsSyncOrig = IO.existsSync; + IO.existsSync = jest.fn(() => { + return true; + }); + + const isDirOrig = IO.isDir; + IO.isDir = jest.fn(() => { + return true; + }); + + const createDirSyncOrig = IO.createDirSync; + IO.createDirSync = jest.fn(); + + const getBasicSystemInfoOrig = ProcessUtils.getBasicSystemInfo; + ProcessUtils.getBasicSystemInfo = jest.fn(() => { + return { + "arch": "ArchNotNeeded", + "platform": "linux" + }; + }); + + const pathOrig = process.env.PATH; + process.env.PATH = "stuff/in/path:" + + nodeJsPath.normalize(ImperativeConfig.instance.cliHome + "/bin") + + ":more/stuff/in/path"; + + // spy on our handler's private enableDaemon() function + unzipTgzSpy = jest.spyOn(EnableDaemonHandler.prototype as any, "unzipTgz"); + unzipTgzSpy.mockImplementation((tgzFile: string, toDir: string, fileToExtract: string) => {return;}); + + let error; + let userInfoMsg: string; + try { + userInfoMsg = await enableHandler.enableDaemon(); + } catch (e) { + error = e; + } + + expect(error).toBeUndefined(); + expect(unzipTgzSpy).toHaveBeenCalledTimes(1); + expect(userInfoMsg).toContain("close this terminal and open a new terminal"); + + IO.existsSync = existsSyncOrig; + IO.isDir = isDirOrig; + IO.createDirSync = createDirSyncOrig; + ProcessUtils.getBasicSystemInfo = getBasicSystemInfoOrig; + process.env.PATH = pathOrig; + }); + + it("should NOT tell you to open new terminal on Windows when PATH is set", async () => { + // Mock the IO functions to simulate stuff is working + const existsSyncOrig = IO.existsSync; + IO.existsSync = jest.fn(() => { + return true; + }); + + const isDirOrig = IO.isDir; + IO.isDir = jest.fn(() => { + return true; + }); + + const createDirSyncOrig = IO.createDirSync; + IO.createDirSync = jest.fn(); + + const getBasicSystemInfoOrig = ProcessUtils.getBasicSystemInfo; + ProcessUtils.getBasicSystemInfo = jest.fn(() => { + return { + "arch": "ArchNotNeeded", + "platform": "win32" + }; + }); + + const pathOrig = process.env.PATH; + process.env.PATH = "stuff/in/path:" + + nodeJsPath.normalize(ImperativeConfig.instance.cliHome + "/bin") + + ":more/stuff/in/path"; + + // spy on our handler's private enableDaemon() function + unzipTgzSpy = jest.spyOn(EnableDaemonHandler.prototype as any, "unzipTgz"); + unzipTgzSpy.mockImplementation((tgzFile: string, toDir: string, fileToExtract: string) => {return;}); + + let error; + let userInfoMsg: string; + try { + userInfoMsg = await enableHandler.enableDaemon(); + } catch (e) { + error = e; + } + + expect(error).toBeUndefined(); + expect(unzipTgzSpy).toHaveBeenCalledTimes(1); + expect(userInfoMsg).not.toContain("close this terminal and open a new terminal"); + + IO.existsSync = existsSyncOrig; + IO.isDir = isDirOrig; + IO.createDirSync = createDirSyncOrig; + ProcessUtils.getBasicSystemInfo = getBasicSystemInfoOrig; + process.env.PATH = pathOrig; + }); + it("should not mention ZOWE_USE_DAEMON if is unset", async () => { // Mock the IO functions to simulate stuff is working const existsSyncOrig = IO.existsSync; diff --git a/packages/cli/src/daemon/disable/Disable.handler.ts b/packages/cli/src/daemon/disable/Disable.handler.ts index 8d19cdcde7..62a2b54386 100644 --- a/packages/cli/src/daemon/disable/Disable.handler.ts +++ b/packages/cli/src/daemon/disable/Disable.handler.ts @@ -10,6 +10,7 @@ */ import * as nodeJsPath from "path"; +import { spawnSync, StdioOptions } from "child_process"; import { ICommandHandler, IHandlerParameters, ImperativeConfig, ImperativeError, @@ -41,6 +42,10 @@ export default class DisableDaemonHandler implements ICommandHandler { } cmdParams.response.console.log("Zowe CLI daemon mode is disabled."); + if (ProcessUtils.getBasicSystemInfo().platform != "win32") { + cmdParams.response.console.log("To run further Zowe commands, close this terminal and open a new terminal."); + } + cmdParams.response.data.setExitCode(0); } @@ -106,14 +111,20 @@ export default class DisableDaemonHandler implements ICommandHandler { }); } - /* Paths in proc list on Windows sometimes have forward slash - * and sometimes backslash, so allow either. + /* Paths in proc list on Windows sometimes have forward slash and + * sometimes backslash, so allow either. This RegEx is designed to + * match patterns like these: + * + * node /home/someUser/.nvm/versions/node/v17.1.0/bin/zowe --daemon + * node /home/someUser/GitHub/zowe-cli-next/packages/cli/lib/main.js --daemon + * "C:\Program Files\nodejs\node.exe" "C:\Program Files\nodejs\node_modules\@zowe\cli\lib\main.js" --daemon */ - const zoweCmdRegEx = "@zowe[/|\\\\]cli[/|\\\\]lib[/|\\\\]main.js"; + const zoweCmdRegEx = "zowe.*[/|\\\\]cli[/|\\\\]lib[/|\\\\]main.js.* --daemon" + "|" + + "[/|\\\\]bin[/|\\\\]zowe.* --daemon"; // match and kill any running Zowe daemon for (const nextProc of procArray) { - if (nextProc.cmd.match(zoweCmdRegEx) && nextProc.cmd.includes("--daemon")) { + if (nextProc.cmd.match(zoweCmdRegEx)) { process.kill(nextProc.pid, "SIGINT"); } } diff --git a/packages/cli/src/daemon/enable/Enable.handler.ts b/packages/cli/src/daemon/enable/Enable.handler.ts index 2e71b9fc30..8b611fef15 100644 --- a/packages/cli/src/daemon/enable/Enable.handler.ts +++ b/packages/cli/src/daemon/enable/Enable.handler.ts @@ -44,7 +44,7 @@ export default class EnableDaemonHandler implements ICommandHandler { return; } - cmdParams.response.console.log("Zowe CLI daemon mode enabled.\n" + userMsg); + cmdParams.response.console.log("Zowe CLI daemon mode is enabled.\n" + userMsg); cmdParams.response.data.setExitCode(0); } @@ -128,10 +128,10 @@ export default class EnableDaemonHandler implements ICommandHandler { // display the version of the executable let userInfoMsg: string = "Zowe CLI native executable version = "; const zoweExePath = nodeJsPath.resolve(zoweHomeBin, exeFileName); - const pipe: StdioOptions = ["pipe", "pipe", process.stderr]; + const ioOpts: StdioOptions = ["pipe", "pipe", process.stderr]; try { const spawnResult = spawnSync(zoweExePath, ["--version-exe"], { - stdio: pipe, + stdio: ioOpts, shell: false }); if (spawnResult.stdout) { @@ -145,8 +145,10 @@ export default class EnableDaemonHandler implements ICommandHandler { } // if ZOWE_CLI_HOME/bin is not on our PATH, add an instruction to add it + let musSetPath = false; if (process.env?.PATH?.length > 0) { if (!process.env.PATH.includes(zoweHomeBin)) { + musSetPath = true; userInfoMsg += `\n\nAdd '${zoweHomeBin}' to your PATH.` + "\nOtherwise, you will continue to run the classic Zowe CLI interpreter."; } @@ -164,6 +166,9 @@ export default class EnableDaemonHandler implements ICommandHandler { } } + if (musSetPath || ProcessUtils.getBasicSystemInfo().platform != "win32") { + userInfoMsg += "\n\nTo run further Zowe commands, close this terminal and open a new terminal."; + } return userInfoMsg; } From 1b7d4615a656568d30738aa17a612e7cbf320c31 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Thu, 13 Jan 2022 19:37:30 -0500 Subject: [PATCH 06/14] Removed unused spawnSync and StdioOptions. Signed-off-by: Gene Johnston --- packages/cli/src/daemon/disable/Disable.handler.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cli/src/daemon/disable/Disable.handler.ts b/packages/cli/src/daemon/disable/Disable.handler.ts index 62a2b54386..626e6f0b67 100644 --- a/packages/cli/src/daemon/disable/Disable.handler.ts +++ b/packages/cli/src/daemon/disable/Disable.handler.ts @@ -10,7 +10,6 @@ */ import * as nodeJsPath from "path"; -import { spawnSync, StdioOptions } from "child_process"; import { ICommandHandler, IHandlerParameters, ImperativeConfig, ImperativeError, From 1b508c3f2e5f031c58d90cd4bbb16eb20b15e7a7 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Fri, 14 Jan 2022 16:53:12 -0500 Subject: [PATCH 07/14] Add logic for adding bin to PATH. Don't call it Signed-off-by: Gene Johnston --- .../cli.daemon.enable.integration.test.ts | 2 +- .../enable/Enable.handler.unit.test.ts | 32 ++-- .../cli/src/daemon/doc/IAnswerQuestions.ts | 22 +++ .../cli/src/daemon/enable/Enable.handler.ts | 173 +++++++++++++++--- 4 files changed, 192 insertions(+), 37 deletions(-) create mode 100644 packages/cli/src/daemon/doc/IAnswerQuestions.ts diff --git a/packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.test.ts b/packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.test.ts index 1de6af2242..75bdceaf72 100644 --- a/packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.test.ts +++ b/packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.test.ts @@ -207,7 +207,7 @@ describe("daemon enable", () => { const stdoutStr = response.stdout.toString(); expect(stdoutStr).toContain("Zowe CLI daemon mode is enabled"); expect(stdoutStr).toContain("Zowe CLI native executable version ="); - expect(stdoutStr).toContain(`Add '${pathToBin}' to your PATH`); + expect(stdoutStr).toContain(`Manually add '${pathToBin}' to your PATH`); expect(stdoutStr).toContain("Otherwise, you will continue to run the classic Zowe CLI interpreter"); expect(stdoutStr).toContain("close this terminal and open a new terminal"); expect(IO.existsSync(exePath)).toBe(true); diff --git a/packages/cli/__tests__/daemon/__unit__/enable/Enable.handler.unit.test.ts b/packages/cli/__tests__/daemon/__unit__/enable/Enable.handler.unit.test.ts index 57bf33de3c..1dd3769af0 100644 --- a/packages/cli/__tests__/daemon/__unit__/enable/Enable.handler.unit.test.ts +++ b/packages/cli/__tests__/daemon/__unit__/enable/Enable.handler.unit.test.ts @@ -13,6 +13,7 @@ jest.mock("child_process"); // using child_process from the __mocks__ directory import { ImperativeConfig, ImperativeError, IO, ProcessUtils, ISystemInfo } from "@zowe/imperative"; +import { IAnswerQuestions } from "../../../../src/daemon/doc/IAnswerQuestions"; import EnableDaemonHandler from "../../../../src/daemon/enable/Enable.handler"; import * as fs from "fs"; @@ -172,6 +173,13 @@ describe("Handler for daemon enable", () => { }); const zoweBinDirMock = cliHomeDirMock + nodeJsPath.sep + "bin"; + const noAskNoAddPath: IAnswerQuestions = { + addBinToPath: { + askUser: false, + defaultVal: "n" + } + }; + it("should fail on an unsupported platform", async () => { const getBasicSystemInfoOrig = ProcessUtils.getBasicSystemInfo; ProcessUtils.getBasicSystemInfo = jest.fn(() => { @@ -183,7 +191,7 @@ describe("Handler for daemon enable", () => { let error; try { - await enableHandler.enableDaemon(); + await enableHandler.enableDaemon(noAskNoAddPath); } catch (e) { error = e; } @@ -200,7 +208,7 @@ describe("Handler for daemon enable", () => { let error; try { - await enableHandler.enableDaemon(); + await enableHandler.enableDaemon(noAskNoAddPath); } catch (e) { error = e; } @@ -222,7 +230,7 @@ describe("Handler for daemon enable", () => { let error; try { - await enableHandler.enableDaemon(); + await enableHandler.enableDaemon(noAskNoAddPath); } catch (e) { error = e; } @@ -247,7 +255,7 @@ describe("Handler for daemon enable", () => { let error; try { - await enableHandler.enableDaemon(); + await enableHandler.enableDaemon(noAskNoAddPath); } catch (e) { error = e; } @@ -280,7 +288,7 @@ describe("Handler for daemon enable", () => { let error; let userInfoMsg: string; try { - userInfoMsg = await enableHandler.enableDaemon(); + userInfoMsg = await enableHandler.enableDaemon(noAskNoAddPath); } catch (e) { error = e; } @@ -322,7 +330,7 @@ describe("Handler for daemon enable", () => { let error; let userInfoMsg: string; try { - userInfoMsg = await enableHandler.enableDaemon(); + userInfoMsg = await enableHandler.enableDaemon(noAskNoAddPath); } catch (e) { error = e; } @@ -361,14 +369,14 @@ describe("Handler for daemon enable", () => { let error; let userInfoMsg: string; try { - userInfoMsg = await enableHandler.enableDaemon(); + userInfoMsg = await enableHandler.enableDaemon(noAskNoAddPath); } catch (e) { error = e; } expect(error).toBeUndefined(); expect(unzipTgzSpy).toHaveBeenCalledTimes(1); - expect(userInfoMsg).toContain(`Add '${zoweBinDirMock}' to your PATH.`); + expect(userInfoMsg).toContain(`Manually add '${zoweBinDirMock}' to your PATH.`); expect(userInfoMsg).toContain("close this terminal and open a new terminal"); IO.existsSync = existsSyncOrig; @@ -412,7 +420,7 @@ describe("Handler for daemon enable", () => { let error; let userInfoMsg: string; try { - userInfoMsg = await enableHandler.enableDaemon(); + userInfoMsg = await enableHandler.enableDaemon(noAskNoAddPath); } catch (e) { error = e; } @@ -463,7 +471,7 @@ describe("Handler for daemon enable", () => { let error; let userInfoMsg: string; try { - userInfoMsg = await enableHandler.enableDaemon(); + userInfoMsg = await enableHandler.enableDaemon(noAskNoAddPath); } catch (e) { error = e; } @@ -501,7 +509,7 @@ describe("Handler for daemon enable", () => { let error; let userInfoMsg: string; try { - userInfoMsg = await enableHandler.enableDaemon(); + userInfoMsg = await enableHandler.enableDaemon(noAskNoAddPath); } catch (e) { error = e; } @@ -542,7 +550,7 @@ describe("Handler for daemon enable", () => { let error; let userInfoMsg: string; try { - userInfoMsg = await enableHandler.enableDaemon(); + userInfoMsg = await enableHandler.enableDaemon(noAskNoAddPath); } catch (e) { error = e; } diff --git a/packages/cli/src/daemon/doc/IAnswerQuestions.ts b/packages/cli/src/daemon/doc/IAnswerQuestions.ts new file mode 100644 index 0000000000..6fb93a9a9c --- /dev/null +++ b/packages/cli/src/daemon/doc/IAnswerQuestions.ts @@ -0,0 +1,22 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +/** + * Specifies wwhether a question can be asked of the user, and if not, + * what value should be used by default. + */ +export interface IAnswerQuestions { + // Can we add .zowe/bin to PATH? + addBinToPath: { + askUser: boolean; // can we ask the user? + defaultVal: string; // default value when we do not ask + } +} diff --git a/packages/cli/src/daemon/enable/Enable.handler.ts b/packages/cli/src/daemon/enable/Enable.handler.ts index 8b611fef15..5ab77dc81e 100644 --- a/packages/cli/src/daemon/enable/Enable.handler.ts +++ b/packages/cli/src/daemon/enable/Enable.handler.ts @@ -19,6 +19,8 @@ import { IO, ISystemInfo, ProcessUtils } from "@zowe/imperative"; +import { IAnswerQuestions } from "../doc/IAnswerQuestions"; + /** * Handler to enable daemon mode. * @export @@ -26,6 +28,8 @@ import { * @implements {ICommandHandler} */ export default class EnableDaemonHandler implements ICommandHandler { + private static openNewTerminalMsg = "To run further Zowe commands, close this terminal and open a new terminal."; + /** * Process the enable daemon command and populates the response * object as needed. @@ -37,7 +41,17 @@ export default class EnableDaemonHandler implements ICommandHandler { public async process(cmdParams: IHandlerParameters): Promise { let userMsg: string; try { - userMsg = await this.enableDaemon(); + const userQuestions: IAnswerQuestions = { + addBinToPath: { + /* TODO: Use this code block when we are ready to automatically add zowe/bin to the PATH + askUser: true, + defaultVal: "y" + */ + askUser: false, + defaultVal: "n" + } + }; + userMsg = await this.enableDaemon(userQuestions); } catch(impErr) { cmdParams.response.console.log("Failed to enable Zowe CLI daemon mode.\n" + (impErr as ImperativeError).message); cmdParams.response.data.setExitCode(1); @@ -54,10 +68,12 @@ export default class EnableDaemonHandler implements ICommandHandler { * * @throws {ImperativeError} * + * @param {boolean} canAskQuestions Can we interactively ask the user questions? + * * @returns {string} An informational message to display to the user after * successful completion of the operation. */ - private async enableDaemon(): Promise { + private async enableDaemon(userQuestions: IAnswerQuestions): Promise { // determine our current OS const sysInfo: ISystemInfo = ProcessUtils.getBasicSystemInfo(); @@ -93,29 +109,29 @@ export default class EnableDaemonHandler implements ICommandHandler { } // form the path to the bin directory in ZOWE_CLI_HOME - const zoweHomeBin = nodeJsPath.normalize(ImperativeConfig.instance.cliHome + "/bin"); + const pathToZoweBin = nodeJsPath.normalize(ImperativeConfig.instance.cliHome + "/bin"); // Does the ZOWE_CLI_HOME bin directory exist? - if (IO.existsSync(zoweHomeBin)) { - if (!IO.isDir(zoweHomeBin)) { + if (IO.existsSync(pathToZoweBin)) { + if (!IO.isDir(pathToZoweBin)) { throw new ImperativeError({ - msg: `The existing file '${zoweHomeBin}' must be a directory.` + msg: `The existing file '${pathToZoweBin}' must be a directory.` }); } } else { // create the directory try { - IO.createDirSync(zoweHomeBin); + IO.createDirSync(pathToZoweBin); } catch(err) { throw new ImperativeError({ - msg: `Unable to create directory '${zoweHomeBin}'.\nReason: ${err}` + msg: `Unable to create directory '${pathToZoweBin}'.\nReason: ${err}` }); } } // extract executable from the tar file into the bin directory - await this.unzipTgz(preBldTgz, zoweHomeBin, ImperativeConfig.instance.rootCommandName); + await this.unzipTgz(preBldTgz, pathToZoweBin, ImperativeConfig.instance.rootCommandName); /* Even though we await the unzip above, the OS still considers the exe file in-use * for a while. We will get the following error message when trying to run the exe. @@ -127,8 +143,8 @@ export default class EnableDaemonHandler implements ICommandHandler { // display the version of the executable let userInfoMsg: string = "Zowe CLI native executable version = "; - const zoweExePath = nodeJsPath.resolve(zoweHomeBin, exeFileName); - const ioOpts: StdioOptions = ["pipe", "pipe", process.stderr]; + const zoweExePath = nodeJsPath.resolve(pathToZoweBin, exeFileName); + const ioOpts: StdioOptions = ["pipe", "pipe", "pipe"]; try { const spawnResult = spawnSync(zoweExePath, ["--version-exe"], { stdio: ioOpts, @@ -138,21 +154,17 @@ export default class EnableDaemonHandler implements ICommandHandler { // remove any newlines from the version number userInfoMsg += spawnResult.stdout.toString().replace(/\r?\n|\r/g, ""); } else { - userInfoMsg += "Failed to get version number"; + userInfoMsg += "Failed to get version number\n"; + if (spawnResult.stderr) { + userInfoMsg += spawnResult.stderr.toString(); + } } } catch (err) { userInfoMsg += err.message; } - // if ZOWE_CLI_HOME/bin is not on our PATH, add an instruction to add it - let musSetPath = false; - if (process.env?.PATH?.length > 0) { - if (!process.env.PATH.includes(zoweHomeBin)) { - musSetPath = true; - userInfoMsg += `\n\nAdd '${zoweHomeBin}' to your PATH.` + - "\nOtherwise, you will continue to run the classic Zowe CLI interpreter."; - } - } + // add our bin directory to the PATH if is it is not already there + userInfoMsg += await this.addZoweBinToPath(pathToZoweBin, userQuestions); // if ZOWE_USE_DAEMON is set, and turned off, add a warning message if (process.env?.ZOWE_USE_DAEMON?.length > 0) { @@ -166,9 +178,6 @@ export default class EnableDaemonHandler implements ICommandHandler { } } - if (musSetPath || ProcessUtils.getBasicSystemInfo().platform != "win32") { - userInfoMsg += "\n\nTo run further Zowe commands, close this terminal and open a new terminal."; - } return userInfoMsg; } @@ -212,4 +221,120 @@ export default class EnableDaemonHandler implements ICommandHandler { }); }); } + + /** + * Add our .zowe/bin directory to the user's PATH. + * + * @param pathToZoweBin The absolute path to our .zowe/bin drectory. + * + * @param {IAnswerQuestions} userQuestions Questions for user (if permitted) + * + * @returns {string} An informational message to display to the user after + * successful completion of the operation. + */ + private async addZoweBinToPath(pathToZoweBin: string, userQuestions: IAnswerQuestions): Promise { + let userInfoMsg: string = ""; + const osPlatform: string = ProcessUtils.getBasicSystemInfo().platform; + + if (process.env.PATH?.includes(pathToZoweBin)) { + // bash & zsh command-path caching forces us to require a new terminal + if ( osPlatform !== "win32") { + userInfoMsg += "\n\n" + EnableDaemonHandler.openNewTerminalMsg; + } + } else { + // ZOWE_CLI_HOME/bin is not on our PATH, we want to add it + let answer: string = null; + if (userQuestions.addBinToPath.askUser) { + // alter PATH question by OS + let pathQuestion = "May we add the Zowe bin directory to your\nPATH in your "; + if ( osPlatform === "win32") { + pathQuestion += "permanent user environment"; + } else { + pathQuestion += ".profile file"; + } + pathQuestion += " [y or n] ? "; + // ask user for permission to update PATH + answer = await CliUtils.readPrompt(pathQuestion); + } else { + // don't ask, just use default + answer = userQuestions.addBinToPath.defaultVal; + } + + if (answer !== null && answer === "y" || answer === "Y") { + // user wants us to do it for him/her + if ( osPlatform === "win32") { + userInfoMsg += await this.addZoweBinOnWindows(pathToZoweBin); + } else { + userInfoMsg += this.addZoweBinOnPosix(pathToZoweBin); + } + } else { + userInfoMsg += `\n\nManually add '${pathToZoweBin}' to your PATH.` + + "\nOtherwise, you will continue to run the classic Zowe CLI interpreter."; + } + + // when zowe/bin not already on path, user needs a new terminal + userInfoMsg += "\n\n" + EnableDaemonHandler.openNewTerminalMsg; + } // end zowe/bin not in path + + return userInfoMsg; + } + + /** + * Add our .zowe/bin directory to the front of the user's PATH on Windows. + * + * @param pathToZoweBin The absolute path to our .zowe/bin drectory. + * + * @returns {string} An informational message to display to the user after + * successful completion of the operation. + */ + private async addZoweBinOnWindows(pathToZoweBin: string): Promise { + let userInfoMsg: string = ""; + try { + /* TODO: + * - Detect if zowe/bin is in system or user PATH env variable + * - For user PATH : reg query "HKCU\Environment" + * - For system PATH: reg query "???" + * - Add zowe/bin to the front of either user or system PATH + * - confirm that we do not exceed max path (1024 for user) + * - For system PATH + * - get user name + * - prompt for password + * - Use setx to set the new PATH value + */ + + const ioOptions: StdioOptions = ["pipe", "pipe", "pipe"]; + const spawnResult = spawnSync("setx", + ["zowe_set_env_test", pathToZoweBin + ";" + process.env.PATH], + { + stdio: ioOptions, + shell: false + } + ); + if (spawnResult.stdout) { + userInfoMsg += spawnResult.stdout.toString(); + } + if (spawnResult.stderr) { + userInfoMsg += spawnResult.stderr.toString(); + } + } catch (err) { + userInfoMsg += "Failed to run setx. Reason = " + err.message; + } + + return userInfoMsg; + } + + /** + * Add our .zowe/bin directory to the front of the user's PATH on Linux and MAC. + * Do that by adding a line at the end of the user's .profile file. + * + * @param pathToZoweBin The absolute path to our .zowe/bin drectory. + * + * @returns {string} An informational message to display to the user after + * successful completion of the operation. + */ + private addZoweBinOnPosix(pathToZoweBin: string): string { + // Todo: Implement addZoweBinOnPosix + const userInfoMsg: string = ""; + return userInfoMsg; + } } From c7b10c04ad6db471e7cdc21a3d5e6958c1986721 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Fri, 14 Jan 2022 17:34:36 -0500 Subject: [PATCH 08/14] Add CHANGELOG entries. Signed-off-by: Gene Johnston --- packages/cli/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index fe8a99eef7..8fb70347cd 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -4,7 +4,9 @@ All notable changes to the Zowe CLI package will be documented in this file. ## Recent Changes +- BugFix: Fixed 'daemon disable' command to kill any running zowe daemon on Linux and Mac. [#1270](https://github.com/zowe/zowe-cli/issues/1270) - BugFix: Fixed stdin data being corrupted when daemon server processes CLI command containing double-byte characters. +- Enhancement: Added a user message within 'daemon enable' and disable to open a new terminal when needed. ## `7.0.0-next.202201121428` From 383e79c565ef320d8f4d0ecf18655f50570f16d5 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Tue, 18 Jan 2022 17:59:07 -0500 Subject: [PATCH 09/14] Rename IAnswerQuestions and simplify structure. Signed-off-by: Gene Johnston --- .../enable/Enable.handler.unit.test.ts | 10 +++---- .../cli/src/daemon/doc/IAnswerQuestions.ts | 22 --------------- .../src/daemon/doc/IDaemonEnableQuestions.ts | 23 +++++++++++++++ .../cli/src/daemon/enable/Enable.handler.ts | 28 +++++++++---------- 4 files changed, 40 insertions(+), 43 deletions(-) delete mode 100644 packages/cli/src/daemon/doc/IAnswerQuestions.ts create mode 100644 packages/cli/src/daemon/doc/IDaemonEnableQuestions.ts diff --git a/packages/cli/__tests__/daemon/__unit__/enable/Enable.handler.unit.test.ts b/packages/cli/__tests__/daemon/__unit__/enable/Enable.handler.unit.test.ts index 1dd3769af0..eba2dccd75 100644 --- a/packages/cli/__tests__/daemon/__unit__/enable/Enable.handler.unit.test.ts +++ b/packages/cli/__tests__/daemon/__unit__/enable/Enable.handler.unit.test.ts @@ -13,7 +13,7 @@ jest.mock("child_process"); // using child_process from the __mocks__ directory import { ImperativeConfig, ImperativeError, IO, ProcessUtils, ISystemInfo } from "@zowe/imperative"; -import { IAnswerQuestions } from "../../../../src/daemon/doc/IAnswerQuestions"; +import { IDaemonEnableQuestions } from "../../../../src/daemon/doc/IDaemonEnableQuestions"; import EnableDaemonHandler from "../../../../src/daemon/enable/Enable.handler"; import * as fs from "fs"; @@ -173,11 +173,9 @@ describe("Handler for daemon enable", () => { }); const zoweBinDirMock = cliHomeDirMock + nodeJsPath.sep + "bin"; - const noAskNoAddPath: IAnswerQuestions = { - addBinToPath: { - askUser: false, - defaultVal: "n" - } + const noAskNoAddPath: IDaemonEnableQuestions = { + canAskUser: false, + addBinToPathVal: "n" }; it("should fail on an unsupported platform", async () => { diff --git a/packages/cli/src/daemon/doc/IAnswerQuestions.ts b/packages/cli/src/daemon/doc/IAnswerQuestions.ts deleted file mode 100644 index 6fb93a9a9c..0000000000 --- a/packages/cli/src/daemon/doc/IAnswerQuestions.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -/** - * Specifies wwhether a question can be asked of the user, and if not, - * what value should be used by default. - */ -export interface IAnswerQuestions { - // Can we add .zowe/bin to PATH? - addBinToPath: { - askUser: boolean; // can we ask the user? - defaultVal: string; // default value when we do not ask - } -} diff --git a/packages/cli/src/daemon/doc/IDaemonEnableQuestions.ts b/packages/cli/src/daemon/doc/IDaemonEnableQuestions.ts new file mode 100644 index 0000000000..96eb9b1ece --- /dev/null +++ b/packages/cli/src/daemon/doc/IDaemonEnableQuestions.ts @@ -0,0 +1,23 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +/** + * Specifies wwhether questions can be asked of the user, and if not, + * what value should be used for a question when we do not ask. + */ +export interface IDaemonEnableQuestions { + canAskUser: boolean; // can we ask the user questions? + + /* Answer for the "can we add .zowe/bin to PATH" question. + * The value is only used when we cannot ask the user. + */ + addBinToPathVal: string; +} diff --git a/packages/cli/src/daemon/enable/Enable.handler.ts b/packages/cli/src/daemon/enable/Enable.handler.ts index 5ab77dc81e..3435852858 100644 --- a/packages/cli/src/daemon/enable/Enable.handler.ts +++ b/packages/cli/src/daemon/enable/Enable.handler.ts @@ -19,7 +19,7 @@ import { IO, ISystemInfo, ProcessUtils } from "@zowe/imperative"; -import { IAnswerQuestions } from "../doc/IAnswerQuestions"; +import { IDaemonEnableQuestions } from "../doc/IDaemonEnableQuestions"; /** * Handler to enable daemon mode. @@ -41,15 +41,13 @@ export default class EnableDaemonHandler implements ICommandHandler { public async process(cmdParams: IHandlerParameters): Promise { let userMsg: string; try { - const userQuestions: IAnswerQuestions = { - addBinToPath: { - /* TODO: Use this code block when we are ready to automatically add zowe/bin to the PATH - askUser: true, - defaultVal: "y" - */ - askUser: false, - defaultVal: "n" - } + const userQuestions: IDaemonEnableQuestions = { + /* TODO: Use this code block when we are ready to automatically add zowe/bin to the PATH + canAskUser: true, + addBinToPathVal: "y" + */ + canAskUser: false, + addBinToPathVal: "n" }; userMsg = await this.enableDaemon(userQuestions); } catch(impErr) { @@ -73,7 +71,7 @@ export default class EnableDaemonHandler implements ICommandHandler { * @returns {string} An informational message to display to the user after * successful completion of the operation. */ - private async enableDaemon(userQuestions: IAnswerQuestions): Promise { + private async enableDaemon(userQuestions: IDaemonEnableQuestions): Promise { // determine our current OS const sysInfo: ISystemInfo = ProcessUtils.getBasicSystemInfo(); @@ -227,12 +225,12 @@ export default class EnableDaemonHandler implements ICommandHandler { * * @param pathToZoweBin The absolute path to our .zowe/bin drectory. * - * @param {IAnswerQuestions} userQuestions Questions for user (if permitted) + * @param {IDaemonEnableQuestions} userQuestions Questions for user (if permitted) * * @returns {string} An informational message to display to the user after * successful completion of the operation. */ - private async addZoweBinToPath(pathToZoweBin: string, userQuestions: IAnswerQuestions): Promise { + private async addZoweBinToPath(pathToZoweBin: string, userQuestions: IDaemonEnableQuestions): Promise { let userInfoMsg: string = ""; const osPlatform: string = ProcessUtils.getBasicSystemInfo().platform; @@ -244,7 +242,7 @@ export default class EnableDaemonHandler implements ICommandHandler { } else { // ZOWE_CLI_HOME/bin is not on our PATH, we want to add it let answer: string = null; - if (userQuestions.addBinToPath.askUser) { + if (userQuestions.canAskUser) { // alter PATH question by OS let pathQuestion = "May we add the Zowe bin directory to your\nPATH in your "; if ( osPlatform === "win32") { @@ -257,7 +255,7 @@ export default class EnableDaemonHandler implements ICommandHandler { answer = await CliUtils.readPrompt(pathQuestion); } else { // don't ask, just use default - answer = userQuestions.addBinToPath.defaultVal; + answer = userQuestions.addBinToPathVal; } if (answer !== null && answer === "y" || answer === "Y") { From 3138c4deca81dc42ae40030f33096e4e68ef655b Mon Sep 17 00:00:00 2001 From: "Andrew W. Harn" Date: Wed, 19 Jan 2022 10:54:50 -0500 Subject: [PATCH 10/14] Make the user field on SSH profiles secure Signed-off-by: Andrew W. Harn --- .../imperative.integration.test.ts | 5 +- package-lock.json | 156 +++++++++--------- packages/cli/CHANGELOG.md | 4 + packages/cli/src/imperative.ts | 5 +- packages/zosuss/CHANGELOG.md | 8 + packages/zosuss/src/SshSession.ts | 8 - 6 files changed, 96 insertions(+), 90 deletions(-) diff --git a/__tests__/__integration__/imperative.integration.test.ts b/__tests__/__integration__/imperative.integration.test.ts index 0b9f93acec..b3d42c0247 100644 --- a/__tests__/__integration__/imperative.integration.test.ts +++ b/__tests__/__integration__/imperative.integration.test.ts @@ -103,8 +103,9 @@ describe("imperative create profile", () => { expect(response.stdout.toString()).toContain("Profile created successfully!"); expect(response.stdout.toString()).toContain("FAKEHOST"); expect(response.stdout.toString()).toContain("22"); - expect(response.stdout.toString()).toContain("FAKEUSER"); - expect(response.stdout.toString()).toContain("managed by Zowe CLI"); + expect(response.stdout.toString()).not.toContain("FAKEUSER"); + expect(response.stdout.toString()).toContain("user: managed by Zowe CLI"); + expect(response.stdout.toString()).toContain("password: managed by Zowe CLI"); }); it("should successfully create a profile without username, password, or host", async () => { diff --git a/package-lock.json b/package-lock.json index 438839b098..88c3e2a79c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,7 +62,7 @@ }, "__tests__/__packages__/cli-test-utils": { "name": "@zowe/cli-test-utils", - "version": "7.0.0-next.202201111811", + "version": "7.0.0-next.202201121428", "license": "EPL-2.0", "dependencies": { "@types/js-yaml": "^4.0.0", @@ -24325,22 +24325,22 @@ }, "packages/cli": { "name": "@zowe/cli", - "version": "7.0.0-next.202201111811", + "version": "7.0.0-next.202201121428", "hasInstallScript": true, "license": "EPL-2.0", "dependencies": { - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "@zowe/perf-timing": "1.0.7", - "@zowe/provisioning-for-zowe-sdk": "7.0.0-next.202201111811", - "@zowe/zos-console-for-zowe-sdk": "7.0.0-next.202201111811", - "@zowe/zos-files-for-zowe-sdk": "7.0.0-next.202201111811", - "@zowe/zos-jobs-for-zowe-sdk": "7.0.0-next.202201111811", - "@zowe/zos-logs-for-zowe-sdk": "7.0.0-next.202201111811", - "@zowe/zos-tso-for-zowe-sdk": "7.0.0-next.202201111811", - "@zowe/zos-uss-for-zowe-sdk": "7.0.0-next.202201111811", - "@zowe/zos-workflows-for-zowe-sdk": "7.0.0-next.202201111811", - "@zowe/zosmf-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/provisioning-for-zowe-sdk": "7.0.0-next.202201121428", + "@zowe/zos-console-for-zowe-sdk": "7.0.0-next.202201121428", + "@zowe/zos-files-for-zowe-sdk": "7.0.0-next.202201121428", + "@zowe/zos-jobs-for-zowe-sdk": "7.0.0-next.202201121428", + "@zowe/zos-logs-for-zowe-sdk": "7.0.0-next.202201121428", + "@zowe/zos-tso-for-zowe-sdk": "7.0.0-next.202201121428", + "@zowe/zos-uss-for-zowe-sdk": "7.0.0-next.202201121428", + "@zowe/zos-workflows-for-zowe-sdk": "7.0.0-next.202201121428", + "@zowe/zosmf-for-zowe-sdk": "7.0.0-next.202201121428", "find-process": "1.4.7", "get-stdin": "7.0.0", "lodash": "4.17.21", @@ -24356,7 +24356,7 @@ "@types/node": "^12.12.24", "@types/tar": "6.1.1", "@types/which": "2.0.1", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", "comment-json": "^4.1.0", "eslint": "^7.32.0", "js-yaml": "^3.13.1", @@ -24427,7 +24427,7 @@ }, "packages/core": { "name": "@zowe/core-for-zowe-sdk", - "version": "7.0.0-next.202201111811", + "version": "7.0.0-next.202201121428", "license": "EPL-2.0", "dependencies": { "comment-json": "4.1.0", @@ -24435,7 +24435,7 @@ }, "devDependencies": { "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "chalk": "^4.1.0", "eslint": "^7.32.0", @@ -24450,7 +24450,7 @@ }, "packages/provisioning": { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "7.0.0-next.202201111811", + "version": "7.0.0-next.202201121428", "license": "EPL-2.0", "dependencies": { "js-yaml": "3.14.1" @@ -24458,8 +24458,8 @@ "devDependencies": { "@types/js-yaml": "^3.12.5", "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "eslint": "^7.32.0", "madge": "^4.0.1", @@ -24480,15 +24480,15 @@ }, "packages/workflows": { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "7.0.0-next.202201111811", + "version": "7.0.0-next.202201121428", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.0.0-next.202201111811" + "@zowe/zos-files-for-zowe-sdk": "7.0.0-next.202201121428" }, "devDependencies": { "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "eslint": "^7.32.0", "madge": "^4.0.1", @@ -24503,12 +24503,12 @@ }, "packages/zosconsole": { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "7.0.0-next.202201111811", + "version": "7.0.0-next.202201121428", "license": "EPL-2.0", "devDependencies": { "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "eslint": "^7.32.0", "madge": "^4.0.1", @@ -24523,17 +24523,17 @@ }, "packages/zosfiles": { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "7.0.0-next.202201111811", + "version": "7.0.0-next.202201121428", "license": "EPL-2.0", "dependencies": { "minimatch": "3.0.4" }, "devDependencies": { "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", - "@zowe/zos-uss-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/zos-uss-for-zowe-sdk": "7.0.0-next.202201121428", "eslint": "^7.32.0", "madge": "^4.0.1", "rimraf": "^2.6.3", @@ -24547,15 +24547,15 @@ }, "packages/zosjobs": { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "7.0.0-next.202201111811", + "version": "7.0.0-next.202201121428", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.0.0-next.202201111811" + "@zowe/zos-files-for-zowe-sdk": "7.0.0-next.202201121428" }, "devDependencies": { "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "eslint": "^7.32.0", "madge": "^4.0.1", @@ -24570,12 +24570,12 @@ }, "packages/zoslogs": { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "7.0.0-next.202201111811", + "version": "7.0.0-next.202201121428", "license": "EPL-2.0", "devDependencies": { "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "eslint": "^7.32.0", "madge": "^4.0.1", @@ -24590,12 +24590,12 @@ }, "packages/zosmf": { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "7.0.0-next.202201111811", + "version": "7.0.0-next.202201121428", "license": "EPL-2.0", "devDependencies": { "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "eslint": "^7.32.0", "madge": "^4.0.1", @@ -24610,15 +24610,15 @@ }, "packages/zostso": { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "7.0.0-next.202201111811", + "version": "7.0.0-next.202201121428", "license": "EPL-2.0", "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "7.0.0-next.202201111811" + "@zowe/zosmf-for-zowe-sdk": "7.0.0-next.202201121428" }, "devDependencies": { "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "eslint": "^7.32.0", "madge": "^4.0.1", @@ -24633,7 +24633,7 @@ }, "packages/zosuss": { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "7.0.0-next.202201111811", + "version": "7.0.0-next.202201121428", "license": "EPL-2.0", "dependencies": { "ssh2": "1.4.0" @@ -24641,7 +24641,7 @@ "devDependencies": { "@types/node": "^12.12.24", "@types/ssh2": "^0.5.44", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "eslint": "^7.32.0", "madge": "^4.0.1", @@ -28608,19 +28608,19 @@ "@types/node": "^12.12.24", "@types/tar": "6.1.1", "@types/which": "2.0.1", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "@zowe/perf-timing": "1.0.7", - "@zowe/provisioning-for-zowe-sdk": "7.0.0-next.202201111811", - "@zowe/zos-console-for-zowe-sdk": "7.0.0-next.202201111811", - "@zowe/zos-files-for-zowe-sdk": "7.0.0-next.202201111811", - "@zowe/zos-jobs-for-zowe-sdk": "7.0.0-next.202201111811", - "@zowe/zos-logs-for-zowe-sdk": "7.0.0-next.202201111811", - "@zowe/zos-tso-for-zowe-sdk": "7.0.0-next.202201111811", - "@zowe/zos-uss-for-zowe-sdk": "7.0.0-next.202201111811", - "@zowe/zos-workflows-for-zowe-sdk": "7.0.0-next.202201111811", - "@zowe/zosmf-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/provisioning-for-zowe-sdk": "7.0.0-next.202201121428", + "@zowe/zos-console-for-zowe-sdk": "7.0.0-next.202201121428", + "@zowe/zos-files-for-zowe-sdk": "7.0.0-next.202201121428", + "@zowe/zos-jobs-for-zowe-sdk": "7.0.0-next.202201121428", + "@zowe/zos-logs-for-zowe-sdk": "7.0.0-next.202201121428", + "@zowe/zos-tso-for-zowe-sdk": "7.0.0-next.202201121428", + "@zowe/zos-uss-for-zowe-sdk": "7.0.0-next.202201121428", + "@zowe/zos-workflows-for-zowe-sdk": "7.0.0-next.202201121428", + "@zowe/zosmf-for-zowe-sdk": "7.0.0-next.202201121428", "comment-json": "^4.1.0", "eslint": "^7.32.0", "find-process": "1.4.7", @@ -28752,7 +28752,7 @@ "version": "file:packages/core", "requires": { "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "chalk": "^4.1.0", "comment-json": "4.1.0", @@ -28900,8 +28900,8 @@ "requires": { "@types/js-yaml": "^3.12.5", "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "eslint": "^7.32.0", "js-yaml": "3.14.1", @@ -28923,8 +28923,8 @@ "version": "file:packages/zosconsole", "requires": { "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "eslint": "^7.32.0", "madge": "^4.0.1", @@ -28937,10 +28937,10 @@ "version": "file:packages/zosfiles", "requires": { "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", - "@zowe/zos-uss-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/zos-uss-for-zowe-sdk": "7.0.0-next.202201121428", "eslint": "^7.32.0", "madge": "^4.0.1", "minimatch": "3.0.4", @@ -28953,10 +28953,10 @@ "version": "file:packages/zosjobs", "requires": { "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", - "@zowe/zos-files-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/zos-files-for-zowe-sdk": "7.0.0-next.202201121428", "eslint": "^7.32.0", "madge": "^4.0.1", "rimraf": "^2.6.3", @@ -28968,8 +28968,8 @@ "version": "file:packages/zoslogs", "requires": { "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "eslint": "^7.32.0", "madge": "^4.0.1", @@ -28982,10 +28982,10 @@ "version": "file:packages/zostso", "requires": { "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", - "@zowe/zosmf-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/zosmf-for-zowe-sdk": "7.0.0-next.202201121428", "eslint": "^7.32.0", "madge": "^4.0.1", "rimraf": "^2.6.3", @@ -28998,7 +28998,7 @@ "requires": { "@types/node": "^12.12.24", "@types/ssh2": "^0.5.44", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "eslint": "^7.32.0", "madge": "^4.0.1", @@ -29012,10 +29012,10 @@ "version": "file:packages/workflows", "requires": { "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", - "@zowe/zos-files-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/zos-files-for-zowe-sdk": "7.0.0-next.202201121428", "eslint": "^7.32.0", "madge": "^4.0.1", "rimraf": "^2.6.3", @@ -29027,8 +29027,8 @@ "version": "file:packages/zosmf", "requires": { "@types/node": "^12.12.24", - "@zowe/cli-test-utils": "7.0.0-next.202201111811", - "@zowe/core-for-zowe-sdk": "7.0.0-next.202201111811", + "@zowe/cli-test-utils": "7.0.0-next.202201121428", + "@zowe/core-for-zowe-sdk": "7.0.0-next.202201121428", "@zowe/imperative": "5.0.0-next.202201111920", "eslint": "^7.32.0", "madge": "^4.0.1", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index c87660c986..626594343a 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the Zowe CLI package will be documented in this file. +## Recent Changes + +- **BREAKING** Enhancement: Make the `user` field on SSH profiles secure. [#682](https://github.com/zowe/zowe-cli/issues/682) + ## `7.0.0-next.202201121428` - BugFix: Set executable attribute on zowe executable file on Linux and Mac. diff --git a/packages/cli/src/imperative.ts b/packages/cli/src/imperative.ts index 1ec30a5862..789c5a0028 100644 --- a/packages/cli/src/imperative.ts +++ b/packages/cli/src/imperative.ts @@ -379,7 +379,7 @@ const config: IImperativeConfig = { properties: { host: { type: "string", - optionDefinition: SshSession.SSH_OPTION_HOST_PROFILE, + optionDefinition: SshSession.SSH_OPTION_HOST, includeInTemplate: true }, port: { @@ -389,7 +389,8 @@ const config: IImperativeConfig = { }, user: { type: "string", - optionDefinition: SshSession.SSH_OPTION_USER_PROFILE + secure: true, + optionDefinition: SshSession.SSH_OPTION_USER }, password: { type: "string", diff --git a/packages/zosuss/CHANGELOG.md b/packages/zosuss/CHANGELOG.md index 9daaa9e09e..30459308a2 100644 --- a/packages/zosuss/CHANGELOG.md +++ b/packages/zosuss/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to the Zowe z/OS USS SDK package will be documented in this file. +## Recent Changes + +- **Breaking**: Removed the following command option definitions: + - SSH_OPTION_HOST_PROFILE + - Replace with SSH_OPTION_HOST + - SSH_OPTION_USER_PROFILE + - Replace with SSH_OPTION_USER + ## `7.0.0-next.202106071827` - **Breaking**: Removed the following [deprecated API functions](https://github.com/zowe/zowe-cli/pull/1022): diff --git a/packages/zosuss/src/SshSession.ts b/packages/zosuss/src/SshSession.ts index eed37052e8..2b779915d3 100644 --- a/packages/zosuss/src/SshSession.ts +++ b/packages/zosuss/src/SshSession.ts @@ -53,10 +53,6 @@ export class SshSession { required: false, group: SshSession.SSH_CONNECTION_OPTION_GROUP }; - public static SSH_OPTION_HOST_PROFILE: ICommandOptionDefinition = { - ...SshSession.SSH_OPTION_HOST, - required: false - }; /** * Option used in profile creation and commands for port for z/OS SSH @@ -81,10 +77,6 @@ export class SshSession { required: false, group: SshSession.SSH_CONNECTION_OPTION_GROUP }; - public static SSH_OPTION_USER_PROFILE: ICommandOptionDefinition = { - ...SshSession.SSH_OPTION_USER, - required: false - }; /** * Option used in profile creation and commands for password/passphrase for z/OS SSH From 72f624a399a7a77f729fd2a4b80284c8f21b8caa Mon Sep 17 00:00:00 2001 From: "Andrew W. Harn" Date: Wed, 19 Jan 2022 11:47:43 -0500 Subject: [PATCH 11/14] Deprecate instead of remove Signed-off-by: Andrew W. Harn --- packages/zosuss/CHANGELOG.md | 2 +- packages/zosuss/src/SshSession.ts | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/zosuss/CHANGELOG.md b/packages/zosuss/CHANGELOG.md index 30459308a2..7336861a00 100644 --- a/packages/zosuss/CHANGELOG.md +++ b/packages/zosuss/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to the Zowe z/OS USS SDK package will be documented in this ## Recent Changes -- **Breaking**: Removed the following command option definitions: +- Documentation: Deprecated the following command option definitions: - SSH_OPTION_HOST_PROFILE - Replace with SSH_OPTION_HOST - SSH_OPTION_USER_PROFILE diff --git a/packages/zosuss/src/SshSession.ts b/packages/zosuss/src/SshSession.ts index 2b779915d3..2c83b30923 100644 --- a/packages/zosuss/src/SshSession.ts +++ b/packages/zosuss/src/SshSession.ts @@ -54,6 +54,11 @@ export class SshSession { group: SshSession.SSH_CONNECTION_OPTION_GROUP }; + /** + * @deprecated Use SSH_OPTION_HOST + */ + public static SSH_OPTION_HOST_PROFILE: ICommandOptionDefinition = this.SSH_OPTION_HOST; + /** * Option used in profile creation and commands for port for z/OS SSH */ @@ -78,6 +83,11 @@ export class SshSession { group: SshSession.SSH_CONNECTION_OPTION_GROUP }; + /** + * @deprecated Use SSH_OPTION_USER + */ + public static SSH_OPTION_USER_PROFILE: ICommandOptionDefinition = this.SSH_OPTION_USER; + /** * Option used in profile creation and commands for password/passphrase for z/OS SSH */ From 96cde271ec8e49df1e4b67fe3d98cbf4ec24312a Mon Sep 17 00:00:00 2001 From: "Andrew W. Harn" Date: Wed, 19 Jan 2022 11:55:52 -0500 Subject: [PATCH 12/14] Don't use 'this' Signed-off-by: Andrew W. Harn --- packages/zosuss/src/SshSession.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/zosuss/src/SshSession.ts b/packages/zosuss/src/SshSession.ts index 2c83b30923..3579651ce2 100644 --- a/packages/zosuss/src/SshSession.ts +++ b/packages/zosuss/src/SshSession.ts @@ -57,7 +57,7 @@ export class SshSession { /** * @deprecated Use SSH_OPTION_HOST */ - public static SSH_OPTION_HOST_PROFILE: ICommandOptionDefinition = this.SSH_OPTION_HOST; + public static SSH_OPTION_HOST_PROFILE: ICommandOptionDefinition = SshSession.SSH_OPTION_HOST; /** * Option used in profile creation and commands for port for z/OS SSH @@ -86,7 +86,7 @@ export class SshSession { /** * @deprecated Use SSH_OPTION_USER */ - public static SSH_OPTION_USER_PROFILE: ICommandOptionDefinition = this.SSH_OPTION_USER; + public static SSH_OPTION_USER_PROFILE: ICommandOptionDefinition = SshSession.SSH_OPTION_USER; /** * Option used in profile creation and commands for password/passphrase for z/OS SSH From 1a0e96e081d8777b1fe3e89d1a4799b309b8a82f Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Wed, 19 Jan 2022 13:01:09 -0500 Subject: [PATCH 13/14] Avoid one test affecting the env of other tests. Signed-off-by: Gene Johnston --- zowex/src/main.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/zowex/src/main.rs b/zowex/src/main.rs index 32aaf59592..d5ecdde542 100644 --- a/zowex/src/main.rs +++ b/zowex/src/main.rs @@ -488,7 +488,7 @@ fn get_port_string() -> String { Ok(val) => _port = val.parse::().unwrap(), Err(_e) => _port = DEFAULT_PORT, } - + _port.to_string() } @@ -729,17 +729,18 @@ mod tests { env::set_var("ZOWE_DAEMON", "777"); let port_string = get_port_string(); assert_eq!("777", port_string); + env::remove_var("ZOWE_DAEMON"); } #[test] fn test_get_zowe_env() { let env = get_zowe_env(); - assert_eq!(env.keys().len(), 0); + assert_eq!(env.get("ZOWE_EDITOR"), None); - env::set_var("ZOWE_DAEMON", "777"); + env::set_var("ZOWE_EDITOR", "nano"); let env = get_zowe_env(); - assert_eq!(env.keys().len(), 1); + assert_eq!(env.get("ZOWE_EDITOR"), Some(&"nano".to_owned())); - env::remove_var("ZOWE_DAEMON"); + env::remove_var("ZOWE_EDITOR"); } } From c8134cbc11326b23f7b62f540e3e0cb57ade826c Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Wed, 19 Jan 2022 13:12:55 -0500 Subject: [PATCH 14/14] Update EXE version for earlier linting changes. Signed-off-by: Gene Johnston --- zowex/Cargo.lock | 2 +- zowex/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zowex/Cargo.lock b/zowex/Cargo.lock index 5fc4d97a94..a8299007d9 100644 --- a/zowex/Cargo.lock +++ b/zowex/Cargo.lock @@ -414,7 +414,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "zowe" -version = "0.6.0" +version = "0.6.1" dependencies = [ "atty", "base64", diff --git a/zowex/Cargo.toml b/zowex/Cargo.toml index fed479d0d0..3ad49256f9 100644 --- a/zowex/Cargo.toml +++ b/zowex/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zowe" -version = "0.6.0" +version = "0.6.1" authors = ["Zowe Project"] edition = "2018" license = "EPL-2.0"