1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-03-03 15:02:35 +02:00

Cf create services in multiclouddeploy step (#1736)

This commit is contained in:
Florian Wilhelm 2020-07-01 17:28:50 +02:00 committed by GitHub
parent 12455ae747
commit b5dbd0dafc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 148 additions and 32 deletions

View File

@ -72,9 +72,9 @@ class ConfigurationHelper implements Serializable {
configSubMap = configSubMap?.get(key)
}
if (configSubMap == null || (configSubMap != null && configSubMap[entry.getKey()] == null)) {
def value = configMap[entry.getValue()]
def value = getConfigPropertyNested(configMap, entry.getValue())
if(null == value)
value = newConfigMap[entry.getValue()]
value = getConfigPropertyNested(newConfigMap, entry.getValue())
if (value != null) {
newConfig[entry.getKey()] = value
def paramName = (paramStructure ? paramStructure + '.' : '') + entry.getKey()

View File

@ -1,9 +1,3 @@
import com.sap.piper.JenkinsUtils
import com.sap.piper.Utils
import hudson.AbortException
import org.junit.Assert
import static org.junit.Assert.assertFalse
import static org.junit.Assert.assertTrue
import org.junit.Before
@ -14,13 +8,13 @@ import org.junit.rules.RuleChain
import util.*
class MulticloudDeployTest extends BasePiperTest {
private ExpectedException thrown = new ExpectedException().none()
private JenkinsStepRule stepRule = new JenkinsStepRule(this)
private JenkinsMockStepRule neoDeployRule = new JenkinsMockStepRule(this, 'neoDeploy')
private JenkinsMockStepRule cloudFoundryDeployRule = new JenkinsMockStepRule(this, 'cloudFoundryDeploy')
private JenkinsMockStepRule cloudFoundryCreateServiceRule = new JenkinsMockStepRule(this, 'cloudFoundryCreateService')
private JenkinsReadMavenPomRule readMavenPomRule = new JenkinsReadMavenPomRule(this, 'test/resources/deploy')
private Map neo1 = [:]
@ -39,6 +33,7 @@ class MulticloudDeployTest extends BasePiperTest {
.around(stepRule)
.around(neoDeployRule)
.around(cloudFoundryDeployRule)
.around(cloudFoundryCreateServiceRule)
.around(readMavenPomRule)
@Before
@ -115,6 +110,9 @@ class MulticloudDeployTest extends BasePiperTest {
]
]
]
helper.registerAllowedMethod('echo', [CharSequence.class], {})
}
@Test
@ -296,6 +294,72 @@ class MulticloudDeployTest extends BasePiperTest {
assert cloudFoundryDeployRule.hasParameter('deployTool', 'cf_native')
}
@Test
void 'cfCreateServices calls cloudFoundryCreateService step with correct parameters'() {
stepRule.step.multicloudDeploy([
script : nullScript,
cfCreateServices: [[apiEndpoint: 'http://mycf.org', serviceManifest: 'services-manifest.yml', manifestVariablesFiles: 'vars.yml', space: 'PerformanceTests', org: 'MyOrg', credentialsId: 'MyCred']],
source : 'file.mtar'
])
assert cloudFoundryCreateServiceRule.hasParameter('cloudFoundry', [
serviceManifest : 'services-manifest.yml',
space : 'PerformanceTests',
org : 'MyOrg',
credentialsId : 'MyCred',
apiEndpoint : 'http://mycf.org',
manifestVariablesFiles: 'vars.yml'
])
}
@Test
void 'cfCreateServices with parallelTestExecution defined in compatible parameter - must run in parallel'() {
def closureRun = null
helper.registerAllowedMethod('error', [String.class], { s->
if (s == "Deployment skipped because no targets defined!") {
// This error is ok because in this test we're not interested in the deployment
} else {
throw new RuntimeException("Unexpected error in test with message: ${s}")
}
})
helper.registerAllowedMethod('parallel', [Map.class], {m -> closureRun = m})
nullScript.commonPipelineEnvironment.configuration.general['features'] = [parallelTestExecution: true]
stepRule.step.multicloudDeploy([
script: nullScript,
cfCreateServices: [[serviceManifest: 'services-manifest.yml', space: 'PerformanceTests', org: 'foo', credentialsId: 'foo']],
source: 'file.mtar'
])
assert closureRun != null
}
@Test
void 'cfCreateServices with parallelExecution defined - must run in parallel'() {
def closureRun = null
helper.registerAllowedMethod('error', [String.class], { s->
if (s == "Deployment skipped because no targets defined!") {
// This error is ok because in this test we're not interested in the deployment
} else {
throw new RuntimeException("Unexpected error in test with message: ${s}")
}
})
helper.registerAllowedMethod('parallel', [Map.class], {m -> closureRun = m})
nullScript.commonPipelineEnvironment.configuration.general = [parallelExecution: true]
stepRule.step.multicloudDeploy([
script: nullScript,
cfCreateServices: [[serviceManifest: 'services-manifest.yml', space: 'PerformanceTests', org: 'foo', credentialsId: 'foo']],
source: 'file.mtar'
])
assert closureRun != null
}
@Test
void multicloudParallelOnK8sTest() {
binding.variables.env.POD_NAME = "name"

View File

@ -253,7 +253,17 @@ class ConfigurationHelperTest {
}
@Test
void testHandleCompatibilityDeep() {
void testHandleCompatibilityDeepSource() {
def configuration = ConfigurationHelper.newInstance(mockScript)
.mixin([features: [parallelTestExecution: true]], null, [parallelExecution: 'features/parallelTestExecution'])
.use()
Assert.assertThat(configuration.size(), is(2))
Assert.assertThat(configuration.parallelExecution, is(true))
}
@Test
void testHandleCompatibilityDeepDestination() {
def configuration = ConfigurationHelper.newInstance(mockScript)
.mixin([old1: 'oldValue1', old2: 'oldValue2', test: 'testValue'], null, [deep:[deeper:[newStructure: [new1: 'old1', new2: 'old2']]]])
.use()
@ -458,4 +468,5 @@ class ConfigurationHelperTest {
.withPropertyInValues('key1', possibleValues)
.use()
}
}

View File

@ -1,10 +1,10 @@
import com.sap.piper.GenerateDocumentation
import com.sap.piper.CloudPlatform
import com.sap.piper.DeploymentType
import com.sap.piper.k8s.ContainerMap
import com.sap.piper.ConfigurationHelper
import com.sap.piper.Utils
import com.sap.piper.JenkinsUtils
import com.sap.piper.k8s.ContainerMap
import groovy.transform.Field
@ -13,23 +13,37 @@ import static com.sap.piper.Prerequisites.checkScript
@Field String STEP_NAME = getClass().getName()
@Field Set GENERAL_CONFIG_KEYS = [
/** Defines the targets to deploy on cloudFoundry.*/
/** Defines the targets to deploy on Cloud Foundry.*/
'cfTargets',
/** Defines the targets to deploy on neo.*/
'neoTargets'
'neoTargets',
/** Executes the deployments in parallel.*/
'parallelExecution'
]
@Field Set STEP_CONFIG_KEYS = []
@Field Set STEP_CONFIG_KEYS = GENERAL_CONFIG_KEYS.plus([
/**
* Defines Cloud Foundry service instances to create as part of the deployment.
* This is a _list_ of _objects_ with the following properties each:
* - apiEndpoint
* - credentialsId
* - serviceManifest
* - manifestVariablesFiles
* - org
* - space
*/
'cfCreateServices'
])
@Field Set PARAMETER_KEYS = GENERAL_CONFIG_KEYS.plus([
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS.plus([
/** Defines the deployment type.*/
'enableZeroDowntimeDeployment',
/** Executes the deployments in parallel.*/
'parallelExecution',
/** The source file to deploy to SAP Cloud Platform.*/
'source'
])
@Field Map CONFIG_KEY_COMPATIBILITY = [parallelExecution: 'features/parallelTestExecution']
/**
* Deploys an application to multiple platforms (Cloud Foundry, SAP Cloud Platform) or to multiple instances of multiple platforms or the same platform.
*/
@ -45,7 +59,9 @@ void call(parameters = [:]) {
ConfigurationHelper configHelper = ConfigurationHelper.newInstance(this)
.loadStepDefaults()
.mixinGeneralConfig(script.commonPipelineEnvironment, GENERAL_CONFIG_KEYS)
.mixinGeneralConfig(script.commonPipelineEnvironment, GENERAL_CONFIG_KEYS, CONFIG_KEY_COMPATIBILITY)
.mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, STEP_CONFIG_KEYS, CONFIG_KEY_COMPATIBILITY)
.mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS, CONFIG_KEY_COMPATIBILITY)
.mixin(parameters, PARAMETER_KEYS)
Map config = configHelper.use()
@ -54,14 +70,35 @@ void call(parameters = [:]) {
.withMandatoryProperty('source', null, { config.neoTargets })
utils.pushToSWA([
step: STEP_NAME,
step : STEP_NAME,
stepParamKey1: 'enableZeroDowntimeDeployment',
stepParam1: config.enableZeroDowntimeDeployment
stepParam1 : config.enableZeroDowntimeDeployment
], config)
def index = 1
def deployments = [:]
if (config.cfCreateServices) {
def createServices = [:]
for (int i = 0; i < config.cfCreateServices.size(); i++) {
Map createServicesConfig = config.cfCreateServices[i]
createServices["Service Creation ${i + 1}"] = {
cloudFoundryCreateService(
script: script,
cloudFoundry: [
apiEndpoint : createServicesConfig.apiEndpoint,
credentialsId : createServicesConfig.credentialsId,
serviceManifest : createServicesConfig.serviceManifest,
manifestVariablesFiles: createServicesConfig.manifestVariablesFiles,
org : createServicesConfig.org,
space : createServicesConfig.space
]
)
}
}
runClosures(config, createServices, "cloudFoundryCreateService")
}
if (config.cfTargets) {
def deploymentType = DeploymentType.selectFor(CloudPlatform.CLOUD_FOUNDRY, config.enableZeroDowntimeDeployment).toString()
@ -123,7 +160,7 @@ void call(parameters = [:]) {
Closure deployment = {
neoDeploy (
neoDeploy(
script: script,
warAction: deploymentType,
source: config.source,
@ -140,17 +177,21 @@ void call(parameters = [:]) {
error "Deployment skipped because no targets defined!"
}
echo "Executing deployments"
if (config.parallelExecution) {
echo "Executing deployments in parallel"
parallel deployments
} else {
echo "Executing deployments in sequence"
def closuresToRun = deployments.values().asList()
Collections.shuffle(closuresToRun) // Shuffle the list so no one tries to rely on the order of execution
for (int i = 0; i < closuresToRun.size(); i++) {
(closuresToRun[i] as Closure)()
}
runClosures(config, deployments, "deployments")
}
}
def runClosures(Map config, Map toRun, String label = "closures") {
echo "Executing $label"
if (config.parallelExecution) {
echo "Executing $label in parallel"
parallel toRun
} else {
echo "Executing $label in sequence"
def closuresToRun = toRun.values().asList()
for (int i = 0; i < closuresToRun.size(); i++) {
(closuresToRun[i] as Closure)()
}
}
}