Skip to content

Commit 96b96ed

Browse files
Merge pull request #76 from pcoop/branch1
Better error handling for SSH
2 parents 229bb0e + 52f2092 commit 96b96ed

File tree

7 files changed

+205
-43
lines changed

7 files changed

+205
-43
lines changed

__tests__/__system__/cli/generate/__snapshots__/cli.generate.bundle.system.test.ts.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ exports[`cics-deploy generate bundle paramters should customise port in generate
134134
# %INCLUDE=&USSCONFIG;/nodejs/sdk.profile
135135
# %INCLUDE=&CONFIGROOT;/debug.profile
136136
#
137-
%INCLUDE=&USSCONFIG;/nodejsapps/general.profile
137+
%INCLUDE=&USSCONFIG;/nodejsprofiles/general.profile
138138
#
139139
#**********************************************************************
140140
#
@@ -314,7 +314,7 @@ exports[`cics-deploy generate bundle should generate a bundle using defaults fro
314314
# %INCLUDE=&USSCONFIG;/nodejs/sdk.profile
315315
# %INCLUDE=&CONFIGROOT;/debug.profile
316316
#
317-
%INCLUDE=&USSCONFIG;/nodejsapps/general.profile
317+
%INCLUDE=&USSCONFIG;/nodejsprofiles/general.profile
318318
#
319319
#**********************************************************************
320320
#

__tests__/api/BundleContent/__snapshots__/Nodejsapp.test.ts.snap

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ exports[`NodejsappBundlePart01 Create a NodejsappBundlePart 3`] = `
8181
# %INCLUDE=&USSCONFIG;/nodejs/sdk.profile
8282
# %INCLUDE=&CONFIGROOT;/debug.profile
8383
#
84-
%INCLUDE=&USSCONFIG;/nodejsapps/general.profile
84+
%INCLUDE=&USSCONFIG;/nodejsprofiles/general.profile
8585
#
8686
#**********************************************************************
8787
#
@@ -211,7 +211,7 @@ exports[`NodejsappBundlePart01 Create a NodejsappBundlePart 4`] = `
211211
# %INCLUDE=&USSCONFIG;/nodejs/sdk.profile
212212
# %INCLUDE=&CONFIGROOT;/debug.profile
213213
#
214-
%INCLUDE=&USSCONFIG;/nodejsapps/general.profile
214+
%INCLUDE=&USSCONFIG;/nodejsprofiles/general.profile
215215
#
216216
#**********************************************************************
217217
#
@@ -348,7 +348,7 @@ exports[`NodejsappBundlePart01 Create a NodejsappBundlePart with bad chars 3`] =
348348
# %INCLUDE=&USSCONFIG;/nodejs/sdk.profile
349349
# %INCLUDE=&CONFIGROOT;/debug.profile
350350
#
351-
%INCLUDE=&USSCONFIG;/nodejsapps/general.profile
351+
%INCLUDE=&USSCONFIG;/nodejsprofiles/general.profile
352352
#
353353
#**********************************************************************
354354
#
@@ -478,7 +478,7 @@ exports[`NodejsappBundlePart01 Create a NodejsappBundlePart with bad chars 4`] =
478478
# %INCLUDE=&USSCONFIG;/nodejs/sdk.profile
479479
# %INCLUDE=&CONFIGROOT;/debug.profile
480480
#
481-
%INCLUDE=&USSCONFIG;/nodejsapps/general.profile
481+
%INCLUDE=&USSCONFIG;/nodejsprofiles/general.profile
482482
#
483483
#**********************************************************************
484484
#
@@ -615,7 +615,7 @@ exports[`NodejsappBundlePart01 Create a NodejsappBundlePart with long name 3`] =
615615
# %INCLUDE=&USSCONFIG;/nodejs/sdk.profile
616616
# %INCLUDE=&CONFIGROOT;/debug.profile
617617
#
618-
%INCLUDE=&USSCONFIG;/nodejsapps/general.profile
618+
%INCLUDE=&USSCONFIG;/nodejsprofiles/general.profile
619619
#
620620
#**********************************************************************
621621
#
@@ -745,7 +745,7 @@ exports[`NodejsappBundlePart01 Create a NodejsappBundlePart with long name 4`] =
745745
# %INCLUDE=&USSCONFIG;/nodejs/sdk.profile
746746
# %INCLUDE=&CONFIGROOT;/debug.profile
747747
#
748-
%INCLUDE=&USSCONFIG;/nodejsapps/general.profile
748+
%INCLUDE=&USSCONFIG;/nodejsprofiles/general.profile
749749
#
750750
#**********************************************************************
751751
#
@@ -882,7 +882,7 @@ exports[`NodejsappBundlePart01 Create a NodejsappBundlePart with missing port nu
882882
# %INCLUDE=&USSCONFIG;/nodejs/sdk.profile
883883
# %INCLUDE=&CONFIGROOT;/debug.profile
884884
#
885-
%INCLUDE=&USSCONFIG;/nodejsapps/general.profile
885+
%INCLUDE=&USSCONFIG;/nodejsprofiles/general.profile
886886
#
887887
#**********************************************************************
888888
#
@@ -1011,7 +1011,7 @@ exports[`NodejsappBundlePart01 Create a NodejsappBundlePart with missing port nu
10111011
# %INCLUDE=&USSCONFIG;/nodejs/sdk.profile
10121012
# %INCLUDE=&CONFIGROOT;/debug.profile
10131013
#
1014-
%INCLUDE=&USSCONFIG;/nodejsapps/general.profile
1014+
%INCLUDE=&USSCONFIG;/nodejsprofiles/general.profile
10151015
#
10161016
#**********************************************************************
10171017
#

__tests__/api/BundlePush/BundlePusher.test.ts

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,22 @@ describe("BundlePusher01", () => {
280280
expect(membersSpy).toHaveBeenCalledTimes(2);
281281
expect(submitSpy).toHaveBeenCalledTimes(1);
282282
});
283+
it("should tolerate delete of empty directory", async () => {
284+
shellSpy.mockImplementation((session: any, cmd: string, dir: string, stdoutHandler: (data: string) => void) => {
285+
stdoutHandler("Injected FSUM9195 empty directory message");
286+
});
287+
288+
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
289+
"PUSH operation completed.");
290+
291+
expect(zosMFSpy).toHaveBeenCalledTimes(1);
292+
expect(sshSpy).toHaveBeenCalledTimes(1);
293+
expect(createSpy).toHaveBeenCalledTimes(1);
294+
expect(listSpy).toHaveBeenCalledTimes(1);
295+
expect(shellSpy).toHaveBeenCalledTimes(1);
296+
expect(membersSpy).toHaveBeenCalledTimes(2);
297+
expect(submitSpy).toHaveBeenCalledTimes(2);
298+
});
283299
it("should handle error with attribs file", async () => {
284300
existsSpy.mockImplementation((data: string) => {
285301
if (data.indexOf(".zosattributes") > -1) {
@@ -308,6 +324,50 @@ describe("BundlePusher01", () => {
308324
expect(existsSpy).toHaveBeenCalledTimes(1);
309325
expect(readSpy).toHaveBeenCalledTimes(2);
310326
});
327+
it("should load zosattribs file", async () => {
328+
existsSpy.mockImplementation((data: string) => {
329+
if (data.indexOf(".zosattributes") > -1) {
330+
return true;
331+
}
332+
});
333+
readSpy.mockImplementation((data: string) => {
334+
if (data.indexOf(".zosattributes") > -1) {
335+
return "";
336+
}
337+
else if (data.indexOf("cics.xml") > -1) {
338+
return "<manifest xmlns=\"http://www.ibm.com/xmlns/prod/cics/bundle\"></manifest>";
339+
}
340+
});
341+
342+
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
343+
"PUSH operation completed.");
344+
345+
expect(consoleText).not.toContain("WARNING: No .zosAttributes file found in the bundle directory, default values will be applied.");
346+
expect(zosMFSpy).toHaveBeenCalledTimes(1);
347+
expect(sshSpy).toHaveBeenCalledTimes(1);
348+
expect(createSpy).toHaveBeenCalledTimes(1);
349+
expect(listSpy).toHaveBeenCalledTimes(1);
350+
expect(shellSpy).toHaveBeenCalledTimes(1);
351+
expect(membersSpy).toHaveBeenCalledTimes(2);
352+
expect(submitSpy).toHaveBeenCalledTimes(2);
353+
expect(existsSpy).toHaveBeenCalledTimes(2);
354+
expect(readSpy).toHaveBeenCalledTimes(2);
355+
});
356+
it("should use a default zosattribs file", async () => {
357+
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
358+
"PUSH operation completed.");
359+
360+
expect(consoleText).toContain("WARNING: No .zosAttributes file found in the bundle directory, default values will be applied.");
361+
expect(zosMFSpy).toHaveBeenCalledTimes(1);
362+
expect(sshSpy).toHaveBeenCalledTimes(1);
363+
expect(createSpy).toHaveBeenCalledTimes(1);
364+
expect(listSpy).toHaveBeenCalledTimes(1);
365+
expect(shellSpy).toHaveBeenCalledTimes(1);
366+
expect(membersSpy).toHaveBeenCalledTimes(2);
367+
expect(submitSpy).toHaveBeenCalledTimes(2);
368+
expect(existsSpy).toHaveBeenCalledTimes(2);
369+
expect(readSpy).toHaveBeenCalledTimes(1);
370+
});
311371
it("should handle error with bundle upload", async () => {
312372
uploadSpy.mockImplementationOnce(() => { throw new Error("Injected upload error"); });
313373

@@ -421,7 +481,8 @@ describe("BundlePusher01", () => {
421481
});
422482

423483
await runPushTestWithError("__tests__/__resources__/ExampleBundle01", false,
424-
"A problem occurred attempting to run 'npm install' in remote directory '/u/ThisDoesNotExist/12345678'. " +
484+
"A problem occurred attempting to run 'export PATH=\"$PATH:/usr/lpp/IBM/cnj/IBM/node-latest-os390-s390x/bin\" " +
485+
"&& npm install' in remote directory '/u/ThisDoesNotExist/12345678'. " +
425486
"Problem is: The output from the remote command implied that an error occurred.");
426487

427488
expect(consoleText).toContain("Injected stdout error message");
@@ -436,6 +497,76 @@ describe("BundlePusher01", () => {
436497
expect(readSpy).toHaveBeenCalledTimes(1);
437498
expect(uploadSpy).toHaveBeenCalledTimes(1);
438499
});
500+
it("should handle failure of remote npm install with FSUM message", async () => {
501+
shellSpy.mockImplementation((session: any, cmd: string, dir: string, stdoutHandler: (data: string) => void) => {
502+
if (cmd.indexOf("npm install") > -1) {
503+
stdoutHandler("Injected FSUM7351 not found message");
504+
}
505+
else {
506+
return true;
507+
}
508+
});
509+
existsSpy.mockImplementation((data: string) => {
510+
if (data.indexOf(".zosattributes") > -1) {
511+
return false;
512+
}
513+
if (data.indexOf("package.json") > -1) {
514+
return true;
515+
}
516+
});
517+
518+
await runPushTestWithError("__tests__/__resources__/ExampleBundle01", false,
519+
"A problem occurred attempting to run 'export PATH=\"$PATH:/usr/lpp/IBM/cnj/IBM/node-latest-os390-s390x/bin\" " +
520+
"&& npm install' in remote directory '/u/ThisDoesNotExist/12345678'. " +
521+
"Problem is: The output from the remote command implied that an error occurred.");
522+
523+
expect(consoleText).toContain("Injected FSUM7351 not found message");
524+
expect(zosMFSpy).toHaveBeenCalledTimes(1);
525+
expect(sshSpy).toHaveBeenCalledTimes(1);
526+
expect(createSpy).toHaveBeenCalledTimes(1);
527+
expect(listSpy).toHaveBeenCalledTimes(1);
528+
expect(shellSpy).toHaveBeenCalledTimes(1);
529+
expect(membersSpy).toHaveBeenCalledTimes(0);
530+
expect(submitSpy).toHaveBeenCalledTimes(0);
531+
expect(existsSpy).toHaveBeenCalledTimes(2);
532+
expect(readSpy).toHaveBeenCalledTimes(1);
533+
expect(uploadSpy).toHaveBeenCalledTimes(1);
534+
});
535+
it("should handle failure of remote npm install with node error", async () => {
536+
shellSpy.mockImplementation((session: any, cmd: string, dir: string, stdoutHandler: (data: string) => void) => {
537+
if (cmd.indexOf("npm install") > -1) {
538+
stdoutHandler("Injected npm ERR! Exit status 1 message");
539+
}
540+
else {
541+
return true;
542+
}
543+
});
544+
existsSpy.mockImplementation((data: string) => {
545+
if (data.indexOf(".zosattributes") > -1) {
546+
return false;
547+
}
548+
if (data.indexOf("package.json") > -1) {
549+
return true;
550+
}
551+
});
552+
553+
await runPushTestWithError("__tests__/__resources__/ExampleBundle01", false,
554+
"A problem occurred attempting to run 'export PATH=\"$PATH:/usr/lpp/IBM/cnj/IBM/node-latest-os390-s390x/bin\" " +
555+
"&& npm install' in remote directory '/u/ThisDoesNotExist/12345678'. " +
556+
"Problem is: The output from the remote command implied that an error occurred.");
557+
558+
expect(consoleText).toContain("Injected npm ERR! Exit status 1 message");
559+
expect(zosMFSpy).toHaveBeenCalledTimes(1);
560+
expect(sshSpy).toHaveBeenCalledTimes(1);
561+
expect(createSpy).toHaveBeenCalledTimes(1);
562+
expect(listSpy).toHaveBeenCalledTimes(1);
563+
expect(shellSpy).toHaveBeenCalledTimes(1);
564+
expect(membersSpy).toHaveBeenCalledTimes(0);
565+
expect(submitSpy).toHaveBeenCalledTimes(0);
566+
expect(existsSpy).toHaveBeenCalledTimes(2);
567+
expect(readSpy).toHaveBeenCalledTimes(1);
568+
expect(uploadSpy).toHaveBeenCalledTimes(1);
569+
});
439570
it("should handle error with remote bundle deploy", async () => {
440571
submitSpy.mockImplementationOnce(() => { throw new Error("Injected deploy error"); });
441572

src/api/BundleContent/Bundle.ts

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,37 @@ import { NodejsappBundlePart } from "./NodejsappBundlePart";
2323
*/
2424
export class Bundle {
2525

26+
/**
27+
* Get a template version of the .zosattributes file
28+
* @returns {string}
29+
* @memberof Bundle
30+
*/
31+
public static getTemplateZosAttributesFile(): string {
32+
return `#z/OS File Attributes Document
33+
#-----------------------------
34+
# This document specfies the encodings for the files within
35+
# the project in a form that is compatible with the
36+
# 'Zowe files upload dir-to-uss' command.
37+
#
38+
# Don't upload node_modules
39+
node_modules -
40+
# Don't upload things that start with dots
41+
.* -
42+
43+
# Upload the following file types in binary
44+
*.jpg binary binary
45+
*.png binary binary
46+
*.gif binary binary
47+
*.zip binary binary
48+
*.eot binary binary
49+
*.svg binary binary
50+
*.ttf binary binary
51+
*.woff binary binary
52+
53+
# Convert CICS Node.js profiles to EBCDIC
54+
*.profile ISO8859-1 IBM-1047`;
55+
}
56+
2657
private path = require("path");
2758
private fs = require("fs");
2859
private manifest: Manifest;
@@ -254,30 +285,7 @@ export class Bundle {
254285
return;
255286
}
256287

257-
const contents = "" +
258-
"#z/OS File Attributes Document\n" +
259-
"#-----------------------------\n" +
260-
"# This document specfies the encodings for the files within\n" +
261-
"# the project in a form that is compatible with the\n" +
262-
"# 'Zowe files upload dir-to-uss' command.\n" +
263-
"#\n" +
264-
"# Don't upload node_modules\n" +
265-
"node_modules -\n" +
266-
"# Don't upload things that start with dots\n" +
267-
".* -\n" +
268-
"\n" +
269-
"# Upload the following file types in binary\n" +
270-
"*.jpg binary binary\n" +
271-
"*.png binary binary\n" +
272-
"*.gif binary binary\n" +
273-
"*.zip binary binary\n" +
274-
"*.eot binary binary\n" +
275-
"*.svg binary binary\n" +
276-
"*.ttf binary binary\n" +
277-
"*.woff binary binary\n" +
278-
"\n" +
279-
"# Convert CICS Node.js profiles to EBCDIC\n" +
280-
"*.profile ISO8859-1 IBM-1047";
288+
const contents = Bundle.getTemplateZosAttributesFile();
281289

282290
// Write the zosattributes file
283291
try {

src/api/BundleContent/TemplateNodejsappProfile.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export class TemplateNodejsappProfile {
8686
"# %INCLUDE=&USSCONFIG;/nodejs/sdk.profile\n" +
8787
"# %INCLUDE=&CONFIGROOT;/debug.profile\n" +
8888
"#\n" +
89-
"%INCLUDE=&USSCONFIG;/nodejsapps/general.profile\n" +
89+
"%INCLUDE=&USSCONFIG;/nodejsprofiles/general.profile\n" +
9090
"#\n" +
9191
"#**********************************************************************\n" +
9292
"#\n" +

src/api/BundleDeploy/BundleDeployer.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ export class BundleDeployer {
263263
this.jobId = statusWords[2];
264264
status.statusMessage += " (Processing DFHDPLOY " + action + " action)";
265265

266+
this.params.response.progress.endBar();
266267
// log the jobid for posterity
267268
if (this.params.arguments.verbose) {
268269
this.params.response.console.log(status.statusMessage + "\n");
@@ -271,6 +272,7 @@ export class BundleDeployer {
271272
const logger = Logger.getAppLogger();
272273
logger.debug(status.statusMessage);
273274
}
275+
this.params.response.progress.startBar({task: status});
274276
}
275277
}
276278
}

0 commit comments

Comments
 (0)