@zowe/cli
Version:
Zowe CLI is a command line interface (CLI) that provides a simple and streamlined way to interact with IBM z/OS.
297 lines • 16.2 kB
JavaScript
"use strict";
/*
* 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 Contributors to the Zowe Project.
*
*/
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 });
const rest_1 = require("../../../rest");
const imperative_1 = require("@zowe/imperative");
const JobsConstants_1 = require("./JobsConstants");
const JobsMessages_1 = require("./JobsMessages");
const GetJobs_1 = require("./GetJobs");
const DownloadJobs_1 = require("./DownloadJobs");
const MonitorJobs_1 = require("./MonitorJobs");
/**
* Class to handle submitting of z/OS batch jobs via z/OSMF
* @export
* @class SubmitJobs
*/
class SubmitJobs {
/**
* Submit a job that resides in a z/OS data set.
* @static
* @param {AbstractSession} session - z/OSMF connection info
* @param {string} jobDataSet - job data set to be translated into parms object
* @returns {Promise<IJob>} - Promise that resolves to an IJob document with details about the submitted job
* @memberof SubmitJobs
*/
static submitJob(session, jobDataSet) {
this.log.trace("submitJob called with data set %s", jobDataSet);
return SubmitJobs.submitJobCommon(session, { jobDataSet });
}
/**
* Submit a job that resides in a z/OS data set.
* @static
* @param {AbstractSession} session - z/OSMF connection info
* @param {ISubmitJobParms} parms - parm object (see for details)
* @returns {Promise<IJob>} - Promise that resolves to an IJob document with details about the submitted job
* @memberof SubmitJobs
*/
static submitJobCommon(session, parms) {
return __awaiter(this, void 0, void 0, function* () {
this.log.trace("submitJobCommon called with parms %s", JSON.stringify(parms));
imperative_1.ImperativeExpect.keysToBeDefined(parms, ["jobDataSet"], "You must provide a data set containing JCL to submit in parms.jobDataSet");
this.log.debug("Submitting a job located in the data set '%s'", parms.jobDataSet);
const fullyQualifiedDataset = "//'" + parms.jobDataSet + "'";
const jobObj = { file: fullyQualifiedDataset };
return rest_1.ZosmfRestClient.putExpectJSON(session, JobsConstants_1.JobsConstants.RESOURCE, [imperative_1.Headers.APPLICATION_JSON], jobObj);
});
}
/**
* Submit a string of JCL to run
* @static
* @param {AbstractSession} session - z/OSMF connection info
* @param {string} jcl - string of JCL that you want to be submit
* @param {string} internalReaderRecfm - record format of the jcl you want to submit. "F" (fixed) or "V" (variable)
* @param {string} internalReaderLrecl - logical record length of the jcl you want to submit
* @returns {Promise<IJob>} - Promise that resolves to an IJob document with details about the submitted job
* @memberof SubmitJobs
*/
static submitJcl(session, jcl, internalReaderRecfm, internalReaderLrecl) {
this.log.trace("submitJcl called with jcl of length %d. internalReaderRecfm %s internalReaderLrecl %s", jcl == null ? "no jcl!" : jcl.length, internalReaderRecfm, internalReaderLrecl);
return SubmitJobs.submitJclCommon(session, { jcl, internalReaderRecfm, internalReaderLrecl });
}
static submitJclString(session, jcl, parms) {
return __awaiter(this, void 0, void 0, function* () {
imperative_1.ImperativeExpect.toNotBeNullOrUndefined(jcl, JobsMessages_1.ZosJobsMessages.missingJcl.message);
imperative_1.ImperativeExpect.toNotBeEqual(jcl, "", JobsMessages_1.ZosJobsMessages.missingJcl.message);
const responseJobInfo = yield SubmitJobs.submitJclCommon(session, { jcl });
const response = this.checkSubmitOptions(session, parms, responseJobInfo);
return response;
});
}
/**
* Submit a JCL string to run
* @static
* @param {AbstractSession} session - z/OSMF connection info
* @param {ISubmitJclParms} parms - parm object (see for details)
* @returns {Promise<IJob>} - Promise that resolves to an IJob document with details about the submitted job
* @memberof SubmitJobs
*/
static submitJclCommon(session, parms) {
return __awaiter(this, void 0, void 0, function* () {
this.log.trace("submitJclCommon called with parms %s", JSON.stringify(parms));
imperative_1.ImperativeExpect.keysToBeDefined(parms, ["jcl"], "You must provide a JCL string to submit. The 'jcl' field of the provided parameters was undefined. ");
this.log.debug("Submitting JCL of length %d", parms.jcl.length);
const headers = [imperative_1.Headers.TEXT_PLAIN_UTF8, rest_1.ZosmfHeaders.X_IBM_INTRDR_MODE_TEXT];
if (parms.internalReaderLrecl) {
this.log.debug("Custom internal reader logical record length (internalReaderLrecl) '%s' specified ", parms.internalReaderLrecl);
headers.push({ "X-IBM-Intrdr-Lrecl": parms.internalReaderLrecl });
}
else {
// default to 80 record length
headers.push(rest_1.ZosmfHeaders.X_IBM_INTRDR_LRECL_80);
}
if (parms.internalReaderRecfm) {
this.log.debug("Custom internal reader record format (internalReaderRecfm) '%s' specified ", parms.internalReaderRecfm);
headers.push({ "X-IBM-Intrdr-Recfm": parms.internalReaderRecfm });
}
else {
// default to fixed format records
headers.push(rest_1.ZosmfHeaders.X_IBM_INTRDR_RECFM_F);
}
return rest_1.ZosmfRestClient.putExpectJSON(session, JobsConstants_1.JobsConstants.RESOURCE, headers, parms.jcl);
});
}
/**
* Submit a JCL string to run
* @static
* @param {AbstractSession} session - z/OSMF connection info
* @param {string} jcl - string of JCL that you want to be submit
* @param {string} internalReaderRecfm - record format of the jcl you want to submit. "F" (fixed) or "V" (variable).
* @param {string} internalReaderLrecl - logical record length of the jcl you want to submit
* @returns {Promise<IJob>} - Promise that resolves to an IJob document with details about the submitted job
* @memberof SubmitJobs
*/
static submitJclNotify(session, jcl, internalReaderRecfm, internalReaderLrecl) {
return __awaiter(this, void 0, void 0, function* () {
this.log.trace("submitJclNotiy called with jcl of length %s, internalReaderRecfm %s, internalReaderLrecl %s", jcl == null ? "no jcl!" : jcl.length, internalReaderRecfm, internalReaderLrecl);
return SubmitJobs.submitJclNotifyCommon(session, { jcl, internalReaderRecfm, internalReaderLrecl });
});
}
/**
* Submit a job from a string of JCL and be notified whenever it reaches the default status on a default polling interval.
* @static
* @param {AbstractSession} session - z/OSMF connection info
* @param {ISubmitJclNotifyParm} parms - parm object (see for details)
* @returns {Promise<IJob>} - Promise that resolves to an IJob document with details about the submitted job
* @memberof SubmitJobs
*/
static submitJclNotifyCommon(session, parms) {
return __awaiter(this, void 0, void 0, function* () {
this.log.trace("submitJclNotifyCommon called with parms %s", JSON.stringify(parms));
const job = yield SubmitJobs.submitJclCommon(session, parms);
return SubmitJobs.submitNotifyCommon(session, job, parms.status, parms.watchDelay);
});
}
/**
* Submit a job and be notified whenever it reaches the default status on a default polling interval.
* @static
* @param {AbstractSession} session - z/OSMF connection info
* @param {string} jobDataSet - job data set to be translated into parms object with assumed defaults
* @returns {Promise<IJob>} - Promise that resolves to an IJob document with details about the submitted job
* @memberof SubmitJobs
*/
static submitJobNotify(session, jobDataSet) {
return __awaiter(this, void 0, void 0, function* () {
this.log.trace("submitJobNotify called with data set %s", jobDataSet);
return SubmitJobs.submitJobNotifyCommon(session, { jobDataSet });
});
}
/**
* Submit a job from a data set and be notified whenever it reaches a certain status.
* If not status is specified, MonitorJobs.DEFAULT_STATUS is assumed.
* The polling interval can also be optionally controlled via parms.watchDelay.
* If not specified, the default polling is MonitorJobs.DEFAULT_WATCH_DELAY.
* @static
* @param {AbstractSession} session - z/OSMF connection info
* @param {ISubmitJobNotifyParm} parms - parm object (see for details)
* @returns {Promise<IJob>} - Promise that resolves to an IJob document with details about the submitted job
* @memberof SubmitJobs
*/
static submitJobNotifyCommon(session, parms) {
return __awaiter(this, void 0, void 0, function* () {
this.log.trace("submitJobNotifyCommon called with parms %s", JSON.stringify(parms));
imperative_1.ImperativeExpect.keysToBeDefined(parms, ["jobDataSet"], "You must provide a data set containing JCL to submit in parms.jobDataSet.");
const job = yield SubmitJobs.submitJobCommon(session, parms);
return SubmitJobs.submitNotifyCommon(session, job, parms.status, parms.watchDelay);
});
}
/**
* Common method to handle job submit options
* @public
* @static
* @param {AbstractSession} session - z/OSMF connection info
* @param {ISubmitParms } parms - Submit options
* @param {IJob} responseJobInfo - job document for a previously submitted job
* @returns {Promise<IJob | ISpoolFile[]>} - Promise that resolves to an IJob or ISpoolFile[]
* @memberof SubmitJobs
*/
static checkSubmitOptions(session, parms, responseJobInfo) {
return __awaiter(this, void 0, void 0, function* () {
if (parms.waitForActive) {
const activeJob = yield MonitorJobs_1.MonitorJobs.waitForStatusCommon(session, {
jobid: responseJobInfo.jobid,
jobname: responseJobInfo.jobname,
status: "ACTIVE"
});
return activeJob;
}
// if viewAppSpoolContent option passed, it waits till job status is output
// then get content of each spool file and return array of ISpoolFiles object
if (parms.viewAllSpoolContent || parms.waitForOutput) {
if (parms.task != null) {
parms.task.statusMessage = "Waiting for " + responseJobInfo.jobid + " to enter OUTPUT";
parms.task.percentComplete = imperative_1.TaskProgress.THIRTY_PERCENT;
}
const job = yield MonitorJobs_1.MonitorJobs.waitForJobOutputStatus(session, responseJobInfo);
if (!parms.viewAllSpoolContent) {
return job;
}
if (parms.task != null) {
parms.task.statusMessage = "Retrieving spool content for " + job.jobid +
(job.retcode == null ? "" : ", " + job.retcode);
parms.task.percentComplete = imperative_1.TaskProgress.SEVENTY_PERCENT;
}
const spoolFiles = yield GetJobs_1.GetJobs.getSpoolFilesForJob(session, job);
const arrOfSpoolFile = [];
for (const file of spoolFiles) {
const spoolContent = yield GetJobs_1.GetJobs.getSpoolContent(session, file);
arrOfSpoolFile.push({
id: file.id,
ddName: file.ddname,
stepName: file.stepname,
procName: file.procstep,
data: spoolContent,
});
}
return arrOfSpoolFile;
// if directory option passed, it waits till job status is output
// then downloads content of all spool files and returns IJob object
}
else if (parms.directory) {
// waits job status to be output
if (parms.task != null) {
parms.task.statusMessage = "Waiting for " + responseJobInfo.jobid + " to enter OUTPUT";
parms.task.percentComplete = imperative_1.TaskProgress.THIRTY_PERCENT;
}
const job = yield MonitorJobs_1.MonitorJobs.waitForJobOutputStatus(session, responseJobInfo);
const downloadParms = {
jobid: job.jobid,
jobname: job.jobname,
outDir: parms.directory
};
if (parms.extension) {
downloadParms.extension = imperative_1.IO.normalizeExtension(parms.extension);
}
if (parms.task != null) {
parms.task.statusMessage = "Downloading spool content for " + job.jobid +
(job.retcode == null ? "" : ", " + job.retcode);
parms.task.percentComplete = imperative_1.TaskProgress.SEVENTY_PERCENT;
}
(yield DownloadJobs_1.DownloadJobs.downloadAllSpoolContentCommon(session, downloadParms));
return job;
}
return responseJobInfo;
});
}
/**
* Common method to watch for a job to reach a certain status whether the job was
* submitted through raw JCL statement or through a data set containing JCL.
* @private
* @static
* @param {AbstractSession} session - z/OSMF connection info
* @param {IJob} job - job document for a previously submitted job
* @param {JOB_STATUS } status - status that we want this job to reach before notifying
* @param {number} watchDelay - delay / interval to poll
* @returns {Promise<IJob>} - Promise that resolves to an IJob document with details about the submitted job
* @memberof SubmitJobs
*/
static submitNotifyCommon(session, job, status, watchDelay) {
return __awaiter(this, void 0, void 0, function* () {
this.log.trace("submitNotiyCommon called with job %s, status %s, watchDelay %s", JSON.stringify(job), status, watchDelay);
imperative_1.ImperativeExpect.keysToBeDefined(job, ["jobname", "jobid"], "The job object you provide must contain both 'jobname' and 'jobid'.");
this.log.debug("Waiting to be notified of job completion from Monitor Jobs API for job %s (%s)", job.jobname, job.jobid);
return MonitorJobs_1.MonitorJobs.waitForStatusCommon(session, {
jobname: job.jobname,
jobid: job.jobid,
status,
watchDelay,
});
});
}
/**
* Getter for brightside logger
* @returns {Logger}
*/
static get log() {
return imperative_1.Logger.getAppLogger();
}
}
exports.SubmitJobs = SubmitJobs;
//# sourceMappingURL=SubmitJobs.js.map