1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2024-12-14 11:03:09 +02:00

Merge pull request #99 from alejandraferreirovidal/environmentValidation

refactor step toolValidate to a utils class
This commit is contained in:
Alejandra Ferreiro Vidal 2018-04-12 14:39:01 +02:00 committed by GitHub
commit 2a8c01ca07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1018 additions and 379 deletions

View File

@ -1,11 +1,15 @@
# mtaBuild
## Description
Executes the SAP MTA Archive Builder to create an mtar archive of the application.
Executes the SAP Multitarget Application Archive Builder to create an mtar archive of the application.
Before doing this, validates that SAP Multitarget Application Archive Builder exists and the version is compatible.
Note that a version is formed by `major.minor.patch`, and a version is compatible to another version if the minor and patch versions are higher, but the major version is not, e.g. if 3.39.10 is the expected version, 3.39.11 and 3.40.1 would be compatible versions, but 4.0.1 would not be a compatible version.
## Prerequisites
* **SAP MTA Archive Builder** - available for download on the SAP Marketplace.
* **Java 8 or higher** - necessary to run the `mta.jar` file.
* **SAP MTA Archive Builder 1.0.6 or compatible version** - available for download on the SAP Marketplace.
* **Java 8 or compatible version** - necessary to run the `mta.jar` file.
* **NodeJS installed** - the MTA Builder uses `npm` to download node module dependencies such as `grunt`.
## Parameters
@ -18,7 +22,7 @@ Executes the SAP MTA Archive Builder to create an mtar archive of the applicatio
* `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.
* `buildTarget` - The target platform to which the mtar can be deployed.
* `mtaJarLocation` - The path of the `mta.jar` file. If no parameter is provided, neither at the level of the method call nor via step configuration, the path is retrieved from the Jenkins environment variables using `env.MTA_JAR_LOCATION`. If the Jenkins environment variable is not set it is assumed that `mta.jar` is located in the current working directory.
* `mtaJarLocation` - The path of the `mta.jar` file. If no parameter is provided, the path is retrieved from the environment variables using the environment variable`MTA_JAR_LOCATION`. If no parameter and no environment variable is provided, the path is retrieved from the step configuration using the step configuration key `mtaJarLocation`. If the previous configurations are not provided, `mta.jar` is expected on the current working directory, and if it is not located on the current working directory an AbortException is thrown.
* `applicationName` - The name of the application which is being built. If the parameter has been provided and no `mta.yaml` exists, the `mta.yaml` will be automatically generated using this parameter and the information (`name` and `version`) from `package.json` before the actual build starts.
## Step configuration

View File

@ -3,6 +3,10 @@
## Description
Deploys an Application to SAP Cloud Platform (SAP CP) using the SAP Cloud Platform Console Client (Neo Java Web SDK).
Before doing this, validates that SAP Cloud Platform Console Client is installed and the version is compatible.
Note that a version is formed by `major.minor.patch`, and a version is compatible to another version if the minor and patch versions are higher, but the major version is not, e.g. if 3.39.10 is the expected version, 3.39.11 and 3.40.1 would be compatible versions, but 4.0.1 would not be a compatible version.
## Prerequisites
* **SAP CP account** - the account to where the application is deployed.
* **SAP CP user for deployment** - a user with deployment permissions in the given account.
@ -10,11 +14,11 @@ Deploys an Application to SAP Cloud Platform (SAP CP) using the SAP Cloud Platfo
![Jenkins credentials configuration](../images/neo_credentials.png)
* **Neo Java Web SDK** - can be downloaded from [Maven Central](http://central.maven.org/maven2/com/sap/cloud/neo-java-web-sdk/). The Neo Java Web SDK
* **Neo Java Web SDK 3.39.10 or compatible version** - can be downloaded from [Maven Central](http://central.maven.org/maven2/com/sap/cloud/neo-java-web-sdk/). The Neo Java Web SDK
needs to be extracted into the folder provided by `neoHome`. In case this parameters is not provided and there is no NEO_HOME parameter in the environment
`<neoRoot>/tools` needs to be in the `PATH`. This step is also capable of triggering the neo deploy tool provided inside a docker image.
* **Java 8 or higher** - needed by the *Neo-Java-Web-SDK*
* **Java 8 or compatible version** - needed by the *Neo-Java-Web-SDK*
## Parameters when using MTA deployment method (default - MTA)
| parameter | mandatory | default | possible values |
@ -67,7 +71,7 @@ needs to be extracted into the folder provided by `neoHome`. In case this parame
* `deployMode` - The deployment mode which should be used. Available options are `'mta'` (default), `'warParams'` (deploying WAR file and passing all the deployment parameters via the function call) and `'warPropertiesFile'` (deploying WAR file and putting all the deployment parameters in a .properties file)
* `host` - The SAP Cloud Platform host to deploy to.
* `neoCredentialsId` - The Jenkins credentials containing user and password used for SAP CP deployment.
* `neoHome` - The path to the `neo-java-web-sdk` tool used for SAP CP deployment. If no parameter is provided, the path is retrieved from the Jenkins environment variables using `env.NEO_HOME`. If this Jenkins environment variable is not set it is assumed that the tool is available in the `PATH`.
* `neoHome` - The path to the `neo-java-web-sdk` tool used for SAP CP deployment. If no parameter is provided, the path is retrieved from the environment variables using the environment variable `NEO_HOME`. If no parameter and no environment variable is provided, the path is retrieved from the step configuration using the step configuration key `neoHome`. If the previous configurations are not provided, the tool is expected on the `PATH`, and if it is not available on the `PATH` an AbortException is thrown.
* `propertiesFile` - The path to the .properties file in which all necessary deployment properties for the application are defined.
* `runtime` - Name of SAP Cloud Platform application runtime
* `runtime-version` - Version of SAP Cloud Platform application runtime

View File

@ -0,0 +1,21 @@
package com.sap.piper
import hudson.AbortException
class EnvironmentUtils implements Serializable {
def static isEnvironmentVariable(script, variable) {
return !getEnvironmentVariable(script, variable).isEmpty()
}
def static getEnvironmentVariable(script, variable) {
try {
def envVar = script.sh returnStdout: true, script: """#!/bin/bash --login
echo \$$variable"""
return envVar.trim()
} catch(AbortException e) {
throw new AbortException("There was an error requesting the environment variable '$variable'. Reason: $e.message.")
}
}
}

View File

@ -6,16 +6,88 @@ import java.io.File
class FileUtils implements Serializable {
static validateDirectory(dir) {
if (!dir) throw new IllegalArgumentException("The parameter 'dir' can not be null or empty.")
def file = new File(dir)
if (!file.exists()) throw new AbortException("'${file.getAbsolutePath()}' does not exist.")
if (!file.isDirectory()) throw new AbortException("'${file.getAbsolutePath()}' is not a directory.")
static directoryOrFileExists(script, dirOrFile) {
if (!dirOrFile) throw new IllegalArgumentException("The parameter 'dirOrFile' can not be null or empty.")
def returnStatus = script.sh returnStatus: true, script: """
set +x
if [ -d $dirOrFile ]; then
echo \"$dirOrFile exists.\"
exit 0
elif [ -f $dirOrFile ]; then
echo \"$dirOrFile exists.\"
exit 0
else
echo \"$dirOrFile does not exist.\"
exit 1
fi
"""
return returnStatus == 0
}
static validateDirectoryIsNotEmpty(dir) {
validateDirectory(dir)
def file = new File(dir)
if (file.list().size() == 0) throw new AbortException("'${file.getAbsolutePath()}' is empty.")
static isDirectory(script, dir) {
if (!dir) throw new IllegalArgumentException("The parameter 'dir' can not be null or empty.")
def returnStatus = script.sh returnStatus: true, script: """
set +x
if [ -d $dir ]; then
echo \"$dir is a directory.\"
exit 0
else
echo \"$dir is not a directory.\"
exit 1
fi
"""
return returnStatus == 0
}
static isDirectoryEmpty(script, dir) {
if (!dir) throw new IllegalArgumentException("The parameter 'dir' can not be null or empty.")
def returnStatus = script.sh returnStatus: true, script: """
set +x
if [ -z "\$(ls -A $dir)" ]; then
echo "$dir is empty."
exit 1
else
echo "$dir is not empty."
exit 0
fi
"""
return returnStatus == 1
}
static isFile(script, filePath) {
if (!filePath) throw new IllegalArgumentException("The parameter 'filePath' can not be null or empty.")
def returnStatus = script.sh returnStatus: true, script: """
set +x
if [ -f $filePath ]; then
echo \"$filePath is a file.\"
exit 0
else
echo \"$filePath is not a file.\"
exit 1
fi
"""
return returnStatus == 0
}
static validateDirectoryOrFileExists(script, dirOrFile) {
if (!dirOrFile) throw new IllegalArgumentException("The parameter 'dirOrFile' can not be null or empty.")
if (!directoryOrFileExists(script, dirOrFile)) throw new AbortException("Validation failed. '$dirOrFile' does not exist.")
}
static validateDirectory(script, dir) {
if (!dir) throw new IllegalArgumentException("The parameter 'dir' can not be null or empty.")
validateDirectoryOrFileExists(script, dir)
if (!isDirectory(script, dir)) throw new AbortException("Validation failed. '$dir' is not a directory.")
}
static validateDirectoryIsNotEmpty(script, dir) {
validateDirectory(script, dir)
if (isDirectoryEmpty(script, dir)) throw new AbortException("Validation failed. '$dir' is empty.")
}
static validateFile(script, filePath) {
if (!filePath) throw new IllegalArgumentException("The parameter 'filePath' can not be null or empty.")
validateDirectoryOrFileExists(script, filePath)
if (!isFile(script, filePath)) throw new AbortException("Validation failed. '$filePath' is not a file.")
}
}

View File

@ -0,0 +1,63 @@
package com.sap.piper.tools
import com.sap.piper.EnvironmentUtils
import com.sap.piper.FileUtils
import hudson.AbortException
class JavaArchiveDescriptor extends ToolDescriptor {
final javaTool
final javaOptions
JavaArchiveDescriptor(name, environmentKey, stepConfigurationKey, executablePath, executableName, version, versionOption, javaTool, javaOptions = '') {
super(name, environmentKey, stepConfigurationKey, executablePath, executableName, version, versionOption)
this.javaTool = javaTool
this.javaOptions = javaOptions
}
@Override
def getToolLocation(script, configuration, log = true) {
def home
if (EnvironmentUtils.isEnvironmentVariable(script, environmentKey)) {
home = EnvironmentUtils.getEnvironmentVariable(script, environmentKey)
if (log) script.echo "$name home '$home' retrieved from environment."
}
else if (configuration.containsKey(stepConfigurationKey)) {
home = configuration.get(stepConfigurationKey)
if (log) script.echo "$name home '$home' retrieved from configuration."
} else if (isOnCurrentWorkingDirectory(script)){
home = ''
if (log) script.echo "$name expected on current working directory."
} else {
throw new AbortException(getMessage())
}
return home
}
@Override
def getToolExecutable(script, configuration, log = true) {
def javaArchive = getTool(script, configuration, log)
if (log) script.echo "Using $name '$javaArchive'."
def javaExecutable = javaTool.getToolExecutable(script, configuration, false)
def javaCall = "$javaExecutable -jar"
if (javaOptions) javaCall += " $javaOptions"
return "$javaCall $javaArchive"
}
@Override
def getMessage() {
def configOptions = "Please, configure $name home. $name home can be set "
if (environmentKey) configOptions += "using the environment variable '$environmentKey'"
if (environmentKey && stepConfigurationKey) configOptions += ", or "
if (stepConfigurationKey) configOptions += "using the configuration key '$stepConfigurationKey'."
return configOptions
}
def isOnCurrentWorkingDirectory(script) {
return FileUtils.isFile(script, executableName)
}
}

View File

@ -0,0 +1,133 @@
package com.sap.piper.tools
import com.sap.piper.EnvironmentUtils
import com.sap.piper.FileUtils
import com.sap.piper.Version
import hudson.AbortException
class ToolDescriptor implements Serializable {
final name
final environmentKey
final stepConfigurationKey
final executablePath
final executableName
final version
final versionOption
ToolDescriptor(name, environmentKey, stepConfigurationKey, executablePath, executableName, version, versionOption) {
this.name = name
this.environmentKey = environmentKey
this.stepConfigurationKey = stepConfigurationKey
this.executablePath = executablePath
this.executableName = executableName
this.version = version
this.versionOption = versionOption
}
def getToolLocation(script, configuration, log = true) {
def toolLocation
if (EnvironmentUtils.isEnvironmentVariable(script, environmentKey)) {
toolLocation = EnvironmentUtils.getEnvironmentVariable(script, environmentKey)
if (log) script.echo "$name home '$toolLocation' retrieved from environment."
}
else if (configuration.containsKey(stepConfigurationKey)) {
toolLocation = configuration.get(stepConfigurationKey)
if (log) script.echo "$name home '$toolLocation' retrieved from configuration."
} else if (isOnPath(script, configuration)){
toolLocation = ''
if (log) script.echo "$name is on PATH."
} else {
throw new AbortException(getMessage())
}
return toolLocation
}
def getTool(script, configuration, log = true) {
def toolLocation = getToolLocation(script, configuration, log)
if (toolLocation) {
return "$toolLocation$executablePath$executableName"
} else {
return executableName
}
}
def getToolExecutable(script, configuration, log = true) {
def executable = getTool(script, configuration, log)
if (log) script.echo "Using $name '$executable'."
return executable
}
def verify(script, configuration) {
verifyToolLocation(script, configuration)
verifyToolExecutable(script, configuration)
verifyVersion(script, configuration)
}
def verifyToolLocation(script, configuration) {
def toolLocation = getToolLocation(script, configuration)
if (toolLocation) {
script.echo "Verifying $name location '$toolLocation'."
FileUtils.validateDirectoryIsNotEmpty(script, toolLocation)
script.echo "Verification success. $name location '$toolLocation' exists."
}
}
def verifyToolExecutable(script, configuration) {
def home = getToolLocation(script, configuration, false)
def tool = getTool(script, configuration, false)
if (home) {
script.echo "Verifying $name '$tool'."
FileUtils.validateFile(script, tool)
script.echo "Verification success. $name '$tool' exists."
}
}
def verifyVersion(script, configuration) {
def executable = getToolExecutable(script, configuration, false)
script.echo "Verifying $name version $version or compatible version."
def toolVersion
try {
toolVersion = script.sh returnStdout: true, script: """#!/bin/bash
$executable $versionOption"""
} catch(AbortException e) {
throw new AbortException("The verification of $name failed. Please check '$executable'. $e.message.")
}
def installedVersion = new Version(toolVersion)
if (!installedVersion.isCompatibleVersion(new Version(version))) {
throw new AbortException("The installed version of $name is ${installedVersion.toString()}. Please install version $version or a compatible version.")
}
script.echo "Verification success. $name version ${installedVersion.toString()} is installed."
}
def getMessage() {
def configOptions = "Please, configure $name home. $name home can be set "
if (environmentKey) configOptions += "using the environment variable '$environmentKey', or "
if (stepConfigurationKey) configOptions += "using the configuration key '$stepConfigurationKey', or "
configOptions += "on PATH."
return configOptions
}
def isOnPath(script, configuration) {
def exitStatus
try {
exitStatus = script.sh returnStatus: true, script: """set +x
which $executableName"""
} catch(AbortException e) {
throw new AbortException("The verification of $name failed, while checking if it was on PATH. Reason: $e.message.")
}
return exitStatus == 0
}
}

View File

@ -60,27 +60,10 @@ public class MtaBuildTest extends BasePipelineTest {
mtaYaml.text = defaultMtaYaml()
helper.registerAllowedMethod('pwd', [], { currentDir } )
helper.registerAllowedMethod('fileExists', [GString.class], { false })
helper.registerAllowedMethod('sh', [Map], { Map m -> getVersionWithoutEnvVars(m) })
binding.setVariable('PATH', '/usr/bin')
//
// needs to be after loading the scripts. Here we have a different behaviour
// for usual steps and for steps contained in the shared lib itself.
//
// toolValidate mocked here since we are not interested in testing
// toolValidate here. This is expected to be done in a test class for
// toolValidate.
//
helper.registerAllowedMethod('toolValidate', [Map], { m ->
if(m.tool == 'mta')
toolMtaValidateCalled = true
if(m.tool == 'java')
toolJavaValidateCalled = true
})
}
@ -130,22 +113,35 @@ public class MtaBuildTest extends BasePipelineTest {
@Test
void mtaJarLocationNotSetTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> getVersionWithoutEnvVarsAndNotInCurrentDir(m) })
thrown.expect(AbortException)
thrown.expectMessage("Please, configure SAP Multitarget Application Archive Builder home. SAP Multitarget Application Archive Builder home can be set using the environment variable 'MTA_JAR_LOCATION', or " +
"using the configuration key 'mtaJarLocation'.")
jsr.step.call(buildTarget: 'NEO')
}
@Test
void mtaJarLocationOnCurrentWorkingDirectoryTest() {
jsr.step.call(buildTarget: 'NEO')
assert jscr.shell.find { c -> c.contains(' -jar mta.jar --mtar ')}
assert jlr.log.contains('[mtaBuild] Using MTA JAR from current working directory.')
assert jlr.log.contains("SAP Multitarget Application Archive Builder expected on current working directory.")
assert jlr.log.contains("Using SAP Multitarget Application Archive Builder 'mta.jar'.")
}
@Test
void mtaJarLocationAsParameterTest() {
jsr.step.call(mtaJarLocation: '/mylocation/mta', buildTarget: 'NEO')
assert jscr.shell.find { c -> c.contains(' -jar /mylocation/mta/mta.jar --mtar ')}
assert jscr.shell.find { c -> c.contains('-jar /mylocation/mta/mta.jar --mtar')}
assert jlr.log.contains('[mtaBuild] MTA JAR "/mylocation/mta/mta.jar" retrieved from configuration.')
assert jlr.log.contains("SAP Multitarget Application Archive Builder home '/mylocation/mta' retrieved from configuration.")
assert jlr.log.contains("Using SAP Multitarget Application Archive Builder '/mylocation/mta/mta.jar'.")
}
@ -186,26 +182,27 @@ public class MtaBuildTest extends BasePipelineTest {
@Test
void mtaJarLocationFromEnvironmentTest() {
binding.setVariable('env', [:])
binding.getVariable('env')['MTA_JAR_LOCATION'] = '/env/mta'
helper.registerAllowedMethod('sh', [Map], { Map m -> getVersionWithEnvVars(m) })
jsr.step.call(buildTarget: 'NEO')
assert jscr.shell.find { c -> c.contains('-jar /env/mta/mta.jar --mtar')}
assert jlr.log.contains('[mtaBuild] MTA JAR "/env/mta/mta.jar" retrieved from environment.')
assert jscr.shell.find { c -> c.contains("-jar /env/mta/mta.jar --mtar")}
assert jlr.log.contains("SAP Multitarget Application Archive Builder home '/env/mta' retrieved from environment.")
assert jlr.log.contains("Using SAP Multitarget Application Archive Builder '/env/mta/mta.jar'.")
}
@Test
void mtaJarLocationFromCustomStepConfigurationTest() {
jer.env.configuration = [steps:[mtaBuild:[mtaJarLocation: '/step/mta']]]
jer.env.configuration = [steps:[mtaBuild:[mtaJarLocation: '/config/mta']]]
jsr.step.call(script: [commonPipelineEnvironment: jer.env],
buildTarget: 'NEO')
assert jscr.shell.find(){ c -> c.contains('-jar /step/mta/mta.jar --mtar')}
assert jlr.log.contains('[mtaBuild] MTA JAR "/step/mta/mta.jar" retrieved from configuration.')
assert jscr.shell.find(){ c -> c.contains("-jar /config/mta/mta.jar --mtar")}
assert jlr.log.contains("SAP Multitarget Application Archive Builder home '/config/mta' retrieved from configuration.")
assert jlr.log.contains("Using SAP Multitarget Application Archive Builder '/config/mta/mta.jar'.")
}
@ -239,41 +236,6 @@ public class MtaBuildTest extends BasePipelineTest {
assert jscr.shell.find { c -> c.contains('java -jar mta.jar --mtar com.mycompany.northwind.mtar --build-target=NEO build')}
}
@Ignore('Tool validation disabled since it does not work properly in conjunction with slaves.')
@Test
void skipValidationInCaseMtarJarFileIsUsedFromWorkingDir() {
jscr.setReturnValue('ls mta.jar', 0)
jsr.step.call(script: [commonPipelineEnvironment: jer.env])
assert !toolMtaValidateCalled
}
@Ignore('Tool validation disabled since it does not work properly in conjunction with slaves.')
@Test
void performValidationInCaseMtarJarFileIsNotUsedFromWorkingDir() {
jscr.setReturnValue('ls mta.jar', 1)
jsr.step.call(script: [commonPipelineEnvironment: jer.env])
assert toolMtaValidateCalled
}
@Ignore('Tool validation disabled since it does not work properly in conjunction with slaves.')
@Test
void toolJavaValidateCalled() {
jsr.step.call(buildTarget: 'NEO')
assert toolJavaValidateCalled
}
@Ignore('Tool validation disabled since it does not work properly in conjunction with slaves.')
@Test
void toolValidateNotCalledWhenJavaHomeIsUnsetButJavaIsInPath() {
jscr.setReturnValue('which java', 0)
jsr.step.call(buildTarget: 'NEO')
assert !toolJavaValidateCalled
assert jlr.log.contains('Tool validation (java) skipped. JAVA_HOME not set, but java executable in path.')
}
private static defaultMtaYaml() {
return '''
@ -336,4 +298,82 @@ public class MtaBuildTest extends BasePipelineTest {
build-result: dist
'''
}
private getVersionWithEnvVars(Map m) {
if(m.script.contains('java -version')) {
return '''openjdk version \"1.8.0_121\"
OpenJDK Runtime Environment (build 1.8.0_121-8u121-b13-1~bpo8+1-b13)
OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)'''
} else if(m.script.contains('mta.jar -v')) {
return '1.0.6'
} else {
return getEnvVars(m)
}
}
private getVersionWithoutEnvVars(Map m) {
if(m.script.contains('java -version')) {
return '''openjdk version \"1.8.0_121\"
OpenJDK Runtime Environment (build 1.8.0_121-8u121-b13-1~bpo8+1-b13)
OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)'''
} else if(m.script.contains('mta.jar -v')) {
return '1.0.6'
} else {
return getNoEnvVars(m)
}
}
private getVersionWithoutEnvVarsAndNotInCurrentDir(Map m) {
if(m.script.contains('java -version')) {
return '''openjdk version \"1.8.0_121\"
OpenJDK Runtime Environment (build 1.8.0_121-8u121-b13-1~bpo8+1-b13)
OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)'''
} else if(m.script.contains('mta.jar -v')) {
return '1.0.6'
} else {
return getNoEnvVarsAndNotInCurrentDir(m)
}
}
private getEnvVars(Map m) {
if(m.script.contains('JAVA_HOME')) {
return ''
} else if(m.script.contains('MTA_JAR_LOCATION')) {
return '/env/mta'
} else if(m.script.contains('which java')) {
return 0
} else {
return 0
}
}
private getNoEnvVars(Map m) {
if(m.script.contains('JAVA_HOME')) {
return ''
} else if(m.script.contains('MTA_JAR_LOCATION')) {
return ''
} else if(m.script.contains('which java')) {
return 0
} else {
return 0
}
}
private getNoEnvVarsAndNotInCurrentDir(Map m) {
if(m.script.contains('JAVA_HOME')) {
return ''
} else if(m.script.contains('MTA_JAR_LOCATION')) {
return ''
} else if(m.script.contains('which java')) {
return 0
} else {
return 1
}
}
}

View File

@ -42,13 +42,12 @@ class NeoDeployTest extends BasePipelineTest {
.around(jsr)
.around(jer)
def toolNeoValidateCalled = false
private static workspacePath
private static warArchiveName
private static propertiesFileName
private static archiveName
@BeforeClass
static void createTestFiles() {
@ -85,25 +84,9 @@ class NeoDeployTest extends BasePipelineTest {
})
binding.setVariable('env', ['NEO_HOME':'/opt/neo'])
helper.registerAllowedMethod('sh', [Map], { Map m -> getVersionWithEnvVars(m) })
jer.env.configuration = [steps:[neoDeploy: [host: 'test.deploy.host.com', account: 'trialuser123']]]
//
// needs to be after loading the scripts. Here we have a different behaviour
// for usual steps and for steps contained in the shared lib itself.
//
// toolValidate mocked here since we are not interested in testing
// toolValidate here. This is expected to be done in a test class for
// toolValidate.
//
helper.registerAllowedMethod('toolValidate', [Map], { m ->
if(m.tool == 'neo')
toolNeoValidateCalled = true
if(m.tool == 'java')
toolJavaValidateCalled = true
})
}
@ -178,29 +161,32 @@ class NeoDeployTest extends BasePipelineTest {
@Test
void neoHomeNotSetTest() {
binding.setVariable('env', [:])
helper.registerAllowedMethod('sh', [Map], { Map m -> getVersionWithPath(m) })
jsr.step.call(script: [commonPipelineEnvironment: jer.env],
archivePath: archiveName
)
assert jscr.shell.find { c -> c.contains('which neo.sh') }
assert jscr.shell.find { c -> c.contains('"neo.sh" deploy-mta') }
assert jlr.log.contains('Using Neo executable from PATH.')
assert jlr.log.contains('SAP Cloud Platform Console Client is on PATH.')
assert jlr.log.contains("Using SAP Cloud Platform Console Client 'neo.sh'.")
}
@Test
void neoHomeAsParameterTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> getVersionWithPath(m) })
jsr.step.call(script: [commonPipelineEnvironment: jer.env],
archivePath: archiveName,
neoCredentialsId: 'myCredentialsId',
neoHome: '/etc/neo'
neoHome: '/param/neo'
)
assert jscr.shell.find{ c -> c = '"/etc/neo/tools/neo.sh" deploy-mta' }
assert jlr.log.contains('[neoDeploy] Neo executable "/etc/neo/tools/neo.sh" retrieved from configuration.')
assert jscr.shell.find{ c -> c = "\"/param/neo/tools/neo.sh\" deploy-mta" }
assert jlr.log.contains("SAP Cloud Platform Console Client home '/param/neo' retrieved from configuration.")
assert jlr.log.contains("Using SAP Cloud Platform Console Client '/param/neo/tools/neo.sh'.")
}
@ -211,22 +197,26 @@ class NeoDeployTest extends BasePipelineTest {
archivePath: archiveName
)
assert jscr.shell.find { c -> c.contains('"/opt/neo/tools/neo.sh" deploy-mta')}
assert jlr.log.contains('[neoDeploy] Neo executable "/opt/neo/tools/neo.sh" retrieved from environment.')
assert jscr.shell.find { c -> c.contains("\"/opt/neo/tools/neo.sh\" deploy-mta")}
assert jlr.log.contains("SAP Cloud Platform Console Client home '/opt/neo' retrieved from environment.")
assert jlr.log.contains("Using SAP Cloud Platform Console Client '/opt/neo/tools/neo.sh'.")
}
@Test
void neoHomeFromCustomStepConfigurationTest() {
jer.env.configuration = [steps:[neoDeploy: [host: 'test.deploy.host.com', account: 'trialuser123', neoHome: '/step/neo']]]
helper.registerAllowedMethod('sh', [Map], { Map m -> getVersionWithPath(m) })
jer.env.configuration = [steps:[neoDeploy: [host: 'test.deploy.host.com', account: 'trialuser123', neoHome: '/config/neo']]]
jsr.step.call(script: [commonPipelineEnvironment: jer.env],
archivePath: archiveName
)
assert jscr.shell.find { c -> c = '"/step/neo/tools/neo.sh" deploy-mta'}
assert jlr.log.contains('[neoDeploy] Neo executable "/step/neo/tools/neo.sh" retrieved from configuration.')
assert jscr.shell.find { c -> c = "\"/config/neo/tools/neo.sh\" deploy-mta"}
assert jlr.log.contains("SAP Cloud Platform Console Client home '/config/neo' retrieved from configuration.")
assert jlr.log.contains("Using SAP Cloud Platform Console Client '/config/neo/tools/neo.sh'.")
}
@ -447,54 +437,64 @@ class NeoDeployTest extends BasePipelineTest {
assert jlr.log.contains("Deprecated parameter 'deployAccount' is used. This will not work anymore in future versions. Use parameter 'account' instead.")
}
@Ignore('Tool validation disabled since it does not work properly in conjunction with slaves.')
@Test
void skipValidationWhenNeoToolsetIsInPathButNeoHomeNotProvidedViaConfigNorEnvironment() {
binding.setVariable('env', [:])
jscr.setReturnValue('which neo.sh', 0)
jsr.step.call(script: [commonPipelineEnvironment: jer.env],
archivePath: archiveName,
neoCredentialsId: 'myCredentialsId'
)
assert !toolNeoValidateCalled
private getVersionWithEnvVars(Map m) {
if(m.script.contains('java -version')) {
return '''openjdk version \"1.8.0_121\"
OpenJDK Runtime Environment (build 1.8.0_121-8u121-b13-1~bpo8+1-b13)
OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)'''
} else if(m.script.contains('neo.sh version')) {
return '''SAP Cloud Platform Console Client
SDK version : 3.39.10
Runtime : neo-java-web'''
} else {
return getEnvVars(m)
}
}
@Ignore('Tool validation disabled since it does not work properly in conjunction with slaves.')
@Test
void performValidationWhenNeoToolsetIsNotInPathAndNeoHomeNotProvidedViaConfigNorEnvironment() {
private getVersionWithPath(Map m) {
binding.setVariable('env', [:])
jscr.setReturnValue('which neo.sh', 1)
jsr.step.call(script: [commonPipelineEnvironment: jer.env],
archivePath: archiveName,
neoCredentialsId: 'myCredentialsId'
)
assert toolNeoValidateCalled
if(m.script.contains('java -version')) {
return '''openjdk version \"1.8.0_121\"
OpenJDK Runtime Environment (build 1.8.0_121-8u121-b13-1~bpo8+1-b13)
OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)'''
} else if(m.script.contains('neo.sh version')) {
return '''SAP Cloud Platform Console Client
SDK version : 3.39.10
Runtime : neo-java-web'''
} else {
return getPath(m)
}
}
@Ignore('Tool validation disabled since it does not work properly in conjunction with slaves.')
@Test
void toolJavaValidateCalled() {
private getEnvVars(Map m) {
jsr.step.call(script: [commonPipelineEnvironment: jer.env],
archivePath: archiveName,
neoCredentialsId: 'myCredentialsId')
assert toolJavaValidateCalled
if(m.script.contains('JAVA_HOME')) {
return '/opt/java'
} else if(m.script.contains('NEO_HOME')) {
return '/opt/neo'
} else if (m.script.contains('which java')) {
return 0
} else if (m.script.contains('which neo')) {
return 0
} else {
return 0
}
}
@Ignore('Tool validation disabled since it does not work properly in conjunction with slaves.')
@Test
void toolValidateSkippedIfJavaHomeNotSetButJavaInPath() {
private getPath(Map m) {
jscr.setReturnValue('which java', 0)
jsr.step.envProps = [:] // make sure we are not confused by JAVA_HOME in current env props.
jsr.step.call(script: [commonPipelineEnvironment: jer.env],
archivePath: archiveName,
neoCredentialsId: 'myCredentialsId')
assert ! toolJavaValidateCalled
assert jlr.log.contains('Skipping tool validate check (java). Java executable in path, but no JAVA_HOME found.')
if(m.script.contains('JAVA_HOME')) {
return ''
} else if(m.script.contains('NEO_HOME')) {
return ''
} else if (m.script.contains('which java')) {
return 0
} else if (m.script.contains('which neo')) {
return 0
} else {
return 0
}
}
}

View File

@ -1,8 +1,6 @@
import org.apache.commons.exec.*
import hudson.AbortException
import org.junit.BeforeClass
import org.junit.ClassRule
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -17,8 +15,6 @@ import util.JenkinsStepRule
import util.Rules
class ToolValidateTest extends BasePipelineTest {
@ClassRule
public static TemporaryFolder tmp = new TemporaryFolder()
private ExpectedException thrown = new ExpectedException().none()
private JenkinsLoggingRule jlr = new JenkinsLoggingRule(this)
@ -31,30 +27,20 @@ class ToolValidateTest extends BasePipelineTest {
.around(jlr)
.around(jsr)
private static home
@BeforeClass
static void createTestFiles() {
home = "${tmp.getRoot()}"
tmp.newFile('mta.jar')
}
@Before
void init() {
binding.setVariable('JAVA_HOME', home)
}
def home = 'home'
@Test
void nullHomeTest() {
thrown.expect(IllegalArgumentException)
thrown.expectMessage("The parameter 'home' can not be null or empty.")
jsr.step.call(tool: 'java', home: null)
jsr.step.call(tool: 'java')
}
@Test
void emptyHomeTest() {
thrown.expect(IllegalArgumentException)
thrown.expectMessage("The parameter 'home' can not be null or empty.")
@ -63,22 +49,31 @@ class ToolValidateTest extends BasePipelineTest {
@Test
void nullToolTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> return 0 })
thrown.expect(IllegalArgumentException)
thrown.expectMessage("The parameter 'tool' can not be null or empty.")
jsr.step.call(tool: null)
jsr.step.call(tool: null, home: home)
}
@Test
void emptyToolTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> return 0 })
thrown.expect(IllegalArgumentException)
thrown.expectMessage("The parameter 'tool' can not be null or empty.")
jsr.step.call(tool: '')
jsr.step.call(tool: '', home: home)
}
@Test
void invalidToolTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> return 0 })
thrown.expect(AbortException)
thrown.expectMessage("The tool 'test' is not supported.")
@ -87,8 +82,9 @@ class ToolValidateTest extends BasePipelineTest {
@Test
void unableToValidateJavaTest() {
thrown.expect(AbortException)
thrown.expectMessage('The validation of Java failed.')
thrown.expectMessage('The verification of Java failed.')
helper.registerAllowedMethod('sh', [Map], { Map m -> getNoVersion(m) })
@ -97,8 +93,9 @@ class ToolValidateTest extends BasePipelineTest {
@Test
void unableToValidateMtaTest() {
thrown.expect(AbortException)
thrown.expectMessage('The validation of SAP Multitarget Application Archive Builder failed.')
thrown.expectMessage('The verification of SAP Multitarget Application Archive Builder failed.')
helper.registerAllowedMethod('sh', [Map], { Map m -> getNoVersion(m) })
@ -107,8 +104,9 @@ class ToolValidateTest extends BasePipelineTest {
@Test
void unableToValidateNeoTest() {
thrown.expect(AbortException)
thrown.expectMessage('The validation of SAP Cloud Platform Console Client failed.')
thrown.expectMessage('The verification of SAP Cloud Platform Console Client failed.')
helper.registerAllowedMethod('sh', [Map], { Map m -> getNoVersion(m) })
@ -117,8 +115,9 @@ class ToolValidateTest extends BasePipelineTest {
@Test
void unableToValidateCmTest() {
thrown.expect(AbortException)
thrown.expectMessage('The validation of Change Management Command Line Interface failed.')
thrown.expectMessage('The verification of Change Management Command Line Interface failed.')
helper.registerAllowedMethod('sh', [Map], { Map m -> getNoVersion(m) })
@ -129,6 +128,7 @@ class ToolValidateTest extends BasePipelineTest {
@Test
void validateIncompatibleVersionJavaTest() {
thrown.expect(AbortException)
thrown.expectMessage('The installed version of Java is 1.7.0.')
@ -139,6 +139,7 @@ class ToolValidateTest extends BasePipelineTest {
@Test
void validateIncompatibleVersionMtaTest() {
thrown.expect(AbortException)
thrown.expectMessage('The installed version of SAP Multitarget Application Archive Builder is 1.0.5.')
@ -149,6 +150,7 @@ class ToolValidateTest extends BasePipelineTest {
@Test
void validateNeoIncompatibleVersionTest() {
thrown.expect(AbortException)
thrown.expectMessage('The installed version of SAP Cloud Platform Console Client is 1.126.51.')
@ -159,6 +161,7 @@ class ToolValidateTest extends BasePipelineTest {
@Test
void validateCmIncompatibleVersionTest() {
thrown.expect(AbortException)
thrown.expectMessage('The installed version of Change Management Command Line Interface is 0.0.0.')
@ -170,49 +173,81 @@ class ToolValidateTest extends BasePipelineTest {
@Test
void validateJavaTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> getVersion(m) })
jsr.step.call(tool: 'java', home: home)
assert jlr.log.contains('[toolValidate] Validating Java version 1.8.0 or compatible version.')
assert jlr.log.contains('[toolValidate] Java version 1.8.0 is installed.')
assert jlr.log.contains('Verifying Java version 1.8.0 or compatible version.')
assert jlr.log.contains('Java version 1.8.0 is installed.')
}
@Test
void validateMtaTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> getVersion(m) })
jsr.step.call(tool: 'mta', home: home)
assert jlr.log.contains('[toolValidate] Validating SAP Multitarget Application Archive Builder version 1.0.6 or compatible version.')
assert jlr.log.contains('[toolValidate] SAP Multitarget Application Archive Builder version 1.0.6 is installed.')
assert jlr.log.contains('Verifying SAP Multitarget Application Archive Builder version 1.0.6 or compatible version.')
assert jlr.log.contains('SAP Multitarget Application Archive Builder version 1.0.6 is installed.')
}
@Test
void validateNeoTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> getVersion(m) })
jsr.step.call(tool: 'neo', home: home)
assert jlr.log.contains('[toolValidate] Validating SAP Cloud Platform Console Client version 3.39.10 or compatible version.')
assert jlr.log.contains('[toolValidate] SAP Cloud Platform Console Client version 3.39.10 is installed.')
assert jlr.log.contains('Verifying SAP Cloud Platform Console Client version 3.39.10 or compatible version.')
assert jlr.log.contains('SAP Cloud Platform Console Client version 3.39.10 is installed.')
}
@Test
void validateCmTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> getVersion(m) })
jsr.step.call(tool: 'cm', home: home)
assert jlr.log.contains('[toolValidate] Validating Change Management Command Line Interface version 0.0.1 or compatible version.')
assert jlr.log.contains('[toolValidate] Change Management Command Line Interface version 0.0.1 is installed.')
assert jlr.log.contains('Verifying Change Management Command Line Interface version 0.0.1 or compatible version.')
assert jlr.log.contains('Change Management Command Line Interface version 0.0.1 is installed.')
}
private getToolHome(Map m) {
if(m.script.contains('JAVA_HOME')) {
return '/env/java'
} else if(m.script.contains('MTA_JAR_LOCATION')) {
return '/env/mta'
} else if(m.script.contains('NEO_HOME')) {
return '/env/neo'
} else if(m.script.contains('CM_CLI_HOME')) {
return '/env/cmclient'
} else {
return 0
}
}
private getNoVersion(Map m) {
throw new AbortException('script returned exit code 127')
if(m.script.contains('java -version')) {
throw new AbortException('script returned exit code 127')
} else if(m.script.contains('mta.jar -v')) {
throw new AbortException('script returned exit code 127')
} else if(m.script.contains('neo.sh version')) {
throw new AbortException('script returned exit code 127')
} else if(m.script.contains('cmclient -v')) {
throw new AbortException('script returned exit code 127')
} else {
return getToolHome(m)
}
}
private getVersion(Map m) {
if(m.script.contains('java -version')) {
return '''openjdk version \"1.8.0_121\"
OpenJDK Runtime Environment (build 1.8.0_121-8u121-b13-1~bpo8+1-b13)
@ -225,10 +260,13 @@ class ToolValidateTest extends BasePipelineTest {
Runtime : neo-java-web'''
} else if(m.script.contains('cmclient -v')) {
return '0.0.1-beta-2 : fc9729964a6acf5c1cad9c6f9cd6469727625a8e'
} else {
return getToolHome(m)
}
}
private getIncompatibleVersion(Map m) {
if(m.script.contains('java -version')) {
return '''openjdk version \"1.7.0_121\"
OpenJDK Runtime Environment (build 1.7.0_121-8u121-b13-1~bpo8+1-b13)
@ -241,6 +279,8 @@ class ToolValidateTest extends BasePipelineTest {
Runtime : neo-java-web'''
} else if(m.script.contains('cmclient -v')) {
return '0.0.0-beta-1 : fc9729964a6acf5c1cad9c6f9cd6469727625a8e'
} else {
return getToolHome(m)
}
}
}

View File

@ -0,0 +1,86 @@
package com.sap.piper.tools
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import org.junit.rules.RuleChain
import util.Rules
import com.lesfurets.jenkins.unit.BasePipelineTest
import com.sap.piper.EnvironmentUtils
import hudson.AbortException
class EnvironmentUtilsTest extends BasePipelineTest {
private ExpectedException thrown = new ExpectedException()
@Rule
public RuleChain rules = Rules.getCommonRules(this)
.around(thrown)
private script
@Before
void setup() {
script = loadScript('commonPipelineEnvironment.groovy').commonPipelineEnvironment
}
@Test
void isEnvironmentVariableFailedTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> throw new AbortException('') })
thrown.expect(AbortException)
thrown.expectMessage("There was an error requesting the environment variable 'JAVA_HOME'.")
EnvironmentUtils.isEnvironmentVariable(script, 'JAVA_HOME')
}
@Test
void isNotEnvironmentVariableTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> return '' })
def isEnvVar = EnvironmentUtils.isEnvironmentVariable(script, 'JAVA_HOME')
assert isEnvVar == false
}
@Test
void isEnvironmentVariableTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> return '/env/java' })
def isEnvVar = EnvironmentUtils.isEnvironmentVariable(script, 'JAVA_HOME')
assert isEnvVar == true
}
@Test
void getEnvironmentVariableFailedTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> throw new AbortException('') })
thrown.expect(AbortException)
thrown.expectMessage("There was an error requesting the environment variable 'JAVA_HOME'.")
EnvironmentUtils.getEnvironmentVariable(script, 'JAVA_HOME')
}
@Test
void getEnvironmentVariableTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> return '/env/java' })
def envVar = EnvironmentUtils.getEnvironmentVariable(script, 'JAVA_HOME')
assert envVar == '/env/java'
}
}

View File

@ -1,95 +1,192 @@
package com.sap.piper
import org.junit.ClassRule
import org.junit.BeforeClass
import org.junit.ClassRule
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import org.junit.rules.TemporaryFolder
import org.junit.rules.RuleChain
import hudson.AbortException
import util.Rules
import com.lesfurets.jenkins.unit.BasePipelineTest
import com.sap.piper.FileUtils
import hudson.AbortException
class FileUtilsTest {
class FileUtilsTest extends BasePipelineTest {
@ClassRule
public static TemporaryFolder tmp = new TemporaryFolder()
private ExpectedException thrown = new ExpectedException()
@Rule
public ExpectedException thrown = new ExpectedException()
public RuleChain rules = Rules.getCommonRules(this)
.around(thrown)
private static emptyDir
private static notEmptyDir
private static file
private static script
@BeforeClass
static void createTestFiles() {
emptyDir = tmp.newFolder('emptyDir').getAbsolutePath()
notEmptyDir = tmp.newFolder('notEmptyDir').getAbsolutePath()
file = tmp.newFile('notEmptyDir/file').getAbsolutePath()
file = tmp.newFile('notEmptyDir/file.txt').getAbsolutePath()
}
@Before
void setup() {
script = loadScript('commonPipelineEnvironment.groovy').commonPipelineEnvironment
}
@Test
void nullValidateDirectoryTest() {
void validateDirectory_nullParameterTest() {
thrown.expect(IllegalArgumentException)
thrown.expectMessage("The parameter 'dir' can not be null or empty.")
FileUtils.validateDirectory()
FileUtils.validateDirectory(script, null)
}
@Test
void emptyValidateDirectoryTest() {
void validateDirectory_emptyParameterTest() {
thrown.expect(IllegalArgumentException)
thrown.expectMessage("The parameter 'dir' can not be null or empty.")
FileUtils.validateDirectory('')
FileUtils.validateDirectory(script, '')
}
@Test
void doestNotExistValidateDirectoryTest() {
void validateDirectory_directoryDoestNotExistTest() {
def path = new File("$emptyDir", 'test').getAbsolutePath()
def dir = new File("$emptyDir", 'test').getAbsolutePath()
helper.registerAllowedMethod('sh', [Map], { Map m -> script(m, dir) })
thrown.expect(AbortException)
thrown.expectMessage("'$path' does not exist.")
thrown.expectMessage("Validation failed. '$dir' does not exist.")
FileUtils.validateDirectory(path)
FileUtils.validateDirectory(script, dir)
}
@Test
void isNotDirectoryValidateDirectoryTest() {
void validateDirectory_isNotDirectoryTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> script(m, file) })
thrown.expect(AbortException)
thrown.expectMessage("'$file' is not a directory.")
thrown.expectMessage("Validation failed. '$file' is not a directory.")
FileUtils.validateDirectory(file)
FileUtils.validateDirectory(script, file)
}
@Test
void validateDirectoryTest() {
FileUtils.validateDirectory(notEmptyDir)
helper.registerAllowedMethod('sh', [Map], { Map m -> script(m, notEmptyDir) })
FileUtils.validateDirectory(script, notEmptyDir)
}
@Test
void emptyDirValidateDirectoryIsNotEmptyTest() {
void validateDirectoryIsNotEmpty_directoryIsEmptyTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> script(m, emptyDir) })
thrown.expect(AbortException)
thrown.expectMessage("'$emptyDir' is empty.")
thrown.expectMessage("Validation failed. '$emptyDir' is empty.")
FileUtils.validateDirectoryIsNotEmpty(emptyDir)
FileUtils.validateDirectoryIsNotEmpty(script, emptyDir)
}
@Test
void validateDirectoryIsNotEmptyTest() {
FileUtils.validateDirectoryIsNotEmpty(notEmptyDir)
helper.registerAllowedMethod('sh', [Map], { Map m -> script(m, notEmptyDir) })
FileUtils.validateDirectoryIsNotEmpty(script, notEmptyDir)
}
@Test
void validateFile_NoFilePathTest() {
thrown.expect(IllegalArgumentException)
thrown.expectMessage("The parameter 'filePath' can not be null or empty.")
FileUtils.validateFile(script, null)
}
@Test
void validateFile_emptyParameterTest() {
thrown.expect(IllegalArgumentException)
thrown.expectMessage("The parameter 'filePath' can not be null or empty.")
FileUtils.validateFile(script, '')
}
@Test
void validateFile_fileDoesNotExistTest() {
def path = new File("$emptyDir", 'test').getAbsolutePath()
helper.registerAllowedMethod('sh', [Map], { Map m -> script(m, path) })
thrown.expect(AbortException)
thrown.expectMessage("Validation failed. '$path' does not exist.")
FileUtils.validateFile(script, path)
}
@Test
void validateFileTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> script(m, file) })
FileUtils.validateFile(script, file)
}
private script(parameters, path) {
if(parameters.script.contains('exists')) return directoryOrFileExists(path)
else if(parameters.script.contains('directory')) return isDirectory(path)
else if(parameters.script.contains('empty')) return isDirectoryEmpty(path)
else if(parameters.script.contains('file')) return isFile(path)
}
private directoryOrFileExists(dirOrFile) {
def file = new File(dirOrFile)
if (file.exists()) return 0
else return 1
}
private isDirectory(dir) {
def file = new File(dir)
if (file.isDirectory()) return 0
else return 1
}
private isDirectoryEmpty(dir) {
def file = new File(dir)
if (file.list().size() == 0) return 1
return 0
}
private isFile(filePath) {
def file = new File(filePath)
if (file.isFile()) return 0
return 1
}
}

View File

@ -0,0 +1,216 @@
package com.sap.piper.tools
import org.junit.BeforeClass
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import org.junit.rules.RuleChain
import util.JenkinsLoggingRule
import util.Rules
import com.lesfurets.jenkins.unit.BasePipelineTest
import com.sap.piper.tools.ToolDescriptor
import com.sap.piper.tools.JavaArchiveDescriptor
import hudson.AbortException
class JavaArchiveDescriptorTest extends BasePipelineTest {
private ExpectedException thrown = new ExpectedException()
private JenkinsLoggingRule jlr = new JenkinsLoggingRule(this)
@Rule
public RuleChain rules = Rules.getCommonRules(this)
.around(thrown)
.around(jlr)
private static tool
private static configuration
private script
@BeforeClass
static void init() {
def java = new ToolDescriptor('Java', 'JAVA_HOME', '', '/bin/', 'java', '1.8.0', '-version 2>&1')
tool = new JavaArchiveDescriptor('SAP Multitarget Application Archive Builder', 'MTA_JAR_LOCATION', 'mtaJarLocation', '/', 'mta.jar', '1.0.6', '-v', java)
}
@Before
void setup() {
helper.registerAllowedMethod('sh', [Map], { Map m -> getNoEnvVars(m) })
script = loadScript('mtaBuild.groovy').mtaBuild
configuration = [:]
}
@Test
void getToolHomeFromEnvironmentTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> getEnvVars(m) })
def toolHome = tool.getToolLocation(script, configuration)
assert toolHome == '/env/mta'
assert jlr.log.contains("$tool.name home '/env/mta' retrieved from environment.")
}
@Test
void getToolHomeFromConfigurationTest() {
configuration = [mtaJarLocation: '/config/mta']
def toolHome = tool.getToolLocation(script, configuration)
assert toolHome == '/config/mta'
assert jlr.log.contains("$tool.name home '/config/mta' retrieved from configuration.")
}
@Test
void getToolHomeFromCurrentWorkingDirectoryTest() {
def toolHome = tool.getToolLocation(script, configuration)
assert toolHome == ''
assert jlr.log.contains("$tool.name expected on current working directory.")
}
@Test
void getToolTest() {
configuration = [mtaJarLocation: '/config/mta']
def toolExecutable = tool.getTool(script, configuration)
assert toolExecutable == '/config/mta/mta.jar'
}
@Test
void getToolExecutableTest() {
configuration = [mtaJarLocation: '/config/mta']
def toolExecutable = tool.getToolExecutable(script, configuration)
assert toolExecutable == 'java -jar /config/mta/mta.jar'
assert jlr.log.contains("Using $tool.name '/config/mta/mta.jar'.")
}
@Test
void verifyToolHomeTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> getEnvVars(m) })
tool.verifyToolLocation(script, configuration)
assert jlr.log.contains("Verifying $tool.name location '/env/mta'.")
assert jlr.log.contains("Verification success. $tool.name location '/env/mta' exists.")
}
@Test
void verifyToolExecutableTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> getEnvVars(m) })
tool.verifyToolExecutable(script, configuration)
assert jlr.log.contains("Verifying $tool.name '/env/mta/mta.jar'.")
assert jlr.log.contains("Verification success. $tool.name '/env/mta/mta.jar' exists.")
}
@Test
void verifyToolVersionTest() {
helper.registerAllowedMethod('sh', [Map], { Map m -> getVersion(m) })
tool.verifyVersion(script, configuration)
assert jlr.log.contains("Verifying $tool.name version $tool.version or compatible version.")
assert jlr.log.contains("Verification success. $tool.name version $tool.version is installed.")
}
@Test
void verifyToolVersion_FailedTest() {
thrown.expect(AbortException)
thrown.expectMessage("The verification of $tool.name failed. Please check 'java -jar mta.jar'. script returned exit code 127.")
helper.registerAllowedMethod('sh', [Map], { Map m -> getVersionFailed(m) })
tool.verifyVersion(script, configuration)
}
@Test
void verifyToolVersion_IncompatibleVersionTest() {
thrown.expect(AbortException)
thrown.expectMessage("The installed version of $tool.name is 1.0.5. Please install version $tool.version or a compatible version.")
helper.registerAllowedMethod('sh', [Map], { Map m -> getIncompatibleVersion(m) })
tool.verifyVersion(script, configuration)
}
private getEnvVars(Map m) {
if(m.script.contains('JAVA_HOME')) {
return '/env/java'
} else if(m.script.contains('MTA_JAR_LOCATION')) {
return '/env/mta'
} else {
return 0
}
}
private getNoEnvVars(Map m) {
if(m.script.contains('JAVA_HOME')) {
return ''
} else if(m.script.contains('MTA_JAR_LOCATION')) {
return ''
} else if(m.script.contains('which java')) {
return 0
} else {
return 0
}
}
private getVersion(Map m) {
if(m.script.contains('java -version')) {
return '''openjdk version \"1.8.0_121\"
OpenJDK Runtime Environment (build 1.8.0_121-8u121-b13-1~bpo8+1-b13)
OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)'''
} else if(m.script.contains('mta.jar -v')) {
return '1.0.6'
} else {
return getNoEnvVars(m)
}
}
private getVersionFailed(Map m) {
if(m.script.contains('java -version') || m.script.contains('mta.jar -v')) {
throw new AbortException('script returned exit code 127')
} else {
return getNoEnvVars(m)
}
}
private getIncompatibleVersion(Map m) {
if(m.script.contains('java -version') || m.script.contains('mta.jar -v')) {
return '1.0.5'
} else {
return getNoEnvVars(m)
}
}
}

View File

@ -1,9 +1,8 @@
import com.sap.piper.ConfigurationMerger
import com.sap.piper.MtaUtils
import com.sap.piper.tools.JavaArchiveDescriptor
import com.sap.piper.tools.ToolDescriptor
import groovy.transform.Field
@Field def DEFAULT_MTA_JAR_NAME = 'mta.jar'
def call(Map parameters = [:]) {
@ -32,40 +31,11 @@ def call(Map parameters = [:]) {
parameters, parameterKeys,
stepConfigurationKeys)
MTA_JAR_FILE_VALIDATE: {
// same order like inside getMtaJar,
def mtaJarLocation = configuration?.mtaJarLocation ?: env?.MTA_JAR_LOCATION
def returnCodeLsMtaJar = sh script: "ls ${DEFAULT_MTA_JAR_NAME}", returnStatus:true
if(mtaJarLocation || ( !mtaJarLocation && returnCodeLsMtaJar != 0)) {
// toolValidate commented since it is does not work in
// conjunction with jenkins slaves.
// TODO: switch on again when the issue is resolved.
// toolValidate tool: 'mta', home: mtaJarLocation
echo 'toolValidate (mta) is disabled.'
} else {
echo "mta toolset (${DEFAULT_MTA_JAR_NAME}) has been found in current working directory. Using this version without further tool validation."
}
}
def java = new ToolDescriptor('Java', 'JAVA_HOME', '', '/bin/', 'java', '1.8.0', '-version 2>&1')
java.verify(this, configuration)
JAVA_HOME_CHECK : {
// in case JAVA_HOME is not set, but java is in the path we should not fail
// in order to be backward compatible. Before introducing that check here
// is worked also in case JAVA_HOME was not set, but java was in the path.
// toolValidate works only upon JAVA_HOME and fails in case it is not set.
def rc = sh script: 'which java' , returnStatus: true
if(script.JAVA_HOME || (!script.JAVA_HOME && rc != 0)) {
// toolValidate commented since it is does not work in
// conjunction with jenkins slaves.
// TODO: switch on again when the issue is resolved.
echo 'toolValidate (mta) is disabled.'
// toolValidate tool: 'java', home: script.JAVA_HOME
echo 'toolValidate (java) is disabled.'
} else {
echo 'Tool validation (java) skipped. JAVA_HOME not set, but java executable in path.'
}
}
def mta = new JavaArchiveDescriptor('SAP Multitarget Application Archive Builder', 'MTA_JAR_LOCATION', 'mtaJarLocation', '/', 'mta.jar', '1.0.6', '-v', java)
mta.verify(this, configuration)
def mtaYmlName = "${pwd()}/mta.yaml"
def applicationName = configuration.applicationName
@ -80,7 +50,7 @@ def call(Map parameters = [:]) {
}
def mtaYaml = readYaml file: "${pwd()}/mta.yaml"
//[Q]: Why not yaml.dump()? [A]: This reformats the whole file.
sh "sed -ie \"s/\\\${timestamp}/`date +%Y%m%d%H%M%S`/g\" \"${pwd()}/mta.yaml\""
@ -90,8 +60,7 @@ def call(Map parameters = [:]) {
}
def mtarFileName = "${id}.mtar"
def mtaJar = getMtaJar(stepName, configuration)
def mtaJar = mta.getToolExecutable(this, configuration)
def buildTarget = configuration.buildTarget
sh """#!/bin/bash
@ -106,21 +75,3 @@ def call(Map parameters = [:]) {
}
}
private getMtaJar(stepName, configuration) {
def mtaJarLocation = DEFAULT_MTA_JAR_NAME //default, maybe it is in current working directory
if(configuration?.mtaJarLocation){
mtaJarLocation = "${configuration.mtaJarLocation}/${DEFAULT_MTA_JAR_NAME}"
echo "[$stepName] MTA JAR \"${mtaJarLocation}\" retrieved from configuration."
return mtaJarLocation
}
if(env?.MTA_JAR_LOCATION){
mtaJarLocation = "${env.MTA_JAR_LOCATION}/${DEFAULT_MTA_JAR_NAME}"
echo "[$stepName] MTA JAR \"${mtaJarLocation}\" retrieved from environment."
return mtaJarLocation
}
echo "[$stepName] Using MTA JAR from current working directory."
return mtaJarLocation
}

View File

@ -1,20 +1,10 @@
import com.sap.piper.Utils
import groovy.transform.Field
import com.sap.piper.ConfigurationLoader
import com.sap.piper.ConfigurationMerger
import com.sap.piper.ConfigurationType
import com.sap.piper.tools.ToolDescriptor
@Field def NEO_DEFAULT_CMD = 'neo.sh'
//
// envProps may be overwritten by tests, but only by tests.
// [Q] Why not simply using the Map returned by getenv() itself?
// [A] The unmodifiable map returned by getenv() is not serializable
// Since everythings needs to be serializabe (CPS pattern) we
// cannot use that map directly.
@Field Map envProps = System.getenv().findAll { true }
def call(parameters = [:]) {
@ -153,8 +143,8 @@ def call(parameters = [:]) {
deployAccount = utils.getMandatoryParameter(configuration, 'account')
}
def neoExecutable = getNeoExecutable(configuration)
def neo = new ToolDescriptor('SAP Cloud Platform Console Client', 'NEO_HOME', 'neoHome', '/tools/', 'neo.sh', '3.39.10', 'version')
def neoExecutable = neo.getToolExecutable(this, configuration)
def neoDeployScript
if (deployMode == 'mta') {
@ -199,50 +189,10 @@ def call(parameters = [:]) {
dockerEnvVars: configuration.get('dockerEnvVars'),
dockerOptions: configuration.get('dockerOptions')) {
NEO_HOME_CHECK: {
// same order like inside getNeoExecutable
String neoHome = configuration.neoHome ?: env?.NEO_HOME
neo.verify(this, configuration)
// In case neo home is not set, but neo toolset is simply
// in the path, we trust that everything is OK. In order to
// validate the version also in this case, we need to adjust
// toolValidate.
def rc = sh script: "which ${NEO_DEFAULT_CMD}", returnStatus: true
if(neoHome || (!neoHome && rc != 0)) {
// toolValidate commented since it is does not work in
// conjunction with jenkins slaves.
// TODO: switch on again when the issue is resolved.
// toolValidate tool: 'neo', home: neoHome
echo 'toolValidate (neo) is disabled.'
} else {
echo "neo (${NEO_DEFAULT_CMD}) has been found in path. Using this neo version without futher tool validation."
}
}
JAVA_HOME_CHECK : {
//
// [Q] How is the java executable resolved by neo?
// [A] They check for JAVA_HOME. If not present, they
// try to resolve it via ```which java```.
//
def javaHome = envProps.JAVA_HOME
def rc = sh script: 'which java', returnStatus: true
if(!javaHome && rc == 0) {
// java home is not set`, but java is in path.
// --> we skip the check and trust that we can work
// with java from the path.
echo "Skipping tool validate check (java). " +
"Java executable in path, but no JAVA_HOME found."
} else {
// toolValidate commented since it is does not work in
// conjunction with jenkins slaves.
// TODO: switch on again when the issue is resolved.
//toolValidate tool: 'java', home: javaHome
echo 'toolValidate (java) is disabled.'
}
}
def java = new ToolDescriptor('Java', 'JAVA_HOME', '', '/bin/', 'java', '1.8.0', '-version 2>&1')
java.verify(this, configuration)
sh """${neoDeployScript} \
${commonDeployParams}
@ -251,23 +201,3 @@ def call(parameters = [:]) {
}
}
}
private getNeoExecutable(configuration) {
def neoExecutable = NEO_DEFAULT_CMD // default, if nothing below applies maybe it is the path.
if (configuration.neoHome) {
neoExecutable = "${configuration.neoHome}/tools/${NEO_DEFAULT_CMD}"
echo "[neoDeploy] Neo executable \"${neoExecutable}\" retrieved from configuration."
return neoExecutable
}
if (env?.NEO_HOME) {
neoExecutable = "${env.NEO_HOME}/tools/${NEO_DEFAULT_CMD}"
echo "[neoDeploy] Neo executable \"${neoExecutable}\" retrieved from environment."
return neoExecutable
}
echo "Using Neo executable from PATH."
return neoExecutable
}

View File

@ -1,5 +1,8 @@
import com.sap.piper.FileUtils
import com.sap.piper.Version
import com.sap.piper.tools.JavaArchiveDescriptor
import com.sap.piper.tools.ToolDescriptor
import hudson.AbortException
@ -7,57 +10,36 @@ def call(Map parameters = [:]) {
handlePipelineStepErrors (stepName: 'toolValidate', stepParameters: parameters) {
echo '[WARNING][toolValidate] This step is deprecated, and it will be removed in future versions. Validation is automatically done inside the steps.'
def tool = parameters.tool
def home = parameters.home
if (!tool) throw new IllegalArgumentException("The parameter 'tool' can not be null or empty.")
if (!home) throw new IllegalArgumentException("The parameter 'home' can not be null or empty.")
FileUtils.validateDirectoryIsNotEmpty(home)
FileUtils.validateDirectoryIsNotEmpty(this, home)
switch(tool) {
case 'java': validateJava(home)
return
case 'mta': validateMta(home)
return
case 'neo': validateNeo(home)
return
case 'cm': validateCm(home)
return
case 'java':
def java = new ToolDescriptor('Java', 'JAVA_HOME', '', '/bin/', 'java', '1.8.0', '-version 2>&1')
java.verifyVersion(this, [:])
return
case 'mta':
def java = new ToolDescriptor('Java', 'JAVA_HOME', '', '/bin/', 'java', '1.8.0', '-version 2>&1')
def mta = new JavaArchiveDescriptor('SAP Multitarget Application Archive Builder', 'MTA_JAR_LOCATION', 'mtaJarLocation', '/', 'mta.jar', '1.0.6', '-v', java)
mta.verifyVersion(this, [mtaJarLocation: home])
return
case 'neo':
def neo = new ToolDescriptor('SAP Cloud Platform Console Client', 'NEO_HOME', 'neoHome', '/tools/', 'neo.sh', '3.39.10', 'version')
neo.verifyVersion(this, [neoHome: home])
return
case 'cm':
def cmCli = new ToolDescriptor('Change Management Command Line Interface', 'CM_CLI_HOME', 'cmCliHome', '/bin/', 'cmclient', '0.0.1', '-v')
cmCli.verifyVersion(this, [cmCliHome: home])
return
default:
throw new AbortException("The tool \'$tool\' is not supported. The following tools are supported: java, mta, neo and cm.")
throw new AbortException("The tool \'$tool\' is not supported. The following tools are supported: java, mta, neo and cm.")
}
}
}
def validateJava(home) {
validateTool('Java', home, "$home/bin/java -version 2>&1", new Version(1,8,0))
}
def validateMta(home) {
validateTool('SAP Multitarget Application Archive Builder', home, "$JAVA_HOME/bin/java -jar $home/mta.jar -v", new Version(1, 0, 6))
}
def validateNeo(home) {
validateTool('SAP Cloud Platform Console Client', home, "$home/tools/neo.sh version", new Version(3, 39, 10))
}
def validateCm(home) {
validateTool('Change Management Command Line Interface', home, "$home/bin/cmclient -v", new Version(0, 0, 1))
}
private validateTool(name, home, command, expectedVersion) {
echo "[toolValidate] Validating $name version ${expectedVersion.toString()} or compatible version."
def output
try {
output = sh returnStdout: true, script: command
} catch(AbortException e) {
throw new AbortException("The validation of $name failed. Please check $name home '$home': $e.message.")
}
def version = new Version(output)
if (!version.isCompatibleVersion(expectedVersion)) {
throw new AbortException("The installed version of $name is ${version.toString()}. Please install version ${expectedVersion.toString()} or a compatible version.")
}
echo "[toolValidate] $name version ${version.toString()} is installed."
}