Skip to content

Commit

Permalink
Implement Write a Directory to PDS/E feature (#96)
Browse files Browse the repository at this point in the history
* implement the feature - declarative

* implement the feature - freestyle

* separate methods - declarative

* separate methods - freestyle

* add unit tests

* add docs

* remove duplicate methods
  • Loading branch information
callbacksin authored Jan 22, 2025
1 parent 240c92d commit a1e2289
Show file tree
Hide file tree
Showing 91 changed files with 891 additions and 244 deletions.
28 changes: 25 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,14 @@ stage ("stage-name") {
downloadDS dsn:"EXAMPLE.DATASET(MEMBER)", vol:"VOL001"
allocateDS dsn:"EXAMPLE.DATASET", alcUnit:"TRK", dsOrg:"PS", primary:1, secondary:1, recFm:"FB", failOnExist:"False"
writeFileToDS dsn:"EXAMPLE.DATASET", file:"workspaceFile"
writeFileToDS dsn:"EXAMPLE.DATASET(MEMBER)", file:"workspaceFile"
writeFileToDS dsn:"EXAMPLE.DATASET", file:"D:\\files\\localFile"
writeFileToDS dsn:"EXAMPLE.DATASET(MEMBER)", file:"D:\\files\\localFile"
writeToDS dsn:"EXAMPLE.DATASET", text:"Write this string to dataset"
writeFileToMember dsn:"EXAMPLE.DATASET", member:"MEMBER", file:"workspaceFile"
writeFileToMember dsn:"EXAMPLE.DATASET", member:"MEMBER", file:"D:\\files\\localFile"
writeToMember dsn:"EXAMPLE.DATASET", member:"MEMBER", text:"Write this string to member"
writeToDS dsn:"EXAMPLE.DATASET(MEMBER)", text:"Write this string to dataset member"
writeDirToDS dir: "app/src/main/cbl/", dsn: "EXAMPLE.DATASET"
writeDirToDS dir: "D:\\resources\\cbl", dsn: "EXAMPLE.DATASET", isLocalPath: true
writeToFile destFile: "u/USER/myfile", text: "Write this string to file"
writeFileToFile destFile: "u/USER/myfile", sourceFile: "myfile.txt"
Expand Down Expand Up @@ -195,6 +198,25 @@ def active_units = performMvsCommand "D A,L"
[Perform MVS command] - The command has been successfully executed
```
### `writeDirToDS` - Write a Directory to a Dataset
```groovy
zosmf ("z/os-connection-name") {
writeDirToDS dir: "app/src/main/cbl", dsn: "EXAMPLE.DATASET"
writeDirToDS dir: "D:\\resources\\cbl", dsn: "EXAMPLE.DATASET", isLocalPath: true
}
```

Mandatory parameters:
* `dir: "app/src/main/cbl/"` - Path to the directory containing the files to be written.
* `dsn: "EXAMPLE.DATASET"` - Name of the dataset (DSN) where the directory contents will be written.

Optional Parameters:
* `isLocalPath: true` - Indicates whether the directory path is local (`true`) or relative to the Jenkins pipeline workspace (`false`)

Important Notes:
* If a member already exists in the dataset, its content will be overwritten.
* The `dir` parameter does not support file masks.


## Use case example
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* Zowe Community
*/

package org.zowe.zdevops.classic.steps
package org.zowe.zdevops.classic.console

import hudson.Extension
import hudson.Launcher
Expand All @@ -23,7 +23,7 @@ import org.kohsuke.stapler.DataBoundConstructor
import org.kohsuke.stapler.QueryParameter
import org.zowe.kotlinsdk.zowe.client.sdk.core.ZOSConnection
import org.zowe.zdevops.Messages
import org.zowe.zdevops.classic.AbstractBuildStep
import org.zowe.zdevops.classic.core.AbstractBuildStep
import org.zowe.zdevops.logic.performMvsCommand
import org.zowe.zdevops.utils.validateFieldIsNotEmpty

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* Copyright IBA Group 2022
*/

package org.zowe.zdevops.classic
package org.zowe.zdevops.classic.core

import hudson.Launcher
import hudson.model.AbstractBuild
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* Copyright IBA Group 2023
*/

package org.zowe.zdevops.classic.steps
package org.zowe.zdevops.classic.files.dsn

import hudson.Extension
import hudson.Launcher
Expand All @@ -25,7 +25,7 @@ import org.zowe.kotlinsdk.DsnameType
import org.zowe.kotlinsdk.RecordFormat
import org.zowe.kotlinsdk.zowe.client.sdk.core.ZOSConnection
import org.zowe.zdevops.Messages
import org.zowe.zdevops.classic.AbstractBuildStep
import org.zowe.zdevops.classic.core.AbstractBuildStep
import org.zowe.zdevops.logic.allocateDataset
import org.zowe.zdevops.utils.validateDatasetName
import java.io.IOException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* Zowe Community
*/

package org.zowe.zdevops.classic.steps
package org.zowe.zdevops.classic.files.dsn

import hudson.Extension
import hudson.Launcher
Expand All @@ -23,7 +23,7 @@ import org.kohsuke.stapler.DataBoundConstructor
import org.kohsuke.stapler.QueryParameter
import org.zowe.kotlinsdk.zowe.client.sdk.core.ZOSConnection
import org.zowe.zdevops.Messages
import org.zowe.zdevops.classic.AbstractBuildStep
import org.zowe.zdevops.classic.core.AbstractBuildStep
import org.zowe.zdevops.logic.deleteDatasetOrMember
import org.zowe.zdevops.utils.validateDsnOrDsnMemberName

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* Copyright IBA Group 2022
*/

package org.zowe.zdevops.classic.steps
package org.zowe.zdevops.classic.files.dsn

import hudson.Extension
import hudson.Launcher
Expand All @@ -17,7 +17,7 @@ import hudson.model.BuildListener
import org.kohsuke.stapler.DataBoundConstructor
import org.zowe.kotlinsdk.zowe.client.sdk.core.ZOSConnection
import org.zowe.zdevops.Messages
import org.zowe.zdevops.classic.AbstractBuildStep
import org.zowe.zdevops.classic.core.AbstractBuildStep
import org.zowe.zdevops.logic.deleteDatasetsByMask

class DeleteDatasetsByMaskStep
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* Zowe Community
*/

package org.zowe.zdevops.classic.steps
package org.zowe.zdevops.classic.files.dsn

import hudson.Extension
import hudson.Launcher
Expand All @@ -24,7 +24,7 @@ import org.kohsuke.stapler.DataBoundSetter
import org.kohsuke.stapler.QueryParameter
import org.zowe.kotlinsdk.zowe.client.sdk.core.ZOSConnection
import org.zowe.zdevops.Messages
import org.zowe.zdevops.classic.AbstractBuildStep
import org.zowe.zdevops.classic.core.AbstractBuildStep
import org.zowe.zdevops.logic.downloadDSOrDSMemberByType
import org.zowe.zdevops.utils.validateDsnOrDsnMemberName

Expand All @@ -42,7 +42,7 @@ class DownloadDatasetStep
constructor(
connectionName: String,
val dsn: String
) :AbstractBuildStep(connectionName) {
) : AbstractBuildStep(connectionName) {

private var vol: String? = null
private var returnEtag: Boolean? = true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright (c) 2025 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
*
* Contributors:
* IBA Group
* Zowe Community
*/
package org.zowe.zdevops.classic.files.dsn

import hudson.AbortException
import hudson.Extension
import hudson.Launcher
import hudson.model.AbstractBuild
import hudson.model.BuildListener
import hudson.util.FormValidation
import org.kohsuke.stapler.DataBoundConstructor
import org.kohsuke.stapler.DataBoundSetter
import org.kohsuke.stapler.QueryParameter
import org.zowe.kotlinsdk.zowe.client.sdk.core.ZOSConnection
import org.zowe.zdevops.classic.core.AbstractBuildStep
import org.zowe.zdevops.logic.writeDirectoryToPdsJenkins
import org.zowe.zdevops.utils.validateDatasetName
import org.zowe.zdevops.utils.validateFieldIsNotEmpty


/**
* A freestyle job Jenkins class for writing the contents of a directory to a PDS/E dataset.
* @see org.zowe.zdevops.declarative.files.dsn.WriteDirToDatasetDeclarative
*/
class WriteDirToDatasetStep
@DataBoundConstructor
constructor(
connectionName: String,
val dir: String,
val dsn: String,
var isLocalPath: Boolean,
) : AbstractBuildStep(connectionName) {

fun getIsLocalPath(): Boolean {
return this.isLocalPath
}

@DataBoundSetter
fun setIsLocalPath(isLocalPath: Boolean) {
this.isLocalPath = isLocalPath
}

override fun perform(
build: AbstractBuild<*, *>,
launcher: Launcher,
listener: BuildListener,
zosConnection: ZOSConnection
) {
val workspace = build.executor?.currentWorkspace ?: throw AbortException("'build.executor' was null")
writeDirectoryToPdsJenkins(dsn, dir, isLocalPath, workspace, listener, zosConnection)
}

@Extension
class DescriptorImpl : Companion.DefaultBuildDescriptor("[z/OS] - Write Dir to PDS/E") {

/**
* Checks if the path to the directory is not empty
*
* @param dir The path to the directory
* @return FormValidation.ok() if the path name is not empty, or an error message otherwise
*/
fun doCheckDir(@QueryParameter dir: String): FormValidation? {
return validateFieldIsNotEmpty(dir)
}

/**
* Checks if the dataset name is valid
*
* @param dsn The dataset name
* @return FormValidation.ok() if the dataset name is valid, or an error message otherwise
*/
fun doCheckDsn(@QueryParameter dsn: String): FormValidation? {
return validateDatasetName(dsn)
}

}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
/*
* Copyright (c) 2023-2025 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
package org.zowe.zdevops.classic.files.dsn

import hudson.AbortException
import hudson.Extension
Expand All @@ -23,9 +27,9 @@ import org.kohsuke.stapler.QueryParameter
import org.kohsuke.stapler.bind.JavaScriptMethod
import org.zowe.kotlinsdk.zowe.client.sdk.core.ZOSConnection
import org.zowe.zdevops.Messages
import org.zowe.zdevops.classic.AbstractBuildStep
import org.zowe.zdevops.logic.writeToDataset
import org.zowe.zdevops.utils.validateDatasetName
import org.zowe.zdevops.classic.core.AbstractBuildStep
import org.zowe.zdevops.logic.writeTextToDatasetJenkins
import org.zowe.zdevops.utils.validateDsnOrDsnMemberName
import org.zowe.zdevops.utils.validateFieldIsNotEmpty
import java.io.File

Expand Down Expand Up @@ -93,7 +97,7 @@ constructor(
listener.logger.println(Messages.zdevops_declarative_writing_DS_from_file(dsn, file?.name, zosConnection.host, zosConnection.zosmfPort))
val fileContent = file?.readText()
if (fileContent != null) {
writeToDataset(listener, zosConnection, dsn, fileContent)
writeTextToDatasetJenkins(listener, zosConnection, dsn, fileContent)
}
}

Expand Down Expand Up @@ -155,7 +159,7 @@ constructor(
* @return FormValidation.ok() if the dataset name is valid, or an error message otherwise
*/
fun doCheckDsn(@QueryParameter dsn: String): FormValidation? {
return validateDatasetName(dsn)
return validateDsnOrDsnMemberName(dsn)
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
/*
* Copyright (c) 2023-2025 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
package org.zowe.zdevops.classic.files.dsn

import hudson.AbortException
import hudson.Extension
Expand All @@ -23,8 +27,8 @@ import org.kohsuke.stapler.QueryParameter
import org.kohsuke.stapler.bind.JavaScriptMethod
import org.zowe.kotlinsdk.zowe.client.sdk.core.ZOSConnection
import org.zowe.zdevops.Messages
import org.zowe.zdevops.classic.AbstractBuildStep
import org.zowe.zdevops.logic.writeToMember
import org.zowe.zdevops.classic.core.AbstractBuildStep
import org.zowe.zdevops.logic.writeTextToDatasetJenkins
import org.zowe.zdevops.utils.validateDatasetName
import org.zowe.zdevops.utils.validateFieldIsNotEmpty
import org.zowe.zdevops.utils.validateMemberName
Expand Down Expand Up @@ -94,9 +98,10 @@ constructor(
else -> throw AbortException(Messages.zdevops_classic_write_options_invalid())
}
listener.logger.println(Messages.zdevops_declarative_writing_DS_from_file(dsn, file?.name, zosConnection.host, zosConnection.zosmfPort))
listener.logger.println("[WARNING] - The method is deprecated. Please, consider switching to `Write File to Dataset` step.")
val fileContent = file?.readText()
if (fileContent != null) {
writeToMember(listener, zosConnection, dsn, member, fileContent)
writeTextToDatasetJenkins(listener, zosConnection, "$dsn($member)", fileContent)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
/*
* Copyright (c) 2023-2025 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
package org.zowe.zdevops.classic.files.dsn

import hudson.Extension
import hudson.Launcher
Expand All @@ -19,9 +23,9 @@ import org.kohsuke.stapler.DataBoundConstructor
import org.kohsuke.stapler.QueryParameter
import org.zowe.kotlinsdk.zowe.client.sdk.core.ZOSConnection
import org.zowe.zdevops.Messages
import org.zowe.zdevops.classic.AbstractBuildStep
import org.zowe.zdevops.logic.writeToDataset
import org.zowe.zdevops.utils.validateDatasetName
import org.zowe.zdevops.classic.core.AbstractBuildStep
import org.zowe.zdevops.logic.writeTextToDatasetJenkins
import org.zowe.zdevops.utils.validateDsnOrDsnMemberName
import org.zowe.zdevops.utils.validateFieldIsNotEmpty

/**
Expand Down Expand Up @@ -57,7 +61,7 @@ constructor(
zosConnection: ZOSConnection
) {
listener.logger.println(Messages.zdevops_declarative_writing_DS_from_input(dsn, zosConnection.host, zosConnection.zosmfPort))
writeToDataset(listener, zosConnection, dsn, text)
writeTextToDatasetJenkins(listener, zosConnection, dsn, text)
}

/**
Expand All @@ -72,7 +76,7 @@ constructor(
* @return FormValidation.ok() if the dataset name is valid, or an error message otherwise
*/
fun doCheckDsn(@QueryParameter dsn: String): FormValidation? {
return validateDatasetName(dsn)
return validateDsnOrDsnMemberName(dsn)
}

/**
Expand Down
Loading

0 comments on commit a1e2289

Please sign in to comment.