1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2024-12-12 10:55:20 +02:00
sap-jenkins-library/vars/cfManifestSubstituteVariables.groovy

266 lines
14 KiB
Groovy
Raw Normal View History

Variable Substitution in YAML Files (#852) * Changes: - New YamlSubstituteVariables step to substitute variables in YAML files with values from another YAML - New Tests, that check the different substitution patterns. - Added test resources, including various manifest and variables files. - Improved usage of JenkinsLoggingRule - Improved JenkinsReadYamlRule to properly reflect the mocked library's behaviour. - Added a new JenkinsWriteYamlRule. * Changes: - added a Logger that checks a config.verbose flag before it logs debug messages. - changed error handling to rethrow Yaml parsing exception in case of wrongly-formatted Yaml files. - changed JenkinsWriteYamlRule to capture Yaml file details of every invocation of writeYaml. This allows sanity checks at end of tests, even if there were multiple invocations. - adjusted tests. * Changes: - Removed javadoc-code blocks from API documentation since they are not supported. - Removed skipDeletion boolean. - Added a new deleteFile script which deletes a file if present. - Added a new JenkinsDeleteFileRule to mock deleteFile script and optionally skip deletion for tests. - Adjusted yamlSubstituteVariables script. - Adjusted tests to include new JenkinsDeleteFileRule. - Changed code that deletes an already existing output file to produce better logs. * Changes: - Turned yamlSubstituteVariables into a script that works purely based on Yaml data (not files). - Added a new cfManifestSubstituteVariables that uses yamlSubstituteVariables under the hood but works based on files. - Adjusted tests, and added new ones. * Adjusted documentation and a few log statements. * Changed documentation to no longer include javadoc code statements. * Made mocking of deletion of a file a default. Adjusted tests. * Changed signature of yamlSubstituteVariables' call method to return void. * Changes: - Fixed naming issues in deleteFile. - Renamed Logger to DebugHelper. - Fixed some documentation. * Changed implementation of deleteFile not to use java.io.File - which is evil when using it for file operations. * PROPERLY Changed implementation of deleteFile not to use java.io.File - which is evil when using it for file operations. * Changes: - Added tests for deleteFile script - Changed JenkinsFileExistsRule to also keep track of which files have been queried for existence. * Changes: - Removed java.io.File usage from cfManifestSubstituteVariables and using fileExists instead now. - Adjusted tests. * Wrapped file path inside ticks to allow spaces in file path when calling deleteFile. * Removed null checks of mandatory parameters, and resorted to ConfigurationHelper.withMandatoryProperty * Fixed a NullPointer due to weird Jenkins / Groovy behaviour. * Changes: - Turned yamlSubstituteVariables step into a utils class. - Added tests - Adjusted cfManifestSubstituteVariables to use utils class instead of step. - Adjusted tests - Adjusted APIs of DebugHelper. * Re-introduced log statement that shows what variables are being replaced and with what. * Changing API of YamlUtils to take the script and config as input. * Test * Test * Test * Test * Test * Fixing issue. * Fixing issue. * Changes: - Refactored DebugHelper and YamlUtils to make usage nicer and rely on dependency injection. - Removed Field for DebugHelper and turned it into local variable. - Adjusted classes using the above. - Adjusted tests where necessary. * Added link to CF standards to YamlUtils also. * Add docu for step cfManifestSubstituteVariables.md * Added documentation. * Added missing script parameter to documentation. Some steps document it, some don't. Right now you need it, so we document it. * Fixed some layouting and typos * Beautified exception listing. * Removed trailing whitespaces to make code climate checks pass. * Trying to get documentation generated, with all the exceptions to markup one should not use. * cosmetics. * cosmetics, part 2 * Code climate changes... * Inlined deleteFile step. * Added two more tests to properly check file deletion and output handling. * Changes: - adjusted API to take a list of variables files, as does 'cf push --vars-file' - adjusted API to allow for an optional list of variable key-value-maps as does 'cf push --vars' - reproduced conflict resolution and overriding behavior of variables files and vars lists - adjusted tests and documentation * Added missing paramter to doc comment. * Re-checked docs for missing paramters or params that have no counterpart in the method signature. * Adjusted documentation. * Removed absolute path usage from documentation. * corrected documentation. * Changed javadoc comment to plain comment. * Turned all comments to plain comments.
2019-09-06 10:20:35 +02:00
import com.sap.piper.ConfigurationHelper
import com.sap.piper.GenerateDocumentation
import com.sap.piper.variablesubstitution.ExecutionContext
import com.sap.piper.variablesubstitution.DebugHelper
import com.sap.piper.variablesubstitution.YamlUtils
import groovy.transform.Field
import static com.sap.piper.Prerequisites.checkScript
@Field String STEP_NAME = getClass().getName()
@Field Set GENERAL_CONFIG_KEYS = []
@Field Set STEP_CONFIG_KEYS = GENERAL_CONFIG_KEYS + [
/**
* The `String` path of the Yaml file to replace variables in.
* Defaults to "manifest.yml" if not specified otherwise.
*/
'manifestFile',
/**
* The `String` path of the Yaml file to produce as output.
* If not specified this will default to `manifestFile` and overwrite it.
*/
'outputManifestFile',
/**
* The `List` of `String` paths of the Yaml files containing the variable values to use as a replacement in the manifest file.
* Defaults to `["manifest-variables.yml"]` if not specified otherwise. The order of the files given in the list is relevant
* in case there are conflicting variable names and values within variable files. In such a case, the values of the last file win.
*/
'manifestVariablesFiles',
/**
* A `List` of `Map` entries for key-value pairs used for variable substitution within the file given by `manifestFile`.
* Defaults to an empty list, if not specified otherwise. This can be used to set variables like it is provided
* by `cf push --var key=value`.
*
* The order of the maps of variables given in the list is relevant in case there are conflicting variable names and values
* between maps contained within the list. In case of conflicts, the last specified map in the list will win.
*
* Though each map entry in the list can contain more than one key-value pair for variable substitution, it is recommended
* to stick to one entry per map, and rather declare more maps within the list. The reason is that
* if a map in the list contains more than one key-value entry, and the entries are conflicting, the
* conflict resolution behavior is undefined (since map entries have no sequence).
*
* Note: variables defined via `manifestVariables` always win over conflicting variables defined via any file given
* by `manifestVariablesFiles` - no matter what is declared before. This reproduces the same behavior as can be
* observed when using `cf push --var` in combination with `cf push --vars-file`.
*/
'manifestVariables'
]
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS
2019-11-11 11:06:40 +02:00
/**
Variable Substitution in YAML Files (#852) * Changes: - New YamlSubstituteVariables step to substitute variables in YAML files with values from another YAML - New Tests, that check the different substitution patterns. - Added test resources, including various manifest and variables files. - Improved usage of JenkinsLoggingRule - Improved JenkinsReadYamlRule to properly reflect the mocked library's behaviour. - Added a new JenkinsWriteYamlRule. * Changes: - added a Logger that checks a config.verbose flag before it logs debug messages. - changed error handling to rethrow Yaml parsing exception in case of wrongly-formatted Yaml files. - changed JenkinsWriteYamlRule to capture Yaml file details of every invocation of writeYaml. This allows sanity checks at end of tests, even if there were multiple invocations. - adjusted tests. * Changes: - Removed javadoc-code blocks from API documentation since they are not supported. - Removed skipDeletion boolean. - Added a new deleteFile script which deletes a file if present. - Added a new JenkinsDeleteFileRule to mock deleteFile script and optionally skip deletion for tests. - Adjusted yamlSubstituteVariables script. - Adjusted tests to include new JenkinsDeleteFileRule. - Changed code that deletes an already existing output file to produce better logs. * Changes: - Turned yamlSubstituteVariables into a script that works purely based on Yaml data (not files). - Added a new cfManifestSubstituteVariables that uses yamlSubstituteVariables under the hood but works based on files. - Adjusted tests, and added new ones. * Adjusted documentation and a few log statements. * Changed documentation to no longer include javadoc code statements. * Made mocking of deletion of a file a default. Adjusted tests. * Changed signature of yamlSubstituteVariables' call method to return void. * Changes: - Fixed naming issues in deleteFile. - Renamed Logger to DebugHelper. - Fixed some documentation. * Changed implementation of deleteFile not to use java.io.File - which is evil when using it for file operations. * PROPERLY Changed implementation of deleteFile not to use java.io.File - which is evil when using it for file operations. * Changes: - Added tests for deleteFile script - Changed JenkinsFileExistsRule to also keep track of which files have been queried for existence. * Changes: - Removed java.io.File usage from cfManifestSubstituteVariables and using fileExists instead now. - Adjusted tests. * Wrapped file path inside ticks to allow spaces in file path when calling deleteFile. * Removed null checks of mandatory parameters, and resorted to ConfigurationHelper.withMandatoryProperty * Fixed a NullPointer due to weird Jenkins / Groovy behaviour. * Changes: - Turned yamlSubstituteVariables step into a utils class. - Added tests - Adjusted cfManifestSubstituteVariables to use utils class instead of step. - Adjusted tests - Adjusted APIs of DebugHelper. * Re-introduced log statement that shows what variables are being replaced and with what. * Changing API of YamlUtils to take the script and config as input. * Test * Test * Test * Test * Test * Fixing issue. * Fixing issue. * Changes: - Refactored DebugHelper and YamlUtils to make usage nicer and rely on dependency injection. - Removed Field for DebugHelper and turned it into local variable. - Adjusted classes using the above. - Adjusted tests where necessary. * Added link to CF standards to YamlUtils also. * Add docu for step cfManifestSubstituteVariables.md * Added documentation. * Added missing script parameter to documentation. Some steps document it, some don't. Right now you need it, so we document it. * Fixed some layouting and typos * Beautified exception listing. * Removed trailing whitespaces to make code climate checks pass. * Trying to get documentation generated, with all the exceptions to markup one should not use. * cosmetics. * cosmetics, part 2 * Code climate changes... * Inlined deleteFile step. * Added two more tests to properly check file deletion and output handling. * Changes: - adjusted API to take a list of variables files, as does 'cf push --vars-file' - adjusted API to allow for an optional list of variable key-value-maps as does 'cf push --vars' - reproduced conflict resolution and overriding behavior of variables files and vars lists - adjusted tests and documentation * Added missing paramter to doc comment. * Re-checked docs for missing paramters or params that have no counterpart in the method signature. * Adjusted documentation. * Removed absolute path usage from documentation. * corrected documentation. * Changed javadoc comment to plain comment. * Turned all comments to plain comments.
2019-09-06 10:20:35 +02:00
* Step to substitute variables in a given YAML file with those specified in one or more variables files given by the
* `manifestVariablesFiles` parameter. This follows the behavior of `cf push --vars-file`, and can be
* used as a pre-deployment step if commands other than `cf push` are used for deployment (e.g. `cf blue-green-deploy`).
*
* The format to reference a variable in the manifest YAML file is to use double parentheses `((` and `))`, e.g. `((variableName))`.
*
* You can declare variable assignments as key value-pairs inside a YAML variables file following the
* [Cloud Foundry standards](https://docs.cloudfoundry.org/devguide/deploy-apps/manifest-attributes.html#variable-substitution) format.
*
* Optionally, you can also specify a direct list of key-value mappings for variables using the `manifestVariables` parameter.
* Variables given in the `manifestVariables` list will take precedence over those found in variables files. This follows
* the behavior of `cf push --var`, and works in combination with `manifestVariablesFiles`.
*
* The step is activated by the presence of the file specified by the `manifestFile` parameter and all variables files
* specified by the `manifestVariablesFiles` parameter, or if variables are passed in directly via `manifestVariables`.
*
* In case no `manifestVariablesFiles` were explicitly specified, a default named `manifest-variables.yml` will be looked
* for and if present will activate this step also. This is to support convention over configuration.
*/
@GenerateDocumentation
void call(Map arguments = [:]) {
handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: arguments) {
def script = checkScript(this, arguments) ?: this
String stageName = arguments.stageName ?: env.STAGE_NAME
Variable Substitution in YAML Files (#852) * Changes: - New YamlSubstituteVariables step to substitute variables in YAML files with values from another YAML - New Tests, that check the different substitution patterns. - Added test resources, including various manifest and variables files. - Improved usage of JenkinsLoggingRule - Improved JenkinsReadYamlRule to properly reflect the mocked library's behaviour. - Added a new JenkinsWriteYamlRule. * Changes: - added a Logger that checks a config.verbose flag before it logs debug messages. - changed error handling to rethrow Yaml parsing exception in case of wrongly-formatted Yaml files. - changed JenkinsWriteYamlRule to capture Yaml file details of every invocation of writeYaml. This allows sanity checks at end of tests, even if there were multiple invocations. - adjusted tests. * Changes: - Removed javadoc-code blocks from API documentation since they are not supported. - Removed skipDeletion boolean. - Added a new deleteFile script which deletes a file if present. - Added a new JenkinsDeleteFileRule to mock deleteFile script and optionally skip deletion for tests. - Adjusted yamlSubstituteVariables script. - Adjusted tests to include new JenkinsDeleteFileRule. - Changed code that deletes an already existing output file to produce better logs. * Changes: - Turned yamlSubstituteVariables into a script that works purely based on Yaml data (not files). - Added a new cfManifestSubstituteVariables that uses yamlSubstituteVariables under the hood but works based on files. - Adjusted tests, and added new ones. * Adjusted documentation and a few log statements. * Changed documentation to no longer include javadoc code statements. * Made mocking of deletion of a file a default. Adjusted tests. * Changed signature of yamlSubstituteVariables' call method to return void. * Changes: - Fixed naming issues in deleteFile. - Renamed Logger to DebugHelper. - Fixed some documentation. * Changed implementation of deleteFile not to use java.io.File - which is evil when using it for file operations. * PROPERLY Changed implementation of deleteFile not to use java.io.File - which is evil when using it for file operations. * Changes: - Added tests for deleteFile script - Changed JenkinsFileExistsRule to also keep track of which files have been queried for existence. * Changes: - Removed java.io.File usage from cfManifestSubstituteVariables and using fileExists instead now. - Adjusted tests. * Wrapped file path inside ticks to allow spaces in file path when calling deleteFile. * Removed null checks of mandatory parameters, and resorted to ConfigurationHelper.withMandatoryProperty * Fixed a NullPointer due to weird Jenkins / Groovy behaviour. * Changes: - Turned yamlSubstituteVariables step into a utils class. - Added tests - Adjusted cfManifestSubstituteVariables to use utils class instead of step. - Adjusted tests - Adjusted APIs of DebugHelper. * Re-introduced log statement that shows what variables are being replaced and with what. * Changing API of YamlUtils to take the script and config as input. * Test * Test * Test * Test * Test * Fixing issue. * Fixing issue. * Changes: - Refactored DebugHelper and YamlUtils to make usage nicer and rely on dependency injection. - Removed Field for DebugHelper and turned it into local variable. - Adjusted classes using the above. - Adjusted tests where necessary. * Added link to CF standards to YamlUtils also. * Add docu for step cfManifestSubstituteVariables.md * Added documentation. * Added missing script parameter to documentation. Some steps document it, some don't. Right now you need it, so we document it. * Fixed some layouting and typos * Beautified exception listing. * Removed trailing whitespaces to make code climate checks pass. * Trying to get documentation generated, with all the exceptions to markup one should not use. * cosmetics. * cosmetics, part 2 * Code climate changes... * Inlined deleteFile step. * Added two more tests to properly check file deletion and output handling. * Changes: - adjusted API to take a list of variables files, as does 'cf push --vars-file' - adjusted API to allow for an optional list of variable key-value-maps as does 'cf push --vars' - reproduced conflict resolution and overriding behavior of variables files and vars lists - adjusted tests and documentation * Added missing paramter to doc comment. * Re-checked docs for missing paramters or params that have no counterpart in the method signature. * Adjusted documentation. * Removed absolute path usage from documentation. * corrected documentation. * Changed javadoc comment to plain comment. * Turned all comments to plain comments.
2019-09-06 10:20:35 +02:00
// load default & individual configuration
Map config = ConfigurationHelper.newInstance(this)
.loadStepDefaults([:], stageName)
.mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
.mixinStageConfig(script.commonPipelineEnvironment, stageName, STEP_CONFIG_KEYS)
.mixin(arguments, PARAMETER_KEYS)
.use()
Variable Substitution in YAML Files (#852) * Changes: - New YamlSubstituteVariables step to substitute variables in YAML files with values from another YAML - New Tests, that check the different substitution patterns. - Added test resources, including various manifest and variables files. - Improved usage of JenkinsLoggingRule - Improved JenkinsReadYamlRule to properly reflect the mocked library's behaviour. - Added a new JenkinsWriteYamlRule. * Changes: - added a Logger that checks a config.verbose flag before it logs debug messages. - changed error handling to rethrow Yaml parsing exception in case of wrongly-formatted Yaml files. - changed JenkinsWriteYamlRule to capture Yaml file details of every invocation of writeYaml. This allows sanity checks at end of tests, even if there were multiple invocations. - adjusted tests. * Changes: - Removed javadoc-code blocks from API documentation since they are not supported. - Removed skipDeletion boolean. - Added a new deleteFile script which deletes a file if present. - Added a new JenkinsDeleteFileRule to mock deleteFile script and optionally skip deletion for tests. - Adjusted yamlSubstituteVariables script. - Adjusted tests to include new JenkinsDeleteFileRule. - Changed code that deletes an already existing output file to produce better logs. * Changes: - Turned yamlSubstituteVariables into a script that works purely based on Yaml data (not files). - Added a new cfManifestSubstituteVariables that uses yamlSubstituteVariables under the hood but works based on files. - Adjusted tests, and added new ones. * Adjusted documentation and a few log statements. * Changed documentation to no longer include javadoc code statements. * Made mocking of deletion of a file a default. Adjusted tests. * Changed signature of yamlSubstituteVariables' call method to return void. * Changes: - Fixed naming issues in deleteFile. - Renamed Logger to DebugHelper. - Fixed some documentation. * Changed implementation of deleteFile not to use java.io.File - which is evil when using it for file operations. * PROPERLY Changed implementation of deleteFile not to use java.io.File - which is evil when using it for file operations. * Changes: - Added tests for deleteFile script - Changed JenkinsFileExistsRule to also keep track of which files have been queried for existence. * Changes: - Removed java.io.File usage from cfManifestSubstituteVariables and using fileExists instead now. - Adjusted tests. * Wrapped file path inside ticks to allow spaces in file path when calling deleteFile. * Removed null checks of mandatory parameters, and resorted to ConfigurationHelper.withMandatoryProperty * Fixed a NullPointer due to weird Jenkins / Groovy behaviour. * Changes: - Turned yamlSubstituteVariables step into a utils class. - Added tests - Adjusted cfManifestSubstituteVariables to use utils class instead of step. - Adjusted tests - Adjusted APIs of DebugHelper. * Re-introduced log statement that shows what variables are being replaced and with what. * Changing API of YamlUtils to take the script and config as input. * Test * Test * Test * Test * Test * Fixing issue. * Fixing issue. * Changes: - Refactored DebugHelper and YamlUtils to make usage nicer and rely on dependency injection. - Removed Field for DebugHelper and turned it into local variable. - Adjusted classes using the above. - Adjusted tests where necessary. * Added link to CF standards to YamlUtils also. * Add docu for step cfManifestSubstituteVariables.md * Added documentation. * Added missing script parameter to documentation. Some steps document it, some don't. Right now you need it, so we document it. * Fixed some layouting and typos * Beautified exception listing. * Removed trailing whitespaces to make code climate checks pass. * Trying to get documentation generated, with all the exceptions to markup one should not use. * cosmetics. * cosmetics, part 2 * Code climate changes... * Inlined deleteFile step. * Added two more tests to properly check file deletion and output handling. * Changes: - adjusted API to take a list of variables files, as does 'cf push --vars-file' - adjusted API to allow for an optional list of variable key-value-maps as does 'cf push --vars' - reproduced conflict resolution and overriding behavior of variables files and vars lists - adjusted tests and documentation * Added missing paramter to doc comment. * Re-checked docs for missing paramters or params that have no counterpart in the method signature. * Adjusted documentation. * Removed absolute path usage from documentation. * corrected documentation. * Changed javadoc comment to plain comment. * Turned all comments to plain comments.
2019-09-06 10:20:35 +02:00
String defaultManifestFileName = "manifest.yml"
String defaultManifestVariablesFileName = "manifest-variables.yml"
Boolean manifestVariablesFilesExplicitlySpecified = config.manifestVariablesFiles != null
String manifestFilePath = config.manifestFile ?: defaultManifestFileName
List<String> manifestVariablesFiles = (config.manifestVariablesFiles != null) ? config.manifestVariablesFiles : [ defaultManifestVariablesFileName ]
List<Map<String, Object>> manifestVariablesList = config.manifestVariables ?: []
String outputFilePath = config.outputManifestFile ?: manifestFilePath
DebugHelper debugHelper = new DebugHelper(script, config)
YamlUtils yamlUtils = new YamlUtils(script, debugHelper)
Boolean manifestExists = fileExists manifestFilePath
Boolean manifestVariablesFilesExist = allManifestVariableFilesExist(manifestVariablesFiles)
Boolean manifestVariablesListSpecified = !manifestVariablesList.isEmpty()
if (!manifestExists) {
echo "[CFManifestSubstituteVariables] Could not find YAML file at ${manifestFilePath}. Skipping variable substitution."
return
}
if (!manifestVariablesFilesExist && manifestVariablesFilesExplicitlySpecified) {
// If the user explicitly specified a list of variables files, make sure they all exist.
// Otherwise throw an error so the user knows that he / she made a mistake.
error "[CFManifestSubstituteVariables] Could not find all given manifest variable substitution files. Make sure all files given as manifestVariablesFiles exist."
}
def result
ExecutionContext context = new ExecutionContext()
if (!manifestVariablesFilesExist && !manifestVariablesFilesExplicitlySpecified) {
// If no variables files exist (not even the default one) we check if at least we have a list of variables.
if (!manifestVariablesListSpecified) {
// If we have no variable values to replace references with, we skip substitution.
echo "[CFManifestSubstituteVariables] Could not find any default manifest variable substitution file at ${defaultManifestVariablesFileName}, and no manifest variables list was specified. Skipping variable substitution."
return
}
// If we have a list of variables specified, we can start replacing them...
result = substitute(manifestFilePath, [], manifestVariablesList, yamlUtils, context, debugHelper)
}
else {
// If we have at least one existing variable substitution file, we can start replacing variables...
result = substitute(manifestFilePath, manifestVariablesFiles, manifestVariablesList, yamlUtils, context, debugHelper)
}
if (!context.variablesReplaced) {
// If no variables have been replaced at all, we skip writing a file.
echo "[CFManifestSubstituteVariables] No variables were found or could be replaced in ${manifestFilePath}. Skipping variable substitution."
return
}
// writeYaml won't overwrite the file. You need to delete it first.
deleteFile(outputFilePath)
writeYaml file: outputFilePath, data: result
echo "[CFManifestSubstituteVariables] Replaced variables in ${manifestFilePath}."
echo "[CFManifestSubstituteVariables] Wrote output file (with variables replaced) at ${outputFilePath}."
}
}
/*
* Substitutes variables specified in files and as lists in a given manifest file.
* @param manifestFilePath - the path to the manifest file to replace variables in.
* @param manifestVariablesFiles - the paths to variables substitution files.
* @param manifestVariablesList - the list of variables data to replace variables with.
* @param yamlUtils - the `YamlUtils` used for variable substitution.
* @param context - an `ExecutionContext` to examine if any variables have been replaced and should be written.
* @param debugHelper - a debug output helper.
* @return an Object graph of Yaml data with variables substituted (if any were found and could be replaced).
*/
private Object substitute(String manifestFilePath, List<String> manifestVariablesFiles, List<Map<String, Object>> manifestVariablesList, YamlUtils yamlUtils, ExecutionContext context, DebugHelper debugHelper) {
Boolean noVariablesReplaced = true
def manifestData = loadManifestData(manifestFilePath, debugHelper)
// replace variables from list first.
2019-11-04 14:46:30 +02:00
List<Map<String,Object>> reversedManifestVariablesList = manifestVariablesList.reverse() // to make sure last one wins.
Variable Substitution in YAML Files (#852) * Changes: - New YamlSubstituteVariables step to substitute variables in YAML files with values from another YAML - New Tests, that check the different substitution patterns. - Added test resources, including various manifest and variables files. - Improved usage of JenkinsLoggingRule - Improved JenkinsReadYamlRule to properly reflect the mocked library's behaviour. - Added a new JenkinsWriteYamlRule. * Changes: - added a Logger that checks a config.verbose flag before it logs debug messages. - changed error handling to rethrow Yaml parsing exception in case of wrongly-formatted Yaml files. - changed JenkinsWriteYamlRule to capture Yaml file details of every invocation of writeYaml. This allows sanity checks at end of tests, even if there were multiple invocations. - adjusted tests. * Changes: - Removed javadoc-code blocks from API documentation since they are not supported. - Removed skipDeletion boolean. - Added a new deleteFile script which deletes a file if present. - Added a new JenkinsDeleteFileRule to mock deleteFile script and optionally skip deletion for tests. - Adjusted yamlSubstituteVariables script. - Adjusted tests to include new JenkinsDeleteFileRule. - Changed code that deletes an already existing output file to produce better logs. * Changes: - Turned yamlSubstituteVariables into a script that works purely based on Yaml data (not files). - Added a new cfManifestSubstituteVariables that uses yamlSubstituteVariables under the hood but works based on files. - Adjusted tests, and added new ones. * Adjusted documentation and a few log statements. * Changed documentation to no longer include javadoc code statements. * Made mocking of deletion of a file a default. Adjusted tests. * Changed signature of yamlSubstituteVariables' call method to return void. * Changes: - Fixed naming issues in deleteFile. - Renamed Logger to DebugHelper. - Fixed some documentation. * Changed implementation of deleteFile not to use java.io.File - which is evil when using it for file operations. * PROPERLY Changed implementation of deleteFile not to use java.io.File - which is evil when using it for file operations. * Changes: - Added tests for deleteFile script - Changed JenkinsFileExistsRule to also keep track of which files have been queried for existence. * Changes: - Removed java.io.File usage from cfManifestSubstituteVariables and using fileExists instead now. - Adjusted tests. * Wrapped file path inside ticks to allow spaces in file path when calling deleteFile. * Removed null checks of mandatory parameters, and resorted to ConfigurationHelper.withMandatoryProperty * Fixed a NullPointer due to weird Jenkins / Groovy behaviour. * Changes: - Turned yamlSubstituteVariables step into a utils class. - Added tests - Adjusted cfManifestSubstituteVariables to use utils class instead of step. - Adjusted tests - Adjusted APIs of DebugHelper. * Re-introduced log statement that shows what variables are being replaced and with what. * Changing API of YamlUtils to take the script and config as input. * Test * Test * Test * Test * Test * Fixing issue. * Fixing issue. * Changes: - Refactored DebugHelper and YamlUtils to make usage nicer and rely on dependency injection. - Removed Field for DebugHelper and turned it into local variable. - Adjusted classes using the above. - Adjusted tests where necessary. * Added link to CF standards to YamlUtils also. * Add docu for step cfManifestSubstituteVariables.md * Added documentation. * Added missing script parameter to documentation. Some steps document it, some don't. Right now you need it, so we document it. * Fixed some layouting and typos * Beautified exception listing. * Removed trailing whitespaces to make code climate checks pass. * Trying to get documentation generated, with all the exceptions to markup one should not use. * cosmetics. * cosmetics, part 2 * Code climate changes... * Inlined deleteFile step. * Added two more tests to properly check file deletion and output handling. * Changes: - adjusted API to take a list of variables files, as does 'cf push --vars-file' - adjusted API to allow for an optional list of variable key-value-maps as does 'cf push --vars' - reproduced conflict resolution and overriding behavior of variables files and vars lists - adjusted tests and documentation * Added missing paramter to doc comment. * Re-checked docs for missing paramters or params that have no counterpart in the method signature. * Adjusted documentation. * Removed absolute path usage from documentation. * corrected documentation. * Changed javadoc comment to plain comment. * Turned all comments to plain comments.
2019-09-06 10:20:35 +02:00
def result = manifestData
for (Map<String, Object> manifestVariableData : reversedManifestVariablesList) {
def executionContext = new ExecutionContext()
result = yamlUtils.substituteVariables(result, manifestVariableData, executionContext)
noVariablesReplaced = noVariablesReplaced && !executionContext.variablesReplaced // remember if variables were replaced.
}
// replace remaining variables from files
List<String> reversedManifestVariablesFilesList = manifestVariablesFiles.reverse() // to make sure last one wins.
for (String manifestVariablesFilePath : reversedManifestVariablesFilesList) {
def manifestVariablesFileData = loadManifestVariableFileData(manifestVariablesFilePath, debugHelper)
def executionContext = new ExecutionContext()
result = yamlUtils.substituteVariables(result, manifestVariablesFileData, executionContext)
noVariablesReplaced = noVariablesReplaced && !executionContext.variablesReplaced // remember if variables were replaced.
}
context.variablesReplaced = !noVariablesReplaced
return result
}
/*
* Loads the contents of a manifest.yml file by parsing Yaml and returning the
* object graph. May return a `List<Object>` (in case more YAML segments are in the file)
* or a `Map<String, Object>` in case there is just one segment.
* @param manifestFilePath - the file path of the manifest to parse.
* @param debugHelper - a debug output helper.
* @return the parsed object graph.
*/
private Object loadManifestData(String manifestFilePath, DebugHelper debugHelper) {
try {
// may return a List<Object> (in case more YAML segments are in the file)
// or a Map<String, Object> in case there is just one segment.
def result = readYaml file: manifestFilePath
echo "[CFManifestSubstituteVariables] Loaded manifest at ${manifestFilePath}!"
return result
}
catch(Exception ex) {
debugHelper.debug("Exception: ${ex}")
echo "[CFManifestSubstituteVariables] Could not load manifest file at ${manifestFilePath}. Exception was: ${ex}"
throw ex
}
}
/*
* Loads the contents of a manifest variables file by parsing Yaml and returning the
* object graph. May return a `List<Object>` (in case more YAML segments are in the file)
* or a `Map<String, Object>` in case there is just one segment.
* @param variablesFilePath - the path to the variables file to parse.
* @param debugHelper - a debug output helper.
* @return the parsed object graph.
*/
private Object loadManifestVariableFileData(String variablesFilePath, DebugHelper debugHelper) {
try {
// may return a List<Object> (in case more YAML segments are in the file)
// or a Map<String, Object> in case there is just one segment.
def result = readYaml file: variablesFilePath
echo "[CFManifestSubstituteVariables] Loaded variables file at ${variablesFilePath}!"
return result
}
catch(Exception ex) {
debugHelper.debug("Exception: ${ex}")
echo "[CFManifestSubstituteVariables] Could not load manifest variables file at ${variablesFilePath}. Exception was: ${ex}"
throw ex
}
}
/*
* Checks if all file paths given in the list exist as files.
* @param manifestVariablesFiles - the list of file paths pointing to manifest variables files.
* @return `true`, if all given files exist, `false` otherwise.
*/
private boolean allManifestVariableFilesExist(List<String> manifestVariablesFiles) {
for (String filePath : manifestVariablesFiles) {
Boolean fileExists = fileExists filePath
if (!fileExists) {
echo "[CFManifestSubstituteVariables] Did not find manifest variable substitution file at ${filePath}."
return false
}
}
return true
}
/*
* Removes the given file, if it exists.
* @param filePath - the path to the file to remove.
*/
private void deleteFile(String filePath) {
Boolean fileExists = fileExists file: filePath
if(fileExists) {
Boolean failure = sh script: "rm '${filePath}'", returnStatus: true
if(!failure) {
echo "[CFManifestSubstituteVariables] Successfully deleted file '${filePath}'."
}
else {
error "[CFManifestSubstituteVariables] Could not delete file '${filePath}'. Check file permissions."
}
}
}