mirror of
https://github.com/SAP/jenkins-library.git
synced 2026-06-19 22:58:55 +02:00
Implement workaround for incompatible change in cloud foundry API (#343)
This commit is contained in:
@@ -61,6 +61,10 @@ Deployment can be done
|
||||
- cfOrg
|
||||
- cfSpace
|
||||
|
||||
!!! note
|
||||
Due to [an incompatible change](https://github.com/cloudfoundry/cli/issues/1445) in the Cloud Foundry CLI, multiple buildpacks are not supported by this step.
|
||||
If your `application` contains a list of `buildpacks` instead a single `buildpack`, this will be automatically re-written by the step when blue-green deployment is used.
|
||||
|
||||
* `deployTool` defines the tool which should be used for deployment.
|
||||
* `deployType` defines the type of deployment, either `standard` deployment which results in a system downtime or a zero-downtime `blue-green` deployment.
|
||||
* `dockerImage` defines the Docker image containing the deployment tools (like cf cli, ...) and `dockerWorkspace` defines the home directory of the default user of the `dockerImage`
|
||||
@@ -106,7 +110,11 @@ The following parameters can also be specified as step/stage/general parameters
|
||||
## Example
|
||||
|
||||
```groovy
|
||||
artifactSetVersion script: this, buildTool: 'maven'
|
||||
cloudFoundryDeploy(
|
||||
script: script,
|
||||
deployType: 'blue-green',
|
||||
cloudFoundry: [apiEndpoint: 'https://test.server.com', appName:'cfAppName', credentialsId: 'cfCredentialsId', manifest: 'cfManifest', org: 'cfOrg', space: 'cfSpace'],
|
||||
deployTool: 'cf_native'
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.sap.piper
|
||||
|
||||
import com.cloudbees.groovy.cps.NonCPS
|
||||
|
||||
class CfManifestUtils {
|
||||
@NonCPS
|
||||
static Map transform(Map manifest) {
|
||||
if (manifest.applications[0].buildpacks) {
|
||||
manifest['applications'].each { Map application ->
|
||||
def buildpacks = application['buildpacks']
|
||||
if (buildpacks) {
|
||||
if (buildpacks instanceof List) {
|
||||
if (buildpacks.size > 1) {
|
||||
throw new RuntimeException('More than one Cloud Foundry Buildpack is not supported. Please check your manifest.yaml file.')
|
||||
}
|
||||
application['buildpack'] = buildpacks[0]
|
||||
application.remove('buildpacks')
|
||||
} else {
|
||||
throw new RuntimeException('"buildpacks" in manifest.yaml is not a list. Please check your manifest.yaml file.')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return manifest
|
||||
}
|
||||
}
|
||||
@@ -105,6 +105,11 @@ class CloudFoundryDeployTest extends BasePiperTest {
|
||||
|
||||
@Test
|
||||
void testCfNativeWithAppName() {
|
||||
jryr.registerYaml('test.yml', "applications: [[name: 'manifestAppName']]")
|
||||
helper.registerAllowedMethod('writeYaml', [Map], { Map parameters ->
|
||||
generatedFile = parameters.file
|
||||
data = parameters.data
|
||||
})
|
||||
jsr.step.cloudFoundryDeploy([
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
@@ -125,6 +130,11 @@ class CloudFoundryDeployTest extends BasePiperTest {
|
||||
|
||||
@Test
|
||||
void testCfNativeWithAppNameCustomApi() {
|
||||
jryr.registerYaml('test.yml', "applications: [[name: 'manifestAppName']]")
|
||||
helper.registerAllowedMethod('writeYaml', [Map], { Map parameters ->
|
||||
generatedFile = parameters.file
|
||||
data = parameters.data
|
||||
})
|
||||
jsr.step.cloudFoundryDeploy([
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
@@ -142,6 +152,11 @@ class CloudFoundryDeployTest extends BasePiperTest {
|
||||
|
||||
@Test
|
||||
void testCfNativeWithAppNameCompatible() {
|
||||
jryr.registerYaml('test.yml', "applications: [[name: 'manifestAppName']]")
|
||||
helper.registerAllowedMethod('writeYaml', [Map], { Map parameters ->
|
||||
generatedFile = parameters.file
|
||||
data = parameters.data
|
||||
})
|
||||
jsr.step.cloudFoundryDeploy([
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
@@ -165,7 +180,11 @@ class CloudFoundryDeployTest extends BasePiperTest {
|
||||
@Test
|
||||
void testCfNativeAppNameFromManifest() {
|
||||
helper.registerAllowedMethod('fileExists', [String.class], { s -> return true })
|
||||
jryr.registerYaml('test.yml', "[applications: [[name: 'manifestAppName']]]")
|
||||
jryr.registerYaml('test.yml', "applications: [[name: 'manifestAppName']]")
|
||||
helper.registerAllowedMethod('writeYaml', [Map], { Map parameters ->
|
||||
generatedFile = parameters.file
|
||||
data = parameters.data
|
||||
})
|
||||
|
||||
jsr.step.cloudFoundryDeploy([
|
||||
script: nullScript,
|
||||
@@ -185,6 +204,10 @@ class CloudFoundryDeployTest extends BasePiperTest {
|
||||
void testCfNativeWithoutAppName() {
|
||||
helper.registerAllowedMethod('fileExists', [String.class], { s -> return true })
|
||||
jryr.registerYaml('test.yml', "applications: [[]]")
|
||||
helper.registerAllowedMethod('writeYaml', [Map], { Map parameters ->
|
||||
generatedFile = parameters.file
|
||||
data = parameters.data
|
||||
})
|
||||
thrown.expect(hudson.AbortException)
|
||||
thrown.expectMessage('[cloudFoundryDeploy] ERROR: No appName available in manifest test.yml.')
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.sap.piper
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import static org.junit.Assert.*
|
||||
|
||||
class CfManifestUtilsTest {
|
||||
|
||||
@Test
|
||||
void testManifestTransform() {
|
||||
Map testFixture = [applications: [[buildpacks: ['sap_java_buildpack']]]]
|
||||
Map expected = [applications: [[buildpack: 'sap_java_buildpack']]]
|
||||
def actual = CfManifestUtils.transform(testFixture)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException)
|
||||
void testManifestTransformMultipleBuildpacks() {
|
||||
Map testFixture = [applications: [[buildpacks: ['sap_java_buildpack', 'another_buildpack']]]]
|
||||
CfManifestUtils.transform(testFixture)
|
||||
}
|
||||
|
||||
@Test
|
||||
void testManifestTransformShouldNotChange() {
|
||||
Map testFixture = [applications: [[buildpack: 'sap_java_buildpack']]]
|
||||
Map expected = [applications: [[buildpack: 'sap_java_buildpack']]]
|
||||
def actual = CfManifestUtils.transform(testFixture)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import com.sap.piper.Utils
|
||||
import com.sap.piper.ConfigurationHelper
|
||||
import com.sap.piper.CfManifestUtils
|
||||
|
||||
import groovy.transform.Field
|
||||
|
||||
@@ -112,6 +113,7 @@ def deployCfNative (config) {
|
||||
def deployCommand = 'push'
|
||||
if (config.deployType == 'blue-green') {
|
||||
deployCommand = 'blue-green-deploy'
|
||||
handleLegacyCfManifest(config)
|
||||
} else {
|
||||
config.smokeTest = ''
|
||||
}
|
||||
@@ -129,7 +131,7 @@ def deployCfNative (config) {
|
||||
}
|
||||
|
||||
sh """#!/bin/bash
|
||||
set +x
|
||||
set +x
|
||||
export HOME=${config.dockerWorkspace}
|
||||
cf login -u \"${username}\" -p '${password}' -a ${config.cloudFoundry.apiEndpoint} -o \"${config.cloudFoundry.org}\" -s \"${config.cloudFoundry.space}\"
|
||||
cf plugins
|
||||
@@ -166,3 +168,18 @@ def deployMta (config) {
|
||||
sh "cf logout"
|
||||
}
|
||||
}
|
||||
|
||||
def handleLegacyCfManifest(config) {
|
||||
def manifest = readYaml file: config.cloudFoundry.manifest
|
||||
String originalManifest = manifest.toString()
|
||||
manifest = CfManifestUtils.transform(manifest)
|
||||
String transformedManifest = manifest.toString()
|
||||
if (originalManifest != transformedManifest) {
|
||||
echo """The file ${config.cloudFoundry.manifest} is not compatible with the Cloud Foundry blue-green deployment plugin. Re-writing inline.
|
||||
See this issue if you are interested in the background: https://github.com/cloudfoundry/cli/issues/1445.\n
|
||||
Original manifest file content: $originalManifest\n
|
||||
Transformed manifest file content: $transformedManifest"""
|
||||
sh "rm ${config.cloudFoundry.manifest}"
|
||||
writeYaml file: config.cloudFoundry.manifest, data: manifest
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user