Skip to content

Commit 3e79aad

Browse files
Merge pull request #88 from pcoop/branch1
Assorted tweaks
2 parents 2f07f41 + bd7bcf1 commit 3e79aad

File tree

5 files changed

+89
-23
lines changed

5 files changed

+89
-23
lines changed

__tests__/api/BundlePush/BundlePusher.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,24 @@ describe("BundlePusher01", () => {
335335
expect(membersSpy).toHaveBeenCalledTimes(2);
336336
expect(submitSpy).toHaveBeenCalledTimes(2);
337337
});
338+
it("should not tolerate mixture of FSUM9195 and other FSUM messages", async () => {
339+
shellSpy.mockImplementation((session: any, cmd: string, dir: string, stdoutHandler: (data: string) => void) => {
340+
stdoutHandler("Injected FSUM9195 and FSUM9196 error message");
341+
});
342+
343+
await runPushTestWithError("__tests__/__resources__/ExampleBundle01", true,
344+
"A problem occurred attempting to run 'rm -r *' in remote directory '/u/ThisDoesNotExist/12345678'. " +
345+
"Problem is: The output from the remote command implied that an error occurred.");
346+
347+
expect(consoleText).toContain("Injected FSUM9195 and FSUM9196 error message");
348+
expect(zosMFSpy).toHaveBeenCalledTimes(1);
349+
expect(sshSpy).toHaveBeenCalledTimes(1);
350+
expect(createSpy).toHaveBeenCalledTimes(1);
351+
expect(listSpy).toHaveBeenCalledTimes(1);
352+
expect(shellSpy).toHaveBeenCalledTimes(1);
353+
expect(membersSpy).toHaveBeenCalledTimes(2);
354+
expect(submitSpy).toHaveBeenCalledTimes(1);
355+
});
338356
it("should handle error with attribs file", async () => {
339357
existsSpy.mockImplementation((data: string) => {
340358
if (data.indexOf(".zosattributes") > -1) {

docs/CLIReadme.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,20 @@ if a bundle is undeployed then the definition is removed. The --csdgroup and
280280

281281
* Overwrite the cics-deploy profile when a profile of the same name exists.
282282

283+
### Examples
284+
285+
*- Create a cics-deploy profile called 'example1' to connect
286+
to a CPSM managed group of CICS regions within the TESTGRP1 scope of a cicsplex
287+
named PLEX1:
288+
289+
* ` $ zowe profiles create cics-deploy-profile example1 --cicsplex PLEX1 --scope TESTGRP1 --cicshlq CICSTS55.CICS720 --cpsmhlq CICSTS55.CPSM550`
290+
291+
*- Create a cics-deploy profile called 'example2' to connect
292+
to the same CPSM managed group of regions, and identify a BAS resource group
293+
BUNDGRP1 in which to store resource definitions:
294+
295+
* ` $ zowe profiles create cics-deploy-profile example2 --cicsplex PLEX1 --scope TESTGRP1 --cicshlq CICSTS55.CICS720 --cpsmhlq CICSTS55.CPSM550 --resgroup BUNDGRP1`
296+
283297
## update | upd<a name="module-update"></a>
284298
Update a profile.You can update any property present within the profile configuration. The updated profile will be printed so that you can review the result of the updates.
285299
### cics-deploy-profile<a name="command-cics-deploy-profile"></a>

src/api/BundlePush/BundlePusher.ts

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ export class BundlePusher {
7070
// Create an SSH session
7171
const sshSession = await this.createSshSession();
7272

73-
// Start a progress bar
73+
// Start a progress bar (but only in non-verbose mode)
7474
this.progressBar = { percentComplete: 0,
7575
statusMessage: "Starting Push operation",
7676
stageName: TaskStage.IN_PROGRESS };
77-
this.params.response.progress.startBar({task: this.progressBar});
77+
this.startProgressBar();
7878

7979
// Attempt to make the target bundledir
8080
await this.makeBundleDir(zosMFSession);
@@ -103,7 +103,7 @@ export class BundlePusher {
103103
// Run DFHDPLOY to install the bundle
104104
await this.deployBundle(zosMFSession, bd);
105105

106-
this.params.response.progress.endBar();
106+
this.endProgressBar();
107107
return "PUSH operation completed.";
108108
}
109109

@@ -223,37 +223,36 @@ export class BundlePusher {
223223
private async undeployExistingBundle(zosMFSession: AbstractSession, bd: BundleDeployer) {
224224
// End the current progress bar so that UNDEPLOY can create its own
225225
this.updateStatus("Undeploying any existing bundle from CICS");
226-
this.params.response.progress.endBar();
226+
this.endProgressBar();
227+
227228

228229
const targetstateLocal = this.params.arguments.targetstate;
229230
this.params.arguments.targetstate = "DISCARDED";
230231
await bd.undeployBundle(zosMFSession);
231232
this.params.arguments.targetstate = targetstateLocal;
232233

233234
// Resume the current progress bar
234-
this.params.response.progress.endBar();
235+
this.endProgressBar();
235236
this.updateStatus("Undeployed existing bundle from CICS");
236-
this.params.response.progress.startBar({task: this.progressBar});
237+
this.startProgressBar();
237238
}
238239

239240
private async deployBundle(zosMFSession: AbstractSession, bd: BundleDeployer) {
240241
// End the current progress bar so that DEPLOY can create its own
241242
this.updateStatus("Deploying the bundle to CICS");
242-
this.params.response.progress.endBar();
243+
this.endProgressBar();
243244

244245
await bd.deployBundle(zosMFSession);
245246
// Resume the current progress bar
246-
this.params.response.progress.endBar();
247+
this.endProgressBar();
247248
this.updateStatus("Deployed existing bundle to CICS");
248-
this.params.response.progress.startBar({task: this.progressBar});
249+
this.startProgressBar();
249250
}
250251

251252
private sshOutput(data: string) {
252253
// If verbose output is requested then log SSH output directly to the console
253254
if (this.params.arguments.verbose) {
254-
this.params.response.progress.endBar();
255255
this.params.response.console.log(Buffer.from(data));
256-
this.params.response.progress.startBar({task: this.progressBar});
257256
}
258257
this.sshOutputText += data;
259258
}
@@ -319,19 +318,30 @@ export class BundlePusher {
319318
try {
320319
this.sshOutputText = "";
321320
const shell = await Shell.executeSshCwd(sshSession, sshCommand, directory, this.sshOutput.bind(this));
321+
const upperCaseOutputText = this.sshOutputText.toUpperCase();
322322

323323
// Did the SSH command work? It's unclear how to tell, but for starters let's look for common
324-
// signifiers in the output text. Note that FSUM9195 implies that we've tried to delete the
324+
// signifiers in the output text. Note that FSUM9195 can imply that we've tried to delete the
325325
// contents of an empty directory - that's not a problem.
326-
const upperCaseOutputText = this.sshOutputText.toUpperCase();
327-
if (upperCaseOutputText.indexOf("ERROR ") > -1 ||
328-
(upperCaseOutputText.indexOf("FSUM") > -1 &&
329-
upperCaseOutputText.indexOf("FSUM9195") === -1) ||
326+
327+
// If there any FSUM messages other than FSUM9195 then that's a problem
328+
let otherFSUMMessages = false;
329+
const countFSUM = (upperCaseOutputText.match(/FSUM/g) || []).length;
330+
const countFSUM9195 = (upperCaseOutputText.match(/FSUM9195/g) || []).length;
331+
if (countFSUM > countFSUM9195) {
332+
otherFSUMMessages = true;
333+
}
334+
335+
// Now check for other common error signifiers
336+
if (otherFSUMMessages ||
337+
upperCaseOutputText.indexOf("ERROR ") > -1 ||
338+
upperCaseOutputText.indexOf("EDC") > -1 ||
330339
upperCaseOutputText.indexOf("ERR!") > -1 ) {
340+
331341
// if we've not already logged the output, log it now
332342
if (this.params.arguments.verbose !== true)
333343
{
334-
this.params.response.console.log(this.sshOutputText);
344+
this.params.response.console.log(Buffer.from(this.sshOutputText));
335345
}
336346
throw new Error("The output from the remote command implied that an error occurred.");
337347
}
@@ -372,13 +382,13 @@ export class BundlePusher {
372382

373383
// A project specific .zosattributes has not been found, so use a default
374384
const warningMsg = "WARNING: No .zosAttributes file found in the bundle directory, default values will be applied.";
375-
this.params.response.progress.endBar();
376-
this.params.response.console.log(warningMsg);
385+
this.endProgressBar();
386+
this.params.response.console.log(Buffer.from(warningMsg));
377387
if (this.params.arguments.silent === undefined) {
378388
const logger = Logger.getAppLogger();
379389
logger.warn(warningMsg);
380390
}
381-
this.params.response.progress.startBar({task: this.progressBar});
391+
this.startProgressBar();
382392
return new ZosFilesAttributes(Bundle.getTemplateZosAttributesFile());
383393
}
384394

@@ -388,12 +398,24 @@ export class BundlePusher {
388398
this.progressBar.statusMessage = status;
389399

390400
if (this.params.arguments.verbose) {
391-
this.params.response.console.log(status + "\n");
401+
this.params.response.console.log(Buffer.from(status + "\n"));
392402
}
393403

394404
if (this.params.arguments.silent === undefined) {
395405
const logger = Logger.getAppLogger();
396406
logger.debug(status);
397407
}
398408
}
409+
410+
private startProgressBar() {
411+
if (this.params.arguments.verbose !== true) {
412+
this.params.response.progress.startBar({task: this.progressBar});
413+
}
414+
}
415+
416+
private endProgressBar() {
417+
if (this.params.arguments.verbose !== true) {
418+
this.params.response.progress.endBar();
419+
}
420+
}
399421
}

src/cli/shared/BundleParent.handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export abstract class BundleParentHandler implements ICommandHandler {
5555
msg = await this.performAction(params);
5656

5757
// Issue the success message
58-
params.response.console.log(msg);
58+
params.response.console.log(Buffer.from(msg));
5959
if (params.arguments.silent === undefined) {
6060
logger.debug(msg);
6161
}

src/imperative.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,19 @@ const config: IImperativeConfig = {
118118
}
119119
},
120120
required: ["cicsplex", "scope", "cicshlq", "cpsmhlq", "jobcard"]
121-
}
121+
},
122+
createProfileExamples: [
123+
{
124+
options: "example1 --cicsplex PLEX1 --scope TESTGRP1 --cicshlq CICSTS55.CICS720 --cpsmhlq CICSTS55.CPSM550",
125+
description: "Create a cics-deploy profile called 'example1' to connect to a CPSM managed group of CICS regions " +
126+
"within the TESTGRP1 scope of a cicsplex named PLEX1"
127+
},
128+
{
129+
options: "example2 --cicsplex PLEX1 --scope TESTGRP1 --cicshlq CICSTS55.CICS720 --cpsmhlq CICSTS55.CPSM550 --resgroup BUNDGRP1",
130+
description: "Create a cics-deploy profile called 'example2' to connect to the same CPSM managed group of regions, " +
131+
"and identify a BAS resource group BUNDGRP1 in which to store resource definitions"
132+
}
133+
]
122134
}
123135
]
124136
};

0 commit comments

Comments
 (0)