Skip to content

Commit 067eaf9

Browse files
authored
Merge branch 'master' into master
2 parents 689228a + fe1bb7b commit 067eaf9

File tree

5 files changed

+82
-35
lines changed

5 files changed

+82
-35
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" ];

docs/pages/cdp/cdp-Create-Zowe-CLI-profiles.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ This profile identifies the z/OSMF server that has access to the directory on z/
1818

1919
For example, to create a z/OSMF profile:
2020
```console
21-
zowe profiles create zosmf-profile myzos --host myzos.example.com --port 3000
22-
--user myuserid --password mypassword --reject-unauthorized false --overwrite
21+
zowe profiles create zosmf-profile myzos --host myzos.example.com --port 3000 --user myuserid --password mypassword --reject-unauthorized false --overwrite
2322
```
2423
For help on using the options:
2524
```console
@@ -42,8 +41,7 @@ It is recommended that you use the same user ID and host to connect with SSH as
4241

4342
For example, to create an SSH profile:
4443
```console
45-
zowe profiles create ssh-profile myzos --host myzos.example.com
46-
--user myuserid --password mypassword --overwrite
44+
zowe profiles create ssh-profile myzos --host myzos.example.com --user myuserid --password mypassword --overwrite
4745
```
4846
For help on using the options:
4947
```console
@@ -66,9 +64,7 @@ This profile identifies the CICS environment for deployment. You need to know th
6664

6765
For example to create a cics-deploy profile:
6866
```console
69-
zowe profiles create cics-deploy-profile example --cicsplex PLEX1
70-
--cicshlq CICSTS55.CICS720 --cpsmhlq CICSTS55.CPSM550
71-
--scope TESTGRP1 --csdgroup BUNDGRP1 --overwrite
67+
zowe profiles create cics-deploy-profile example --cicsplex PLEX1 --cicshlq CICSTS55.CICS720 --cpsmhlq CICSTS55.CPSM550 --scope TESTGRP1 --csdgroup BUNDGRP1 --overwrite
7268
```
7369
For help on using the options:
7470
```console

docs/pages/cdp/cdp-Developer-pushing-Node.js-apps.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ You also need an existing CICS bundle in the current working directory. For more
3737

3838
The `cics-deploy push bundle` command pushes a bundle from the working directory to a target CICS environment. It requires the use of a z/OSMF profile and an ssh profile to do so, use of a cics-deploy profile is also encouraged (for more information on these dependencies see [Requirements for Push](#push_req)). You can request assistance on using the push command by issuing the following command:
3939

40-
`zowe cics-deploy push bundle --help`
40+
```console
41+
zowe cics-deploy push bundle --help
42+
```
4143

4244
If you have configured default profiles for zosmf, ssh and cics-deploy then only two further items are needed:
4345

@@ -46,16 +48,21 @@ If you have configured default profiles for zosmf, ssh and cics-deploy then only
4648

4749
For example, you might issue the following command:
4850

49-
`zowe cics-deploy push bundle --name EXAMPLE1 --targetdir /u/user01/myBundles`
51+
```console
52+
zowe cics-deploy push bundle --name EXAMPLE1 --targetdir /u/user01/myBundles
53+
```
5054

5155
This command causes cics-deploy to attempt to deploy a bundle from the current working directory to the target CICS environment under the name `EXAMPLE1`. If a bundle exists in the target environment with the same name, cics-deploy returns an error. You can instruct cics-deploy to overwrite the existing bundle by adding the --overwrite parameter, for example:
5256

53-
`zowe cics-deploy push bundle --name EXAMPLE1 --targetdir /u/user01/myBundles --overwrite`
57+
```console
58+
zowe cics-deploy push bundle --name EXAMPLE1 --targetdir /u/user01/myBundles --overwrite
59+
```
5460

5561
You can also request verbose messages from cics-deploy by adding the --verbose option, for example:
5662

57-
`zowe cics-deploy push bundle --name EXAMPLE1 --targetdir /u/user01/myBundles --overwrite --verbose`
58-
63+
```console
64+
zowe cics-deploy push bundle --name EXAMPLE1 --targetdir /u/user01/myBundles --overwrite --verbose
65+
```
5966

6067
<a name="push_components"></a>
6168
### Subcomponents of the push command
@@ -67,5 +74,4 @@ The `cics-deploy push bundle` command consists of several separate actions, each
6774
3. If the bundle contains a package.json file, it runs `npm install` on the remote system by using `zowe zos-uss issue ssh`.
6875
4. It deploys a bundle by using `zowe cics-deploy deploy bundle` (See [Deploying a CICS bundle](#deploying)).
6976

70-
Advanced users might prefer to use these subcommands in preference to the `push` command. For example, if the target CICS regions are not CPSM-managed then you might use Zowe to generate and then upload the bundle, and your own scripts to deploy the bundle into a CICS region.
71-
77+
Advanced users might prefer to use these subcommands in preference to the `push` command. For example, if the target CICS regions are not CPSM-managed then you might use Zowe to generate and then upload the bundle, and your own scripts to deploy the bundle into a CICS region.

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.");

src/cli/generate/bundle/options/Port.option.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ export const PortOption: ICommandOptionDefinition = {
1919
name: "port",
2020
aliases: ["p"],
2121
type: "string",
22-
description: "An optional TCP/IP port number that the Node.js application expects to use. " +
23-
"If a value is specified, it is stored within the generated NODEJSAPP's profile " +
24-
"and the associated value can be referenced programmatically by using the 'PORT' " +
25-
"environment variable."
22+
description: "The TCP/IP port number the Node.js application should use for clients to connect to. " +
23+
"If a value is specified, it is set within the generated NODEJSAPP's profile. " +
24+
"The Node.js application can reference this value by accessing the PORT environment variable, " +
25+
"for example using process.env.PORT. " +
26+
"Additional environment variables can be set by manually editing the profile."
2627
};
27-

0 commit comments

Comments
 (0)