From ef2076ee4b4116c88d8a85fa510378d03b1df5b6 Mon Sep 17 00:00:00 2001 From: Anatoli Kalbasin Date: Thu, 10 Oct 2024 14:30:10 +0200 Subject: [PATCH 1/4] implement the feature Signed-off-by: Anatoli Kalbasin --- .../classic/steps/DownloadDatasetStep.kt | 3 ++- .../jobs/DownloadFileDeclarative.kt | 8 ++++++-- .../zowe/zdevops/logic/DownloadOperation.kt | 18 ++++++++++++------ 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/org/zowe/zdevops/classic/steps/DownloadDatasetStep.kt b/src/main/kotlin/org/zowe/zdevops/classic/steps/DownloadDatasetStep.kt index fe1288d..58cfd31 100644 --- a/src/main/kotlin/org/zowe/zdevops/classic/steps/DownloadDatasetStep.kt +++ b/src/main/kotlin/org/zowe/zdevops/classic/steps/DownloadDatasetStep.kt @@ -70,7 +70,8 @@ constructor( zosConnection: ZOSConnection ) { val workspace = build.executor?.currentWorkspace!! - downloadDSOrDSMemberByType(dsn, vol, returnEtag, listener, zosConnection, workspace) + val jenkinsJobUrl = build.getEnvironment(listener)["JOB_URL"] + downloadDSOrDSMemberByType(dsn, vol, returnEtag, listener, zosConnection, workspace, jenkinsJobUrl) } diff --git a/src/main/kotlin/org/zowe/zdevops/declarative/jobs/DownloadFileDeclarative.kt b/src/main/kotlin/org/zowe/zdevops/declarative/jobs/DownloadFileDeclarative.kt index fbc61f7..12ec8ec 100644 --- a/src/main/kotlin/org/zowe/zdevops/declarative/jobs/DownloadFileDeclarative.kt +++ b/src/main/kotlin/org/zowe/zdevops/declarative/jobs/DownloadFileDeclarative.kt @@ -10,7 +10,10 @@ package org.zowe.zdevops.declarative.jobs -import hudson.* +import hudson.EnvVars +import hudson.Extension +import hudson.FilePath +import hudson.Launcher import hudson.model.Run import hudson.model.TaskListener import org.jenkinsci.Symbol @@ -47,7 +50,8 @@ class DownloadFileDeclarative @DataBoundConstructor constructor(val dsn: String) zosConnection: ZOSConnection ) { val workspacePath = FilePath(null, workspace.remote.replace(workspace.name,"")) - downloadDSOrDSMemberByType(dsn, vol, returnEtag, listener, zosConnection, workspacePath) + val jenkinsJobUrl = env["BUILD_URL"] + "/execution/node/3/" + downloadDSOrDSMemberByType(dsn, vol, returnEtag, listener, zosConnection, workspacePath, jenkinsJobUrl) } diff --git a/src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt b/src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt index 69edb90..099f54d 100644 --- a/src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt +++ b/src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt @@ -12,6 +12,7 @@ package org.zowe.zdevops.logic import hudson.AbortException import hudson.FilePath +import hudson.console.HyperlinkNote import hudson.model.TaskListener import org.apache.commons.io.IOUtils import org.zowe.kotlinsdk.DatasetOrganization @@ -36,6 +37,7 @@ import java.io.StringWriter * @param zosConnection The connection to the z/OS system. * @param workspace The workspace where the dataset will be downloaded. * @param listener The listener for capturing task progress and logs. + * @param jenkinsJobUrl The job/pipeline URL */ fun downloadDS( dsn: String, @@ -43,7 +45,8 @@ fun downloadDS( returnEtag: Boolean?, zosConnection: ZOSConnection, workspace: FilePath, - listener: TaskListener + listener: TaskListener, + jenkinsJobUrl: String?, ) { var downloadedDSN: InputStream? try { @@ -55,7 +58,8 @@ fun downloadDS( IOUtils.copy(downloadedDSN, writer, "UTF-8") val file = File("$workspace\\$dsn") file.writeText(writer.toString()) - listener.logger.println(Messages.zdevops_declarative_DSN_downloaded_success(dsn)) + listener.logger.println(Messages.zdevops_declarative_DSN_downloaded_success( + HyperlinkNote.encodeTo("${jenkinsJobUrl}ws/$dsn/*view*/", dsn))) } /** @@ -67,6 +71,7 @@ fun downloadDS( * @param listener The listener for capturing task progress and logs. * @param zosConnection The connection to the z/OS system. * @param workspace The workspace where the dataset will be downloaded. + * @param jenkinsJobUrl The job/pipeline URL */ fun downloadDSOrDSMemberByType( dsn: String, @@ -74,23 +79,24 @@ fun downloadDSOrDSMemberByType( returnEtag: Boolean?, listener: TaskListener, zosConnection: ZOSConnection, - workspace: FilePath + workspace: FilePath, + jenkinsJobUrl: String? ) { listener.logger.println(Messages.zdevops_declarative_DSN_downloading(dsn, vol, zosConnection.host, zosConnection.zosmfPort)) val dsnMemberPattern = Regex("[\\w#\$@.-]{1,}\\([\\w#\$@]{1,8}\\)") //means it's a PDS member if (dsn.contains(dsnMemberPattern)) { - downloadDS(dsn, vol, returnEtag, zosConnection, workspace, listener) + downloadDS(dsn, vol, returnEtag, zosConnection, workspace, listener, jenkinsJobUrl) } else { val dsnList = ZosDsnList(zosConnection).listDsn(dsn, ListParams(vol)) if (dsnList.items.isEmpty()) { throw AbortException("Can't find $dsn ${ if(vol.isNullOrBlank()) "" else "on volume $vol"}") } when (dsnList.items.first().datasetOrganization) { - DatasetOrganization.PS -> downloadDS(dsn, vol, returnEtag, zosConnection, workspace, listener) + DatasetOrganization.PS -> downloadDS(dsn, vol, returnEtag, zosConnection, workspace, listener, jenkinsJobUrl) DatasetOrganization.PO, DatasetOrganization.POE -> { listener.logger.println(Messages.zdevops_declarative_DSN_downloading_members(dsn)) ZosDsnList(zosConnection).listDsnMembers(dsn, ListParams(vol)).items.forEach { - downloadDS("${dsn}(${it.name})", vol, returnEtag, zosConnection, workspace, listener) + downloadDS("${dsn}(${it.name})", vol, returnEtag, zosConnection, workspace, listener, jenkinsJobUrl) } } else -> listener.logger.println(Messages.zdevops_declarative_DSN_downloading_invalid_dsorg()) From 29d908865985bdacee78c4a9c60311aea3fb51b2 Mon Sep 17 00:00:00 2001 From: Anatoli Kalbasin Date: Thu, 10 Oct 2024 14:32:10 +0200 Subject: [PATCH 2/4] add licenses Signed-off-by: Anatoli Kalbasin --- .../org/zowe/zdevops/classic/steps/DownloadDatasetStep.kt | 6 +++++- .../zdevops/declarative/jobs/DownloadFileDeclarative.kt | 6 +++++- src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/org/zowe/zdevops/classic/steps/DownloadDatasetStep.kt b/src/main/kotlin/org/zowe/zdevops/classic/steps/DownloadDatasetStep.kt index 58cfd31..b997637 100644 --- a/src/main/kotlin/org/zowe/zdevops/classic/steps/DownloadDatasetStep.kt +++ b/src/main/kotlin/org/zowe/zdevops/classic/steps/DownloadDatasetStep.kt @@ -1,11 +1,15 @@ /* + * Copyright (c) 2023-2024 IBA Group. + * * 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 IBA Group 2023 + * Contributors: + * IBA Group + * Zowe Community */ package org.zowe.zdevops.classic.steps diff --git a/src/main/kotlin/org/zowe/zdevops/declarative/jobs/DownloadFileDeclarative.kt b/src/main/kotlin/org/zowe/zdevops/declarative/jobs/DownloadFileDeclarative.kt index 12ec8ec..f5231b6 100644 --- a/src/main/kotlin/org/zowe/zdevops/declarative/jobs/DownloadFileDeclarative.kt +++ b/src/main/kotlin/org/zowe/zdevops/declarative/jobs/DownloadFileDeclarative.kt @@ -1,11 +1,15 @@ /* + * Copyright (c) 2022-2024 IBA Group. + * * 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 IBA Group 2022 + * Contributors: + * IBA Group + * Zowe Community */ package org.zowe.zdevops.declarative.jobs diff --git a/src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt b/src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt index 099f54d..cf8555a 100644 --- a/src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt +++ b/src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt @@ -1,11 +1,15 @@ /* + * Copyright (c) 2023-2024 IBA Group. + * * 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 IBA Group 2023 + * Contributors: + * IBA Group + * Zowe Community */ package org.zowe.zdevops.logic From c8e9dd54ae33b322798f7ac4e45a2fff3bfead6f Mon Sep 17 00:00:00 2001 From: Anatoli Kalbasin Date: Thu, 10 Oct 2024 15:23:22 +0200 Subject: [PATCH 3/4] fix tests Signed-off-by: Anatoli Kalbasin --- .../zowe/zdevops/classic/steps/DownloadDatasetStepSpec.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/kotlin/org/zowe/zdevops/classic/steps/DownloadDatasetStepSpec.kt b/src/test/kotlin/org/zowe/zdevops/classic/steps/DownloadDatasetStepSpec.kt index 7bf225c..ec2f2a4 100644 --- a/src/test/kotlin/org/zowe/zdevops/classic/steps/DownloadDatasetStepSpec.kt +++ b/src/test/kotlin/org/zowe/zdevops/classic/steps/DownloadDatasetStepSpec.kt @@ -11,9 +11,11 @@ package org.zowe.zdevops.classic.steps import hudson.AbortException +import hudson.EnvVars import hudson.FilePath import hudson.model.Executor import hudson.model.Item +import hudson.model.TaskListener import hudson.util.FormValidation import io.kotest.assertions.assertSoftly import io.kotest.assertions.fail @@ -68,6 +70,12 @@ class DownloadDatasetStepSpec : ShouldSpec({ every { mockInstance.currentWorkspace } returns FilePath(virtualChannel, mockDir.absolutePath) return mockInstance } + + override fun getEnvironment(log: TaskListener): EnvVars { + val env = EnvVars() + env["JOB_URL"] = "TEST" + return env + } } afterEach { From ea433ee8cb558d47e92c6c44a0d1e0bfaf272fb2 Mon Sep 17 00:00:00 2001 From: Anatoli Kalbasin Date: Tue, 5 Nov 2024 16:19:06 +0100 Subject: [PATCH 4/4] encode hyperlinks Signed-off-by: Anatoli Kalbasin --- src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt | 6 ++++-- .../kotlin/org/zowe/zdevops/logic/SubmitJobOperation.kt | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt b/src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt index cf8555a..e82a05a 100644 --- a/src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt +++ b/src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt @@ -29,7 +29,8 @@ import org.zowe.zdevops.Messages import java.io.File import java.io.InputStream import java.io.StringWriter - +import java.net.URLEncoder +import java.nio.charset.StandardCharsets /** @@ -62,8 +63,9 @@ fun downloadDS( IOUtils.copy(downloadedDSN, writer, "UTF-8") val file = File("$workspace\\$dsn") file.writeText(writer.toString()) + val urlEncodedDsn = URLEncoder.encode(dsn, StandardCharsets.UTF_8.toString()) listener.logger.println(Messages.zdevops_declarative_DSN_downloaded_success( - HyperlinkNote.encodeTo("${jenkinsJobUrl}ws/$dsn/*view*/", dsn))) + HyperlinkNote.encodeTo("${jenkinsJobUrl}ws/$urlEncodedDsn/*view*/", dsn))) } /** diff --git a/src/main/kotlin/org/zowe/zdevops/logic/SubmitJobOperation.kt b/src/main/kotlin/org/zowe/zdevops/logic/SubmitJobOperation.kt index 8fd19bd..0586d1c 100644 --- a/src/main/kotlin/org/zowe/zdevops/logic/SubmitJobOperation.kt +++ b/src/main/kotlin/org/zowe/zdevops/logic/SubmitJobOperation.kt @@ -25,6 +25,8 @@ import org.zowe.zdevops.Messages import org.zowe.zdevops.utils.extractSubmitJobMessage import org.zowe.zdevops.utils.runMFTryCatchWrappedQuery import java.io.File +import java.net.URLEncoder +import java.nio.charset.StandardCharsets /** * Submits a z/OS job @@ -93,10 +95,11 @@ fun submitJobSync( val logPath = "$workspacePath/${finalResult.jobName}.${finalResult.jobId}" val file = File(logPath) file.writeText(fullLog) + val urlEncodedJobName = URLEncoder.encode(finalResult.jobName, StandardCharsets.UTF_8.toString()) listener.logger.println(Messages.zdevops_declarative_ZOSJobs_got_log( HyperlinkNote.encodeTo( linkBuilder(buildUrl, finalResult.jobName, finalResult.jobId), - "${finalResult.jobName}.${finalResult.jobId}" + "$urlEncodedJobName.${finalResult.jobId}" ) )) } else {