UNPKG

zowe-cli-cics-deploy-plugin

Version:

IBM CICS Bundle generation and deployment for Zowe CLI

761 lines 38.9 kB
/* * 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 IBM Corp, 2019 * */ "use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BundlePusher = void 0; const imperative_1 = require("@zowe/imperative"); const cli_1 = require("@zowe/cli"); const cics_for_zowe_cli_1 = require("@zowe/cics-for-zowe-cli"); const BundleDeployer_1 = require("../BundleDeploy/BundleDeployer"); const Bundle_1 = require("../BundleContent/Bundle"); const SubtaskWithStatus_1 = require("./SubtaskWithStatus"); const ZosmfConfig_1 = require("./ZosmfConfig"); const SshConfig_1 = require("./SshConfig"); const CmciConfig_1 = require("./CmciConfig"); /** * Class to represent a CICS Bundle Pusher. * * @export * @class BundlePusher */ class BundlePusher { /** * Constructor for a BundlePusher. * @param {IHandlerParameters} params - The Imperative handler parameters * @param {string} localDirectory - The bundle directory. * @throws ImperativeError * @memberof BundlePusher */ constructor(params, localDirectory) { this.sshOutputText = ""; this.path = require("path"); this.fs = require("fs"); this.defaultRemoteNodehomeCmd = "export PATH=\"$PATH:/usr/lpp/IBM/cnj/v8r0/IBM/node-latest-os390-s390x/bin\""; this.envSetupCommand = "export _BPXK_AUTOCVT=ON"; this.params = params; this.localDirectory = localDirectory; this.validateParameters(); // The targetdir may contain escaped slashes, get rid of them this.params.arguments.targetdir = this.path.posix.normalize(this.params.arguments.targetdir); // Set an initial bundledir value for validation purposes (we'll replace it with a better value shortly) this.params.arguments.bundledir = this.path.posix.join(this.params.arguments.targetdir, this.params.arguments.name); } performPush() { return __awaiter(this, void 0, void 0, function* () { // Start by validating any parameters that will be used by the deploy action, // this should flush out most input errors before we go on to attempt upload // of the bundle const bd = new BundleDeployer_1.BundleDeployer(this.params); bd.validateDeployParms(); // Check that the current working directory is a CICS bundle const bundle = new Bundle_1.Bundle(this.localDirectory, true, true); bundle.validate(); // If the bundle has an id, use it in the target directory name if (bundle.getId() !== undefined) { this.params.arguments.bundledir = this.path.posix.join(this.params.arguments.targetdir, bundle.getId()) + "_" + bundle.getVersion(); } if (this.params.arguments.silent === undefined) { const logger = imperative_1.Logger.getAppLogger(); logger.debug("Loading profiles"); } // Get the profiles const zosMFProfile = this.getProfile("zosmf"); const sshProfile = this.getProfile("ssh"); let cicsProfile = this.getProfile("cics"); ZosmfConfig_1.ZosmfConfig.mergeProfile(zosMFProfile, this.params); SshConfig_1.SshConfig.mergeProfile(sshProfile, this.params); CmciConfig_1.CmciConfig.mergeProfile(cicsProfile, this.params); // The cics profile is optional, detect whether it has been set (or constructed) if (Object.keys(cicsProfile).length === 0) { cicsProfile = undefined; } // Now detect any mismatches between the values from the profiles this.validateProfiles(zosMFProfile, sshProfile, cicsProfile); if (this.params.arguments.silent === undefined) { const logger = imperative_1.Logger.getAppLogger(); logger.debug("Creating sessions"); } // Create a zOSMF session const zosMFSession = yield this.createZosMFSession(zosMFProfile); // Create an SSH session const sshSession = yield this.createSshSession(sshProfile); // If relevant, start a CICS session const cicsSession = yield this.createCicsSession(cicsProfile); // Start a progress bar (but only in non-verbose mode) this.progressBar = { percentComplete: 0, statusMessage: "Starting Push operation", stageName: imperative_1.TaskStage.IN_PROGRESS }; this.startProgressBar(); // Attempt to make the target bundledir yield this.makeBundleDir(zosMFSession); // Check that the remote bundledir is suitable. yield this.validateBundleDirExistsAndIsEmpty(zosMFSession); // If --overwrite is set then undeploy any existing bundle from CICS if (this.params.arguments.overwrite) { yield this.undeployExistingBundle(zosMFSession, bd); } // Find all of the package.json files in the Bundle const packageJsonFiles = []; this.findAllPackageJSONDirs(this.localDirectory, this.params.arguments.bundledir, packageJsonFiles); // If --overwrite is set then empty the remote directory structure if (this.params.arguments.overwrite) { // Run 'npm uninstall' for each package.json file that exists in the bundle. // This is a courtesy to give npm a chance to clean up itself, we have seen // things get installed that are difficult to remove simply by deleting the // directory. try { yield this.runAllNpmUninstalls(sshSession, packageJsonFiles); } catch (error) { // Something went wrong, but never mind, we'll destroy the entire directory in // a moment. } // Now delete the directory yield this.deleteBundleDirContents(sshSession); } // Upload the bundle yield this.uploadBundle(zosMFSession); // Run 'npm install' for each package.json file that exists in the bundle yield this.runAllNpmInstalls(sshSession, packageJsonFiles); // Run DFHDPLOY to install the bundle (note that this will end the progress bar) yield this.deployBundle(zosMFSession, bd, cicsSession, bundle); return "PUSH operation completed"; }); } validateParameters() { // Most of the parameters are validated by the bundle deployer, but we have // to check the --name and --targetdir parameters here, as they are used // to construct one of the values used by the BundleDeployer. this.validateName(); this.validateTargetdir(); } validateName() { // Name is mandatory if (this.params.arguments.name === undefined) { throw new Error("--name parameter is not set"); } if (typeof this.params.arguments.name !== "string") { throw new Error("--name parameter is not a string"); } const MAX_LEN = 8; if (this.params.arguments.name.length > MAX_LEN) { throw new Error("--name parameter is too long"); } if (this.params.arguments.name === "") { throw new Error("--name parameter is empty"); } } validateTargetdir() { // targetdir is mandatory if (this.params.arguments.targetdir === undefined) { throw new Error("--targetdir parameter is not set"); } if (typeof this.params.arguments.targetdir !== "string") { throw new Error("--targetdir parameter is not a string"); } const MAX_LEN = 255; if (this.params.arguments.targetdir.length > MAX_LEN) { throw new Error("--targetdir parameter is too long"); } if (this.params.arguments.targetdir === "") { throw new Error("--targetdir parameter is empty"); } } getProfile(type) { let profile; try { profile = this.params.profiles.get(type); } catch (error) { // Tolerate errors } if (profile === undefined) { profile = {}; } return profile; } issueWarning(msg) { const warningMsg = "WARNING: " + msg + "\n"; this.issueMessage(warningMsg); } issueMessage(msg) { this.params.response.console.log(Buffer.from(msg)); if (this.params.arguments.silent === undefined) { const logger = imperative_1.Logger.getAppLogger(); logger.warn(msg); } } validateProfiles(zosmfProfile, sshProfile, cicsProfile) { // Do the required profiles share the same host name? let sameHostAndUser = true; if (zosmfProfile.host !== sshProfile.host) { sameHostAndUser = false; this.issueWarning("--ssh-host value '" + sshProfile.host + "' does not match --zosmf-host value '" + zosmfProfile.host + "'."); } // Do the required profiles share the same user name? if (zosmfProfile.user.toUpperCase() !== sshProfile.user.toUpperCase()) { sameHostAndUser = false; this.issueWarning("--ssh-user value '" + sshProfile.user + "' does not match --zosmf-user value '" + zosmfProfile.user + "'."); } // If the zoSMF user and host are the same then validate that the passwords are the same too. // It's possible, especially over a password change, that one profile may have been updated // and not the other. Attemps to use the wrong password could result in the account being revoked. if (sameHostAndUser) { if (sshProfile.password !== undefined) { if (zosmfProfile.password !== sshProfile.password) { throw new Error("Different passwords are specified for the same user ID in the zosmf and ssh configurations."); } } } // Is the optional CICS profile compatible? if (cicsProfile !== undefined) { sameHostAndUser = true; if (zosmfProfile.host !== cicsProfile.host) { sameHostAndUser = false; this.issueWarning("--cics-host value '" + cicsProfile.host + "' does not match --zosmf-host value '" + zosmfProfile.host + "'."); } if (zosmfProfile.user.toUpperCase() !== cicsProfile.user.toUpperCase()) { sameHostAndUser = false; this.issueWarning("--cics-user value '" + cicsProfile.user + "' does not match --zosmf-user value '" + zosmfProfile.user + "'."); } if (sameHostAndUser) { if (zosmfProfile.password !== cicsProfile.password) { throw new Error("Different passwords are specified for the same user ID in the zosmf and cics configurations."); } } } } createZosMFSession(zosmfProfile) { return __awaiter(this, void 0, void 0, function* () { try { return cli_1.ZosmfSession.createBasicZosmfSession(zosmfProfile); } catch (error) { throw new Error("Failure occurred creating a zosmf session: " + error.message); } }); } createSshSession(sshProfile) { return __awaiter(this, void 0, void 0, function* () { try { return cli_1.SshSession.createBasicSshSession(sshProfile); } catch (error) { throw new Error("Failure occurred creating an ssh session: " + error.message); } }); } createCicsSession(cicsProfile) { return __awaiter(this, void 0, void 0, function* () { if (cicsProfile === undefined) { return undefined; } // At time of writing, the CicsSession object in the @zowe/cics project isn't // accessible, so the following code is copied out of CicsSession.createBasicCicsSession(). try { return new imperative_1.Session({ type: "basic", hostname: cicsProfile.host, port: cicsProfile.port, user: cicsProfile.user, password: cicsProfile.password, basePath: cicsProfile.basePath, protocol: cicsProfile.protocol || "http", rejectUnauthorized: cicsProfile.rejectUnauthorized }); } catch (error) { throw new Error("Failure occurred creating a cics session: " + error.message); } }); } validateBundleDirExistsAndIsEmpty(zosMFSession) { return __awaiter(this, void 0, void 0, function* () { try { this.updateStatus("Accessing contents of remote bundle directory"); const fileListResponse = yield cli_1.List.fileList(zosMFSession, this.params.arguments.bundledir, {}); if (!fileListResponse.success) { throw new Error("Command Failed."); } if (fileListResponse.apiResponse === undefined) { throw new Error("Command response is empty."); } if (fileListResponse.apiResponse.items === undefined) { throw new Error("Command response items are missing."); } // There are always at least two files in all directories: . and .. const MIN_FILES = 2; // Check that if there are files in the directory, one of them is called META-INF let foundMETAINF = false; if (fileListResponse.apiResponse.items.length > MIN_FILES) { for (const file of fileListResponse.apiResponse.items) { if (file.name === "META-INF") { foundMETAINF = true; } } if (!foundMETAINF) { throw new Error("The remote directory is already populated and does not contain a bundle."); } } // Check that --overwrite is set if the directory is not empty if (fileListResponse.apiResponse.items.length > MIN_FILES && this.params.arguments.overwrite !== true) { throw new Error("The remote directory has existing content and --overwrite has not been set."); } } catch (error) { throw new Error("A problem occurred accessing remote bundle directory '" + this.params.arguments.bundledir + "'. Problem is: " + error.message); } }); } undeployExistingBundle(zosMFSession, bd) { return __awaiter(this, void 0, void 0, function* () { // End the current progress bar so that UNDEPLOY can create its own this.updateStatus("Undeploying bundle '" + this.params.arguments.name + "' from CICS"); const targetstateLocal = this.params.arguments.targetstate; this.params.arguments.targetstate = "DISCARDED"; const subtask = new SubtaskWithStatus_1.SubtaskWithStatus(this.progressBar, imperative_1.TaskProgress.THIRTY_PERCENT); yield bd.undeployBundle(zosMFSession, subtask); this.params.arguments.targetstate = targetstateLocal; // Resume the current progress bar this.endProgressBar(); this.updateStatus("Undeploy complete"); this.startProgressBar(); }); } deployBundle(zosMFSession, bd, cicsSession, bundle) { return __awaiter(this, void 0, void 0, function* () { // End the current progress bar so that DEPLOY can create its own this.updateStatus("Deploying bundle '" + this.params.arguments.name + "' to CICS"); const subtask = new SubtaskWithStatus_1.SubtaskWithStatus(this.progressBar, imperative_1.TaskProgress.THIRTY_PERCENT); let deployError; let dfhdployOutput = ""; try { yield bd.deployBundle(zosMFSession, subtask); } catch (error) { // temporarily ignore the error as we might want to generate additional resource // specific diagnostics even if something went wrong. deployError = error; } dfhdployOutput = bd.getJobOutput(); // End the main progress bar this.progressBar.percentComplete = imperative_1.TaskProgress.ONE_HUNDRED_PERCENT; this.endProgressBar(); if (deployError === undefined) { this.updateStatus("Deploy complete"); } else { this.updateStatus("Deploy ended with errors"); } // Collect general information about the regions in the CICSplex scope let deployMessages = yield this.generateGeneralDiagnostics(cicsSession); if (deployError !== undefined && dfhdployOutput.indexOf("DFHRL2067") === -1) { // If we have an error, but DFHDPLOY did not report that some bundleparts are disabled, // we can assume bundle didn't install at all. In this case skip generation of // Node.js diagnostics. deployMessages += "DFHDPLOY output implied the bundle failed to install. Check the output above for further information. "; deployMessages += "Consider examining the JESMSGLG, MSGUSR, SYSPRINT and SYSOUT spool files of the CICS region job, "; deployMessages += "or consult your CICS system programmer.\n"; } else if (deployMessages !== "" && bundle.containsDefinitionsOfType("http://www.ibm.com/xmlns/prod/cics/bundle/NODEJSAPP")) { // Generate additional diagnostic output for Node.js deployMessages += yield this.generateNodejsSpecificDiagnostics(cicsSession); } // Report any console messages now this.issueMessage(deployMessages); // Now rethrow the original error, if there was one. if (deployError !== undefined) { throw deployError; } }); } sshOutput(data) { // If verbose output is requested then log SSH output directly to the console if (this.params.arguments.verbose) { this.params.response.console.log(Buffer.from(data)); } this.sshOutputText += data; } makeBundleDir(zosMFSession) { return __awaiter(this, void 0, void 0, function* () { if (this.params.arguments.verbose) { this.updateStatus("Making remote bundle directory '" + this.params.arguments.bundledir + "'"); } else { this.updateStatus("Making remote bundle directory"); } const WARNING = 4; const ALREADY_EXISTS = 19; const EIGHT = 8; const TARGET_DIR_NOT_EXIST = 93651005; const NO_PERMISSION = -276865003; try { yield cli_1.Create.uss(zosMFSession, this.params.arguments.bundledir, "directory"); } catch (error) { if (error.causeErrors !== undefined) { let cause; if (typeof error.causeErrors !== "object") { try { cause = JSON.parse(error.causeErrors); } catch (error) { // whatever we received here it wasn't JSON. Oh well, never mind. } } else { cause = error.causeErrors; } // Special case some known errors if (cause !== undefined) { if (cause.category === 1 && cause.rc === WARNING && cause.reason === ALREADY_EXISTS) { // if it already exists, no worries return; } if (cause.category === EIGHT && cause.rc === -1 && cause.reason === TARGET_DIR_NOT_EXIST) { throw new Error("The target directory does not exist, consider creating it by issuing: \n" + "zowe zos-uss issue ssh \"mkdir -p " + this.params.arguments.targetdir + "\""); } if (cause.category === EIGHT && cause.rc === -1 && cause.reason === NO_PERMISSION) { throw new Error("You are not authorized to create the target bundle directory '" + this.params.arguments.bundledir + "'."); } } } throw new Error("A problem occurred attempting to create directory '" + this.params.arguments.bundledir + "'. " + "Problem is: " + error.message); } }); } deleteBundleDirContents(sshSession) { return __awaiter(this, void 0, void 0, function* () { this.updateStatus("Removing contents of remote bundle directory"); yield this.runSshCommandInRemoteDirectory(sshSession, this.params.arguments.bundledir, "if [ \"$(ls)\" ]; then rm -r *; fi"); }); } runSingleNpmInstall(sshSession, remoteDirectory) { return __awaiter(this, void 0, void 0, function* () { if (this.params.arguments.verbose) { this.updateStatus("Running 'npm install' in '" + remoteDirectory + "'"); } else { this.updateStatus("Running 'npm install' in remote directory"); } yield this.runSshCommandInRemoteDirectory(sshSession, remoteDirectory, this.defaultRemoteNodehomeCmd + " && " + this.envSetupCommand + " && npm install"); }); } runSingleNpmUninstall(sshSession, remoteDirectory) { return __awaiter(this, void 0, void 0, function* () { if (this.params.arguments.verbose) { this.updateStatus("Running 'npm uninstall *' in '" + remoteDirectory + "'"); } else { this.updateStatus("Running 'npm uninstall *' in remote directory"); } // uninstall each module individually yield this.runSshCommandInRemoteDirectory(sshSession, remoteDirectory, this.defaultRemoteNodehomeCmd + " && " + this.envSetupCommand + " && " + "if [ -d \"node_modules\" ] && [ \"$(ls node_modules)\" ]; then npm uninstall `ls -1 node_modules | tr '/\n' ' '`; fi"); }); } runSshCommandInRemoteDirectory(sshSession, directory, sshCommand) { return __awaiter(this, void 0, void 0, function* () { try { if (this.params.arguments.verbose) { this.updateStatus("Issuing SSH command '" + sshCommand + "' in remote directory '" + directory + "'"); } this.sshOutputText = ""; const sshReturnCode = yield cli_1.Shell.executeSshCwd(sshSession, sshCommand, directory, this.sshOutput.bind(this)); const upperCaseOutputText = this.sshOutputText.toUpperCase(); // Note that FSUM9195 can imply that we've tried to delete the // contents of an empty directory - that's not a problem. // Check if FSUM9195 is the only FSUM error let isOnlyFSUM9195 = false; const countFSUM = (upperCaseOutputText.match(/FSUM/g) || []).length; const countFSUM9195 = (upperCaseOutputText.match(/FSUM9195/g) || []).length; if (countFSUM9195 !== 0 && countFSUM === countFSUM9195 && sshReturnCode === 1) { isOnlyFSUM9195 = true; } // Now check // A. If exit code is non zero // B. FSUM9195 is not the only FSUM error if (sshReturnCode !== 0 && !isOnlyFSUM9195) { // if we've not already logged the output, log it now if (this.params.arguments.verbose !== true) { this.params.response.console.log(Buffer.from(this.sshOutputText)); } throw new Error("The output from the remote command implied that an error occurred, return code " + sshReturnCode + "."); } } catch (error) { throw new Error("A problem occurred attempting to run '" + sshCommand + "' in remote directory '" + directory + "'. Problem is: " + error.message); } }); } uploadBundle(zosMFSession) { return __awaiter(this, void 0, void 0, function* () { this.updateStatus("Uploading bundle contents to remote directory"); const uploadOptions = { recursive: true }; uploadOptions.attributes = this.findZosAttributes(); uploadOptions.task = new SubtaskWithStatus_1.SubtaskWithStatus(this.progressBar, imperative_1.TaskProgress.TEN_PERCENT); try { yield cli_1.Upload.dirToUSSDirRecursive(zosMFSession, this.localDirectory, this.params.arguments.bundledir, uploadOptions); } catch (error) { throw new Error("A problem occurred uploading the bundle contents to the remote directory '" + this.params.arguments.bundledir + "'. Problem is: " + error.message); } }); } findZosAttributes() { const attributesFileName = this.path.join(this.localDirectory, ".zosattributes"); if (this.fs.existsSync(attributesFileName)) { try { const attributesFileContents = this.fs.readFileSync(attributesFileName).toString(); return new cli_1.ZosFilesAttributes(attributesFileContents, this.localDirectory); } catch (error) { throw new Error("A problem occurred reading the local .zosattributes file '" + attributesFileName + "'. Problem is: " + error.message); } } // A project specific .zosattributes has not been found, so use a default this.issueWarning("No .zosattributes file found in the bundle directory, default values will be applied."); return new cli_1.ZosFilesAttributes(Bundle_1.Bundle.getTemplateZosAttributesFile()); } updateStatus(status, percentageIncrease = 3) { const MAX_PROGRESS_BAR_MESSAGE = 60; this.progressBar.percentComplete += percentageIncrease; if (status.length > MAX_PROGRESS_BAR_MESSAGE) { this.progressBar.statusMessage = status.substring(0, MAX_PROGRESS_BAR_MESSAGE) + "..."; } else { this.progressBar.statusMessage = status; } if (this.params.arguments.verbose) { this.params.response.console.log(Buffer.from(status + "\n")); } if (this.params.arguments.silent === undefined) { const logger = imperative_1.Logger.getAppLogger(); logger.debug(status); } } startProgressBar() { if (this.params.arguments.verbose !== true && this.progressBar !== undefined) { this.params.response.progress.startBar({ task: this.progressBar }); } } endProgressBar() { if (this.params.arguments.verbose !== true && this.progressBar !== undefined) { this.params.response.progress.endBar(); } } findAllPackageJSONDirs(directoryNameLocal, directoryNameRemote, found) { // accumulate an array of all directories / sub-directories that contain a package.json file const files = this.fs.readdirSync(directoryNameLocal); for (const currentFile of files) { const localFileName = this.path.join(directoryNameLocal, currentFile); const remoteFileName = this.path.posix.join(directoryNameRemote, currentFile); const stat = this.fs.lstatSync(localFileName); if (stat.isDirectory() && currentFile !== "node_modules") { // If we've found a sub-directory, and it's not the special node_modules directory, scan it too. this.findAllPackageJSONDirs(localFileName, remoteFileName, found); } else if (currentFile === "package.json") { // The current directory has a package.json found.push(directoryNameRemote); } } } runAllNpmInstalls(sshSession, packageJsonFiles) { return __awaiter(this, void 0, void 0, function* () { for (const remoteDirectory of packageJsonFiles) { yield this.runSingleNpmInstall(sshSession, remoteDirectory); } }); } runAllNpmUninstalls(sshSession, packageJsonFiles) { return __awaiter(this, void 0, void 0, function* () { for (const remoteDirectory of packageJsonFiles) { yield this.runSingleNpmUninstall(sshSession, remoteDirectory); } }); } generateGeneralDiagnostics(cicsSession) { return __awaiter(this, void 0, void 0, function* () { let msgBuffer = ""; try { if (cicsSession !== undefined) { // Attempt to gather additional Node.js specific information from CICS this.updateStatus("Gathering scope information"); msgBuffer = yield this.gatherGeneralDiagnosticsFromCics(cicsSession); } } catch (diagnosticsError) { // Something went wrong generating scope info. Don't trouble the user // with what might be an exotic error message (e.g. hex dump of an entire HTML page), // just log the failure. if (this.params.arguments.silent === undefined) { const logger = imperative_1.Logger.getAppLogger(); logger.debug(diagnosticsError.message); } } // Something went wrong, suggest a command that can be run to figure out more. if (msgBuffer === "") { this.issueMessage("An attempt to query the remote CICSplex using the cics plug-in has failed.\n"); } return msgBuffer; }); } generateNodejsSpecificDiagnostics(cicsSession) { return __awaiter(this, void 0, void 0, function* () { let msgBuffer = ""; if (cicsSession === undefined) { return msgBuffer; } try { // Attempt to gather additional Node.js specific information from CICS this.updateStatus("Gathering Node.js diagnostics"); msgBuffer = yield this.gatherNodejsDiagnosticsFromCics(cicsSession); } catch (diagnosticsError) { // Something went wrong generating diagnostic info. Don't trouble the user // with what might be an exotic error message (e.g. hex dump of an entire HTML page), // just log the failure. if (this.params.arguments.silent === undefined) { const logger = imperative_1.Logger.getAppLogger(); logger.debug(diagnosticsError.message); } } // We must have a cics profile in order to have got this far, so suggest a command that can be run to figure out more. if (msgBuffer === "") { msgBuffer += "For further information on the state of your NODEJSAPP resources, consider running the following command:\n\n" + "zowe cics get resource CICSNodejsapp --region-name " + this.params.arguments.scope + " --criteria \"BUNDLE=" + this.params.arguments.name + "\" --cics-plex " + this.params.arguments.cicsplex + "\n\n"; } return msgBuffer; }); } gatherGeneralDiagnosticsFromCics(cicsSession) { return __awaiter(this, void 0, void 0, function* () { // Issue a CMCI get to the target CICSplex try { this.updateStatus("Querying regions in scope over CMCI"); const regionData = { name: "CICSRegion", regionName: this.params.arguments.scope, cicsPlex: this.params.arguments.cicsplex }; const cmciRegionResponse = yield cics_for_zowe_cli_1.getResource(cicsSession, regionData); if (cmciRegionResponse === undefined || cmciRegionResponse.response === undefined || cmciRegionResponse.response.records === undefined || cmciRegionResponse.response.records.cicsregion === undefined) { throw new Error("CICSRegion CMCI output record not found."); } const outputRegionRecords = cmciRegionResponse.response.records.cicsregion; let msgBuffer = "Regions in scope '" + this.params.arguments.scope + "' of CICSplex '" + this.params.arguments.cicsplex + "':\n"; // We may have an array of records if there was more than one Region in the scope if (Array.isArray(outputRegionRecords)) { for (const record of outputRegionRecords) { msgBuffer = this.reportRegionData(record, msgBuffer); } } else { msgBuffer = this.reportRegionData(outputRegionRecords, msgBuffer); } return msgBuffer; } catch (error) { throw new Error("Failure collecting diagnostics for Bundle " + this.params.arguments.name + ": " + error.message); } }); } gatherNodejsDiagnosticsFromCics(cicsSession) { return __awaiter(this, void 0, void 0, function* () { try { // Process each NODEJSAPP in the Scope this.updateStatus("Querying NODEJSAPP resources over CMCI"); const nodejsData = { name: "CICSNodejsapp", criteria: "BUNDLE=" + this.params.arguments.name, regionName: this.params.arguments.scope, cicsPlex: this.params.arguments.cicsplex }; const cmciNodejsResponse = yield cics_for_zowe_cli_1.getResource(cicsSession, nodejsData); if (cmciNodejsResponse === undefined || cmciNodejsResponse.response === undefined || cmciNodejsResponse.response.records === undefined || cmciNodejsResponse.response.records.cicsnodejsapp === undefined) { throw new Error("CICSNodejsapp CMCI output record not found."); } const outputNodejsRecords = cmciNodejsResponse.response.records.cicsnodejsapp; let msgBuffer = "\nNODEJSAPP resources for bundle '" + this.params.arguments.name + "' in scope '" + this.params.arguments.scope + "':\n"; // We may have an array of records if there was more than one NODEJSAPP in the bundle if (Array.isArray(outputNodejsRecords)) { for (const record of outputNodejsRecords) { msgBuffer = this.reportNODEJSAPPData(record, msgBuffer); } } else { msgBuffer = this.reportNODEJSAPPData(outputNodejsRecords, msgBuffer); } return msgBuffer; } catch (error) { throw new Error("Failure collecting diagnostics for Bundle " + this.params.arguments.name + ": " + error.message); } }); } reportRegionData(outputRecord, msgBuffer) { const MAX_LENGTH = 8; const applid = outputRecord.applid.padEnd(MAX_LENGTH, " "); const jobid = outputRecord.jobid.padEnd(MAX_LENGTH, " "); const jobname = outputRecord.jobname.padEnd(MAX_LENGTH, " "); const sysname = outputRecord.mvssysname.padEnd(MAX_LENGTH, " "); return msgBuffer + " Applid: " + applid + " jobname: " + jobname + " jobid: " + jobid + " sysname: " + sysname + "\n"; } reportNODEJSAPPData(outputRecord, msgBuffer) { const name = outputRecord.name; const enablestatus = outputRecord.enablestatus; const pid = outputRecord.pid; const region = outputRecord.eyu_cicsname; let stdout = outputRecord.stdout; let stderr = outputRecord.stderr; if (stdout === undefined || stdout.trim() === "") { stdout = "<not available>"; } if (stderr === undefined || stderr.trim() === "") { stderr = "<not available>"; } return msgBuffer + "NODEJSAPP resource '" + name + "' is in '" + enablestatus + "' state in region '" + region + "' with process id '" + pid + "'.\n" + " stdout: " + stdout + "\n" + " stderr: " + stderr + "\n"; } } exports.BundlePusher = BundlePusher; //# sourceMappingURL=BundlePusher.js.map