1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-01-18 05:18:24 +02:00

Merge pull request #162 from alejandraferreirovidal/addCmClient

Add cm client
This commit is contained in:
Marcus Holl 2018-06-26 14:15:21 +02:00 committed by GitHub
commit eb5461a8f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 723 additions and 0 deletions

View File

@ -0,0 +1,40 @@
# transportRequestCreate
## Description
Creates a Transport Request for a Change Document on the Solution Manager.
## Prerequisites
* **[Change Management Client 2.0.0 or compatible version](http://central.maven.org/maven2/com/sap/devops/cmclient/dist.cli/)** - available for download on Maven Central.
## Parameters
| parameter | mandatory | default | possible values |
| -----------------|-----------|--------------------------------------------------------|--------------------|
| `script` | yes | | |
| `changeId` | yes | | |
| `cmCredentialsId` | yes | | |
| `cmEndpoint` | yes | | |
* `script` - The common script environment of the Jenkinsfile running. Typically the reference to the script calling the pipeline step is provided with the `this` parameter, as in `script: this`. This allows the function to access the [`commonPipelineEnvironment`](commonPipelineEnvironment.md) for retrieving, for example, configuration parameters.
* `changeId` - The id of the change document to transport.
* `cmCredentialsId` - The credentials to connect to the Solution Manager.
* `cmEndpoint` - The address of the Solution Manager.
## Step configuration
The following parameters can also be specified as step parameters using the global configuration file:
* `cmCredentialsId`
* `cmEndpoint`
## Return value
The id of the Transport Request that has been created.
## Exceptions
* `AbortException`:
* If the change id is not provided.
* If the creation of the transport request fails.
## Example
```groovy
def transportRequestId = transportRequestCreate script:this, changeId: '001'
```

View File

@ -0,0 +1,43 @@
# transportRequestRelease
## Description
Releases a Transport Request for a Change Document on the Solution Manager.
## Prerequisites
* **[Change Management Client 2.0.0 or compatible version](http://central.maven.org/maven2/com/sap/devops/cmclient/dist.cli/)** - available for download on Maven Central.
## Parameters
| parameter | mandatory | default | possible values |
| -----------------|-----------|--------------------------------------------------------|--------------------|
| `script` | yes | | |
| `changeId` | yes | | |
| `transportRequestId`| yes | | |
| `cmCredentialsId` | yes | | |
| `cmEndpoint` | yes | | |
* `script` - The common script environment of the Jenkinsfile running. Typically the reference to the script calling the pipeline step is provided with the `this` parameter, as in `script: this`. This allows the function to access the [`commonPipelineEnvironment`](commonPipelineEnvironment.md) for retrieving, for example, configuration parameters.
* `changeId` - The id of the change document related to the transport request to release.
* `transportRequestId` - The id of the transport request to release.
* `cmCredentialsId` - The credentials to connect to the Solution Manager.
* `cmEndpoint` - The address of the Solution Manager.
## Step configuration
The following parameters can also be specified as step parameters using the global configuration file:
* `cmCredentialsId`
* `cmEndpoint`
## Return value
None.
## Exceptions
* `AbortException`:
* If the change id is not provided.
* If the transport request id is not provided.
* If the release of the transport request fails.
## Example
```groovy
transportRequestRelease script:this, changeId: '001', transportRequestId: '001'
```

View File

@ -0,0 +1,49 @@
# transportRequestUploadFile
## Description
Uploads a file to a Transport Request for a Change Document on the Solution Manager.
## Prerequisites
* **[Change Management Client 2.0.0 or compatible version](http://central.maven.org/maven2/com/sap/devops/cmclient/dist.cli/)** - available for download on Maven Central.
## Parameters
| parameter | mandatory | default | possible values |
| -----------------|-----------|--------------------------------------------------------|--------------------|
| `script` | yes | | |
| `changeId` | yes | | |
| `transportRequestId`| yes | | |
| `applicationId` | yes | | |
| `filePath` | yes | | |
| `cmCredentialsId` | yes | | |
| `cmEndpoint` | yes | | |
* `script` - The common script environment of the Jenkinsfile running. Typically the reference to the script calling the pipeline step is provided with the `this` parameter, as in `script: this`. This allows the function to access the [`commonPipelineEnvironment`](commonPipelineEnvironment.md) for retrieving, for example, configuration parameters.
* `changeId` - The id of the change document related to the transport request to release.
* `transportRequestId` - The id of the transport request to release.
* `applicationId` - The id of the application.
* `filePath` - The path of the file to upload.
* `cmCredentialsId` - The credentials to connect to the Solution Manager.
* `cmEndpoint` - The address of the Solution Manager.
## Step configuration
The following parameters can also be specified as step parameters using the global configuration file:
* `cmCredentialsId`
* `cmEndpoint`
## Return value
None.
## Exceptions
* `AbortException`:
* If the change id is not provided.
* If the transport request id is not provided.
* If the application id is not provided.
* If the file path is not provided.
* If the upload fails.
## Example
```groovy
transportRequestUploadFile script:this, changeId: '001', transportRequestId: '001', applicationId: '001', filePath: '/path'
```

View File

@ -0,0 +1,69 @@
package com.sap.piper.cm
import hudson.AbortException
public class ChangeManagement implements Serializable {
private script
public ChangeManagement(def script) {
this.script = script
}
String createTransportRequest(String changeId, String developmentSystemId, String endpoint, String username, String password) {
try {
String transportRequest = script.sh(returnStdout: true,
script:
"""#!/bin/bash
cmclient -e '$endpoint' \
-u '$username' \
-p '$password' \
-t SOLMAN \
create-transport -cID '$changeId' -dID '$developmentSystemId'
""")
return transportRequest.trim()
} catch(AbortException e) {
throw new ChangeManagementException("Cannot create a transport request for change id '$changeId'. $e.message.")
}
}
void uploadFileToTransportRequest(String changeId, String transportRequestId, String applicationId, String filePath, String endpoint, String username, String password) {
int rc = script.sh(returnStatus: true,
script:
"""#!/bin/bash
cmclient -e '$endpoint' \
-u '$username' \
-p '$password' \
-t SOLMAN \
upload-file-to-transport -cID '$changeId' -tID '$transportRequestId' '$applicationId' '$filePath'
""")
if(rc == 0) {
return
} else {
throw new ChangeManagementException("Cannot upload file '$filePath' for change document '$changeId' with transport request '$transportRequestId'. Return code from cmclient: $rc.")
}
}
void releaseTransportRequest(String changeId, String transportRequestId, String endpoint, String username, String password) {
int rc = script.sh(returnStatus: true,
script:
"""#!/bin/bash
cmclient -e '$endpoint' \
-u '$username' \
-p '$password' \
-t SOLMAN \
release-transport -cID '$changeId' -tID '$transportRequestId'
""")
if(rc == 0) {
return
} else {
throw new ChangeManagementException("Cannot release Transport Request '$transportRequestId'. Return code from cmclient: $rc.")
}
}
}

View File

@ -0,0 +1,10 @@
package com.sap.piper.cm;
public class ChangeManagementException extends RuntimeException {
private static final long serialVersionUID = -139169285551665766L
ChangeManagementException(String message) {
super(message)
}
}

View File

@ -0,0 +1,96 @@
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import org.junit.rules.RuleChain
import util.BasePiperTest
import util.JenkinsStepRule
import util.JenkinsLoggingRule
import util.Rules
import hudson.AbortException
public class TransportRequestCreateTest extends BasePiperTest {
private ExpectedException thrown = new ExpectedException()
private JenkinsStepRule jsr = new JenkinsStepRule(this)
private JenkinsLoggingRule jlr = new JenkinsLoggingRule(this)
@Rule
public RuleChain ruleChain = Rules.getCommonRules(this)
.around(thrown)
.around(jsr)
.around(jlr)
@Before
public void setup() {
helper.registerAllowedMethod('usernamePassword', [Map.class], {m -> return m})
helper.registerAllowedMethod('withCredentials', [List, Closure], { l, c ->
credentialsId = l[0].credentialsId
binding.setProperty('username', 'anonymous')
binding.setProperty('password', '********')
try {
c()
} finally {
binding.setProperty('username', null)
binding.setProperty('password', null)
}
})
helper.registerAllowedMethod('sh', [Map], { Map m -> return 0 })
nullScript.commonPipelineEnvironment.configuration = [steps:
[transportRequestCreate:
[
cmCredentialsId: 'CM',
cmEndpoint: 'https://example.org/cm'
]
]
]
}
@Test
public void changeIdNotProvidedTest() {
thrown.expect(AbortException)
thrown.expectMessage("Change id not provided (parameter: 'changeId').")
jsr.step.call(script: nullScript, developmentSystemId: '001')
}
@Test
public void developmentSystemIdNotProvidedTest() {
thrown.expect(AbortException)
thrown.expectMessage("Development system id not provided (parameter: 'developmentSystemId').")
jsr.step.call(script: nullScript, changeId: '001')
}
@Test
public void createTransportRequestFailureTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> throw new AbortException('Exception message.') })
thrown.expect(AbortException)
thrown.expectMessage("Cannot create a transport request for change id '001'. Exception message.")
jsr.step.call(script: nullScript, changeId: '001', developmentSystemId: '001')
}
@Test
public void createTransportRequestSuccessTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> return '001' })
jsr.step.call(script: nullScript, changeId: '001', developmentSystemId: '001')
assert jlr.log.contains("[INFO] Creating transport request for change document '001' and development system '001'.")
assert jlr.log.contains("[INFO] Transport Request '001' has been successfully created.")
}
}

