2019-09-11 13:42:38 +02:00
import static org . hamcrest . Matchers . allOf
import static org . hamcrest . Matchers . contains
2019-12-16 11:40:44 +02:00
import static org . hamcrest . Matchers . containsInAnyOrder
2019-09-11 13:42:38 +02:00
import static org . hamcrest . Matchers . containsString
2019-12-13 17:05:55 +02:00
import static org . hamcrest . Matchers . equalTo
2019-09-11 13:42:38 +02:00
import static org . hamcrest . Matchers . is
2019-12-13 17:05:55 +02:00
import static org . hamcrest . Matchers . not
import static org . hamcrest . Matchers . nullValue
import static org . junit . Assert . assertThat
2019-09-11 13:42:38 +02:00
2019-12-13 17:05:55 +02:00
import org.hamcrest.Matchers
import org.hamcrest.core.IsNull
import org.junit.Before
2019-09-11 13:42:38 +02:00
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import org.junit.rules.RuleChain
2019-12-13 17:05:55 +02:00
import com.sap.piper.PiperGoUtils
import hudson.AbortException
2019-09-11 13:42:38 +02:00
import util.BasePiperTest
import util.CommandLineMatcher
import util.JenkinsCredentialsRule
import util.JenkinsDockerExecuteRule
import util.JenkinsLockRule
2019-12-13 17:05:55 +02:00
import util.JenkinsReadJsonRule
2019-09-11 13:42:38 +02:00
import util.JenkinsReadYamlRule
import util.JenkinsShellCallRule
import util.JenkinsStepRule
2019-12-13 17:05:55 +02:00
import util.JenkinsWriteFileRule
2019-09-11 13:42:38 +02:00
import util.Rules
class XsDeployTest extends BasePiperTest {
private ExpectedException thrown = ExpectedException . none ( )
private JenkinsStepRule stepRule = new JenkinsStepRule ( this )
private JenkinsShellCallRule shellRule = new JenkinsShellCallRule ( this )
private JenkinsLockRule lockRule = new JenkinsLockRule ( this )
2019-12-13 17:05:55 +02:00
private JenkinsDockerExecuteRule dockerRule = new JenkinsDockerExecuteRule ( this )
private JenkinsWriteFileRule writeFileRule = new JenkinsWriteFileRule ( this )
List env
2019-09-11 13:42:38 +02:00
@Rule
public RuleChain ruleChain = Rules . getCommonRules ( this )
. around ( new JenkinsReadYamlRule ( this ) )
2019-12-13 17:05:55 +02:00
. around ( new JenkinsReadJsonRule ( this ) )
2019-09-11 13:42:38 +02:00
. around ( stepRule )
2019-12-13 17:05:55 +02:00
. around ( dockerRule )
. around ( writeFileRule )
2019-09-11 13:42:38 +02:00
. around ( new JenkinsCredentialsRule ( this )
. withCredentials ( 'myCreds' , 'cred_xs' , 'topSecret' ) )
. around ( lockRule )
. around ( shellRule )
. around ( thrown )
2019-12-13 17:05:55 +02:00
private PiperGoUtils goUtils = new PiperGoUtils ( null ) {
void unstashPiperBin ( ) {
2019-09-11 13:42:38 +02:00
}
}
2019-12-13 17:05:55 +02:00
@Before
public void init ( ) {
helper . registerAllowedMethod ( 'withEnv' , [ List , Closure ] , { l , c - > env = l ; c ( ) } )
2020-01-16 10:44:13 +02:00
2019-12-20 15:41:17 +02:00
shellRule . setReturnValue ( JenkinsShellCallRule . Type . REGEX , '.*getConfig.*--contextConfig.*' , '{"dockerImage": "xs", "dockerPullImage": false, "credentialsId":"myCreds"}' )
2020-01-16 10:44:13 +02:00
// what we set on the shell rule and on the null script is the same. We read it on the groovy level, and also via go getConfig, hence we need it twice.
nullScript . commonPipelineEnvironment . configuration = [ steps: [ xsDeploy: [ mode: 'BG_DEPLOY' , action: 'NONE' , apiUrl: 'https://example.org/xs' , org: 'myOrg' , space: 'mySpace' ] ] ]
2019-12-16 11:40:44 +02:00
shellRule . setReturnValue ( JenkinsShellCallRule . Type . REGEX , 'getConfig.* (?!--contextConfig)' , '{"mode": "BG_DEPLOY", "action": "NONE", "apiUrl": "https://example.org/xs", "org": "myOrg", "space": "mySpace"}' )
2020-01-16 10:44:13 +02:00
2019-12-13 17:05:55 +02:00
nullScript . commonPipelineEnvironment . xsDeploymentId = null
2019-09-11 13:42:38 +02:00
}
@Test
2019-12-13 17:05:55 +02:00
public void testDeployFailed ( ) {
2019-09-11 13:42:38 +02:00
thrown . expect ( AbortException )
2019-12-13 17:05:55 +02:00
thrown . expectMessage ( 'script returned exit code 1' )
2019-09-11 13:42:38 +02:00
2019-12-13 17:05:55 +02:00
shellRule . setReturnValue ( JenkinsShellCallRule . Type . REGEX , '.*xsDeploy .*' , { throw new AbortException ( 'script returned exit code 1' ) } )
2019-09-11 13:42:38 +02:00
stepRule . step . xsDeploy (
script: nullScript ,
2019-12-13 17:05:55 +02:00
piperGoUtils: goUtils ,
2019-09-11 13:42:38 +02:00
)
}
@Test
2019-12-13 17:05:55 +02:00
public void testInvalidDeploymentModeProvided ( ) {
2019-09-11 13:42:38 +02:00
thrown . expect ( IllegalArgumentException )
thrown . expectMessage ( 'No enum constant' )
2019-12-16 11:40:44 +02:00
shellRule . setReturnValue ( JenkinsShellCallRule . Type . REGEX , 'getConfig.* (?!--contextConfig)' , '{"mode": "DOES_NOT_EXIST", "action": "NONE", "apiUrl": "https://example.org/xs", "org": "myOrg", "space": "mySpace"}' )
2020-01-16 10:44:13 +02:00
nullScript . commonPipelineEnvironment . configuration = [ steps: [ xsDeploy: [ mode: 'DOES_NOT_EXIST' , action: 'NONE' , apiUrl: 'https://example.org/xs' , org: 'myOrg' , space: 'mySpace' ] ] ]
2019-12-13 17:05:55 +02:00
2019-09-11 13:42:38 +02:00
stepRule . step . xsDeploy (
script: nullScript ,
2019-12-13 17:05:55 +02:00
piperGoUtils: goUtils ,
2019-09-11 13:42:38 +02:00
)
}
2020-01-16 10:44:13 +02:00
@Test
public void testDeployableViaCPE ( ) {
shellRule . setReturnValue ( JenkinsShellCallRule . Type . REGEX , '.*xsDeploy .*' , ' ' )
nullScript . commonPipelineEnvironment . mtarFilePath = "my.mtar"
stepRule . step . xsDeploy (
script: nullScript ,
apiUrl: 'https://example.org/xs' ,
org: 'myOrg' ,
space: 'mySpace' ,
credentialsId: 'myCreds' ,
deployOpts: '-t 60' ,
mtaPath: 'myApp.mta' ,
mode: 'DEPLOY' ,
action: 'NONE' ,
piperGoUtils: goUtils
)
assertThat ( shellRule . shell ,
new CommandLineMatcher ( )
. hasProlog ( '#!/bin/bash ./piper xsDeploy' )
// explicitly provided, it is not contained in project config.
. hasOption ( 'mtaPath' , 'my.mtar' ) )
}
2019-09-11 13:42:38 +02:00
@Test
2019-12-13 17:05:55 +02:00
public void testParametersViaSignature ( ) {
2019-09-11 13:42:38 +02:00
2019-12-13 17:05:55 +02:00
shellRule . setReturnValue ( JenkinsShellCallRule . Type . REGEX , '.*xsDeploy .*' , '{"operationId": "1234"}' )
2019-09-11 13:42:38 +02:00
stepRule . step . xsDeploy (
script: nullScript ,
apiUrl: 'https://example.org/xs' ,
org: 'myOrg' ,
space: 'mySpace' ,
credentialsId: 'myCreds' ,
deployOpts: '-t 60' ,
mtaPath: 'myApp.mta' ,
2019-12-13 17:05:55 +02:00
mode: 'DEPLOY' ,
action: 'NONE' ,
piperGoUtils: goUtils
2019-09-11 13:42:38 +02:00
)
2019-12-13 17:05:55 +02:00
// nota bene: script and piperGoUtils are not contained in the json below.
assertThat ( env * . toString ( ) , contains ( 'PIPER_parametersJSON={"apiUrl":"https://example.org/xs","org":"myOrg","space":"mySpace","credentialsId":"myCreds","deployOpts":"-t 60","mtaPath":"myApp.mta","mode":"DEPLOY","action":"NONE"}' ) )
2019-09-11 13:42:38 +02:00
}
@Test
2019-12-13 17:05:55 +02:00
public void testBlueGreenDeployInit ( ) {
2019-09-11 13:42:38 +02:00
2019-12-13 17:05:55 +02:00
//
// Only difference between bg deploy and standard deploy is in the config.
// The surrounding behavior is the same. Hence there is no dedicated test here
// in the groovy layer for standard deploy
//
2019-09-11 13:42:38 +02:00
2019-12-13 17:05:55 +02:00
boolean unstashCalled
2019-09-11 13:42:38 +02:00
2019-12-13 17:05:55 +02:00
assertThat ( nullScript . commonPipelineEnvironment . xsDeploymentId , nullValue ( ) )
2019-12-16 11:40:44 +02:00
2019-12-13 17:05:55 +02:00
shellRule . setReturnValue ( JenkinsShellCallRule . Type . REGEX , '.*xsDeploy .*' , '{"operationId": "1234"}' )
2019-09-11 13:42:38 +02:00
2019-12-13 17:05:55 +02:00
goUtils = new PiperGoUtils ( null ) {
void unstashPiperBin ( ) {
unstashCalled = true
}
}
2019-09-11 13:42:38 +02:00
stepRule . step . xsDeploy (
script: nullScript ,
2019-12-13 17:05:55 +02:00
piperGoUtils: goUtils
2019-09-11 13:42:38 +02:00
)
2019-12-13 17:05:55 +02:00
assertThat ( unstashCalled , equalTo ( true ) )
2019-09-11 13:42:38 +02:00
assertThat ( nullScript . commonPipelineEnvironment . xsDeploymentId , is ( '1234' ) )
2019-12-16 11:40:44 +02:00
assertThat ( writeFileRule . files . keySet ( ) , containsInAnyOrder (
'.pipeline/additionalConfigs/default_pipeline_environment.yml' ,
2019-12-19 09:56:10 +02:00
'.pipeline/metadata/xsDeploy.yaml' ,
2019-12-16 11:40:44 +02:00
) )
2019-12-13 17:05:55 +02:00
assertThat ( dockerRule . dockerParams . dockerImage , equalTo ( 'xs' ) )
assertThat ( dockerRule . dockerParams . dockerPullImage , equalTo ( false ) )
2019-12-16 11:40:44 +02:00
2019-09-11 13:42:38 +02:00
assertThat ( shellRule . shell ,
allOf (
new CommandLineMatcher ( )
2019-12-13 17:05:55 +02:00
. hasProlog ( './piper version' ) ,
new CommandLineMatcher ( )
2019-12-16 11:40:44 +02:00
. hasProlog ( './piper getConfig' )
. hasArgument ( '--contextConfig' ) ,
2019-09-11 13:42:38 +02:00
new CommandLineMatcher ( )
2019-12-19 09:56:10 +02:00
. hasProlog ( './piper getConfig --stepMetadata \'.pipeline/metadata/xsDeploy.yaml\'' ) ,
2019-09-11 13:42:38 +02:00
new CommandLineMatcher ( )
2020-09-16 11:33:03 +02:00
. hasProlog ( '#!/bin/bash ./piper xsDeploy --defaultConfig ".pipeline/additionalConfigs/default_pipeline_environment.yml" --username \\$\\{USERNAME\\} --password \\$\\{PASSWORD\\}' ) ,
2019-12-13 17:05:55 +02:00
not ( new CommandLineMatcher ( )
2019-12-19 09:56:10 +02:00
. hasProlog ( '#!/bin/bash ./piper xsDeploy' )
. hasOption ( 'operationId' , '1234' ) )
2019-09-11 13:42:38 +02:00
)
)
assertThat ( lockRule . getLockResources ( ) , contains ( 'xsDeploy:https://example.org/xs:myOrg:mySpace' ) )
}
@Test
2019-12-13 17:05:55 +02:00
public void testBlueGreenDeployResume ( ) {
2019-09-11 13:42:38 +02:00
2019-12-13 17:05:55 +02:00
nullScript . commonPipelineEnvironment . xsDeploymentId = '1234'
2019-09-11 13:42:38 +02:00
2020-01-16 10:44:13 +02:00
nullScript . commonPipelineEnvironment . configuration = [ steps: [ xsDeploy: [ mode: 'BG_DEPLOY' , action: 'RESUME' , apiUrl: 'https://example.org/xs' , org: 'myOrg' , space: 'mySpace' ] ] ]
2019-12-16 11:40:44 +02:00
shellRule . setReturnValue ( JenkinsShellCallRule . Type . REGEX , 'getConfig.* (?!--contextConfig)' , '{"mode": "BG_DEPLOY", "action": "RESUME", "apiUrl": "https://example.org/xs", "org": "myOrg", "space": "mySpace"}' )
2019-09-11 13:42:38 +02:00
stepRule . step . xsDeploy (
script: nullScript ,
2019-12-13 17:05:55 +02:00
piperGoUtils: goUtils
2019-09-11 13:42:38 +02:00
)
2019-12-13 17:05:55 +02:00
assertThat ( shellRule . shell ,
new CommandLineMatcher ( )
2019-12-19 09:56:10 +02:00
. hasProlog ( '#!/bin/bash ./piper xsDeploy' )
. hasOption ( 'operationId' , '1234' )
2019-09-11 13:42:38 +02:00
)
2019-12-13 17:05:55 +02:00
assertThat ( lockRule . getLockResources ( ) , contains ( 'xsDeploy:https://example.org/xs:myOrg:mySpace' ) )
2019-09-11 13:42:38 +02:00
}
@Test
2019-12-13 17:05:55 +02:00
public void testBlueGreenDeployResumeWithoutDeploymentId ( ) {
2019-09-11 13:42:38 +02:00
2019-12-13 17:05:55 +02:00
// this happens in case we would like to complete a deployment without having a (successful) deployments before.
2019-09-11 13:42:38 +02:00
2019-12-13 17:05:55 +02:00
thrown . expect ( IllegalArgumentException )
thrown . expectMessage (
allOf (
containsString ( 'No operationId provided' ) ,
containsString ( 'Was there a deployment before?' ) ) )
2019-09-11 13:42:38 +02:00
2020-01-16 10:44:13 +02:00
nullScript . commonPipelineEnvironment . configuration = [ steps: [ xsDeploy: [ mode: 'BG_DEPLOY' , action: 'RESUME' , apiUrl: 'https://example.org/xs' , org: 'myOrg' , space: 'mySpace' ] ] ]
2019-12-16 11:40:44 +02:00
shellRule . setReturnValue ( JenkinsShellCallRule . Type . REGEX , 'getConfig.* (?!--contextConfig)' , '{"mode": "BG_DEPLOY", "action": "RESUME", "apiUrl": "https://example.org/xs", "org": "myOrg", "space": "mySpace"}' )
2019-09-11 13:42:38 +02:00
2019-12-13 17:05:55 +02:00
assertThat ( nullScript . commonPipelineEnvironment . xsDeploymentId , nullValue ( ) )
2019-09-11 13:42:38 +02:00
stepRule . step . xsDeploy (
script: nullScript ,
2019-12-13 17:05:55 +02:00
piperGoUtils: goUtils ,
failOnError: true ,
2019-09-11 13:42:38 +02:00
)
}
2019-12-16 11:40:44 +02:00
2019-12-20 15:49:57 +02:00
@Test
public void testBlueGreenDeployResumeOperationIdViaSignature ( ) {
// this happens in case we would like to complete a deployment without having a (successful) deployments before.
2020-01-16 10:44:13 +02:00
nullScript . commonPipelineEnvironment . configuration = [ steps: [ xsDeploy: [ mode: 'BG_DEPLOY' , action: 'RESUME' , apiUrl: 'https://example.org/xs' , org: 'myOrg' , space: 'mySpace' ] ] ]
2019-12-20 15:49:57 +02:00
shellRule . setReturnValue ( JenkinsShellCallRule . Type . REGEX , 'getConfig.* (?!--contextConfig)' , '{"mode": "BG_DEPLOY", "action": "RESUME", "apiUrl": "https://example.org/xs", "org": "myOrg", "space": "mySpace"}' )
assertThat ( nullScript . commonPipelineEnvironment . xsDeploymentId , nullValue ( ) )
stepRule . step . xsDeploy (
script: nullScript ,
piperGoUtils: goUtils ,
failOnError: true ,
operationId: '1357'
)
assertThat ( shellRule . shell ,
new CommandLineMatcher ( )
. hasProlog ( '#!/bin/bash ./piper xsDeploy' )
. hasOption ( 'operationId' , '1357' )
)
}
2020-01-16 10:44:13 +02:00
@Test
public void testDockerParamsViaProjectConfig ( ) {
nullScript . commonPipelineEnvironment . configuration = [ steps:
[ xsDeploy:
[
dockerImage: 'xs1'
]
]
]
stepRule . step . xsDeploy (
script: nullScript ,
piperGoUtils: goUtils
)
// 'xs' provided on the context config is superseded by the value set in the project
assertThat ( dockerRule . dockerParams . dockerImage , equalTo ( 'xs1' ) )
}
@Test
public void testDockerParamsViaProjectConfigNested ( ) {
nullScript . commonPipelineEnvironment . configuration = [ steps:
[ xsDeploy:
[
docker: [
dockerImage: 'xs1'
]
]
]
]
stepRule . step . xsDeploy (
script: nullScript ,
piperGoUtils: goUtils
)
// 'xs' provided on the context config is superseded by the value set in the project
assertThat ( dockerRule . dockerParams . dockerImage , equalTo ( 'xs1' ) )
}
@Test
public void testDockerParamsViaSignature ( ) {
nullScript . commonPipelineEnvironment . configuration = [ steps:
[ xsDeploy:
[
dockerImage: 'xs1'
]
]
]
stepRule . step . xsDeploy (
script: nullScript ,
piperGoUtils: goUtils ,
dockerImage: 'xs2' ,
)
// 'xs' provided on the context config and 'xs1' provided by project config
// is superseded by the value set in the project
assertThat ( dockerRule . dockerParams . dockerImage , equalTo ( 'xs2' ) )
}
2019-12-16 11:40:44 +02:00
@Test
public void testAdditionalCustomConfigLayers ( ) {
def resources = [ 'a.yml' : '- x: y}' , 'b.yml' : '- a: b}' ]
helper . registerAllowedMethod ( 'libraryResource' , [ String ] , {
r - >
def resource = resources [ r ]
if ( resource ) return resource
File res = new File ( new File ( 'resources' ) , r )
if ( res . exists ( ) ) {
return res . getText ( )
}
throw new RuntimeException ( "Resource '${r}' not found." )
} )
assertThat ( nullScript . commonPipelineEnvironment . xsDeploymentId , nullValue ( ) )
shellRule . setReturnValue ( JenkinsShellCallRule . Type . REGEX , '.*xsDeploy .*' , '{"operationId": "1234"}' )
nullScript . commonPipelineEnvironment = [ 'reset' : { } , 'getCustomDefaults' : { [ 'a.yml' , 'b.yml' ] } ]
goUtils = new PiperGoUtils ( null ) {
void unstashPiperBin ( ) {
}
}
stepRule . step . xsDeploy (
script: nullScript ,
piperGoUtils: goUtils
)
assertThat ( writeFileRule . files . keySet ( ) , containsInAnyOrder (
'.pipeline/additionalConfigs/a.yml' ,
'.pipeline/additionalConfigs/b.yml' ,
'.pipeline/additionalConfigs/default_pipeline_environment.yml' ,
2019-12-19 09:56:10 +02:00
'.pipeline/metadata/xsDeploy.yaml' ,
2019-12-16 11:40:44 +02:00
) )
assertThat ( shellRule . shell ,
allOf (
new CommandLineMatcher ( )
. hasProlog ( './piper getConfig' )
. hasArgument ( '--contextConfig' )
2019-12-19 09:56:10 +02:00
. hasArgument ( '--defaultConfig ".pipeline/additionalConfigs/b.yml" ".pipeline/additionalConfigs/a.yml" ".pipeline/additionalConfigs/default_pipeline_environment.yml"' ) ,
2019-12-16 11:40:44 +02:00
new CommandLineMatcher ( )
2019-12-19 09:56:10 +02:00
. hasProlog ( './piper getConfig --stepMetadata \'.pipeline/metadata/xsDeploy.yaml\'' ) ,
2019-12-16 11:40:44 +02:00
)
)
}
2020-09-16 11:33:03 +02:00
}