diff --git a/docs/cli-configuration.md b/docs/cli-configuration.md index d96d298d..597776a1 100644 --- a/docs/cli-configuration.md +++ b/docs/cli-configuration.md @@ -14,26 +14,27 @@ ## update-db ### Options -|Names|Default value|Needs argument|Possible arguments|Description|Examples| -|---|---|---|---|---|---| -|--path|./scripts/|✔|TEXT|path to directory containing scripts|```src/main/resources/scripts/```| -|--identifier-regex|(.*)|✔|TEXT|regex to extract identifier part from scripts|```v(.*)_.*```| -|--whitelisted-tags|No default value|✔|TEXT|tags to whitelist (separated by ',')|```WHITELISTED_TAG1,WHITELISTED_TAG2```| -|--blacklisted-tags|No default value|✔|TEXT|tags to blacklist (separated by ',')|```BLACKLISTED_TAG1,BLACKLISTED_TAG2```| -|--tags-to-play-again|No default value|✔|TEXT|tags to play again at each datamaintain execution (separated by ',')|```TAG_TO_PLAY_AGAIN1,TAG_TO_PLAY_AGAIN2```| -|--create-tags-from-folder|false|✘|N/A|create automatically tags from parent folders|| -|--execution-mode|NORMAL|✔|```NORMAL``` or ```DRY```|execution mode|| -|--action|RUN|✔|```RUN``` or ```MARK_AS_EXECUTED``` or ```OVERRIDE_EXECUTED```|script action|| -|--allow-auto-override|false|✘|N/A|Allow datamaintain to automaticaly override scripts|| -|--verbose|false|✘|N/A|verbose|| -|--save-db-output|false|✘|N/A|save your script and db output|| -|--print-db-output|false|✘|N/A|print your script and db output|| -|--tag|No default value|✔| |Tag defined using glob path matchers. To define multiple tags, use option multiple times. Syntax example: MYTAG1=[pathMatcher1, pathMatcher2]|```MYTAG1=[pathMatcher1, pathMatcher2]```| -|--rule|No default value|✔|```SameScriptsAsExecutedCheck```|check rule to play. To define multiple rules, use option multiple times.|| -|--mongo-shell|mongo|✔|```mongo``` or ```mongosh```|mongo binary, can be mongo or mongosh. mongo by default|| -|--porcelain|false|✘|N/A|for each executed script, display relative path to scan path|| -|--flags|No default value|✔|TEXT|add a flag on the executed scripts. To define multiple rules, use option multiple times.|| -|-h, --help|No default value|✘|N/A|Display command help and exit|| +| Names |Default value|Needs argument|Possible arguments| Description |Examples| +|---------------------------|---|---|---|-----------------------------------------------------------------------------------------------------------------------------------------------|---| +| --path |./scripts/|✔|TEXT| path to directory containing scripts |```src/main/resources/scripts/```| +| --identifier-regex |(.*)|✔|TEXT| regex to extract identifier part from scripts |```v(.*)_.*```| +| --whitelisted-tags |No default value|✔|TEXT| tags to whitelist (separated by ',') |```WHITELISTED_TAG1,WHITELISTED_TAG2```| +| --blacklisted-tags |No default value|✔|TEXT| tags to blacklist (separated by ',') |```BLACKLISTED_TAG1,BLACKLISTED_TAG2```| +| --tags-to-play-again |No default value|✔|TEXT| tags to play again at each datamaintain execution (separated by ',') |```TAG_TO_PLAY_AGAIN1,TAG_TO_PLAY_AGAIN2```| +| --create-tags-from-folder |false|✘|N/A| create automatically tags from parent folders || +| --execution-mode |NORMAL|✔|```NORMAL``` or ```DRY```| execution mode || +| --action |RUN|✔|```RUN``` or ```MARK_AS_EXECUTED``` or ```OVERRIDE_EXECUTED```| script action || +| --allow-auto-override |false|✘|N/A| Allow datamaintain to automaticaly override scripts || +| --verbose |false|✘|N/A| verbose || +| -vv |false|✘|N/A| verbose level 2 || +| --save-db-output |false|✘|N/A| save your script and db output || +| --print-db-output |false|✘|N/A| print your script and db output || +| --tag |No default value|✔| | Tag defined using glob path matchers. To define multiple tags, use option multiple times. Syntax example: MYTAG1=[pathMatcher1, pathMatcher2] |```MYTAG1=[pathMatcher1, pathMatcher2]```| +| --rule |No default value|✔|```SameScriptsAsExecutedCheck```| check rule to play. To define multiple rules, use option multiple times. || +| --mongo-shell |mongo|✔|```mongo``` or ```mongosh```| mongo binary, can be mongo or mongosh. mongo by default || +| --porcelain |false|✘|N/A| for each executed script, display relative path to scan path || +| --flags |No default value|✔|TEXT| add a flag on the executed scripts. To define multiple rules, use option multiple times. || +| -h, --help |No default value|✘|N/A| Display command help and exit || ## list ### Options diff --git a/docs/configuration.md b/docs/configuration.md index db58413b..41158b79 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -2,24 +2,25 @@ ## Core configuration -| Key | Description | Default value | Mandatory? | Values examples | -|---|---|---|---|---| -| name | Allow to name your config. For now will only be used to logging purpose | None | no | | -| working.directory.path | Indicates the directory to use to find relative paths | Java default working directory path | no | | -| parent.config.path | Path to an other configuration file to inherit properties. Can be absolute or relative to `working.directory.path` | None | no | | -| default.script.action | The default script action | ```RUN``` | no | ```RUN``` or ```MARK_AS_EXECUTED``` | -| scan.path | Path to the folder containing all your scripts. Can be absolute or relative to `working.directory.path` | ```./scripts/``` | yes | | -| scan.identifier.regex | Regex that will be used to determine an identifier for each file. It has to contain a capturing group. Identifiers are then used to sort the scripts before running them. | ```(.*)``` (with this regex, the script's whole name will be its identifier) | no | With the regex ```(.*?)_.*```, a script named ```1.23_my-script.js``` will have ```1.23``` as its identifier | -| scan.tags.createFromFolder | If true, scripts will have their parent folders names as tags. Relative path to ```scan.path``` is used. | ```false``` | no | ```false``` or ```true``` | -| tag.*your_tag* | Glob paths to your scripts that you want to apply the tag "your_tag" on. To declare multiple tags, you will have to add multiple properties in your settings. A tag ```my_tag``` will have as as property name ```tag.my_tag``` **WARNING:** ALWAYS declare your tags using absolute paths. Relative paths and even using a tilde (~) won't do the trick. | | no | ```[data/*, script1.js, old/old_script1.js]``` | -| filter.tags.whitelisted | Scripts that have these tags will be considered | None | no | ```DATA,tag``` | -| filter.tags.blacklisted | Scripts that have these tags will be ignored. A script having a whitelisted tag and a blacklisted tag will be ignored | None | no | ```DATA,tag``` | -| prune.tags.to.run.again | Scripts that have these tags will be run, even they were already executed | None | no | ```tag,again``` | -| execution.mode | Execution mode. Possible values:
- ```NORMAL```: Regular execution: your scripts will be run on your database.
- ```DRY```: Scripts will not be executed. A full report of what would happen is you ran Datamaintain normally will be logged.
| ```NORMAL``` | no | ```NORMAL```, ```DRY``` | -| verbose | If true, more logs will be printed. **WARNING:** Can't be used alongside with porcelain. If both are set, porcelain will prevail | ```false``` | no | ```true``` or ```false``` | -| prune.scripts.override.executed | Allow datamaintain to override a script if it detect a checksum change on a script already runned (assuming its filename) | ```false``` | no | ```true``` or ```false``` | -| db.trust.uri | Bypass all checks that could be done on your URI because you are very sure of it and think our checks are just liars | ```false``` | no | ```true``` or ```false``` | -| porcelain | For each executed script, print path relative to scan path **WARNING:** Can't be used alongside with verbose. If both are set, porcelain will prevail | ```false``` | no | ```true``` or ```false``` | +| Key | Description | Default value | Mandatory? | Values examples | +|---------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---|---|---| +| name | Allow to name your config. For now will only be used to logging purpose | None | no | | +| working.directory.path | Indicates the directory to use to find relative paths | Java default working directory path | no | | +| parent.config.path | Path to an other configuration file to inherit properties. Can be absolute or relative to `working.directory.path` | None | no | | +| default.script.action | The default script action | ```RUN``` | no | ```RUN``` or ```MARK_AS_EXECUTED``` | +| scan.path | Path to the folder containing all your scripts. Can be absolute or relative to `working.directory.path` | ```./scripts/``` | yes | | +| scan.identifier.regex | Regex that will be used to determine an identifier for each file. It has to contain a capturing group. Identifiers are then used to sort the scripts before running them. | ```(.*)``` (with this regex, the script's whole name will be its identifier) | no | With the regex ```(.*?)_.*```, a script named ```1.23_my-script.js``` will have ```1.23``` as its identifier | +| scan.tags.createFromFolder | If true, scripts will have their parent folders names as tags. Relative path to ```scan.path``` is used. | ```false``` | no | ```false``` or ```true``` | +| tag.*your_tag* | Glob paths to your scripts that you want to apply the tag "your_tag" on. To declare multiple tags, you will have to add multiple properties in your settings. A tag ```my_tag``` will have as as property name ```tag.my_tag``` **WARNING:** ALWAYS declare your tags using absolute paths. Relative paths and even using a tilde (~) won't do the trick. | | no | ```[data/*, script1.js, old/old_script1.js]``` | +| filter.tags.whitelisted | Scripts that have these tags will be considered | None | no | ```DATA,tag``` | +| filter.tags.blacklisted | Scripts that have these tags will be ignored. A script having a whitelisted tag and a blacklisted tag will be ignored | None | no | ```DATA,tag``` | +| prune.tags.to.run.again | Scripts that have these tags will be run, even they were already executed | None | no | ```tag,again``` | +| execution.mode | Execution mode. Possible values:
- ```NORMAL```: Regular execution: your scripts will be run on your database.
- ```DRY```: Scripts will not be executed. A full report of what would happen is you ran Datamaintain normally will be logged.
| ```NORMAL``` | no | ```NORMAL```, ```DRY``` | +| verbose | If true, more logs will be printed. **WARNING:** Can't be used alongside with porcelain. If both are set, porcelain will prevail | ```false``` | no | ```true``` or ```false``` | +| trace | If true, more logs will be printed than verbose. **WARNING:** Can't be used alongside with porcelain. If both are set, porcelain will prevail | ```false``` | no | ```true``` or ```false``` | +| prune.scripts.override.executed | Allow datamaintain to override a script if it detect a checksum change on a script already runned (assuming its filename) | ```false``` | no | ```true``` or ```false``` | +| db.trust.uri | Bypass all checks that could be done on your URI because you are very sure of it and think our checks are just liars | ```false``` | no | ```true``` or ```false``` | +| porcelain | For each executed script, print path relative to scan path **WARNING:** Can't be used alongside with verbose. If both are set, porcelain will prevail | ```false``` | no | ```true``` or ```false``` | ### Common driver configuration diff --git a/modules/cli/src/main/kotlin/datamaintain/cli/app/DatamaintainCliCommand.kt b/modules/cli/src/main/kotlin/datamaintain/cli/app/DatamaintainCliCommand.kt index a811b9cd..e18f84a8 100644 --- a/modules/cli/src/main/kotlin/datamaintain/cli/app/DatamaintainCliCommand.kt +++ b/modules/cli/src/main/kotlin/datamaintain/cli/app/DatamaintainCliCommand.kt @@ -2,8 +2,7 @@ package datamaintain.cli.app import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.findObject -import datamaintain.cli.app.utils.CliSpecificKey -import datamaintain.cli.app.utils.loadConfig +import datamaintain.cli.app.utils.* import datamaintain.core.config.DatamaintainConfig import datamaintain.core.exception.DatamaintainBaseException import java.util.* @@ -17,10 +16,24 @@ abstract class DatamaintainCliCommand(name: String, help: String = "") : CliktCo overloadProps(props) val config = loadConfig(props) - if (props.getProperty(CliSpecificKey.__PRINT_CONFIG_ONLY.key, CliSpecificKey.__PRINT_CONFIG_ONLY.default)!!.toBoolean()) { + val isPrintConfigOnly = props.getBooleanCliProperty(CliSpecificKey.__PRINT_CONFIG_ONLY) + if (isPrintConfigOnly) { + // config log nothing in INFO level so apply DEBUG level + applyLoggerLevel(CliDatamaintainLoggerLevel.VERBOSE) config.log() } else { - executeCommand(config) + val level = if (props.getBooleanCliProperty(CliSpecificKey.TRACE)) { + CliDatamaintainLoggerLevel.TRACE + } else if (props.getBooleanCliProperty(CliSpecificKey.VERBOSE)) { + CliDatamaintainLoggerLevel.VERBOSE + } else if (props.getBooleanCliProperty(CliSpecificKey.PORCELAIN)) { + CliDatamaintainLoggerLevel.PORCELAIN + } else { + CliDatamaintainLoggerLevel.INFO + } + applyLoggerLevel(level) + + executeCommand(config, level == CliDatamaintainLoggerLevel.PORCELAIN) } } catch (e: DatamaintainBaseException) { echo(e.message, err = true) @@ -37,5 +50,5 @@ abstract class DatamaintainCliCommand(name: String, help: String = "") : CliktCo protected abstract fun overloadProps(props: Properties) - protected abstract fun executeCommand(config: DatamaintainConfig) + protected abstract fun executeCommand(config: DatamaintainConfig, porcelain: Boolean) } diff --git a/modules/cli/src/main/kotlin/datamaintain/cli/app/ListExecutedScripts.kt b/modules/cli/src/main/kotlin/datamaintain/cli/app/ListExecutedScripts.kt index 4883731e..366f958f 100644 --- a/modules/cli/src/main/kotlin/datamaintain/cli/app/ListExecutedScripts.kt +++ b/modules/cli/src/main/kotlin/datamaintain/cli/app/ListExecutedScripts.kt @@ -10,9 +10,9 @@ class ListExecutedScripts : DatamaintainCliCommand(name = "list") { } - override fun executeCommand(config: DatamaintainConfig) { + override fun executeCommand(config: DatamaintainConfig, porcelain: Boolean) { Datamaintain(config).listExecutedScripts().forEach { - logger.info { "${it.name} (${it.checksum})" } + echo("${it.name} (${it.checksum})") } } } diff --git a/modules/cli/src/main/kotlin/datamaintain/cli/app/update/db/DatamaintainCliUpdateDbCommand.kt b/modules/cli/src/main/kotlin/datamaintain/cli/app/update/db/DatamaintainCliUpdateDbCommand.kt index 22a917a8..90d62f70 100644 --- a/modules/cli/src/main/kotlin/datamaintain/cli/app/update/db/DatamaintainCliUpdateDbCommand.kt +++ b/modules/cli/src/main/kotlin/datamaintain/cli/app/update/db/DatamaintainCliUpdateDbCommand.kt @@ -1,29 +1,35 @@ package datamaintain.cli.app.update.db +import com.github.ajalt.clikt.output.TermUi.echo import datamaintain.cli.app.DatamaintainCliCommand import datamaintain.core.Datamaintain import datamaintain.core.config.DatamaintainConfig import datamaintain.core.exception.DatamaintainException import kotlin.system.exitProcess -fun defaultUpdateDbRunner(config: DatamaintainConfig) { - Datamaintain(config).updateDatabase().print(config.logs.verbose, porcelain = config.logs.porcelain) +fun defaultUpdateDbRunner(config: DatamaintainConfig, porcelain: Boolean) { + val report = Datamaintain(config).updateDatabase() + + if (porcelain) { + report.executedScripts.asSequence() + .map { it.name } + .forEach { echo(it) } // Use echo because logger level is ERROR + } else { + report.print() + } } abstract class DatamaintainCliUpdateDbCommand( name: String, - val runner: (DatamaintainConfig) -> Unit, + val runner: (DatamaintainConfig, Boolean) -> Unit, help: String = "" ): DatamaintainCliCommand(name, help) { - override fun executeCommand(config: DatamaintainConfig) { + override fun executeCommand(config: DatamaintainConfig, porcelain: Boolean) { try { - runner(config) + runner(config, porcelain) } catch (e: DatamaintainException) { - val verbose: Boolean = config.logs.verbose - val porcelain: Boolean = config.logs.porcelain - echo("Error at step ${e.step}", err = true) - e.report.print(verbose, porcelain = porcelain) + e.report.print() echo("") echo(e.message, err = true) diff --git a/modules/cli/src/main/kotlin/datamaintain/cli/app/update/db/MarkOneScriptAsExecuted.kt b/modules/cli/src/main/kotlin/datamaintain/cli/app/update/db/MarkOneScriptAsExecuted.kt index f15df50f..62f55cf3 100644 --- a/modules/cli/src/main/kotlin/datamaintain/cli/app/update/db/MarkOneScriptAsExecuted.kt +++ b/modules/cli/src/main/kotlin/datamaintain/cli/app/update/db/MarkOneScriptAsExecuted.kt @@ -1,14 +1,14 @@ package datamaintain.cli.app.update.db import com.github.ajalt.clikt.parameters.options.flag -import com.github.ajalt.clikt.parameters.options.option +import datamaintain.cli.app.utils.CliSpecificKey import datamaintain.cli.app.utils.detailedOption import datamaintain.core.config.CoreConfigKey import datamaintain.core.config.DatamaintainConfig import datamaintain.core.script.ScriptAction import java.util.* -class MarkOneScriptAsExecuted(runner: (DatamaintainConfig) -> Unit = ::defaultUpdateDbRunner) : +class MarkOneScriptAsExecuted(runner: (DatamaintainConfig, Boolean) -> Unit = ::defaultUpdateDbRunner) : DatamaintainCliUpdateDbCommand( name = "mark-script-as-executed", runner = runner, @@ -20,9 +20,14 @@ class MarkOneScriptAsExecuted(runner: (DatamaintainConfig) -> Unit = ::defaultUp defaultValue = CoreConfigKey.SCAN_PATH.default ) - private val verbose: Boolean? by detailedOption( + private val verbose: Boolean? by detailedOption("--verbose", "-v", help = "verbose", - defaultValue = CoreConfigKey.VERBOSE.default + defaultValue = CliSpecificKey.VERBOSE.default + ).flag() + + private val trace: Boolean? by detailedOption("-vv", + help = "trace is more verbose than verbose", + defaultValue = CliSpecificKey.VERBOSE.default ).flag() override fun overloadProps(props: Properties) { @@ -30,6 +35,7 @@ class MarkOneScriptAsExecuted(runner: (DatamaintainConfig) -> Unit = ::defaultUp // Overload from arguments path?.let { props.put(CoreConfigKey.SCAN_PATH.key, it) } - verbose?.let { props.put(CoreConfigKey.VERBOSE.key, it.toString()) } + verbose?.let { props.put(CliSpecificKey.VERBOSE.key, it.toString()) } + trace?.let { props.put(CliSpecificKey.TRACE.key, it.toString()) } } -} \ No newline at end of file +} diff --git a/modules/cli/src/main/kotlin/datamaintain/cli/app/update/db/UpdateDb.kt b/modules/cli/src/main/kotlin/datamaintain/cli/app/update/db/UpdateDb.kt index 07850106..ece6f6e7 100644 --- a/modules/cli/src/main/kotlin/datamaintain/cli/app/update/db/UpdateDb.kt +++ b/modules/cli/src/main/kotlin/datamaintain/cli/app/update/db/UpdateDb.kt @@ -5,6 +5,7 @@ import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.multiple import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.types.choice +import datamaintain.cli.app.utils.CliSpecificKey import datamaintain.cli.app.utils.detailedOption import datamaintain.core.config.CoreConfigKey import datamaintain.core.config.DatamaintainConfig @@ -16,7 +17,7 @@ import datamaintain.db.driver.mongo.MongoConfigKey import datamaintain.db.driver.mongo.MongoShell import java.util.* -class UpdateDb(runner: (DatamaintainConfig) -> Unit = ::defaultUpdateDbRunner) : DatamaintainCliUpdateDbCommand( +class UpdateDb(runner: (DatamaintainConfig, Boolean) -> Unit = ::defaultUpdateDbRunner) : DatamaintainCliUpdateDbCommand( name = "update-db", runner = runner ) { @@ -67,9 +68,14 @@ class UpdateDb(runner: (DatamaintainConfig) -> Unit = ::defaultUpdateDbRunner) : defaultValue = CoreConfigKey.PRUNE_OVERRIDE_UPDATED_SCRIPTS.default ).flag() - private val verbose: Boolean? by detailedOption( + private val verbose: Boolean? by detailedOption("--verbose", "-v", help = "verbose", - defaultValue = CoreConfigKey.VERBOSE.default + defaultValue = CliSpecificKey.VERBOSE.default + ).flag() + + private val trace: Boolean? by detailedOption("-vv", + help = "trace is more verbose than verbose", + defaultValue = CliSpecificKey.VERBOSE.default ).flag() private val saveDbOutput: Boolean? by detailedOption( @@ -112,7 +118,7 @@ class UpdateDb(runner: (DatamaintainConfig) -> Unit = ::defaultUpdateDbRunner) : private val porcelain: Boolean? by detailedOption( help = "for each executed script, display relative path to scan path", - defaultValue = CoreConfigKey.PRINT_RELATIVE_PATH_OF_SCRIPT.default + defaultValue = CliSpecificKey.PORCELAIN.default ).flag() private val flags: List? by option(help = "add a flag on the executed scripts. " + @@ -126,7 +132,8 @@ class UpdateDb(runner: (DatamaintainConfig) -> Unit = ::defaultUpdateDbRunner) : blacklistedTags?.let { props.put(CoreConfigKey.TAGS_BLACKLISTED.key, it) } tagsToPlayAgain?.let { props.put(CoreConfigKey.PRUNE_TAGS_TO_RUN_AGAIN.key, it) } createTagsFromFolder?.let { props.put(CoreConfigKey.CREATE_TAGS_FROM_FOLDER.key, it.toString()) } - verbose?.let { props.put(CoreConfigKey.VERBOSE.key, it.toString()) } + verbose?.let { props.put(CliSpecificKey.VERBOSE.key, it.toString()) } + trace?.let { props.put(CliSpecificKey.TRACE.key, it.toString()) } saveDbOutput?.let { props.put(DriverConfigKey.DB_SAVE_OUTPUT.key, it.toString()) } printDbOutput?.let { props.put(DriverConfigKey.DB_PRINT_OUTPUT.key, it.toString()) } executionMode?.let { props.put(CoreConfigKey.EXECUTION_MODE.key, it) } @@ -136,7 +143,7 @@ class UpdateDb(runner: (DatamaintainConfig) -> Unit = ::defaultUpdateDbRunner) : } checkRules?.let { props.put(CoreConfigKey.CHECK_RULES.key, it.optionListToString()) } allowAutoOverride?.let { props.put(CoreConfigKey.PRUNE_OVERRIDE_UPDATED_SCRIPTS.key, it.toString()) } - porcelain?.let { props.put(CoreConfigKey.PRINT_RELATIVE_PATH_OF_SCRIPT.key, it.toString()) } + porcelain?.let { props.put(CliSpecificKey.PORCELAIN.key, it.toString()) } mongoShell?.let { props.put(MongoConfigKey.DB_MONGO_SHELL.key, it.toUpperCase()) } flags?.let { props.put(CoreConfigKey.FLAGS.key, it.optionListToString()) } } diff --git a/modules/cli/src/main/kotlin/datamaintain/cli/app/utils/CliLogger.kt b/modules/cli/src/main/kotlin/datamaintain/cli/app/utils/CliLogger.kt new file mode 100644 index 00000000..78fd2613 --- /dev/null +++ b/modules/cli/src/main/kotlin/datamaintain/cli/app/utils/CliLogger.kt @@ -0,0 +1,36 @@ +package datamaintain.cli.app.utils + +import ch.qos.logback.classic.Level +import ch.qos.logback.classic.LoggerContext +import org.slf4j.LoggerFactory + +/** + * Translate cli level to logback level and set that level on datamaintain loggers + */ +fun applyLoggerLevel(level: CliDatamaintainLoggerLevel) { + val context = LoggerFactory.getILoggerFactory() as LoggerContext + val datamaintainLogger = context.getLogger("datamaintain") + + when(level) { + CliDatamaintainLoggerLevel.INFO -> datamaintainLogger.level = Level.INFO + CliDatamaintainLoggerLevel.VERBOSE -> datamaintainLogger.level = Level.DEBUG + CliDatamaintainLoggerLevel.TRACE -> datamaintainLogger.level = Level.TRACE + CliDatamaintainLoggerLevel.PORCELAIN -> datamaintainLogger.level = Level.ERROR + else -> error("Cannot set log level of $level") + } +} + +enum class CliDatamaintainLoggerLevel { + // normal log level + INFO, + + // debug log level + VERBOSE, + + // trace log level + TRACE, + + // special mode for cli, the datamaintain logs are disabled (except error) and specific logs are print. + // This is use for scripts that may need to parse datamaintain logs (e.g: for take in account execution results) + PORCELAIN +} diff --git a/modules/cli/src/main/kotlin/datamaintain/cli/app/utils/CliSpecificKey.kt b/modules/cli/src/main/kotlin/datamaintain/cli/app/utils/CliSpecificKey.kt index 3e06cfb9..fa09570a 100644 --- a/modules/cli/src/main/kotlin/datamaintain/cli/app/utils/CliSpecificKey.kt +++ b/modules/cli/src/main/kotlin/datamaintain/cli/app/utils/CliSpecificKey.kt @@ -1,5 +1,7 @@ package datamaintain.cli.app.utils +import java.util.Properties + /** * An enum used to define specific keys that can be used by commands for internal behaviour */ @@ -9,5 +11,13 @@ enum class CliSpecificKey( ) { // Each commands need to manage that in order to only print the effective configuration (so not execute the action) __PRINT_CONFIG_ONLY("__PRINT_CONFIG_ONLY", "false"), - VERSION("version", "dev") + VERSION("version", "dev"), + VERBOSE("verbose", "false"), + TRACE("trace", "false"), + PORCELAIN("porcelain", "false"), } + +fun Properties.getCliProperty(cliKey: CliSpecificKey) = this.getProperty(cliKey.key, cliKey.default)!! + +fun Properties.getBooleanCliProperty(cliKey: CliSpecificKey) = this.getCliProperty(cliKey).toBoolean() + diff --git a/modules/core/src/main/kotlin/datamaintain/core/util/PorcelainUtil.kt b/modules/cli/src/main/kotlin/datamaintain/cli/app/utils/PorcelainUtil.kt similarity index 82% rename from modules/core/src/main/kotlin/datamaintain/core/util/PorcelainUtil.kt rename to modules/cli/src/main/kotlin/datamaintain/cli/app/utils/PorcelainUtil.kt index a7d7862e..1969857e 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/util/PorcelainUtil.kt +++ b/modules/cli/src/main/kotlin/datamaintain/cli/app/utils/PorcelainUtil.kt @@ -1,4 +1,4 @@ -package datamaintain.core.util +package datamaintain.cli.app.utils import java.nio.file.Path diff --git a/modules/cli/src/test/kotlin/datamaintain/cli/app/BaseCliTest.kt b/modules/cli/src/test/kotlin/datamaintain/cli/app/BaseCliTest.kt index ae32a06f..41524ba9 100644 --- a/modules/cli/src/test/kotlin/datamaintain/cli/app/BaseCliTest.kt +++ b/modules/cli/src/test/kotlin/datamaintain/cli/app/BaseCliTest.kt @@ -10,7 +10,7 @@ open class BaseCliTest { protected val configWrapper = ConfigWrapper() - private fun runner(config: DatamaintainConfig) { + private fun runner(config: DatamaintainConfig, porcelain: Boolean) { configWrapper.datamaintainConfig = config } diff --git a/modules/cli/src/test/kotlin/datamaintain/cli/app/PrintConfigTest.kt b/modules/cli/src/test/kotlin/datamaintain/cli/app/PrintConfigTest.kt index a4e3d548..a198ba82 100644 --- a/modules/cli/src/test/kotlin/datamaintain/cli/app/PrintConfigTest.kt +++ b/modules/cli/src/test/kotlin/datamaintain/cli/app/PrintConfigTest.kt @@ -19,7 +19,7 @@ internal class PrintConfigTest : BaseCliTest() { } @Test - fun `should print config when command is mark-script-as-exectued`() { + fun `should print config when command is mark-script-as-executed`() { // Given val path = "/myPath" @@ -52,8 +52,6 @@ internal class PrintConfigTest : BaseCliTest() { get { get(index++).message }.isEqualTo("- allow override executed script -> false") get { get(index++).message }.isEqualTo("- script action -> MARK_AS_EXECUTED") get { get(index++).message }.isEqualTo("- flags -> []") - get { get(index++).message }.isEqualTo("- verbose -> false") - get { get(index++).message }.isEqualTo("- porcelain -> false") } } @@ -94,8 +92,6 @@ internal class PrintConfigTest : BaseCliTest() { get { get(index++).message }.isEqualTo("- allow override executed script -> false") get { get(index++).message }.isEqualTo("- script action -> MARK_AS_EXECUTED") get { get(index++).message }.isEqualTo("- flags -> []") - get { get(index++).message }.isEqualTo("- verbose -> false") - get { get(index++).message }.isEqualTo("- porcelain -> false") } } @@ -142,8 +138,6 @@ internal class PrintConfigTest : BaseCliTest() { get { get(index++).message }.isEqualTo("- allow override executed script -> false") get { get(index++).message }.isEqualTo("- script action -> RUN") get { get(index++).message }.isEqualTo("- flags -> []") - get { get(index++).message }.isEqualTo("- verbose -> true") - get { get(index++).message }.isEqualTo("- porcelain -> true") } } @@ -192,8 +186,6 @@ internal class PrintConfigTest : BaseCliTest() { get { get(index++).message }.isEqualTo("- allow override executed script -> false") get { get(index++).message }.isEqualTo("- script action -> RUN") get { get(index++).message }.isEqualTo("- flags -> []") - get { get(index++).message }.isEqualTo("- verbose -> true") - get { get(index++).message }.isEqualTo("- porcelain -> true") } } } diff --git a/modules/cli/src/test/kotlin/datamaintain/cli/app/update/db/MarkOneScriptAsExecutedTest.kt b/modules/cli/src/test/kotlin/datamaintain/cli/app/update/db/MarkOneScriptAsExecutedTest.kt index ee4dc4e8..ecd15cea 100644 --- a/modules/cli/src/test/kotlin/datamaintain/cli/app/update/db/MarkOneScriptAsExecutedTest.kt +++ b/modules/cli/src/test/kotlin/datamaintain/cli/app/update/db/MarkOneScriptAsExecutedTest.kt @@ -1,13 +1,17 @@ package datamaintain.cli.app.update.db +import ch.qos.logback.classic.Level +import ch.qos.logback.classic.Logger +import ch.qos.logback.classic.LoggerContext import datamaintain.cli.app.BaseCliTest import datamaintain.core.script.ScriptAction +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test +import org.slf4j.LoggerFactory import strikt.api.expectThat import strikt.assertions.isEqualTo -import strikt.assertions.isFalse -import strikt.assertions.isTrue import java.nio.file.Paths internal class MarkOneScriptAsExecutedTest : BaseCliTest() { @@ -34,6 +38,23 @@ internal class MarkOneScriptAsExecutedTest : BaseCliTest() { @Nested inner class Verbose { + private lateinit var datamaintainLogger: Logger + private lateinit var datamaintainLoggerLevel: Level + + @BeforeEach + fun beforeEach() { + if (!::datamaintainLogger.isInitialized) { + val context = LoggerFactory.getILoggerFactory() as LoggerContext + datamaintainLogger = context.getLogger("datamaintain") + datamaintainLoggerLevel = datamaintainLogger.level + } + } + + @AfterEach + fun afterEach() { + datamaintainLogger.level = datamaintainLoggerLevel + } + @Test fun `should build config with verbose set to true`() { // Given @@ -43,7 +64,7 @@ internal class MarkOneScriptAsExecutedTest : BaseCliTest() { runMarkScriptAsExecuted(markScriptAsExecutedArguments) // Then - expectThat(configWrapper.datamaintainConfig!!.logs.verbose).isTrue() + expectThat(datamaintainLogger.level).isEqualTo(Level.DEBUG) } @Test @@ -54,7 +75,31 @@ internal class MarkOneScriptAsExecutedTest : BaseCliTest() { runMarkScriptAsExecuted() // Then - expectThat(configWrapper.datamaintainConfig!!.logs.verbose).isFalse() + expectThat(datamaintainLogger.level).isEqualTo(Level.INFO) + } + + @Test + fun `should build config with trace set to true`() { + // Given + val markScriptAsExecutedArguments = listOf("-vv") + + // When + runMarkScriptAsExecuted(markScriptAsExecutedArguments) + + // Then + expectThat(datamaintainLogger.level).isEqualTo(Level.TRACE) + } + + @Test + fun `should build config with trace set to true even if verbose is set`() { + // Given + val markScriptAsExecutedArguments = listOf("--verbose", "-vv") + + // When + runMarkScriptAsExecuted(markScriptAsExecutedArguments) + + // Then + expectThat(datamaintainLogger.level).isEqualTo(Level.TRACE) } } @@ -80,3 +125,4 @@ internal class MarkOneScriptAsExecutedTest : BaseCliTest() { ) } } + diff --git a/modules/cli/src/test/kotlin/datamaintain/cli/app/update/db/UpdateDbTest.kt b/modules/cli/src/test/kotlin/datamaintain/cli/app/update/db/UpdateDbTest.kt index f4e39261..a321bc37 100644 --- a/modules/cli/src/test/kotlin/datamaintain/cli/app/update/db/UpdateDbTest.kt +++ b/modules/cli/src/test/kotlin/datamaintain/cli/app/update/db/UpdateDbTest.kt @@ -1,5 +1,8 @@ package datamaintain.cli.app.update.db +import ch.qos.logback.classic.Level +import ch.qos.logback.classic.Logger +import ch.qos.logback.classic.LoggerContext import datamaintain.cli.app.BaseCliTest import datamaintain.core.script.ScriptAction import datamaintain.core.script.Tag @@ -7,11 +10,10 @@ import datamaintain.core.script.TagMatcher import datamaintain.core.step.check.rules.implementations.SameScriptsAsExecutedCheck import datamaintain.db.driver.mongo.MongoDriverConfig import datamaintain.db.driver.mongo.MongoShell -import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Nested -import org.junit.jupiter.api.Test +import org.junit.jupiter.api.* import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.EnumSource +import org.slf4j.LoggerFactory import strikt.api.expectThat import strikt.assertions.* import java.nio.file.Paths @@ -77,6 +79,23 @@ internal class UpdateDbTest : BaseCliTest() { @Nested inner class Verbose { + private lateinit var datamaintainLogger: Logger + private lateinit var datamaintainLoggerLevel: Level + + @BeforeEach + fun beforeEach() { + if (!::datamaintainLogger.isInitialized) { + val context = LoggerFactory.getILoggerFactory() as LoggerContext + datamaintainLogger = context.getLogger("datamaintain") + datamaintainLoggerLevel = datamaintainLogger.level + } + } + + @AfterEach + fun afterEach() { + datamaintainLogger.level = datamaintainLoggerLevel + } + @Test fun `should build config with verbose set to true`() { // Given @@ -86,7 +105,7 @@ internal class UpdateDbTest : BaseCliTest() { runUpdateDb(updateDbArguments) // Then - expectThat(configWrapper.datamaintainConfig!!.logs.verbose).isTrue() + expectThat(datamaintainLogger.level).isEqualTo(Level.DEBUG) } @Test @@ -97,7 +116,31 @@ internal class UpdateDbTest : BaseCliTest() { runUpdateDb() // Then - expectThat(configWrapper.datamaintainConfig!!.logs.verbose).isFalse() + expectThat(datamaintainLogger.level).isEqualTo(Level.INFO) + } + + @Test + fun `should build config with trace set to true`() { + // Given + val updateDbArguments = listOf("-vv") + + // When + runUpdateDb(updateDbArguments) + + // Then + expectThat(datamaintainLogger.level).isEqualTo(Level.TRACE) + } + + @Test + fun `should build config with trace set to true even if verbose is set`() { + // Given + val updateDbArguments = listOf("--verbose", "-vv") + + // When + runUpdateDb(updateDbArguments) + + // Then + expectThat(datamaintainLogger.level).isEqualTo(Level.TRACE) } } @@ -279,6 +322,23 @@ internal class UpdateDbTest : BaseCliTest() { @Nested inner class Porcelain { + private lateinit var datamaintainLogger: Logger + private lateinit var datamaintainLoggerLevel: Level + + @BeforeEach + fun beforeEach() { + if (!::datamaintainLogger.isInitialized) { + val context = LoggerFactory.getILoggerFactory() as LoggerContext + datamaintainLogger = context.getLogger("datamaintain") + datamaintainLoggerLevel = datamaintainLogger.level + } + } + + @AfterEach + fun afterEach() { + datamaintainLogger.level = datamaintainLoggerLevel + } + @Test fun `should build default config without auto override`() { // Given @@ -290,9 +350,7 @@ internal class UpdateDbTest : BaseCliTest() { expectThat(configWrapper) { get { datamaintainConfig }.isNotNull() } - expectThat(configWrapper.datamaintainConfig!!.logs.porcelain) { - isFalse() - } + expectThat(datamaintainLogger.level).isEqualTo(Level.INFO) } @Test @@ -304,12 +362,8 @@ internal class UpdateDbTest : BaseCliTest() { runUpdateDb(updateDbArguments) // Then - expectThat(configWrapper) { - get { datamaintainConfig }.isNotNull() - } - expectThat(configWrapper.datamaintainConfig!!.logs.porcelain) { - isTrue() - } + expectThat(configWrapper) { get { datamaintainConfig }.isNotNull() } + expectThat(datamaintainLogger.level).isEqualTo(Level.ERROR) } } diff --git a/modules/core/src/test/kotlin/datamaintain/core/util/PorcelainUtilTest.kt b/modules/cli/src/test/kotlin/datamaintain/cli/app/utils/PorcelainUtilTest.kt similarity index 96% rename from modules/core/src/test/kotlin/datamaintain/core/util/PorcelainUtilTest.kt rename to modules/cli/src/test/kotlin/datamaintain/cli/app/utils/PorcelainUtilTest.kt index 5ecd70ab..a578c1c8 100644 --- a/modules/core/src/test/kotlin/datamaintain/core/util/PorcelainUtilTest.kt +++ b/modules/cli/src/test/kotlin/datamaintain/cli/app/utils/PorcelainUtilTest.kt @@ -1,4 +1,4 @@ -package datamaintain.core.util +package datamaintain.cli.app.utils import org.junit.jupiter.api.Test import strikt.api.expectThat @@ -31,4 +31,4 @@ internal class PorcelainUtilTest { // Then expectThat(actualRelativePath).isEqualTo("files/my_file") } -} \ No newline at end of file +} diff --git a/modules/core/src/main/kotlin/datamaintain/core/Datamaintain.kt b/modules/core/src/main/kotlin/datamaintain/core/Datamaintain.kt index e8d3dd10..8ce32aba 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/Datamaintain.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/Datamaintain.kt @@ -16,10 +16,8 @@ private val logger = KotlinLogging.logger {} class Datamaintain(config: DatamaintainConfig) { init { - if (config.logs.verbose && !config.logs.porcelain) { - config.log() - config.scanner.log() - } + config.log() + config.driverConfig.log() } val context = Context( diff --git a/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainCheckerConfig.kt b/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainCheckerConfig.kt index bc8c4502..25c3b0d5 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainCheckerConfig.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainCheckerConfig.kt @@ -8,7 +8,7 @@ data class DatamaintainCheckerConfig @JvmOverloads constructor( val rules: List = emptyList(), ) { fun log() { - rules.let { logger.info { "- rules -> $it" } } + rules.let { logger.debug { "- rules -> $it" } } } } diff --git a/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainConfig.kt b/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainConfig.kt index 8fb1e71d..21058f9f 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainConfig.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainConfig.kt @@ -26,7 +26,6 @@ data class DatamaintainConfig @JvmOverloads constructor( val checker: DatamaintainCheckerConfig = DatamaintainCheckerConfig(), val executor: DatamaintainExecutorConfig = DatamaintainExecutorConfig(), val driverConfig: DatamaintainDriverConfig, - val logs: DatamaintainLogsConfig = DatamaintainLogsConfig(), ) { private constructor(builder: Builder) : this( @@ -55,10 +54,6 @@ data class DatamaintainConfig @JvmOverloads constructor( builder.flags ), builder.driverConfig, - DatamaintainLogsConfig( - builder.verbose, - builder.porcelain, - ), ) companion object { @@ -111,10 +106,6 @@ data class DatamaintainConfig @JvmOverloads constructor( extractList(props.getNullableProperty(FLAGS)) ), driverConfig, - DatamaintainLogsConfig( - props.getProperty(VERBOSE).toBoolean(), - props.getProperty(PRINT_RELATIVE_PATH_OF_SCRIPT).toBoolean(), - ), ) } @@ -187,17 +178,16 @@ data class DatamaintainConfig @JvmOverloads constructor( } fun log() { - logger.info { "Configuration: " } + logger.debug { "Configuration: " } - workingDirectory.also { logger.info { "- working directory -> $it" } } - name?.also { logger.info { "- name -> $it" } } + workingDirectory.also { logger.debug { "- working directory -> $it" } } + name?.also { logger.debug { "- name -> $it" } } scanner.log() filter.log() pruner.log() checker.log() executor.log() - logs.log() - logger.info { "" } + logger.debug { "" } } class Builder { @@ -232,10 +222,6 @@ data class DatamaintainConfig @JvmOverloads constructor( private set var defaultScriptAction: ScriptAction = DatamaintainExecutorConfig.defaultAction private set - var verbose: Boolean = VERBOSE.default!!.toBoolean() - private set - var porcelain: Boolean = PRINT_RELATIVE_PATH_OF_SCRIPT.default!!.toBoolean() - private set var flags: MutableList = mutableListOf() private set @@ -248,8 +234,6 @@ data class DatamaintainConfig @JvmOverloads constructor( fun withExecutionMode(executionMode: ExecutionMode) = apply { this.executionMode = executionMode } fun withDefaultScriptAction(defaultScriptAction: ScriptAction) = apply { this.defaultScriptAction = defaultScriptAction } fun withDriverConfig(driverConfig: DatamaintainDriverConfig) = apply { this.driverConfig = driverConfig } - fun withVerbose(verbose: Boolean) = apply { this.verbose = verbose } - fun withPorcelain(porcelain: Boolean) = apply { this.porcelain = porcelain } // Collection fun addWhitelistedTag(whitelistedTag: Tag) = apply { this.whitelistedTags.add(whitelistedTag) } @@ -291,9 +275,7 @@ enum class CoreConfigKey(override val key: String, WORKING_DIRECTORY_PATH("working.directory.path", System.getProperty("user.dir")), PARENT_CONFIG_PATH("parent.config.path"), DB_TYPE("db.type", "mongo"), - VERBOSE("verbose", "false"), DEFAULT_SCRIPT_ACTION("default.script.action", "RUN"), - PRINT_RELATIVE_PATH_OF_SCRIPT("porcelain", "false"), FLAGS("flags"), // SCAN diff --git a/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainExecutorConfig.kt b/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainExecutorConfig.kt index a81faa75..967102c1 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainExecutorConfig.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainExecutorConfig.kt @@ -13,10 +13,10 @@ data class DatamaintainExecutorConfig @JvmOverloads constructor( val flags: List = emptyList(), ) { fun log() { - executionMode.let { logger.info { "- execution mode -> $it" } } - overrideExecutedScripts.let { logger.info { "- allow override executed script -> $it" } } - defaultScriptAction.let { logger.info { "- script action -> $it" } } - flags.let { logger.info { "- flags -> $it" } } + executionMode.let { logger.debug { "- execution mode -> $it" } } + overrideExecutedScripts.let { logger.debug { "- allow override executed script -> $it" } } + defaultScriptAction.let { logger.debug { "- script action -> $it" } } + flags.let { logger.debug { "- flags -> $it" } } } companion object { diff --git a/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainFilterConfig.kt b/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainFilterConfig.kt index 50a12892..dcd480d4 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainFilterConfig.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainFilterConfig.kt @@ -10,8 +10,8 @@ data class DatamaintainFilterConfig @JvmOverloads constructor( val blacklistedTags: Set = setOf(), ) { fun log() { - whitelistedTags.let { logger.info { "- whitelisted tags -> $it" } } - blacklistedTags.let { logger.info { "- blacklisted tags -> $it" } } + whitelistedTags.let { logger.debug { "- whitelisted tags -> $it" } } + blacklistedTags.let { logger.debug { "- blacklisted tags -> $it" } } } } diff --git a/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainLogsConfig.kt b/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainLogsConfig.kt index 0c19004d..cdb28cfe 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainLogsConfig.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainLogsConfig.kt @@ -4,12 +4,3 @@ import mu.KotlinLogging private val logger = KotlinLogging.logger {} -data class DatamaintainLogsConfig @JvmOverloads constructor( - val verbose: Boolean = CoreConfigKey.VERBOSE.default!!.toBoolean(), - val porcelain: Boolean = CoreConfigKey.PRINT_RELATIVE_PATH_OF_SCRIPT.default!!.toBoolean(), -) { - fun log() { - verbose.let { logger.info { "- verbose -> $it" } } - porcelain.let { logger.info { "- porcelain -> $it" } } - } -} diff --git a/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainPrunerConfig.kt b/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainPrunerConfig.kt index e431fcb1..02d84494 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainPrunerConfig.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainPrunerConfig.kt @@ -9,7 +9,7 @@ data class DatamaintainPrunerConfig @JvmOverloads constructor( val tagsToPlayAgain: Set = setOf(), ) { fun log() { - tagsToPlayAgain.let { logger.info { "- tags to play again -> $it" } } + tagsToPlayAgain.let { logger.debug { "- tags to play again -> $it" } } } } diff --git a/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainScannerConfig.kt b/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainScannerConfig.kt index 27fff2c6..cfa6d225 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainScannerConfig.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/config/DatamaintainScannerConfig.kt @@ -14,9 +14,9 @@ data class DatamaintainScannerConfig @JvmOverloads constructor( val tagsMatchers: Set = setOf(), ) { fun log() { - path.let { logger.info { "- path -> $it" } } - identifierRegex.let { logger.info { "- identifier regex -> $it" } } - doesCreateTagsFromFolder.let { logger.info { "- create tags from folder -> $it" } } - tagsMatchers.let { logger.info { "- tags -> $it" } } + path.let { logger.debug { "- path -> $it" } } + identifierRegex.let { logger.debug { "- identifier regex -> $it" } } + doesCreateTagsFromFolder.let { logger.debug { "- create tags from folder -> $it" } } + tagsMatchers.let { logger.debug { "- tags -> $it" } } } } diff --git a/modules/core/src/main/kotlin/datamaintain/core/report/Report.kt b/modules/core/src/main/kotlin/datamaintain/core/report/Report.kt index 10745f53..5e650062 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/report/Report.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/report/Report.kt @@ -15,49 +15,37 @@ class Report @JvmOverloads constructor( val executedScripts: List = listOf(), val validatedCheckRules: List = listOf() ) { - fun print(verbose: Boolean, porcelain: Boolean = false) { + fun print() { val stepWithMaxExecutionOrder: Step = Step.values().asSequence().maxByOrNull { step -> step.executionOrder }!! - print(verbose, porcelain, stepWithMaxExecutionOrder) + print(stepWithMaxExecutionOrder) } - fun print(verbose: Boolean, porcelain: Boolean, maxStepToShow: Step) { - if (!porcelain) { - logger.info { "Summary => " } + fun print(maxStepToShow: Step) { + logger.info { "Summary => " } - // Scanner - logger.info { "- ${scannedScripts.size} files scanned" } - if (verbose) { - scannedScripts.forEach {logger.info { " -> ${it.name}" }} - } + // Scanner + logger.debug { "- ${scannedScripts.size} files scanned" } + scannedScripts.forEach { logger.trace { " -> ${it.name}" } } - if (Step.FILTER.isSameStepOrExecutedBefore(maxStepToShow)) { - logger.info { "- ${filteredScripts.size} files filtered" } - if (verbose) { - filteredScripts.forEach { logger.info { " -> ${it.name}" } } - } - } + if (Step.FILTER.isSameStepOrExecutedBefore(maxStepToShow)) { + logger.debug { "- ${filteredScripts.size} files filtered" } + filteredScripts.forEach { logger.trace { " -> ${it.name}" } } + } - if (Step.PRUNE.isSameStepOrExecutedBefore(maxStepToShow)) { - logger.info { "- ${prunedScripts.size} files pruned" } - if (verbose) { - prunedScripts.forEach { logger.info { " -> ${it.name}" } } - } - } + if (Step.PRUNE.isSameStepOrExecutedBefore(maxStepToShow)) { + logger.debug { "- ${prunedScripts.size} files pruned" } + prunedScripts.forEach { logger.trace { " -> ${it.name}" } } + } - if (Step.CHECK.isSameStepOrExecutedBefore(maxStepToShow)) { - logger.info { "- ${validatedCheckRules.size} check rules validated" } - if (verbose) { - validatedCheckRules.forEach { logger.info { " -> ${it.getName()}" } } - } - } + if (Step.CHECK.isSameStepOrExecutedBefore(maxStepToShow)) { + logger.debug { "- ${validatedCheckRules.size} check rules validated" } + validatedCheckRules.forEach { logger.trace { " -> ${it.getName()}" } } } if (Step.EXECUTE.isSameStepOrExecutedBefore(maxStepToShow)) { - if (!porcelain) { logger.info { "- ${executedScripts.size} files executed" } } + logger.info { "- ${executedScripts.size} files executed" } executedScripts.forEach { - logger.info { - if (!porcelain) { " -> ${it.name}" } else { "${it.porcelainName}" } - } + logger.info { " -> ${it.name}" } } } } diff --git a/modules/core/src/main/kotlin/datamaintain/core/script/FileScript.kt b/modules/core/src/main/kotlin/datamaintain/core/script/FileScript.kt index a3797fb5..6d9eb06f 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/script/FileScript.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/script/FileScript.kt @@ -4,7 +4,6 @@ import java.math.BigInteger import datamaintain.core.config.DatamaintainConfig import datamaintain.core.config.DatamaintainExecutorConfig import datamaintain.core.exception.DatamaintainFileIdentifierPatternException -import datamaintain.core.util.extractRelativePath import java.io.File import java.nio.file.Path import java.security.MessageDigest @@ -14,7 +13,6 @@ class FileScript @JvmOverloads constructor( identifierRegex: Regex, override val tags: Set = setOf(), override var action: ScriptAction = DatamaintainExecutorConfig.defaultAction, - override val porcelainName: String? = null ) : ScriptWithContent { companion object { @@ -25,16 +23,8 @@ class FileScript @JvmOverloads constructor( config.scanner.identifierRegex, tags, config.executor.defaultScriptAction, - computePorcelainName(config, path) ) } - - private fun computePorcelainName(config: DatamaintainConfig, path: Path): String? = - if(!config.logs.porcelain) { - null - } else { - extractRelativePath(config.scanner.path, path) - } } override val name: String diff --git a/modules/core/src/main/kotlin/datamaintain/core/script/Script.kt b/modules/core/src/main/kotlin/datamaintain/core/script/Script.kt index b4af6e01..c599143d 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/script/Script.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/script/Script.kt @@ -138,7 +138,6 @@ data class ReportExecutedScript( override val executionDurationInMillis: Long? = null, override val executionOutput: String? = null, override val flags: List = listOf(), - val porcelainName: String? = null ) : ExecutedScript( name, checksum, @@ -150,7 +149,7 @@ data class ReportExecutedScript( flags ) { companion object { - fun from(executedScript: ExecutedScript, porcelainName: String?) = ReportExecutedScript( + fun from(executedScript: ExecutedScript) = ReportExecutedScript( executedScript.name, executedScript.checksum, executedScript.identifier, @@ -159,7 +158,6 @@ data class ReportExecutedScript( executedScript.executionDurationInMillis, executedScript.executionOutput, executedScript.flags, - porcelainName ) } } @@ -168,7 +166,6 @@ interface ScriptWithContent : Script { val content: String val tags: Set var action: ScriptAction - val porcelainName: String? } diff --git a/modules/core/src/main/kotlin/datamaintain/core/step/Filter.kt b/modules/core/src/main/kotlin/datamaintain/core/step/Filter.kt index b1b45cb7..358a1e39 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/step/Filter.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/step/Filter.kt @@ -8,21 +8,22 @@ import mu.KotlinLogging private val logger = KotlinLogging.logger {} -class Filter(private val context: Context) { +class Filter(val context: Context) { private val filterConfig get() = context.config.filter fun filter(scripts: List): List { try { - if (!context.config.logs.porcelain) { logger.info { "Filter scripts..." } } + logger.info { "Filter scripts..." } var filteredScripts = scripts if (filterConfig.whitelistedTags.isNotEmpty()) { + logger.trace { "Check whitelisted tags ${filterConfig.whitelistedTags}" } filteredScripts = filteredScripts.filter { script -> val kept = filterConfig.whitelistedTags.any { it isIncluded script } - if (context.config.logs.verbose && !kept && !context.config.logs.porcelain) { - logger.info { "${script.name} is skipped because not whitelisted" } + if (!kept) { + logger.debug { "${script.name} is skipped because not whitelisted" } } kept @@ -30,10 +31,11 @@ class Filter(private val context: Context) { } if (filterConfig.blacklistedTags.isNotEmpty()) { + logger.trace { "Check blacklisted tags ${filterConfig.blacklistedTags}" } filteredScripts = filteredScripts.filterNot { script -> val skipped = filterConfig.blacklistedTags.any { it isIncluded script } - if (context.config.logs.verbose && skipped && !context.config.logs.porcelain) { - logger.info { "${script.name} is skipped because blacklisted" } + if (skipped) { + logger.debug { "${script.name} is skipped because blacklisted" } } skipped } @@ -41,10 +43,10 @@ class Filter(private val context: Context) { filteredScripts = filteredScripts.onEach { context.reportBuilder.addFilteredScript(it) } - if (!context.config.logs.porcelain) { - logger.info { "${filteredScripts.size} scripts filtered (${scripts.size - filteredScripts.size} skipped)" } - logger.info { "" } - } + + logger.info { "${filteredScripts.size} scripts filtered (${scripts.size - filteredScripts.size} skipped)" } + logger.trace { filteredScripts.map { it.name } } + logger.info { "" } return filteredScripts } catch (datamaintainException: DatamaintainBaseException) { throw DatamaintainException( diff --git a/modules/core/src/main/kotlin/datamaintain/core/step/Pruner.kt b/modules/core/src/main/kotlin/datamaintain/core/step/Pruner.kt index 979bca4d..b7430b94 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/step/Pruner.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/step/Pruner.kt @@ -14,7 +14,7 @@ class Pruner(private val context: Context) { get() = context.config.pruner fun prune(scripts: List): List { - if (!context.config.logs.porcelain) { logger.info { "Prune scripts..." } } + logger.info { "Prune scripts..." } try { val listExecutedScripts = context.dbDriver.listExecutedScripts() @@ -37,10 +37,9 @@ class Pruner(private val context: Context) { prunedScripts = prunedScripts.onEach { context.reportBuilder.addPrunedScript(it) } - if (!context.config.logs.porcelain) { - logger.info { "${prunedScripts.size} scripts pruned (${executedChecksums.size} skipped)" } - logger.info { "" } - } + logger.info { "${prunedScripts.size} scripts pruned (${executedChecksums.size} skipped)" } + logger.trace { prunedScripts.map { it.name } } + logger.info { "" } return prunedScripts } catch (datamaintainException: DatamaintainBaseException) { @@ -56,11 +55,9 @@ class Pruner(private val context: Context) { private fun doesScriptAlreadyExecuted(script: ScriptWithContent, executedChecksums: List): Boolean { val skipped = executedChecksums.contains(script.checksum) && script.tags.intersect(prunerConfig.tagsToPlayAgain).isEmpty() - if (context.config.logs.verbose && skipped && !context.config.logs.porcelain) { - logger.info { - "${script.name} is skipped because it was already executed " + - "and it does not have a tag to play again." - } + if (skipped) { + logger.debug { "${script.name} is skipped because it was already executed " + + "and it does not have a tag to play again." } } return skipped } diff --git a/modules/core/src/main/kotlin/datamaintain/core/step/Scanner.kt b/modules/core/src/main/kotlin/datamaintain/core/step/Scanner.kt index 6288cf1f..3f8e39c1 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/step/Scanner.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/step/Scanner.kt @@ -16,32 +16,27 @@ private val logger = KotlinLogging.logger {} class Scanner(private val context: Context) { private val scannerConfig get() = context.config.scanner - + fun scan(): List { try { val rootFolder: File = scannerConfig.path.toFile() - if (!context.config.logs.porcelain) { logger.info { "Scan ${rootFolder.absolutePath}..." } } + logger.info { "Scan ${rootFolder.absolutePath}..." } val scannedFiles = rootFolder.walk() .filter { it.isFile } - .map { FileScript.from(context.config, buildTags(rootFolder, it).toSet(), it) } .sortedBy { it.name } + .map { FileScript.from(context.config, buildTags(rootFolder, it).toSet(), it) } .onEach { context.reportBuilder.addScannedScript(it) } - .onEach { - if (context.config.logs.verbose && !context.config.logs.porcelain) { - logger.info { "${it.name} is scanned" } - } - } + .onEach { logger.debug { "${it.name} is scanned" } } .toList() - if (!context.config.logs.porcelain) { logger.info { "${scannedFiles.size} files scanned" } } + logger.info { "${scannedFiles.size} files scanned" } + logger.trace { scannedFiles.map { it.name }} scannerConfig.tagsMatchers.onEach { tagMatcher -> if (scannedFiles.none { it.tags.contains(tagMatcher.tag) }) { - if (!context.config.logs.porcelain) { logger.warn {"WARNING: ${tagMatcher.tag} did not match any scripts"} } + logger.warn {"WARNING: ${tagMatcher.tag} did not match any scripts"} } } - if (!context.config.logs.porcelain) { - logger.info { "" } - if (scannedFiles.isEmpty()) { logger.warn { "WARNING: No scripts were found" } } - } + logger.info { "" } + if (scannedFiles.isEmpty()) { logger.warn { "WARNING: No scripts were found" } } return scannedFiles } catch (datamaintainException: DatamaintainBaseException) { throw DatamaintainException( @@ -54,14 +49,30 @@ class Scanner(private val context: Context) { } private fun buildTags(rootFolder: File, file: File): Set { + logger.debug { "Search tags for ${file.path}" } val tags = mutableSetOf() if (scannerConfig.doesCreateTagsFromFolder) { tags.addAll(buildTagsFromFolder(rootFolder, file)) } - tags.addAll(scannerConfig.tagsMatchers.filter { it.matches(file.toPath()) }.map { it.tag }) + tags.addAll( + scannerConfig.tagsMatchers + .filter { + val matches = it.matches(file.toPath()) + + if (matches) { + logger.debug { "${file.path} match tag ${it.tag} with glob ${it.globPaths}" } + } else { + logger.debug { "${file.path} does not match tag ${it.tag} with glob ${it.globPaths}" } + } + + matches + } + .map { it.tag } + ) + logger.debug { "${file.path} - Tags $tags" } return tags } diff --git a/modules/core/src/main/kotlin/datamaintain/core/step/check/Checker.kt b/modules/core/src/main/kotlin/datamaintain/core/step/check/Checker.kt index 82673120..7e289477 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/step/check/Checker.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/step/check/Checker.kt @@ -15,6 +15,7 @@ import datamaintain.core.step.check.rules.implementations.AlwaysFailedCheck import datamaintain.core.step.check.rules.implementations.AlwaysSucceedCheck import datamaintain.core.step.check.rules.implementations.SameScriptsAsExecutedCheck import mu.KotlinLogging +import kotlin.math.log private val logger = KotlinLogging.logger {} @@ -28,7 +29,7 @@ class Checker(private val context: Context) { fun check(checkedData: CheckerData): List { try { - if (!context.config.logs.porcelain) { logger.info { "Check scripts..." } } + logger.info { "Check scripts..." } // we want to ensure all rule can be built before to launch the first check, // so end the sequence stream by building a list. @@ -36,14 +37,14 @@ class Checker(private val context: Context) { .map { buildCheckRule(it) } .toList() + logger.trace { "Rules: ${rules}" } + // All rules exist so we can launch them. Check must throw an DatamaintainCheckException for been catch rules.onEach { executeRule(it, checkedData) } .forEach { context.reportBuilder.addValidatedCheckRules(it) } - if (!context.config.logs.porcelain) { - logger.info { "All check rules were executed!" } - logger.info { "" } - } + logger.info { "All check rules were executed!" } + logger.info { "" } // Checker doesn't have responsability to add or remove script. // So if all checks passed then return the prunedScripts return checkedData.prunedScripts.toList() @@ -71,7 +72,7 @@ class Checker(private val context: Context) { } private fun executeRule(checkRule: CheckRule, checkerData: CheckerData) { - if (!context.config.logs.porcelain) { logger.info { "Execute ${checkRule.getName()}" } } + logger.info { "Execute ${checkRule.getName()}" } val scripts = getScriptsFromCheckerDataByType(checkerData, checkRule.scriptType()) @@ -87,7 +88,7 @@ class Checker(private val context: Context) { } } - if (!context.config.logs.porcelain) { logger.info { "${checkRule.getName()} executed" } } + logger.info { "${checkRule.getName()} executed" } } private fun getScriptsFromCheckerDataByType(checkerData: CheckerData, scriptType: ScriptType): Sequence { diff --git a/modules/core/src/main/kotlin/datamaintain/core/step/executor/Executor.kt b/modules/core/src/main/kotlin/datamaintain/core/step/executor/Executor.kt index b6dd1843..1fe49841 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/step/executor/Executor.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/step/executor/Executor.kt @@ -18,7 +18,7 @@ class Executor(private val context: Context) { get() = context.config.executor fun execute(scripts: List): Report { - if (!context.config.logs.porcelain) { logger.info { "Executes scripts.." } } + logger.info { "Executes scripts.." } try { for (script in scripts) { val executedScript = when (executorConfig.executionMode) { @@ -30,18 +30,17 @@ class Executor(private val context: Context) { context.reportBuilder.addReportExecutedScript( ReportExecutedScript.from( executedScript, - scripts.first { it.checksum == executedScript.checksum }.porcelainName ) ) if (executedScript.executionStatus == ExecutionStatus.KO) { - if (!context.config.logs.porcelain) { logger.info { "" } } + logger.info { "" } // TODO handle interactive shell throw DatamaintainScriptExecutionException(executedScript) } } - if (!context.config.logs.porcelain) { logger.info { "" } } + logger.info { "" } return context.reportBuilder.toReport() } catch (datamaintainException: DatamaintainBaseException) { throw DatamaintainException( @@ -67,7 +66,7 @@ class Executor(private val context: Context) { if (executedScript.executionStatus == ExecutionStatus.OK) { markAsExecuted(executedScript) - if (!context.config.logs.porcelain) { logger.info { "${executedScript.name} executed" } } + logger.info { "${executedScript.name} executed" } } executedScript @@ -78,7 +77,7 @@ class Executor(private val context: Context) { try { markAsExecuted(executedScript) - if (!context.config.logs.porcelain) { logger.info { "${executedScript.name} only marked as executed (so not executed)" } } + logger.info { "${executedScript.name} only marked as executed (so not executed)" } } catch (e: DatamaintainQueryException) { logger.warn { "Failed to mark script ${executedScript.name} as executed. Use the following command to force mark the script as executed : " + "./datamaintain-cli --db-type ${context.config.driverConfig.dbType} --db-uri ${context.config.driverConfig.uri} update-db --path ${context.config.scanner.path} --action MARK_AS_EXECUTED" } @@ -91,7 +90,7 @@ class Executor(private val context: Context) { val executedScript = ExecutedScript.build(script, Execution(ExecutionStatus.OK), executorConfig.flags) overrideExecuted(executedScript) - if (!context.config.logs.porcelain) { logger.info { "${executedScript.name} only marked as executed (so not executed)" } } + logger.info { "${executedScript.name} only marked as executed (so not executed)" } executedScript } @@ -101,9 +100,9 @@ class Executor(private val context: Context) { private fun simulateAction(script: ScriptWithContent): ExecutedScript { when (script.action) { ScriptAction.RUN -> - if (!context.config.logs.porcelain) { logger.info { "${script.name} would have been executed" } } + logger.info { "${script.name} would have been executed" } ScriptAction.MARK_AS_EXECUTED -> - if (!context.config.logs.porcelain) { logger.info { "${script.name} would have been only marked as executed (so not executed)" } } + logger.info { "${script.name} would have been only marked as executed (so not executed)" } } return ExecutedScript.simulateExecuted(script, ExecutionStatus.OK, executorConfig.flags) @@ -113,7 +112,7 @@ class Executor(private val context: Context) { try { context.dbDriver.markAsExecuted(it) } catch (e: Exception) { - if (!context.config.logs.porcelain) { logger.error { "error during mark execution of ${it.name} " } } + logger.error { "error during mark execution of ${it.name} " } throw e // TODO handle interactive shell } @@ -123,7 +122,7 @@ class Executor(private val context: Context) { try { context.dbDriver.overrideScript(it) } catch (e: Exception) { - if (!context.config.logs.porcelain) { logger.error { "error during override of ${it.fullName()} " } } + logger.error { "error during override of ${it.fullName()} " } throw e } } diff --git a/modules/core/src/main/kotlin/datamaintain/core/step/sort/Sorter.kt b/modules/core/src/main/kotlin/datamaintain/core/step/sort/Sorter.kt index 93815ec0..75266b28 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/step/sort/Sorter.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/step/sort/Sorter.kt @@ -13,15 +13,14 @@ private val logger = KotlinLogging.logger {} class Sorter(private val context: Context) { fun sort(scripts: List): List { try { - if (!context.config.logs.porcelain) { logger.info { "Sort scripts..." } } + logger.info { "Sort scripts..." } val sortingStrategy = ByCaseInsensitiveSeparatorFreeAlphabeticalSortingStrategy() val sortedScripts = sortingStrategy.sort(scripts, Script::identifier) - if (!context.config.logs.porcelain) { - logger.info { "Scripts sorted" } - logger.info { "" } - } + logger.info { "Scripts sorted" } + logger.trace { sortedScripts.map { it.name } } + logger.info { "" } return sortedScripts } catch (datamaintainException: DatamaintainBaseException) { diff --git a/modules/core/src/main/kotlin/datamaintain/core/util/ProcessUtil.kt b/modules/core/src/main/kotlin/datamaintain/core/util/ProcessUtil.kt index fe845076..1ac557cc 100644 --- a/modules/core/src/main/kotlin/datamaintain/core/util/ProcessUtil.kt +++ b/modules/core/src/main/kotlin/datamaintain/core/util/ProcessUtil.kt @@ -1,29 +1,46 @@ package datamaintain.core.util import datamaintain.core.exception.DatamaintainProcessException +import mu.KotlinLogging import java.io.File import java.io.IOException import java.io.InputStream import java.util.concurrent.TimeUnit +private val logger = KotlinLogging.logger {} + fun List.runProcess( workingDir: File = File("."), timeoutValue: Long = 60, timeoutUnit: TimeUnit = TimeUnit.MINUTES, - outputReadFunction: ((InputStream) -> Unit)? = null + outputReadFunction: ((Sequence) -> Unit)? = null ): Int { try { + logger.trace { "executing shell command: '${this.joinToString(" ")}'" } val proc = ProcessBuilder(*this.toTypedArray()) .directory(workingDir) .redirectOutput(ProcessBuilder.Redirect.PIPE) .redirectError(ProcessBuilder.Redirect.PIPE) .start() + + // capture and print output if trace level is activated + val output = if (logger.isTraceEnabled) + proc.inputStream.bufferedReader().lineSequence().onEach { logger.trace { it } } + else + proc.inputStream.bufferedReader().lineSequence() + if (outputReadFunction != null) { - outputReadFunction(proc.inputStream) + outputReadFunction(output) + } else { + output.forEach { } } + proc.waitFor(timeoutValue, timeoutUnit) - return proc.exitValue() + val exitValue = proc.exitValue() + logger.trace { "shell command done with exit code: $exitValue" } + return exitValue } catch (e: IOException) { + logger.trace { "shell command error: $e" } throw DatamaintainProcessException(this, e.message ?: "") } } diff --git a/modules/core/src/test/kotlin/datamaintain/core/DatamaintainConfigTest.kt b/modules/core/src/test/kotlin/datamaintain/core/DatamaintainConfigTest.kt index eb5e4a09..fee11816 100644 --- a/modules/core/src/test/kotlin/datamaintain/core/DatamaintainConfigTest.kt +++ b/modules/core/src/test/kotlin/datamaintain/core/DatamaintainConfigTest.kt @@ -34,8 +34,6 @@ class DatamaintainConfigTest { get { scanner.identifierRegex.pattern }.isEqualTo(CoreConfigKey.SCAN_IDENTIFIER_REGEX.default) get { scanner.doesCreateTagsFromFolder }.isEqualTo(CoreConfigKey.CREATE_TAGS_FROM_FOLDER.default!!.toBoolean()) get { executor.executionMode }.isEqualTo(ExecutionMode.NORMAL) - get { logs.verbose }.isFalse() - get { logs.porcelain }.isFalse() get { name }.isNull() } } @@ -45,8 +43,6 @@ class DatamaintainConfigTest { System.setProperty("scan.path", "/new") System.setProperty(CoreConfigKey.CREATE_TAGS_FROM_FOLDER.key, "false") System.setProperty(CoreConfigKey.EXECUTION_MODE.key, "NORMAL") - System.setProperty(CoreConfigKey.VERBOSE.key, "FALSE") - System.setProperty(CoreConfigKey.PRINT_RELATIVE_PATH_OF_SCRIPT.key, "false") val config = DatamaintainConfig.buildConfig(DatamaintainConfigTest::class.java.getResourceAsStream("/config/default.properties"), FakeDriverConfig()) @@ -57,15 +53,11 @@ class DatamaintainConfigTest { get { filter.blacklistedTags }.isEqualTo(setOf(Tag("un"), Tag("deux"))) get { pruner.tagsToPlayAgain }.isEqualTo(setOf(Tag("again"))) get { executor.executionMode }.isEqualTo(ExecutionMode.NORMAL) - get { logs.verbose }.isFalse() - get { logs.porcelain }.isFalse() } System.clearProperty("scan.path") System.clearProperty(CoreConfigKey.CREATE_TAGS_FROM_FOLDER.key) System.clearProperty(CoreConfigKey.EXECUTION_MODE.key) - System.clearProperty(CoreConfigKey.VERBOSE.key) - System.clearProperty(CoreConfigKey.PRINT_RELATIVE_PATH_OF_SCRIPT.key) } @Test @@ -139,8 +131,6 @@ class DatamaintainConfigTest { expectedPath.resolve(Paths.get("src/test/resources/scanner_test_files/subfolder/03_file3")).toString() )) ) - get { logs.verbose }.isTrue() - get { logs.porcelain }.isTrue() get { name }.isEqualTo("myDefaultConfig") } } @@ -159,8 +149,6 @@ class DatamaintainConfigTest { .withOverrideExecutedScripts(true) .withExecutionMode(ExecutionMode.DRY) .withDefaultScriptAction(ScriptAction.OVERRIDE_EXECUTED) - .withVerbose(true) - .withPorcelain(true) .addWhitelistedTag(Tag("whitelisted1")) .addWhitelistedTag(Tag("whitelisted2")) .addBlacklistedTag(Tag("blacklisted1")) @@ -183,8 +171,6 @@ class DatamaintainConfigTest { get { executor.overrideExecutedScripts }.isTrue() get { executor.executionMode } isEqualTo ExecutionMode.DRY get { executor.defaultScriptAction } isEqualTo ScriptAction.OVERRIDE_EXECUTED - get { logs.verbose }.isTrue() - get { logs.porcelain }.isTrue() get { filter.whitelistedTags }.containsExactlyInAnyOrder(Tag("whitelisted1"), Tag("whitelisted2")) get { filter.blacklistedTags }.containsExactlyInAnyOrder(Tag("blacklisted1"), Tag("blacklisted2")) get { pruner.tagsToPlayAgain }.containsExactlyInAnyOrder(Tag("tagToPlayAgain1"), Tag("tagToPlayAgain2")) @@ -212,8 +198,6 @@ class DatamaintainConfigTest { get { executor.overrideExecutedScripts } isEqualTo CoreConfigKey.PRUNE_OVERRIDE_UPDATED_SCRIPTS.default!!.toBoolean() get { executor.executionMode } isEqualTo ExecutionMode.NORMAL get { executor.defaultScriptAction } isEqualTo ScriptAction.RUN - get { logs.verbose }.isFalse() - get { logs.porcelain }.isFalse() get { filter.whitelistedTags }.isEmpty() get { filter.blacklistedTags }.isEmpty() get { pruner.tagsToPlayAgain }.isEmpty() diff --git a/modules/core/src/test/kotlin/datamaintain/core/report/ReportTest.kt b/modules/core/src/test/kotlin/datamaintain/core/report/ReportTest.kt index 21e2f608..18021fa3 100644 --- a/modules/core/src/test/kotlin/datamaintain/core/report/ReportTest.kt +++ b/modules/core/src/test/kotlin/datamaintain/core/report/ReportTest.kt @@ -1,6 +1,8 @@ package datamaintain.core.report +import ch.qos.logback.classic.Level import ch.qos.logback.classic.Logger +import ch.qos.logback.classic.LoggerContext import datamaintain.core.step.Step import datamaintain.core.step.check.rules.implementations.AlwaysSucceedCheck import datamaintain.test.ScriptWithContentWithFixedChecksum @@ -19,14 +21,21 @@ import strikt.assertions.map internal class ReportTest { private val logger = LoggerFactory.getLogger("datamaintain.core.report.Report") as Logger + private val loggerLevel: Level? = logger.level private val testAppender = TestAppender() @BeforeEach fun setupLogger() { + logger.level = Level.INFO logger.addAppender(testAppender) testAppender.start() } + @AfterEach + fun afterEach() { + logger.level = loggerLevel + } + /// builds an example report containining everything private fun buildReport(): Report = Report( @@ -34,13 +43,8 @@ internal class ReportTest { filteredScripts = listOf(ScriptWithContentWithFixedChecksum("Filtered Script 1", "Filter Identifier 1", "CHKFIL2")), prunedScripts = listOf(ScriptWithContentWithFixedChecksum("Pruned Script 1", "Prune Identifier 1", "CHKPRUN3")), executedScripts = listOf( - buildReportExecutedScript( - "script1", - "porcelainName1" - ), buildReportExecutedScript( - "script2", - "porcelainName2" - ) + buildReportExecutedScript("script1"), + buildReportExecutedScript("script2") ), validatedCheckRules = listOf(AlwaysSucceedCheck()) ) @@ -48,81 +52,100 @@ internal class ReportTest { @Nested inner class ExecuteLogs { @Test - fun `should display relative paths when porcelain is true`() { + fun `should print script name in trace`() { // Given val report = Report( executedScripts = listOf( buildReportExecutedScript( "script1", - "porcelainName1" ), buildReportExecutedScript( "script2", - "porcelainName2" ) ) ) + // switch to TRACE + logger.level = Level.TRACE // When - report.print(verbose = true, porcelain = true) + report.print() // Then expectThat(testAppender.events) { - get { get(0).message }.isEqualTo( - "porcelainName1" + get { get(6).message }.isEqualTo( + " -> script1" ) - get { get(1).message }.isEqualTo( - "porcelainName2" + get { get(7).message }.isEqualTo( + " -> script2" ) } } @Test - fun `should not display relative paths when porcelain is false`() { + fun `should print only summary`() { // Given - val report = Report( - executedScripts = listOf( - buildReportExecutedScript( - "script1", - "porcelainName1" - ), buildReportExecutedScript( - "script2", - "porcelainName2" - ) - ) - ) + val report = buildReport() // When - report.print(verbose = true, porcelain = false) + report.print() // Then - expectThat(testAppender.events) { - get { get(6).message }.isEqualTo( - " -> script1" - ) - get { get(7).message }.isEqualTo( + expectThat(testAppender.events).map { it.message }.containsExactly(listOf( + "Summary => ", + "- 2 files executed", + " -> script1", " -> script2" - ) - } + )) } @Test - fun `should print only summary if neither verbose nor porcelain are set`() { + fun `should print only summary on debug`() { // Given val report = buildReport() + // switch to DEBUG + logger.level = Level.DEBUG + // When - report.print(verbose = false, porcelain = false) + report.print() // Then expectThat(testAppender.events).map { it.message }.containsExactly(listOf( - "Summary => ", - "- 1 files scanned", - "- 1 files filtered", - "- 1 files pruned", - "- 1 check rules validated", - "- 2 files executed", - " -> script1", - " -> script2" + "Summary => ", + "- 1 files scanned", + "- 1 files filtered", + "- 1 files pruned", + "- 1 check rules validated", + "- 2 files executed", + " -> script1", + " -> script2" + )) + } + + @Test + fun `should print only summary on trace`() { + // Given + val report = buildReport() + + // switch to TRACE + logger.level = Level.TRACE + + // When + report.print() + + // Then + expectThat(testAppender.events).map { it.message }.containsExactly(listOf( + "Summary => ", + "- 1 files scanned", + " -> Scanned Script 1", + "- 1 files filtered", + " -> Filtered Script 1", + "- 1 files pruned", + " -> Pruned Script 1", + "- 1 check rules validated", + " -> AlwaysSucceed", + "- 2 files executed", + " -> script1", + " -> script2" )) } @@ -132,8 +155,11 @@ internal class ReportTest { // Given val report = buildReport() + // switch to TRACE + logger.level = Level.TRACE + // When - report.print(verbose = true, porcelain = false) + report.print() // Then expectThat(testAppender.events).map { it.message }.containsExactly(listOf( @@ -157,8 +183,11 @@ internal class ReportTest { // Given val report = buildReport() + // switch to TRACE + logger.level = Level.TRACE + // When - report.print(verbose = true, porcelain = false, maxStepToShow = Step.SCAN) + report.print(maxStepToShow = Step.SCAN) // Then expectThat(testAppender.events).map { it.message }.containsExactly(listOf( @@ -173,8 +202,11 @@ internal class ReportTest { // Given val report = buildReport() + // switch to TRACE + logger.level = Level.TRACE + // When - report.print(verbose = true, porcelain = false, maxStepToShow = Step.FILTER) + report.print(maxStepToShow = Step.FILTER) // Then expectThat(testAppender.events).map { it.message }.containsExactly(listOf( @@ -191,8 +223,11 @@ internal class ReportTest { // Given val report = buildReport() + // switch to TRACE + logger.level = Level.TRACE + // When - report.print(verbose = true, porcelain = false, maxStepToShow = Step.SORT) + report.print(maxStepToShow = Step.SORT) // Then expectThat(testAppender.events).map { it.message }.containsExactly(listOf( @@ -209,8 +244,11 @@ internal class ReportTest { // Given val report = buildReport() + // switch to TRACE + logger.level = Level.TRACE + // When - report.print(verbose = true, porcelain = false, maxStepToShow = Step.PRUNE) + report.print(maxStepToShow = Step.PRUNE) // Then expectThat(testAppender.events).map { it.message }.containsExactly(listOf( @@ -229,8 +267,11 @@ internal class ReportTest { // Given val report = buildReport() + // switch to TRACE + logger.level = Level.TRACE + // When - report.print(verbose = true, porcelain = false, maxStepToShow = Step.CHECK) + report.print(maxStepToShow = Step.CHECK) // Then expectThat(testAppender.events).map { it.message }.containsExactly(listOf( @@ -251,8 +292,11 @@ internal class ReportTest { // Given val report = buildReport() + // switch to TRACE + logger.level = Level.TRACE + // When - report.print(verbose = true, porcelain = false, maxStepToShow = Step.EXECUTE) + report.print(maxStepToShow = Step.EXECUTE) // Then expectThat(testAppender.events).map { it.message }.containsExactly(listOf( @@ -270,7 +314,6 @@ internal class ReportTest { " -> script2" )) } - } @AfterEach diff --git a/modules/core/src/test/kotlin/datamaintain/core/script/FileScriptTest.kt b/modules/core/src/test/kotlin/datamaintain/core/script/FileScriptTest.kt index 3eabd826..cf353dca 100644 --- a/modules/core/src/test/kotlin/datamaintain/core/script/FileScriptTest.kt +++ b/modules/core/src/test/kotlin/datamaintain/core/script/FileScriptTest.kt @@ -39,33 +39,4 @@ internal class FileScriptTest { .failed() .isA() } - - @Test - fun `should not compute the porcelainName when porcelain is set to false`() { - //Given - val config = buildDatamaintainConfig(path = Paths.get("/scan/path"), porcelain = false) - val scriptFile = File("/scan/path/files/my_file") - - //WHEN - val fileScript = FileScript.from(config = config, tags = setOf(), scriptFile = scriptFile) - - //THEN - expectThat(fileScript.porcelainName) - .isNull() - } - - @Test - fun `should compute the porcelainName when porcelain is set to true`() { - //Given - val config = buildDatamaintainConfig(path = Paths.get("/scan/path"), porcelain = true) - val scriptFile = File("/scan/path/files/my_file") - - //WHEN - val fileScript = FileScript.from(config = config, tags = setOf(), scriptFile = scriptFile) - - //THEN - expectThat(fileScript.porcelainName) - .isNotNull() - .isEqualTo("files/my_file") - } } diff --git a/modules/core/src/test/kotlin/datamaintain/core/script/InMemoryScript.kt b/modules/core/src/test/kotlin/datamaintain/core/script/InMemoryScript.kt index e0f64215..cd0e2df9 100644 --- a/modules/core/src/test/kotlin/datamaintain/core/script/InMemoryScript.kt +++ b/modules/core/src/test/kotlin/datamaintain/core/script/InMemoryScript.kt @@ -10,7 +10,7 @@ data class InMemoryScript( override val identifier: String, override val tags: Set = setOf(), override var action: ScriptAction = DatamaintainExecutorConfig.defaultAction, - override val porcelainName: String = "") : ScriptWithContent { +) : ScriptWithContent { override val checksum: String by lazy { content.hash() diff --git a/modules/core/src/test/kotlin/datamaintain/core/step/ScannerTest.kt b/modules/core/src/test/kotlin/datamaintain/core/step/ScannerTest.kt index aa8ae12f..faeb63ec 100644 --- a/modules/core/src/test/kotlin/datamaintain/core/step/ScannerTest.kt +++ b/modules/core/src/test/kotlin/datamaintain/core/step/ScannerTest.kt @@ -15,14 +15,13 @@ import java.nio.file.Paths internal class ScannerTest { private val scanner = prepareScanner() - fun prepareScanner(tagsMatchers: Set = emptySet(), doesCreateTagsFromFolder: Boolean = false, porcelain: Boolean = true): Scanner { + fun prepareScanner(tagsMatchers: Set = emptySet(), doesCreateTagsFromFolder: Boolean = false): Scanner { return Scanner(Context( buildDatamaintainConfig( Paths.get("src/test/resources/scanner_test_files"), Regex("(.*?)_.*"), tagsMatchers = tagsMatchers, doesCreateTagsFromFolder = doesCreateTagsFromFolder, - porcelain = porcelain ), dbDriver = FakeDatamaintainDriver())) } @@ -137,25 +136,6 @@ internal class ScannerTest { } } - @Test - fun `should collect script porcelain names`() { - // Given - - // When - val scripts = scanner.scan() - - // Then - expectThat(scripts) { - size.isEqualTo(6) - get(0).get { this.porcelainName }.isEqualTo("01_file1") - get(1).get { this.porcelainName }.isEqualTo("02_file2") - get(2).get { this.porcelainName }.isEqualTo("subfolder/03_file3") - get(3).get { this.porcelainName }.isEqualTo("subfolder/04_file4") - get(4).get { this.porcelainName }.isEqualTo("10_file10") - get(5).get { this.porcelainName }.isEqualTo("subfolder/old/11_file11") - } - } - @Nested inner class TagsFromParents { @Test @@ -200,53 +180,4 @@ internal class ScannerTest { } } } - - @Nested - inner class PorcelainNameComputation { - @Test - fun `should not compute porcelainName when porcelain is set to false`() { - //GIVEN - val scanner = prepareScanner(porcelain = false) - - //WHEN - val scripts: List = scanner.scan() - - //THEN - expectThat(scripts) { - size.isEqualTo(6) - get(0).get { this.porcelainName }.isNull() - get(1).get { this.porcelainName }.isNull() - get(2).get { this.porcelainName }.isNull() - get(3).get { this.porcelainName }.isNull() - get(4).get { this.porcelainName }.isNull() - get(5).get { this.porcelainName }.isNull() - } - } - - @Test - fun `should compute porcelainName when porcelain is set to true`() { - //GIVEN - val scanner = prepareScanner(porcelain = true) - - //WHEN - val scripts: List = scanner.scan() - - //THEN - expectThat(scripts) { - size.isEqualTo(6) - get(0).get { this.porcelainName }.isNotNull() - get(0).get { this.porcelainName }.isEqualTo("01_file1") - get(1).get { this.porcelainName }.isNotNull() - get(1).get { this.porcelainName }.isEqualTo("02_file2") - get(2).get { this.porcelainName }.isNotNull() - get(2).get { this.porcelainName }.isEqualTo("subfolder/03_file3") - get(3).get { this.porcelainName }.isNotNull() - get(3).get { this.porcelainName }.isEqualTo("subfolder/04_file4") - get(4).get { this.porcelainName }.isNotNull() - get(4).get { this.porcelainName }.isEqualTo("10_file10") - get(5).get { this.porcelainName }.isNotNull() - get(5).get { this.porcelainName }.isEqualTo("subfolder/old/11_file11") - } - } - } } diff --git a/modules/core/src/test/kotlin/datamaintain/test/DatamaintainConfigBuildingUtils.kt b/modules/core/src/test/kotlin/datamaintain/test/DatamaintainConfigBuildingUtils.kt index d4e167cb..a18f8bb5 100644 --- a/modules/core/src/test/kotlin/datamaintain/test/DatamaintainConfigBuildingUtils.kt +++ b/modules/core/src/test/kotlin/datamaintain/test/DatamaintainConfigBuildingUtils.kt @@ -23,8 +23,6 @@ fun buildDatamaintainConfig( executionMode: ExecutionMode = ExecutionMode.NORMAL, defaultScriptAction: ScriptAction = DatamaintainExecutorConfig.defaultAction, driverConfig: DatamaintainDriverConfig = FakeDriverConfig(), - verbose: Boolean = CoreConfigKey.VERBOSE.default!!.toBoolean(), - porcelain: Boolean = CoreConfigKey.PRINT_RELATIVE_PATH_OF_SCRIPT.default!!.toBoolean() ) = DatamaintainConfig( scanner = DatamaintainScannerConfig( path = path, @@ -48,8 +46,4 @@ fun buildDatamaintainConfig( overrideExecutedScripts = overrideExecutedScripts ), driverConfig = driverConfig, - logs = DatamaintainLogsConfig( - verbose = verbose, - porcelain = porcelain - ) ) diff --git a/modules/core/src/test/kotlin/datamaintain/test/ScriptBuildingUtils.kt b/modules/core/src/test/kotlin/datamaintain/test/ScriptBuildingUtils.kt index 8fb7b9ca..fec30a11 100644 --- a/modules/core/src/test/kotlin/datamaintain/test/ScriptBuildingUtils.kt +++ b/modules/core/src/test/kotlin/datamaintain/test/ScriptBuildingUtils.kt @@ -3,11 +3,10 @@ package datamaintain.test import datamaintain.core.script.ExecutionStatus import datamaintain.core.script.ReportExecutedScript -fun buildReportExecutedScript(scriptName: String, porcelainName: String?) = +fun buildReportExecutedScript(scriptName: String) = ReportExecutedScript( name = scriptName, - porcelainName = porcelainName, checksum = "", identifier = "", executionStatus = ExecutionStatus.OK - ) \ No newline at end of file + ) diff --git a/modules/core/src/test/kotlin/datamaintain/test/ScriptWithContentWithfixedHashCode.kt b/modules/core/src/test/kotlin/datamaintain/test/ScriptWithContentWithfixedHashCode.kt index 8ccba2e0..b5abeedf 100644 --- a/modules/core/src/test/kotlin/datamaintain/test/ScriptWithContentWithfixedHashCode.kt +++ b/modules/core/src/test/kotlin/datamaintain/test/ScriptWithContentWithfixedHashCode.kt @@ -10,7 +10,6 @@ class ScriptWithContentWithFixedChecksum( override val checksum: String, override val tags: Set = setOf(), override var action: ScriptAction = ScriptAction.RUN, - override val porcelainName: String = "" ) : ScriptWithContent { override val content: String get() = "" diff --git a/modules/core/src/test/kotlin/datamaintain/test/TestScriptWithContent.kt b/modules/core/src/test/kotlin/datamaintain/test/TestScriptWithContent.kt index 5aa87a62..923abc68 100644 --- a/modules/core/src/test/kotlin/datamaintain/test/TestScriptWithContent.kt +++ b/modules/core/src/test/kotlin/datamaintain/test/TestScriptWithContent.kt @@ -9,7 +9,6 @@ class TestScriptWithContent( override val identifier: String, override val tags: Set = setOf(), override var action: ScriptAction = ScriptAction.RUN, - override val porcelainName: String ) : ScriptWithContent { override val checksum: String get() = name.hashCode().toString() diff --git a/modules/driver-jdbc/src/main/kotlin/datamaintain/db/driver/jdbc/JdbcDriver.kt b/modules/driver-jdbc/src/main/kotlin/datamaintain/db/driver/jdbc/JdbcDriver.kt index 012a5bb0..c37603a7 100644 --- a/modules/driver-jdbc/src/main/kotlin/datamaintain/db/driver/jdbc/JdbcDriver.kt +++ b/modules/driver-jdbc/src/main/kotlin/datamaintain/db/driver/jdbc/JdbcDriver.kt @@ -4,12 +4,15 @@ import datamaintain.core.db.driver.DatamaintainDriver import datamaintain.core.script.* import datamaintain.core.step.executor.Execution import datamaintain.db.driver.jdbc.exception.JdbcQueryException +import mu.KotlinLogging import java.sql.Connection import java.sql.DriverManager import java.sql.ResultSet import java.sql.SQLException import java.util.* +private val logger = KotlinLogging.logger {} + /** * @param jdbcUri uri of the jdbc to use * @param connection session with the wanted database @@ -29,11 +32,13 @@ class JdbcDriver(jdbcUri: String, connection.createStatement().executeUpdate(script.content) Execution(ExecutionStatus.OK, null) } catch (e: SQLException) { + logger.debug { "Script ${script.name} - KO - ${e.message}" } Execution(ExecutionStatus.KO, e.message) } } override fun listExecutedScripts(): Sequence { + logger.debug { "Fetching executed scripts" } createExecutedScriptsTableIfNotExists() val statement = connection.createStatement() @@ -46,6 +51,7 @@ class JdbcDriver(jdbcUri: String, } override fun markAsExecuted(executedScript: ExecutedScript): ExecutedScript { + logger.debug { "Script ${executedScript.name} - Mark as executed" } val insertStmt = connection.prepareStatement(""" INSERT INTO $EXECUTED_SCRIPTS_TABLE (id, name, checksum, identifier, executionStatus, action) VALUES (?, ?, ?, ?, ?, ?)""" @@ -71,6 +77,7 @@ class JdbcDriver(jdbcUri: String, } fun createExecutedScriptsTableIfNotExists() { + logger.debug { "Creating table $EXECUTED_SCRIPTS_TABLE" } val tableCreationStatement = connection.prepareStatement(""" CREATE TABLE IF NOT EXISTS $EXECUTED_SCRIPTS_TABLE ( id VARCHAR(255) NOT NULL, @@ -87,6 +94,7 @@ class JdbcDriver(jdbcUri: String, } override fun overrideScript(executedScript: ExecutedScript): ExecutedScript { + logger.debug { "Script ${executedScript.name} - Overriding executed script" } connection.prepareStatement(""" UPDATE $EXECUTED_SCRIPTS_TABLE SET action = '${ScriptAction.OVERRIDE_EXECUTED.name}', diff --git a/modules/driver-jdbc/src/main/kotlin/datamaintain/db/driver/jdbc/JdbcDriverConfig.kt b/modules/driver-jdbc/src/main/kotlin/datamaintain/db/driver/jdbc/JdbcDriverConfig.kt index 9d96663f..700cf135 100644 --- a/modules/driver-jdbc/src/main/kotlin/datamaintain/db/driver/jdbc/JdbcDriverConfig.kt +++ b/modules/driver-jdbc/src/main/kotlin/datamaintain/db/driver/jdbc/JdbcDriverConfig.kt @@ -40,12 +40,12 @@ data class JdbcDriverConfig @JvmOverloads constructor( override fun toDriver(connectionString: String) = JdbcDriver(connectionString) override fun log() { - logger.info { "JDBC driver configuration: " } - logger.info { "- jdbc uri -> $uri" } - logger.info { "- trust uri -> $trustUri" } - logger.info { "- print output -> $printOutput" } - logger.info { "- save output -> $saveOutput" } - logger.info { "" } + logger.debug { "JDBC driver configuration: " } + logger.debug { "- jdbc uri -> $uri" } + logger.debug { "- trust uri -> $trustUri" } + logger.debug { "- print output -> $printOutput" } + logger.debug { "- save output -> $saveOutput" } + logger.debug { "" } } class Builder { diff --git a/modules/driver-jdbc/src/test/kotlin/datamaintain/db/driver/jdbc/InMemoryScript.kt b/modules/driver-jdbc/src/test/kotlin/datamaintain/db/driver/jdbc/InMemoryScript.kt index a1db6446..247d3d51 100644 --- a/modules/driver-jdbc/src/test/kotlin/datamaintain/db/driver/jdbc/InMemoryScript.kt +++ b/modules/driver-jdbc/src/test/kotlin/datamaintain/db/driver/jdbc/InMemoryScript.kt @@ -13,7 +13,6 @@ data class InMemoryScript( override val identifier: String, override val tags: Set = setOf(), override var action: ScriptAction = DatamaintainExecutorConfig.defaultAction, - override val porcelainName: String? ) : ScriptWithContent { override val checksum: String by lazy { @@ -25,3 +24,4 @@ data class InMemoryScript( return BigInteger(1, md.digest(toByteArray())).toString(16).padStart(32, '0') } } + diff --git a/modules/driver-mongo/src/main/kotlin/datamaintain/db/driver/mongo/MongoDriver.kt b/modules/driver-mongo/src/main/kotlin/datamaintain/db/driver/mongo/MongoDriver.kt index f7a163c1..8ef5d29d 100644 --- a/modules/driver-mongo/src/main/kotlin/datamaintain/db/driver/mongo/MongoDriver.kt +++ b/modules/driver-mongo/src/main/kotlin/datamaintain/db/driver/mongo/MongoDriver.kt @@ -45,29 +45,33 @@ class MongoDriver(mongoUri: String, var executionOutput: String? = null - val exitCode = listOf(clientPath.toString(), uri, "--quiet", scriptPath.toString()).runProcess() { inputStream -> - executionOutput = processDriverOutput(inputStream) + val exitCode = listOf(clientPath.toString(), uri, "--quiet", scriptPath.toString()).runProcess { outputLines -> + executionOutput = processDriverOutput(outputLines) } - return Execution(if (exitCode == 0) ExecutionStatus.OK else ExecutionStatus.KO, executionOutput) + return if (exitCode == 0) { + Execution(ExecutionStatus.OK, executionOutput) + } else { + Execution(ExecutionStatus.KO, executionOutput) + } } - private fun processDriverOutput(inputStream: InputStream): String? { + private fun processDriverOutput(outputLines: Sequence): String? { if (saveOutput || printOutput) { - val lines = inputStream.bufferedReader().lines().asSequence() - .onEach { - if (printOutput) { - logger.info { it } - } + val lines = outputLines + .onEach { + if (printOutput) { + logger.info { it } } - .toList() + } + .toList() if (saveOutput) { val totalOutputSize = lines.map { line -> line.length }.foldRight(0, Int::plus) var dropped = 0 return lines .dropLastWhile { line -> val drop = totalOutputSize - dropped > OUTPUT_MAX_SIZE - if(drop) { + if (drop) { dropped += line.length } drop @@ -123,15 +127,13 @@ class MongoDriver(mongoUri: String, } // Execute - val exitCode = listOf(clientPath.toString(), uri, "--quiet", "--eval", evalQuery).runProcess { inputStream -> - var lines = inputStream.bufferedReader().lines().toList() - + val exitCode = listOf(clientPath.toString(), uri, "--quiet", "--eval", evalQuery).runProcess { outputLines -> // Dropwhile is a workaround to fix this issue: https://jira.mongodb.org/browse/SERVER-27159 if (mongoShell == MongoShell.MONGO) { - lines = lines.dropWhile { !(it.startsWith("[").or(it.startsWith("{"))) } + outputLines.dropWhile { !(it.startsWith("[").or(it.startsWith("{"))) } } - executionOutput = lines.joinToString("\n") + executionOutput = outputLines.joinToString("\n") } if (exitCode != 0 || executionOutput == null) { diff --git a/modules/driver-mongo/src/main/kotlin/datamaintain/db/driver/mongo/MongoDriverConfig.kt b/modules/driver-mongo/src/main/kotlin/datamaintain/db/driver/mongo/MongoDriverConfig.kt index 33bd31be..f5803076 100644 --- a/modules/driver-mongo/src/main/kotlin/datamaintain/db/driver/mongo/MongoDriverConfig.kt +++ b/modules/driver-mongo/src/main/kotlin/datamaintain/db/driver/mongo/MongoDriverConfig.kt @@ -83,13 +83,13 @@ data class MongoDriverConfig @JvmOverloads constructor(override val uri: String, ) override fun log() { - logger.info { "Mongo driver configuration: " } - logger.info { "- mongo uri -> $uri" } - logger.info { "- mongo tmp file -> $tmpFilePath" } - logger.info { "- mongo client -> $clientPath" } - logger.info { "- mongo print output -> $printOutput" } - logger.info { "- mongo save output -> $saveOutput" } - logger.info { "" } + logger.debug { "Mongo driver configuration: " } + logger.debug { "- mongo uri -> $uri" } + logger.debug { "- mongo tmp file -> $tmpFilePath" } + logger.debug { "- mongo client -> $clientPath" } + logger.debug { "- mongo print output -> $printOutput" } + logger.debug { "- mongo save output -> $saveOutput" } + logger.debug { "" } } class Builder { diff --git a/modules/driver-mongo/src/test/kotlin/datamaintain/db/driver/mongo/InMemoryScript.kt b/modules/driver-mongo/src/test/kotlin/datamaintain/db/driver/mongo/InMemoryScript.kt index 51062607..2c2d6605 100644 --- a/modules/driver-mongo/src/test/kotlin/datamaintain/db/driver/mongo/InMemoryScript.kt +++ b/modules/driver-mongo/src/test/kotlin/datamaintain/db/driver/mongo/InMemoryScript.kt @@ -13,7 +13,7 @@ data class InMemoryScript( override val identifier: String, override val tags: Set = setOf(), override var action: ScriptAction = DatamaintainExecutorConfig.defaultAction, - override val porcelainName: String = "") : ScriptWithContent { +) : ScriptWithContent { override val checksum: String by lazy { content.hash() diff --git a/modules/test/src/test/kotlin/datamaintain/test/MongoIT.kt b/modules/test/src/test/kotlin/datamaintain/test/MongoIT.kt index 3f8522c1..8fa7e2ff 100644 --- a/modules/test/src/test/kotlin/datamaintain/test/MongoIT.kt +++ b/modules/test/src/test/kotlin/datamaintain/test/MongoIT.kt @@ -147,7 +147,6 @@ class MongoIT : AbstractMongoDbTest() { "--db-type", "mongo", "--db-uri", mongoUri(), "update-db", - "--verbose", "--path", "src/test/resources/integration/override", "--identifier-regex", "(.*?)_.*", "--execution-mode", "NORMAL",