View File

@ -0,0 +1,96 @@
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import org.junit.rules.RuleChain
import util.BasePiperTest
import util.JenkinsStepRule
import util.JenkinsLoggingRule
import util.Rules
import hudson.AbortException
public class TransportRequestReleaseTest extends BasePiperTest {
private ExpectedException thrown = new ExpectedException()
private JenkinsStepRule jsr = new JenkinsStepRule(this)
private JenkinsLoggingRule jlr = new JenkinsLoggingRule(this)
@Rule
public RuleChain ruleChain = Rules.getCommonRules(this)
.around(thrown)
.around(jsr)
.around(jlr)
@Before
public void setup() {
helper.registerAllowedMethod('usernamePassword', [Map.class], {m -> return m})
helper.registerAllowedMethod('withCredentials', [List, Closure], { l, c ->
credentialsId = l[0].credentialsId
binding.setProperty('username', 'anonymous')
binding.setProperty('password', '********')
try {
c()
} finally {
binding.setProperty('username', null)
binding.setProperty('password', null)
}
})
helper.registerAllowedMethod('sh', [Map], { Map m -> return 0 })
nullScript.commonPipelineEnvironment.configuration = [steps:
[transportRequestRelease:
[
cmCredentialsId: 'CM',
cmEndpoint: 'https://example.org/cm'
]
]
]
}
@Test
public void changeIdNotProvidedTest() {
thrown.expect(AbortException)
thrown.expectMessage("Change id not provided (parameter: 'changeId').")
jsr.step.call(script: nullScript, transportRequestId: '001')
}
@Test
public void transportRequestIdNotProvidedTest() {
thrown.expect(AbortException)
thrown.expectMessage("Transport Request id not provided (parameter: 'transportRequestId').")
jsr.step.call(script: nullScript, changeId: '001')
}
@Test
public void releaseTransportRequestFailureTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> return 1 })
thrown.expect(AbortException)
thrown.expectMessage("Cannot release Transport Request '001'. Return code from cmclient: 1.")
jsr.step.call(script: nullScript, changeId: '001', transportRequestId: '001')
}
@Test
public void releaseTransportRequestSuccessTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> return 0 })
jsr.step.call(script: nullScript, changeId: '001', transportRequestId: '001')
assert jlr.log.contains("[INFO] Closing transport request '001' for change document '001'.")
assert jlr.log.contains("[INFO] Transport Request '001' has been successfully closed.")
}
}

