Skip to content

Commit 10806d6

Browse files
authored
Merge pull request #136 from ChrisPark89/enh/sshrc
Check ssh command exit code when looking for errors
2 parents 89dd604 + 5364f0a commit 10806d6

File tree

2 files changed

+61
-16
lines changed

2 files changed

+61
-16
lines changed

__tests__/api/BundlePush/BundlePusher.test.ts

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ let createSpy = jest.spyOn(Create, "uss").mockImplementation(() => ({}));
7070
let listSpy = jest.spyOn(List, "fileList").mockImplementation(() => ({}));
7171
let membersSpy = jest.spyOn(List, "allMembers").mockImplementation(() => ({}));
7272
let submitSpy = jest.spyOn(SubmitJobs, "submitJclString").mockImplementation(() => ({}));
73-
let shellSpy = jest.spyOn(Shell, "executeSshCwd").mockImplementation(() => ({}));
73+
let shellSpy = jest.spyOn(Shell, "executeSshCwd").mockImplementation(() => (0));
7474
let existsSpy = jest.spyOn(fs, "existsSync").mockImplementation(() => ({}));
7575
let readSpy = jest.spyOn(fs, "readFileSync").mockImplementation(() => ({}));
7676
let uploadSpy = jest.spyOn(Upload, "dirToUSSDirRecursive").mockImplementation(() => ({}));
@@ -88,7 +88,7 @@ describe("BundlePusher01", () => {
8888
membersSpy = jest.spyOn(List, "allMembers").mockImplementation(() => ( { val: "DFHDPLOY, EYU9ABSI" }));
8989
submitSpy = jest.spyOn(SubmitJobs, "submitJclString").mockImplementation(() =>
9090
[{ddName: "SYSTSPRT", stepName: "DFHDPLOY", data: "DFHRL2012I"}] );
91-
shellSpy = jest.spyOn(Shell, "executeSshCwd").mockImplementation(() => ({}));
91+
shellSpy = jest.spyOn(Shell, "executeSshCwd").mockImplementation(() => (0));
9292
existsSpy = jest.spyOn(fs, "existsSync").mockReturnValue(false);
9393
readSpy = jest.spyOn(fs, "readFileSync").mockImplementation((data: string) => {
9494
if (data.indexOf("cics.xml") > -1) {
@@ -393,6 +393,7 @@ describe("BundlePusher01", () => {
393393
it("should tolerate delete of empty directory", async () => {
394394
shellSpy.mockImplementation((session: any, cmd: string, dir: string, stdoutHandler: (data: string) => void) => {
395395
stdoutHandler("FSUM9195 cannot unlink entry \"*\": EDC5129I No such file or directory.");
396+
return 1;
396397
});
397398

398399
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
@@ -406,9 +407,48 @@ describe("BundlePusher01", () => {
406407
expect(membersSpy).toHaveBeenCalledTimes(2);
407408
expect(submitSpy).toHaveBeenCalledTimes(2);
408409
});
410+
it("should not tolerate non zero return code from ssh command", async () => {
411+
shellSpy.mockImplementation((session: any, cmd: string, dir: string, stdoutHandler: (data: string) => void) => {
412+
stdoutHandler("Ssh command exit with non zero status");
413+
return 1;
414+
});
415+
416+
await runPushTestWithError("__tests__/__resources__/ExampleBundle01", true,
417+
"A problem occurred attempting to run 'rm -r *' in remote directory '/u/ThisDoesNotExist/12345678'. " +
418+
"Problem is: The output from the remote command implied that an error occurred.");
419+
420+
expect(consoleText).toContain("Ssh command exit with non zero status");
421+
expect(zosMFSpy).toHaveBeenCalledTimes(1);
422+
expect(sshSpy).toHaveBeenCalledTimes(1);
423+
expect(createSpy).toHaveBeenCalledTimes(1);
424+
expect(listSpy).toHaveBeenCalledTimes(1);
425+
expect(shellSpy).toHaveBeenCalledTimes(1);
426+
expect(membersSpy).toHaveBeenCalledTimes(2);
427+
expect(submitSpy).toHaveBeenCalledTimes(1);
428+
});
429+
it("should not tolerate mixture of FSUM9195 but exit status is not 1", async () => {
430+
shellSpy.mockImplementation((session: any, cmd: string, dir: string, stdoutHandler: (data: string) => void) => {
431+
stdoutHandler("Injected FSUM9195 error message");
432+
return 127;
433+
});
434+
435+
await runPushTestWithError("__tests__/__resources__/ExampleBundle01", true,
436+
"A problem occurred attempting to run 'rm -r *' in remote directory '/u/ThisDoesNotExist/12345678'. " +
437+
"Problem is: The output from the remote command implied that an error occurred.");
438+
439+
expect(consoleText).toContain("Injected FSUM9195 error message");
440+
expect(zosMFSpy).toHaveBeenCalledTimes(1);
441+
expect(sshSpy).toHaveBeenCalledTimes(1);
442+
expect(createSpy).toHaveBeenCalledTimes(1);
443+
expect(listSpy).toHaveBeenCalledTimes(1);
444+
expect(shellSpy).toHaveBeenCalledTimes(1);
445+
expect(membersSpy).toHaveBeenCalledTimes(2);
446+
expect(submitSpy).toHaveBeenCalledTimes(1);
447+
});
409448
it("should not tolerate mixture of FSUM9195 and other FSUM messages", async () => {
410449
shellSpy.mockImplementation((session: any, cmd: string, dir: string, stdoutHandler: (data: string) => void) => {
411450
stdoutHandler("Injected FSUM9195 and FSUM9196 error message");
451+
return 1;
412452
});
413453

414454
await runPushTestWithError("__tests__/__resources__/ExampleBundle01", true,
@@ -594,6 +634,7 @@ describe("BundlePusher01", () => {
594634
shellSpy.mockImplementation((session: any, cmd: string, dir: string, stdoutHandler: (data: string) => void) => {
595635
if (cmd.indexOf("npm install") > -1) {
596636
stdoutHandler("Injected stdout error message");
637+
return 1;
597638
}
598639
else {
599640
return true;
@@ -626,6 +667,7 @@ describe("BundlePusher01", () => {
626667
shellSpy.mockImplementation((session: any, cmd: string, dir: string, stdoutHandler: (data: string) => void) => {
627668
if (cmd.indexOf("npm install") > -1) {
628669
stdoutHandler("Injected FSUM7351 not found message");
670+
return 1;
629671
}
630672
else {
631673
return true;
@@ -658,6 +700,7 @@ describe("BundlePusher01", () => {
658700
shellSpy.mockImplementation((session: any, cmd: string, dir: string, stdoutHandler: (data: string) => void) => {
659701
if (cmd.indexOf("npm install") > -1) {
660702
stdoutHandler("Injected npm ERR! Exit status 1 message");
703+
return 1;
661704
}
662705
else {
663706
return true;
@@ -725,6 +768,7 @@ describe("BundlePusher01", () => {
725768
parms.arguments.targetdir = "//u//escapedDirName";
726769
shellSpy.mockImplementation((session: any, cmd: string, dir: string, stdoutHandler: (data: string) => void) => {
727770
stdoutHandler("Injected stdout shell message");
771+
return 0;
728772
});
729773
readdirSpy.mockImplementation((data: string) => {
730774
return [ "package.json" ];
@@ -752,6 +796,7 @@ describe("BundlePusher01", () => {
752796
parms.arguments.targetdir = "//u//escapedDirName";
753797
shellSpy.mockImplementation((session: any, cmd: string, dir: string, stdoutHandler: (data: string) => void) => {
754798
stdoutHandler("Injected stdout shell message for " + dir);
799+
return 0;
755800
});
756801
readdirSpy.mockImplementation((data: string) => {
757802
if (data.endsWith("XXXDIRXXX")) {
@@ -799,6 +844,7 @@ describe("BundlePusher01", () => {
799844
parms.arguments.verbose = true;
800845
shellSpy.mockImplementation((session: any, cmd: string, dir: string, stdoutHandler: (data: string) => void) => {
801846
stdoutHandler("Injected stdout shell message");
847+
return 0;
802848
});
803849
readdirSpy.mockImplementation((data: string) => {
804850
return [ "package.json" ];
@@ -832,6 +878,7 @@ describe("BundlePusher01", () => {
832878
parms.arguments.verbose = true;
833879
shellSpy.mockImplementation((session: any, cmd: string, dir: string, stdoutHandler: (data: string) => void) => {
834880
stdoutHandler("Injected stdout shell message");
881+
return 0;
835882
});
836883
readdirSpy.mockImplementation((data: string) => {
837884
return [ "package.json" ];

src/api/BundlePush/BundlePusher.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -375,26 +375,24 @@ export class BundlePusher {
375375
const shell = await Shell.executeSshCwd(sshSession, sshCommand, directory, this.sshOutput.bind(this));
376376
const upperCaseOutputText = this.sshOutputText.toUpperCase();
377377

378-
// Did the SSH command work? It's unclear how to tell, but for starters let's look for common
379-
// signifiers in the output text. Note that FSUM9195 can imply that we've tried to delete the
378+
// Note that FSUM9195 can imply that we've tried to delete the
380379
// contents of an empty directory - that's not a problem.
381-
382-
// If there any FSUM messages other than FSUM9195 then that's a problem
383-
let otherFSUMMessages = false;
380+
// Check if FSUM9195 is the only FSUM error
381+
let isOnlyFSUM9195 = false;
384382
const countFSUM = (upperCaseOutputText.match(/FSUM/g) || []).length;
385383
const countFSUM9195 = (upperCaseOutputText.match(/FSUM9195/g) || []).length;
386-
if (countFSUM > countFSUM9195) {
387-
otherFSUMMessages = true;
384+
if (countFSUM9195 !== 0 &&
385+
countFSUM === countFSUM9195 &&
386+
shell === 1) {
387+
isOnlyFSUM9195 = true;
388388
}
389389

390-
// Now check for other common error signifiers
391-
if (otherFSUMMessages ||
392-
upperCaseOutputText.indexOf("ERROR ") > -1 ||
393-
upperCaseOutputText.indexOf("ERR!") > -1 ) {
394-
390+
// Now check
391+
// A. If exit code is non zero
392+
// B. FSUM9195 is not the only FSUM error
393+
if (shell !== 0 && !isOnlyFSUM9195) {
395394
// if we've not already logged the output, log it now
396-
if (this.params.arguments.verbose !== true)
397-
{
395+
if (this.params.arguments.verbose !== true) {
398396
this.params.response.console.log(Buffer.from(this.sshOutputText));
399397
}
400398
throw new Error("The output from the remote command implied that an error occurred.");

0 commit comments

Comments
 (0)