Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FTP ext] Close connection #1324

Merged
merged 10 commits into from
Jun 8, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,11 @@ export abstract class AbstractFtpApi implements ZoweExplorerApi.ICommon {
secureFtp: ftpProfile.secureFtp,
});
}
public releaseConnection(connection: any): void {
if (connection != null) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
connection.close();
return;
}
}
}
280 changes: 156 additions & 124 deletions packages/zowe-explorer-ftp-extension/src/ZoweExplorerFtpJesApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,143 +20,165 @@ import { AbstractFtpApi } from "./ZoweExplorerAbstractFtpApi";
// The Zowe FTP CLI plugin is written and uses mostly JavaScript, so relax the rules here.
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unused-vars*/

export class FtpJesApi extends AbstractFtpApi implements ZoweExplorerApi.IJes {
public async getJobsByOwnerAndPrefix(owner: string, prefix: string): Promise<zowe.IJob[]> {
const result = this.getIJobResponse();
const connection = await this.ftpClient(this.checkedProfile());
if (connection) {
const options = {
owner: owner,
};
const response = await JobUtils.listJobs(connection, prefix, options);
if (response) {
const results = response.map((job: IJob) => {
return {
...result,
/* it’s prepared for the potential change in zftp api, renaming jobid to jobId, jobname to jobName. */
jobid: (job as any).jobId || job.jobid,
jobname: (job as any).jobName || job.jobname,
owner: job.owner,
class: job.class,
status: job.status,
};
});
return results;
let connection: any;
try {
connection = await this.ftpClient(this.checkedProfile());
if (connection) {
const options = {
owner: owner,
};
const response = (await JobUtils.listJobs(connection, prefix, options)) as IJob[];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When running yarn package, I received the following ESLint error:

Screen Shot 2021-06-04 at 3 56 13 PM

To resolve this error, I had to delete as IJob[] from the end of line 34.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think as IJob[] is unnecessary now. JobUtils.listJobs returns Promise<IJob[]>. Thanks!

public static async listJobs(connection: any, prefix: string, option?: IListJobOption): Promise<IJob[]>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @std4lqi for confirming this. I've pushed a commit removing as IJob[] to the PR branch. (@tiantn I hope this is ok with you! I just figured it would be quicker to do a direct push since this was a small, low-risk change.)

if (response) {
const results = response.map((job: IJob) => {
return {
...result,
/* it’s prepared for the potential change in zftp api, renaming jobid to jobId, jobname to jobName. */
jobid: (job as any).jobId || job.jobid,
jobname: (job as any).jobName || job.jobname,
owner: job.owner,
class: job.class,
status: job.status,
};
});
return results;
}
}
return [result];
} finally {
this.releaseConnection(connection);
}
return [result];
}

public async getJob(jobid: string): Promise<zowe.IJob> {
const result = this.getIJobResponse();
const connection = await this.ftpClient(this.checkedProfile());
if (connection) {
const jobStatus: IJobStatus = await JobUtils.findJobByID(connection, jobid);
if (jobStatus) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return {
...result,
/* it’s prepared for the potential change in zftp api, renaming jobid to jobId, jobname to jobName. */
jobid: (jobStatus as any).jobId || jobStatus.jobid,
jobname: (jobStatus as any).jobName || jobStatus.jobname,
owner: jobStatus.owner,
class: jobStatus.class,
status: jobStatus.status,
};
let connection: any;
try {
connection = await this.ftpClient(this.checkedProfile());
if (connection) {
const jobStatus: IJobStatus = await JobUtils.findJobByID(connection, jobid);
if (jobStatus) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return {
...result,
/* it’s prepared for the potential change in zftp api, renaming jobid to jobId, jobname to jobName. */
jobid: (jobStatus as any).jobId || jobStatus.jobid,
jobname: (jobStatus as any).jobName || jobStatus.jobname,
owner: jobStatus.owner,
class: jobStatus.class,
status: jobStatus.status,
};
}
}
return result;
} finally {
this.releaseConnection(connection);
}
return result;
}

public async getSpoolFiles(jobname: string, jobid: string): Promise<zowe.IJobFile[]> {
const result = this.getIJobFileResponse();
const connection = await this.ftpClient(this.checkedProfile());
if (connection) {
const response: IJobStatus = await JobUtils.findJobByID(connection, jobid);
const files: any = response.spoolFiles;
if (files) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return files.map((file: ISpoolFile) => {
return {
/* it’s prepared for the potential change in zftp api, renaming stepname to stepName, procstep to procStep, ddname to ddName. */
jobid: jobid,
jobname: jobname,
"byte-count": file.byteCount,
id: file.id,
stepname: (file as any).stepName || file.stepname,
procstep: (file as any).procStep || file.procstep,
class: file.class,
ddname: (file as any).ddName || file.ddname,
};
});
let connection: any;
try {
connection = await this.ftpClient(this.checkedProfile());
if (connection) {
const response: IJobStatus = await JobUtils.findJobByID(connection, jobid);
const files: any = response.spoolFiles;
if (files) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-call
return files.map((file: ISpoolFile) => {
return {
/* it’s prepared for the potential change in zftp api, renaming stepname to stepName, procstep to procStep, ddname to ddName. */
jobid: jobid,
jobname: jobname,
"byte-count": file.byteCount,
id: file.id,
stepname: (file as any).stepName || file.stepname,
procstep: (file as any).procStep || file.procstep,
class: file.class,
ddname: (file as any).ddName || file.ddname,
};
});
}
}
return [result];
} finally {
this.releaseConnection(connection);
}
return [result];
}
public async downloadSpoolContent(parms: zowe.IDownloadAllSpoolContentParms): Promise<void> {
const connection = await this.ftpClient(this.checkedProfile());
/* it's duplicate code with zftp. We may add new job API in the next zftp to cover spool file downloading. */
if (connection) {
const destination = parms.outDir == null ? "./output/" : parms.outDir;
const jobDetails = await JobUtils.findJobByID(connection, parms.jobid);
if (jobDetails.spoolFiles == null || jobDetails.spoolFiles.length === 0) {
throw new Error("No spool files were available.");
}
const fullSpoolFiles = await JobUtils.getSpoolFiles(connection, jobDetails.jobid);
for (const spoolFileToDownload of fullSpoolFiles) {
const mockJobFile: IJobFile = {
// mock a job file to get the same format of download directories
jobid: jobDetails.jobid,
jobname: jobDetails.jobname,
recfm: "FB",
lrecl: 80,
"byte-count": Number(spoolFileToDownload.byteCount),
// todo is recfm or lrecl available? FB 80 could be wrong
"record-count": 0,
"job-correlator": "", // most of these options don't matter for download
class: "A",
ddname: String(spoolFileToDownload.ddname),
id: Number(spoolFileToDownload.id),
"records-url": "",
subsystem: "JES2",
stepname: String(spoolFileToDownload.stepname),
procstep: String(
spoolFileToDownload.procstep === "N/A" || spoolFileToDownload.procstep == null
? undefined
: spoolFileToDownload.procstep
),
};
const destinationFile = DownloadJobs.getSpoolDownloadFile(
mockJobFile,
parms.omitJobidDirectory,
parms.outDir
);
imperative.IO.createDirsSyncFromFilePath(destinationFile);
imperative.IO.writeFile(destinationFile, spoolFileToDownload.contents as Buffer);
let connection: any;
try {
connection = await this.ftpClient(this.checkedProfile());
/* it's duplicate code with zftp. We may add new job API in the next zftp to cover spool file downloading. */
if (connection) {
const destination = parms.outDir == null ? "./output/" : parms.outDir;
const jobDetails = await JobUtils.findJobByID(connection, parms.jobid);
if (jobDetails.spoolFiles == null || jobDetails.spoolFiles.length === 0) {
throw new Error("No spool files were available.");
}
const fullSpoolFiles = await JobUtils.getSpoolFiles(connection, jobDetails.jobid);
for (const spoolFileToDownload of fullSpoolFiles) {
const mockJobFile: IJobFile = {
// mock a job file to get the same format of download directories
jobid: jobDetails.jobid,
jobname: jobDetails.jobname,
recfm: "FB",
lrecl: 80,
"byte-count": Number(spoolFileToDownload.byteCount),
// todo is recfm or lrecl available? FB 80 could be wrong
"record-count": 0,
"job-correlator": "", // most of these options don't matter for download
class: "A",
ddname: String(spoolFileToDownload.ddname),
id: Number(spoolFileToDownload.id),
"records-url": "",
subsystem: "JES2",
stepname: String(spoolFileToDownload.stepname),
procstep: String(
spoolFileToDownload.procstep === "N/A" || spoolFileToDownload.procstep == null
? undefined
: spoolFileToDownload.procstep
),
};
const destinationFile = DownloadJobs.getSpoolDownloadFile(
mockJobFile,
parms.omitJobidDirectory,
parms.outDir
);
imperative.IO.createDirsSyncFromFilePath(destinationFile);
imperative.IO.writeFile(destinationFile, spoolFileToDownload.contents as Buffer);
}
}
} finally {
this.releaseConnection(connection);
}
}

public async getSpoolContentById(jobname: string, jobid: string, spoolId: number): Promise<string> {
const connection = await this.ftpClient(this.checkedProfile());
if (connection) {
const options = {
fileId: spoolId.toString(),
jobName: jobname,
jobId: jobid,
owner: "*",
};
const response: Buffer = await JobUtils.getSpoolFileContent(connection, options);
if (response) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return response.toString();
let connection: any;
try {
connection = await this.ftpClient(this.checkedProfile());
if (connection) {
const options = {
fileId: spoolId.toString(),
jobName: jobname,
jobId: jobid,
owner: "*",
};
const response: Buffer = await JobUtils.getSpoolFileContent(connection, options);
if (response) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return response.toString();
}
}
return "";
} finally {
this.releaseConnection(connection);
}
return "";
}

public getJclForJob(job: zowe.IJob): Promise<string> {
Expand All @@ -169,24 +191,34 @@ export class FtpJesApi extends AbstractFtpApi implements ZoweExplorerApi.IJes {

public async submitJob(jobDataSet: string): Promise<zowe.IJob> {
const result = this.getIJobResponse();
const connection = await this.ftpClient(this.checkedProfile());
if (connection) {
const transferOptions = {
transferType: TRANSFER_TYPE_ASCII,
};
const content = await DataSetUtils.downloadDataSet(connection, jobDataSet, transferOptions);
const jcl = content.toString();
const jobId: string = await JobUtils.submitJob(connection, jcl);
if (jobId) {
result.jobid = jobId;
let connection: any;
try {
connection = await this.ftpClient(this.checkedProfile());
if (connection) {
const transferOptions = {
transferType: TRANSFER_TYPE_ASCII,
};
const content = await DataSetUtils.downloadDataSet(connection, jobDataSet, transferOptions);
const jcl = content.toString();
const jobId: string = await JobUtils.submitJob(connection, jcl);
if (jobId) {
result.jobid = jobId;
}
}
return result;
} finally {
this.releaseConnection(connection);
}
return result;
}
public async deleteJob(jobname: string, jobid: string): Promise<void> {
const connection = await this.ftpClient(this.checkedProfile());
if (connection) {
await JobUtils.deleteJob(connection, jobid);
let connection: any;
try {
connection = await this.ftpClient(this.checkedProfile());
if (connection) {
await JobUtils.deleteJob(connection, jobid);
}
} finally {
this.releaseConnection(connection);
}
}

Expand Down
Loading