View File

@ -0,0 +1,114 @@
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import org.junit.rules.RuleChain
import util.BasePiperTest
import util.JenkinsStepRule
import util.JenkinsLoggingRule
import util.Rules
import hudson.AbortException
public class TransportRequestUploadFileTest extends BasePiperTest {
private ExpectedException thrown = new ExpectedException()
private JenkinsStepRule jsr = new JenkinsStepRule(this)
private JenkinsLoggingRule jlr = new JenkinsLoggingRule(this)
@Rule
public RuleChain ruleChain = Rules.getCommonRules(this)
.around(thrown)
.around(jsr)
.around(jlr)
@Before
public void setup() {
helper.registerAllowedMethod('usernamePassword', [Map.class], {m -> return m})
helper.registerAllowedMethod('withCredentials', [List, Closure], { l, c ->
credentialsId = l[0].credentialsId
binding.setProperty('username', 'anonymous')
binding.setProperty('password', '********')
try {
c()
} finally {
binding.setProperty('username', null)
binding.setProperty('password', null)
}
})
helper.registerAllowedMethod('sh', [Map], { Map m -> return 0 })
nullScript.commonPipelineEnvironment.configuration = [steps:
[transportRequestUploadFile:
[
cmCredentialsId: 'CM',
cmEndpoint: 'https://example.org/cm'
]
]
]
}
@Test
public void changeIdNotProvidedTest() {
thrown.expect(AbortException)
thrown.expectMessage("Change id not provided (parameter: 'changeId').")
jsr.step.call(script: nullScript, transportRequestId: '001', applicationId: 'app', filePath: '/path')
}
@Test
public void transportRequestIdNotProvidedTest() {
thrown.expect(AbortException)
thrown.expectMessage("Transport Request id not provided (parameter: 'transportRequestId').")
jsr.step.call(script: nullScript, changeId: '001', applicationId: 'app', filePath: '/path')
}
@Test
public void applicationIdNotProvidedTest() {
thrown.expect(AbortException)
thrown.expectMessage("Application id not provided (parameter: 'applicationId').")
jsr.step.call(script: nullScript, changeId: '001', transportRequestId: '001', filePath: '/path')
}
@Test
public void filePathNotProvidedTest() {
thrown.expect(AbortException)
thrown.expectMessage("File path not provided (parameter: 'filePath').")
jsr.step.call(script: nullScript, changeId: '001', transportRequestId: '001', applicationId: 'app')
}
@Test
public void uploadFileToTransportRequestFailureTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> return 1 })
thrown.expect(AbortException)
thrown.expectMessage("Cannot upload file '/path' for change document '001' with transport request '001'. Return code from cmclient: 1.")
jsr.step.call(script: nullScript, changeId: '001', transportRequestId: '001', applicationId: 'app', filePath: '/path')
}
@Test
public void uploadFileToTransportRequestSuccessTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> return 0 })
jsr.step.call(script: nullScript, changeId: '001', transportRequestId: '001', applicationId: 'app', filePath: '/path')
assert jlr.log.contains("[INFO] Uploading file '/path' to transport request '001' of change document '001'.")
assert jlr.log.contains("[INFO] File '/path' has been successfully uploaded to transport request '001' of change document '001'.")
}
}

View File

@ -0,0 +1,68 @@
import com.sap.piper.GitUtils
import groovy.transform.Field
import com.sap.piper.ConfigurationMerger
import com.sap.piper.cm.ChangeManagement
import com.sap.piper.cm.ChangeManagementException
import hudson.AbortException
@Field def STEP_NAME = 'transportRequestCreate'
@Field Set parameterKeys = [
'changeId',
'developmentSystemId',
'cmCredentialsId',
'cmEndpoint'
]
@Field Set stepConfigurationKeys = [
'cmCredentialsId',
'cmEndpoint'
]
def call(parameters = [:]) {
handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters) {
def script = parameters?.script ?: [commonPipelineEnvironment: commonPipelineEnvironment]
ChangeManagement cm = new ChangeManagement(script)
Map configuration = ConfigurationMerger.merge(parameters.script, STEP_NAME,
parameters, parameterKeys,
stepConfigurationKeys)
def changeId = configuration.changeId
if(!changeId) throw new AbortException('Change id not provided (parameter: \'changeId\').')
def developmentSystemId = configuration.developmentSystemId
if(!developmentSystemId) throw new AbortException('Development system id not provided (parameter: \'developmentSystemId\').')
def cmCredentialsId = configuration.cmCredentialsId
if(!cmCredentialsId) throw new AbortException('Credentials id not provided (parameter: \'cmCredentialsId\').')
def cmEndpoint = configuration.cmEndpoint
if(!cmEndpoint) throw new AbortException('Solution Manager endpoint not provided (parameter: \'cmEndpoint\').')
def transportRequestId
echo "[INFO] Creating transport request for change document '$changeId' and development system '$developmentSystemId'."
withCredentials([usernamePassword(
credentialsId: cmCredentialsId,
passwordVariable: 'password',
usernameVariable: 'username')]) {
try {
transportRequestId = cm.createTransportRequest(changeId, developmentSystemId, cmEndpoint, username, password)
} catch(ChangeManagementException ex) {
throw new AbortException(ex.getMessage())
}
}
echo "[INFO] Transport Request '$transportRequestId' has been successfully created."
return transportRequestId
}
}

View File

@ -0,0 +1,65 @@
import com.sap.piper.GitUtils
import groovy.transform.Field
import com.sap.piper.ConfigurationMerger
import com.sap.piper.cm.ChangeManagement
import com.sap.piper.cm.ChangeManagementException
import hudson.AbortException
@Field def STEP_NAME = 'transportRequestRelease'
@Field Set parameterKeys = [
'changeId',
'transportRequestId',
'cmCredentialsId',
'cmEndpoint'
]
@Field Set stepConfigurationKeys = [
'cmCredentialsId',
'cmEndpoint'
]
def call(parameters = [:]) {
handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters) {
def script = parameters?.script ?: [commonPipelineEnvironment: commonPipelineEnvironment]
ChangeManagement cm = new ChangeManagement(script)
Map configuration = ConfigurationMerger.merge(script, STEP_NAME,
parameters, parameterKeys,
stepConfigurationKeys)
def changeId = configuration.changeId
if(!changeId) throw new AbortException("Change id not provided (parameter: 'changeId').")
def transportRequestId = configuration.transportRequestId
if(!transportRequestId) throw new AbortException("Transport Request id not provided (parameter: 'transportRequestId').")
def cmCredentialsId = configuration.cmCredentialsId
if(!cmCredentialsId) throw new AbortException("Credentials id not provided (parameter: 'cmCredentialsId').")
def cmEndpoint = configuration.cmEndpoint
if(!cmEndpoint) throw new AbortException("Solution Manager endpoint not provided (parameter: 'cmEndpoint').")
echo "[INFO] Closing transport request '$transportRequestId' for change document '$changeId'."
withCredentials([usernamePassword(
credentialsId: cmCredentialsId,
passwordVariable: 'password',
usernameVariable: 'username')]) {
try {
cm.releaseTransportRequest(changeId, transportRequestId, cmEndpoint, username, password)
} catch(ChangeManagementException ex) {
throw new AbortException(ex.getMessage())
}
}
echo "[INFO] Transport Request '${transportRequestId}' has been successfully closed."
}
}

View File

@ -0,0 +1,73 @@
import com.sap.piper.GitUtils
import groovy.transform.Field
import com.sap.piper.ConfigurationMerger
import com.sap.piper.cm.ChangeManagement
import com.sap.piper.cm.ChangeManagementException
import hudson.AbortException
@Field def STEP_NAME = 'transportRequestUploadFile'
@Field Set parameterKeys = [
'changeId',
'transportRequestId',
'applicationId',
'filePath',
'cmCredentialsId',
'cmEndpoint'
]
@Field Set generalConfigurationKeys = [
'cmCredentialsId',
'cmEndpoint'
]
def call(parameters = [:]) {
handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters) {
def script = parameters?.script ?: [commonPipelineEnvironment: commonPipelineEnvironment]
ChangeManagement cm = new ChangeManagement(script)
Map configuration = ConfigurationMerger.merge(parameters.script, STEP_NAME,
parameters, parameterKeys,
generalConfigurationKeys)
def changeId = configuration.changeId
if(!changeId) throw new AbortException("Change id not provided (parameter: 'changeId').")
def transportRequestId = configuration.transportRequestId
if(!transportRequestId) throw new AbortException("Transport Request id not provided (parameter: 'transportRequestId').")
def applicationId = configuration.applicationId
if(!applicationId) throw new AbortException("Application id not provided (parameter: 'applicationId').")
def filePath = configuration.filePath
if(!filePath) throw new AbortException("File path not provided (parameter: 'filePath').")
def cmCredentialsId = configuration.cmCredentialsId
if(!cmCredentialsId) throw new AbortException("Credentials id not provided (parameter: 'cmCredentialsId').")
def cmEndpoint = configuration.cmEndpoint
if(!cmEndpoint) throw new AbortException("Solution Manager endpoint not provided (parameter: 'cmEndpoint').")
echo "[INFO] Uploading file '$filePath' to transport request '$transportRequestId' of change document '$changeId'."
withCredentials([usernamePassword(
credentialsId: cmCredentialsId,
passwordVariable: 'password',
usernameVariable: 'username')]) {
try {
cm.uploadFileToTransportRequest(changeId, transportRequestId, applicationId, filePath, cmEndpoint, username, password)
} catch(ChangeManagementException ex) {
throw new AbortException(ex.getMessage())
}
}
echo "[INFO] File '$filePath' has been successfully uploaded to transport request '$transportRequestId' of change document '$changeId'."
}
}