make progress info level configurable

merge-requests/1/merge
ansgarz 3 years ago
parent 2d4607964f
commit 122fa68850

@ -10,11 +10,12 @@ buildscript {
} }
apply plugin: 'org.jetbrains.kotlin.jvm' apply plugin: 'org.jetbrains.kotlin.jvm'
apply plugin: 'java-library'
apply plugin: 'java-test-fixtures' apply plugin: 'java-test-fixtures'
apply plugin: 'maven-publish' apply plugin: 'maven-publish'
group = 'io.provs' group = 'io.provs'
version = '0.8.10-SNAPSHOT' version = '0.8.11-SNAPSHOT'
repositories { repositories {
mavenCentral() mavenCentral()
@ -38,6 +39,7 @@ test {
} }
compileJava.options.debugOptions.debugLevel = "source,lines,vars" compileJava.options.debugOptions.debugLevel = "source,lines,vars"
compileTestFixturesJava.options.debugOptions.debugLevel = "source,lines,vars"
compileTestJava.options.debugOptions.debugLevel = "source,lines,vars" compileTestJava.options.debugOptions.debugLevel = "source,lines,vars"
sourceCompatibility = 1.11 sourceCompatibility = 1.11

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

@ -5,68 +5,103 @@ import io.provs.platforms.UbuntuProv
import io.provs.platforms.WinProv import io.provs.platforms.WinProv
import io.provs.processors.LocalProcessor import io.provs.processors.LocalProcessor
import io.provs.processors.Processor import io.provs.processors.Processor
import org.slf4j.LoggerFactory
enum class ProgressType { NONE, DOTS, BASIC, FULL_LOG }
enum class ResultMode { NONE, LAST, ALL, FAILEXIT } enum class ResultMode { NONE, LAST, ALL, FAILEXIT }
enum class OS { WINDOWS, LINUX } enum class OS { WINDOWS, LINUX }
/** /**
* This main class offers methods to execute shell commands either locally or remotely (via ssh) or in a docker * This main class offers methods to execute shell commands.
* The commands are executed locally, remotely (via ssh) or in a docker container
* depending on the processor which is passed to the constructor. * depending on the processor which is passed to the constructor.
*/ */
open class Prov protected constructor(private val processor: Processor, val name: String? = null) { open class Prov protected constructor(
private val processor: Processor,
val name: String? = null,
private val progressType: ProgressType = ProgressType.BASIC
) {
init {
if (progressType == ProgressType.FULL_LOG) {
val log = LoggerFactory.getILoggerFactory()
.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME) as (ch.qos.logback.classic.Logger)
log.level = ch.qos.logback.classic.Level.INFO
}
}
companion object Factory { companion object Factory {
lateinit var prov: Prov private lateinit var defaultProvInstance: Prov
fun defaultInstance(platform: String? = null): Prov { fun defaultInstance(platform: String? = null): Prov {
return if (::prov.isInitialized) { return if (::defaultProvInstance.isInitialized) {
prov defaultProvInstance
} else { } else {
prov = newInstance(platform = platform, name = "default instance") defaultProvInstance = newInstance(platform = platform, name = "default instance")
prov defaultProvInstance
} }
} }
fun newInstance(processor: Processor = LocalProcessor(), platform: String? = null, name: String? = null): Prov { fun newInstance(
processor: Processor = LocalProcessor(),
platform: String? = null,
name: String? = null,
progressType: ProgressType = ProgressType.BASIC
): Prov {
val os = platform ?: System.getProperty("os.name") val os = platform ?: System.getProperty("os.name")
return when { return when {
os.toUpperCase().contains(OS.LINUX.name) -> UbuntuProv(processor, name) os.toUpperCase().contains(OS.LINUX.name) -> UbuntuProv(processor, name, progressType)
os.toUpperCase().contains(OS.WINDOWS.name) -> WinProv(processor, name) os.toUpperCase().contains(OS.WINDOWS.name) -> WinProv(processor, name, progressType)
else -> throw Exception("OS not supported") else -> throw Exception("OS not supported")
} }
} }
} }
private val internalResults = arrayListOf<InternalResult>()
private val internalResults = arrayListOf<ResultLine>()
private var level = 0 private var level = 0
private var previousLevel = 0 private var previousLevel = 0
private var exit = false private var exit = false
private var runInContainerWithName: String? = null private var runInContainerWithName: String? = null
/**
// task defining functions * defines a task with default success behavior, i.e. returns success if all subtasks finished with success.
* Same as requireAll.
*/
fun def(a: Prov.() -> ProvResult): ProvResult { fun def(a: Prov.() -> ProvResult): ProvResult {
return handle(ResultMode.ALL) { a() } return handle(ResultMode.ALL) { a() }
} }
/**
* defines a task, which returns success if the the last subtasks or last value returns success
*/
fun requireLast(a: Prov.() -> ProvResult): ProvResult { fun requireLast(a: Prov.() -> ProvResult): ProvResult {
return handle(ResultMode.LAST) { a() } return handle(ResultMode.LAST) { a() }
} }
/**
* defines a task, which always returns success
*/
fun optional(a: Prov.() -> ProvResult): ProvResult { fun optional(a: Prov.() -> ProvResult): ProvResult {
return handle(ResultMode.NONE) { a() } return handle(ResultMode.NONE) { a() }
} }
/**
* defines a task, which returns success if all subtasks finished with success
*/
fun requireAll(a: Prov.() -> ProvResult): ProvResult { fun requireAll(a: Prov.() -> ProvResult): ProvResult {
return handle(ResultMode.ALL) { a() } return handle(ResultMode.ALL) { a() }
} }
/**
* defines a task, which exits the overall execution on failure
*/
fun exitOnFailure(a: Prov.() -> ProvResult): ProvResult { fun exitOnFailure(a: Prov.() -> ProvResult): ProvResult {
return handle(ResultMode.FAILEXIT) { a() } return handle(ResultMode.FAILEXIT) { a() }
} }
@ -80,7 +115,9 @@ open class Prov protected constructor(private val processor: Processor, val name
} }
// execute programs /**
* execute program with parameters
*/
fun xec(vararg s: String): ProvResult { fun xec(vararg s: String): ProvResult {
val cmd = runInContainerWithName?.let { cmdInContainer(it, *s) } ?: s val cmd = runInContainerWithName?.let { cmdInContainer(it, *s) } ?: s
val result = processor.x(*cmd) val result = processor.x(*cmd)
@ -92,6 +129,9 @@ open class Prov protected constructor(private val processor: Processor, val name
) )
} }
/**
* execute program with parameters without logging (to be used if secrets are involved)
*/
fun xecNoLog(vararg s: String): ProvResult { fun xecNoLog(vararg s: String): ProvResult {
val cmd = runInContainerWithName?.let { cmdInContainer(it, *s) } ?: s val cmd = runInContainerWithName?.let { cmdInContainer(it, *s) } ?: s
val result = processor.xNoLog(*cmd) val result = processor.xNoLog(*cmd)
@ -103,19 +143,6 @@ open class Prov protected constructor(private val processor: Processor, val name
) )
} }
private fun cmdInContainer(containerName: String, vararg args: String): Array<String> {
return arrayOf(SHELL, "-c", "sudo docker exec $containerName " + buildCommand(*args))
}
private fun buildCommand(vararg args: String) : String {
return if (args.size == 1)
args[0].escapeAndEncloseByDoubleQuoteForShell()
else
if (args.size == 3 && SHELL.equals(args[0]) && "-c".equals(args[1]))
SHELL + " -c " + args[2].escapeAndEncloseByDoubleQuoteForShell()
else
args.joinToString(separator = " ")
}
/** /**
* Executes a command by using the shell. * Executes a command by using the shell.
@ -172,7 +199,7 @@ open class Prov protected constructor(private val processor: Processor, val name
/** /**
* Adds an ProvResult to the overall success evaluation. * Adds a ProvResult to the overall success evaluation.
* Intended for use in methods which do not automatically add results. * Intended for use in methods which do not automatically add results.
*/ */
fun addResultToEval(result: ProvResult) = requireAll { fun addResultToEval(result: ProvResult) = requireAll {
@ -200,6 +227,22 @@ open class Prov protected constructor(private val processor: Processor, val name
} }
// todo: put logic in subclasses, such as UbuntuProv
private fun cmdInContainer(containerName: String, vararg args: String): Array<String> {
return arrayOf(SHELL, "-c", "sudo docker exec $containerName " + buildCommand(*args))
}
private fun buildCommand(vararg args: String): String {
return if (args.size == 1)
args[0].escapeAndEncloseByDoubleQuoteForShell()
else
if (args.size == 3 && SHELL.equals(args[0]) && "-c".equals(args[1]))
SHELL + " -c " + args[2].escapeAndEncloseByDoubleQuoteForShell()
else
args.joinToString(separator = " ")
}
/** /**
* Provides result handling, e.g. gather results for result summary * Provides result handling, e.g. gather results for result summary
*/ */
@ -210,13 +253,14 @@ open class Prov protected constructor(private val processor: Processor, val name
internalResults.clear() internalResults.clear()
previousLevel = -1 previousLevel = -1
exit = false exit = false
ProgressBar.init() initProgress()
} }
// pre-handling // pre-handling
val resultIndex = internalResults.size val resultIndex = internalResults.size
val method = getCallingMethodName() val method = getCallingMethodName()
internalResults.add(InternalResult(level, method, null)) val internalResult = ResultLine(level, method, null)
internalResults.add(internalResult)
previousLevel = level previousLevel = level
@ -224,7 +268,7 @@ open class Prov protected constructor(private val processor: Processor, val name
// call the actual function // call the actual function
val res = if (!exit) { val res = if (!exit) {
ProgressBar.progress() progress(internalResult)
@Suppress("UNUSED_EXPRESSION") // false positive @Suppress("UNUSED_EXPRESSION") // false positive
a() a()
} else { } else {
@ -261,7 +305,7 @@ open class Prov protected constructor(private val processor: Processor, val name
internalResults[resultIndex].provResult = returnValue internalResults[resultIndex].provResult = returnValue
if (level == 0) { if (level == 0) {
ProgressBar.end() endProgress()
processor.close() processor.close()
printResults() printResults()
} }
@ -270,16 +314,16 @@ open class Prov protected constructor(private val processor: Processor, val name
} }
private fun internalResultIsLeaf(resultIndex: Int) : Boolean { private fun internalResultIsLeaf(resultIndex: Int): Boolean {
return !(resultIndex < internalResults.size - 1 && internalResults[resultIndex + 1].level > internalResults[resultIndex].level) return !(resultIndex < internalResults.size - 1 && internalResults[resultIndex + 1].level > internalResults[resultIndex].level)
} }
private fun cumulativeSuccessSublevel(resultIndex: Int) : Boolean? { private fun cumulativeSuccessSublevel(resultIndex: Int): Boolean? {
val currentLevel = internalResults[resultIndex].level val currentLevel = internalResults[resultIndex].level
var res : Boolean? = null var res: Boolean? = null
var i = resultIndex + 1 var i = resultIndex + 1
while ( i < internalResults.size && internalResults[i].level > currentLevel) { while (i < internalResults.size && internalResults[i].level > currentLevel) {
if (internalResults[i].level == currentLevel + 1) { if (internalResults[i].level == currentLevel + 1) {
res = res =
if (res == null) internalResults[i].provResult?.success else res && (internalResults[i].provResult?.success if (res == null) internalResults[i].provResult?.success else res && (internalResults[i].provResult?.success
@ -291,23 +335,6 @@ open class Prov protected constructor(private val processor: Processor, val name
} }
private data class InternalResult(val level: Int, val method: String?, var provResult: ProvResult?) {
override fun toString() : String {
val provResult = provResult
return if (provResult != null) {
prefix(level) + (if (provResult.success) "Success -- " else "FAILED -- ") +
method + " " + (provResult.cmd ?: "") +
(if (!provResult.success && provResult.err != null) " -- Error: " + provResult.err.escapeNewline() else "")
} else
prefix(level) + " " + method + " " + "... in progress ... "
}
private fun prefix(level: Int): String {
return "---".repeat(level) + "> "
}
}
private val ANSI_RESET = "\u001B[0m" private val ANSI_RESET = "\u001B[0m"
private val ANSI_BRIGHT_RED = "\u001B[91m" private val ANSI_BRIGHT_RED = "\u001B[91m"
private val ANSI_BRIGHT_GREEN = "\u001B[92m" private val ANSI_BRIGHT_GREEN = "\u001B[92m"
@ -320,15 +347,17 @@ open class Prov protected constructor(private val processor: Processor, val name
// val ANSI_PURPLE = "\u001B[35m" // val ANSI_PURPLE = "\u001B[35m"
// val ANSI_CYAN = "\u001B[36m" // val ANSI_CYAN = "\u001B[36m"
// val ANSI_WHITE = "\u001B[37m" // val ANSI_WHITE = "\u001B[37m"
// val ANSI_GRAY = "\u001B[90m" val ANSI_GRAY = "\u001B[90m"
private fun printResults() { private fun printResults() {
println("============================================== SUMMARY " + (if (name != null) "(" + name + ") " else "") + println(
"============================================== ") "============================================== SUMMARY " + (if (name != null) "(" + name + ") " else "") +
"============================================== "
)
for (result in internalResults) { for (result in internalResults) {
println( println(
result.toString().escapeNewline(). result.toString().escapeNewline()
replace("Success --", ANSI_BRIGHT_GREEN + "Success" + ANSI_RESET + " --") .replace("Success --", ANSI_BRIGHT_GREEN + "Success" + ANSI_RESET + " --")
.replace("FAILED --", ANSI_BRIGHT_RED + "FAILED" + ANSI_RESET + " --") .replace("FAILED --", ANSI_BRIGHT_RED + "FAILED" + ANSI_RESET + " --")
) )
} }
@ -342,20 +371,70 @@ open class Prov protected constructor(private val processor: Processor, val name
} }
println("============================================ SUMMARY END ============================================ " + newline()) println("============================================ SUMMARY END ============================================ " + newline())
} }
private fun String.formattedAsResultLine(): String = this
.replace("Success", ANSI_BRIGHT_GREEN + "Success" + ANSI_RESET)
.replace("FAILED", ANSI_BRIGHT_RED + "FAILED" + ANSI_RESET)
.replace("executing...", ANSI_GRAY + "executing..." + ANSI_RESET)
private fun initProgress() {
if ((progressType == ProgressType.DOTS) || (progressType == ProgressType.BASIC)) {
println("---------- Processing started ----------")
System.out.flush()
}
}
private fun progress(line: ResultLine) {
if (progressType == ProgressType.DOTS) {
print(".")
System.out.flush()
} else if (progressType == ProgressType.BASIC) {
val shortLine = line.inProgress()
if (!shortLine.endsWith("cmd") && !shortLine.endsWith("sh")) {
println(shortLine.formattedAsResultLine())
System.out.flush()
}
}
}
private fun endProgress() {
if ((progressType == ProgressType.DOTS) || (progressType == ProgressType.BASIC)) {
println("---------- Processing completed ----------")
}
}
} }
private object ProgressBar { internal data class ResultLine(val level: Int, val method: String?, var provResult: ProvResult?) {
fun init() { override fun toString(): String {
print("Processing started ...\n") val provResult = provResult
return if (provResult != null) {
prefix(level) + (if (provResult.success) "Success -- " else "FAILED -- ") +
method + " " + (provResult.cmd ?: "") +
(if (!provResult.success && provResult.err != null) " -- Error: " + provResult.err.escapeNewline() else "")
} else
prefix(level) + method + " " + "... in progress ... "
}
fun inProgress(): String {
return prefix(level) + "executing... -- " + method
} }
fun progress() { private fun prefix(level: Int): String {
print(".") return "---".repeat(level) + "> "
System.out.flush()
} }
}
fun Prov.myfu() = def {
cmd("echo asdf222")
}
fun main() {
fun end() { local().def {
println("processing completed.") cmd("echo asdfasdf")
myfu()
} }
} }

@ -23,11 +23,3 @@ data class ProvResult(val success: Boolean,
if (err != null) " Error: " + err else "") else "" if (err != null) " Error: " + err else "") else ""
} }
} }
@Suppress("unused") // might be used by custom methods
data class TypedResult<T>(val success: Boolean, val resultObject: T? = null) {
override fun toString(): String {
return "TypedResult:: ${if (success) "Succeeded" else "FAILED"} -- Result object: " + resultObject?.run { toString().escapeNewline() }
}
}

@ -28,10 +28,11 @@ fun UbuntuProv.provideContainerPlatform(
throw RuntimeException("could not start docker") throw RuntimeException("could not start docker")
} }
} else if (startMode == ContainerStartMode.USE_RUNNING_ELSE_CREATE) { } else if (startMode == ContainerStartMode.USE_RUNNING_ELSE_CREATE) {
val r = val runCheckResult = cmdNoEval(dockerCmd + "inspect -f '{{.State.Running}}' $containerName")
cmd(dockerCmd + "inspect -f '{{.State.Running}}' $containerName")
if (!r.success || "false\n" == r.out) { // if either container not found or container found but not running
cmd(dockerCmd + "rm -f $containerName") if (!runCheckResult.success || "false\n" == runCheckResult.out) {
cmdNoEval(dockerCmd + "rm -f $containerName")
cmd(dockerCmd + "run -dit --name=$containerName $imageName") cmd(dockerCmd + "run -dit --name=$containerName $imageName")
} }
} }
@ -83,7 +84,7 @@ fun UbuntuProv.dockerProvideImagePlatform(image: DockerImage, skipIfExisting: Bo
fun UbuntuProv.dockerImageExistsPlatform(imageName: String, sudo: Boolean): Boolean { fun UbuntuProv.dockerImageExistsPlatform(imageName: String, sudo: Boolean): Boolean {
val dockerCmd = if (sudo) "sudo docker " else "docker " val dockerCmd = if (sudo) "sudo docker " else "docker "
return (cmd(dockerCmd + "images $imageName -q").out != "") return (cmdNoEval(dockerCmd + "images $imageName -q").out != "")
} }

@ -1,15 +1,17 @@
package io.provs.platforms package io.provs.platforms
import io.provs.ProgressType
import io.provs.Prov import io.provs.Prov
import io.provs.ProvResult import io.provs.ProvResult
import io.provs.escapeAndEncloseByDoubleQuoteForShell import io.provs.escapeAndEncloseByDoubleQuoteForShell
import io.provs.processors.LocalProcessor import io.provs.processors.LocalProcessor
import io.provs.processors.Processor import io.provs.processors.Processor
const val SHELL = "/bin/bash" // could be changed to another shell like "sh", "/bin/csh" if required const val SHELL = "/bin/bash"
class UbuntuProv internal constructor(processor : Processor = LocalProcessor(), name: String? = null) : Prov (processor, name) { class UbuntuProv internal constructor(processor : Processor = LocalProcessor(), name: String? = null, progressType: ProgressType)
: Prov (processor, name, progressType) {
override fun cmd(cmd: String, dir: String?, sudo: Boolean) : ProvResult = def { override fun cmd(cmd: String, dir: String?, sudo: Boolean) : ProvResult = def {
xec(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo)) xec(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo))

@ -1,12 +1,14 @@
package io.provs.platforms package io.provs.platforms
import io.provs.ProgressType
import io.provs.Prov import io.provs.Prov
import io.provs.ProvResult import io.provs.ProvResult
import io.provs.processors.LocalProcessor import io.provs.processors.LocalProcessor
import io.provs.processors.Processor import io.provs.processors.Processor
class WinProv internal constructor(processor : Processor = LocalProcessor(), name: String? = null) : Prov (processor, name) { class WinProv internal constructor(processor : Processor = LocalProcessor(), name: String? = null, progressType: ProgressType)
: Prov (processor, name, progressType) {
private val SHELL = "cmd.exe" private val SHELL = "cmd.exe"

@ -1,5 +1,6 @@
package io.provs.processors package io.provs.processors
import io.provs.ProgressType
import io.provs.Prov import io.provs.Prov
import io.provs.docker.provideContainer import io.provs.docker.provideContainer
import io.provs.escapeAndEncloseByDoubleQuoteForShell import io.provs.escapeAndEncloseByDoubleQuoteForShell
@ -28,7 +29,7 @@ open class ContainerUbuntuHostProcessor(
) : Processor { ) : Processor {
private val dockerCmd = if (sudo) "sudo docker " else "docker " private val dockerCmd = if (sudo) "sudo docker " else "docker "
private var localExecution = LocalProcessor() private var localExecution = LocalProcessor()
private var a = Prov.newInstance(name = "LocalProcessor for Docker operations") private var a = Prov.newInstance(name = "LocalProcessor for Docker operations", progressType = ProgressType.NONE)
init { init {
val r = a.provideContainer(containerName, dockerImage, startMode, sudo) val r = a.provideContainer(containerName, dockerImage, startMode, sudo)

@ -1,6 +1,7 @@
package io.provs.processors package io.provs.processors
@Suppress("unused") // used externally
class PrintOnlyProcessor : Processor { class PrintOnlyProcessor : Processor {
override fun x(vararg args: String): ProcessResult override fun x(vararg args: String): ProcessResult

@ -12,6 +12,16 @@
</encoder> </encoder>
</appender> </appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<target>System.out</target>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{35}) - %msg %n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>./logs/provs-${byTime}.log</file> <file>./logs/provs-${byTime}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
@ -31,9 +41,13 @@
<appender-ref ref="FILE" /> <appender-ref ref="FILE" />
</logger> </logger>
<root level="DEBUG"> <root level="INFO">
<appender-ref ref="STDERR" /> <appender-ref ref="STDERR" />
<appender-ref ref="FILE" /> <appender-ref ref="FILE" />
</root> </root>
<root level="WARN">
<appender-ref ref="STDOUT" />
</root>
</configuration> </configuration>

@ -3,6 +3,7 @@ package io.provs
import io.provs.docker.provideContainer import io.provs.docker.provideContainer
import io.provs.test.tags.ContainerTest import io.provs.test.tags.ContainerTest
import io.provs.test.tags.NonCi import io.provs.test.tags.NonCi
import io.provs.test.testLocal
import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@ -115,7 +116,7 @@ internal class ProvTest {
} }
// when // when
val res = Prov.defaultInstance().tst_def().success val res = testLocal().tst_def().success
// then // then
assert(res) assert(res)
@ -130,7 +131,7 @@ internal class ProvTest {
} }
// when // when
val res = Prov.defaultInstance().tst_def().success val res = testLocal().tst_def().success
// then // then
assert(res) assert(res)
@ -145,7 +146,7 @@ internal class ProvTest {
} }
// when // when
val res = Prov.defaultInstance().tst_def().success val res = testLocal().tst_def().success
// then // then
assert(!res) assert(!res)
@ -160,7 +161,7 @@ internal class ProvTest {
} }
// when // when
val res = Prov.defaultInstance().tst_def_all_true_mode_ALL().success val res = testLocal().tst_def_all_true_mode_ALL().success
// then // then
assert(res) assert(res)
@ -176,7 +177,7 @@ internal class ProvTest {
@Test @Test
fun def_modeALL_resultFalse() { fun def_modeALL_resultFalse() {
// when // when
val res = Prov.defaultInstance().tst_def_one_false_mode_ALL().success val res = testLocal().tst_def_one_false_mode_ALL().success
// then // then
assert(!res) assert(!res)
@ -198,7 +199,7 @@ internal class ProvTest {
@Test @Test
fun def_modeALLnested_resultFalse() { fun def_modeALLnested_resultFalse() {
// when // when
val res = Prov.defaultInstance().tst_def_one_false_mode_ALL_nested().success val res = testLocal().tst_def_one_false_mode_ALL_nested().success
// then // then
assert(!res) assert(!res)
@ -218,7 +219,7 @@ internal class ProvTest {
} }
// when // when
val res = Prov.defaultInstance().tst_def_one_false_mode_ALL().success val res = testLocal().tst_def_one_false_mode_ALL().success
// then // then
assert(!res) assert(!res)
@ -238,7 +239,7 @@ internal class ProvTest {
} }
// when // when
val res = Prov.defaultInstance().tst_def_failexit_outer().success val res = testLocal().tst_def_failexit_outer().success
// then // then
assert(!res) assert(!res)
@ -258,7 +259,7 @@ internal class ProvTest {
} }
// when // when
val res = Prov.defaultInstance().tst_def_failexit_outer().success val res = testLocal().tst_def_failexit_outer().success
// then // then
assert(res) assert(res)
@ -283,7 +284,7 @@ internal class ProvTest {
} }
// when // when
val res = Prov.defaultInstance().tst_nested().success val res = testLocal().tst_nested().success
// then // then
assert(!res) assert(!res)
@ -322,7 +323,7 @@ internal class ProvTest {
System.setErr(PrintStream(errContent)) System.setErr(PrintStream(errContent))
// when // when
local().methodThatProvidesSomeOutput() Prov.newInstance(name = "test instance", progressType = ProgressType.NONE).methodThatProvidesSomeOutput()
// then // then
System.setOut(originalOut) System.setOut(originalOut)
@ -330,9 +331,8 @@ internal class ProvTest {
println(outContent.toString()) println(outContent.toString())
// todo : simplify next lines
val expectedOutput = if (OS.WINDOWS.isCurrentOs) "\n" + val expectedOutput = if (OS.WINDOWS.isCurrentOs) "\n" +
"============================================== SUMMARY (default Instance) ============================================== \n" + "============================================== SUMMARY (test Instance) ============================================== \n" +
"> Success -- methodThatProvidesSomeOutput (requireLast) \n" + "> Success -- methodThatProvidesSomeOutput (requireLast) \n" +
"---> FAILED -- checkPrereq_evaluateToFailure (requireLast) -- Error: This is a test error.\n" + "---> FAILED -- checkPrereq_evaluateToFailure (requireLast) -- Error: This is a test error.\n" +
"---> Success -- sh \n" + "---> Success -- sh \n" +
@ -342,9 +342,7 @@ internal class ProvTest {
"------> Success -- cmd [cmd.exe, /c, echo -End test-]\n" + "------> Success -- cmd [cmd.exe, /c, echo -End test-]\n" +
"============================================ SUMMARY END ============================================ \n" "============================================ SUMMARY END ============================================ \n"
else if (OS.LINUX.isCurrentOs()) { else if (OS.LINUX.isCurrentOs()) {
"Processing started ...\n" + "============================================== SUMMARY (test instance) ============================================== \n" +
".......processing completed.\n" +
"============================================== SUMMARY (default instance) ============================================== \n" +
"> \u001B[92mSuccess\u001B[0m -- methodThatProvidesSomeOutput (requireLast) \n" + "> \u001B[92mSuccess\u001B[0m -- methodThatProvidesSomeOutput (requireLast) \n" +
"---> \u001B[91mFAILED\u001B[0m -- checkPrereq_evaluateToFailure (requireLast) -- Error: This is a test error.\n" + "---> \u001B[91mFAILED\u001B[0m -- checkPrereq_evaluateToFailure (requireLast) -- Error: This is a test error.\n" +
"---> \u001B[92mSuccess\u001B[0m -- sh \n" + "---> \u001B[92mSuccess\u001B[0m -- sh \n" +
@ -366,7 +364,7 @@ internal class ProvTest {
@Test @Test
fun check_returnsTrue() { fun check_returnsTrue() {
// when // when
val res = local().chk("echo 123") val res = testLocal().chk("echo 123")
// then // then
assertTrue(res) assertTrue(res)
@ -375,7 +373,7 @@ internal class ProvTest {
@Test @Test
fun check_returnsFalse() { fun check_returnsFalse() {
// when // when
val res = local().chk("cmddoesnotexist") val res = testLocal().chk("cmddoesnotexist")
// then // then
assertFalse(res) assertFalse(res)
@ -384,7 +382,7 @@ internal class ProvTest {
@Test @Test
fun getSecret_returnsSecret() { fun getSecret_returnsSecret() {
// when // when
val res = local().getSecret("echo 123") val res = testLocal().getSecret("echo 123")
// then // then
assertEquals("123", res?.plain()?.trim()) assertEquals("123", res?.plain()?.trim())
@ -403,7 +401,7 @@ internal class ProvTest {
} }
// when // when
val res = local().outer() val res = testLocal().outer()
//then //then
assertEquals(ProvResult(true), res) assertEquals(ProvResult(true), res)
@ -422,7 +420,7 @@ internal class ProvTest {
} }
// when // when
val res = local().outer() val res = testLocal().outer()
//then //then
assertEquals(ProvResult(false), res) assertEquals(ProvResult(false), res)
@ -434,7 +432,7 @@ internal class ProvTest {
fun inContainer_locally() { fun inContainer_locally() {
// given // given
val containerName = "provs_test" val containerName = "provs_test"
local().provideContainer(containerName, "ubuntu") testLocal().provideContainer(containerName, "ubuntu")
fun Prov.inner() = def { fun Prov.inner() = def {
cmd("echo in container") cmd("echo in container")
@ -448,7 +446,7 @@ internal class ProvTest {
} }
} }
val res = local().def { outer() } val res = testLocal().def { outer() }
// then // then
assertEquals(true, res.success) assertEquals(true, res.success)

@ -4,8 +4,8 @@ import io.provs.ProvResult
import io.provs.docker.containerRuns import io.provs.docker.containerRuns
import io.provs.docker.exitAndRmContainer import io.provs.docker.exitAndRmContainer
import io.provs.docker.runContainer import io.provs.docker.runContainer
import io.provs.local
import io.provs.test.tags.NonCi import io.provs.test.tags.NonCi
import io.provs.test.testLocal
import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.condition.EnabledOnOs import org.junit.jupiter.api.condition.EnabledOnOs
@ -19,7 +19,7 @@ internal class UbuntuHostDockerKtTest {
fun runAndCheckAndExitContainer() { fun runAndCheckAndExitContainer() {
// when // when
val containerName = "testContainer" val containerName = "testContainer"
val result = local().requireAll { val result = testLocal().requireAll {
runContainer(containerName) runContainer(containerName)
addResultToEval(ProvResult(containerRuns(containerName))) addResultToEval(ProvResult(containerRuns(containerName)))

@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test
@Suppress("unused") @Suppress("unused")
fun test() { fun testfun() {
println("test is fun") println("test is fun")
} }
@ -13,6 +13,6 @@ internal class EntryKtTest {
@Test @Test
fun test_main_no_arg() { fun test_main_no_arg() {
main("io.provs.entry.EntryTestKt", "test") main("io.provs.entry.EntryTestKt", "testfun")
} }
} }

@ -2,19 +2,18 @@ package io.provs.platformTest
import io.provs.Prov import io.provs.Prov
import io.provs.test.tags.NonCi import io.provs.test.tags.NonCi
import io.provs.test.testLocal
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.condition.EnabledOnOs import org.junit.jupiter.api.condition.EnabledOnOs
import org.junit.jupiter.api.condition.OS import org.junit.jupiter.api.condition.OS
internal class UbuntuProvTests { internal class UbuntuProvTests {
private val prov = Prov.defaultInstance() private fun Prov.ping(url: String) = def {
private fun ping(url: String) = prov.def {
xec("ping", "-c", "4", url) xec("ping", "-c", "4", url)
} }
private fun outerPing() = prov.def { private fun Prov.outerPing() = def {
ping("gitlab.com") ping("gitlab.com")
} }
@ -22,7 +21,7 @@ internal class UbuntuProvTests {
@EnabledOnOs(OS.LINUX) @EnabledOnOs(OS.LINUX)
fun that_ping_works() { fun that_ping_works() {
// when // when
val res = outerPing() val res = testLocal().outerPing()
// then // then
assert(res.success) assert(res.success)
@ -32,7 +31,7 @@ internal class UbuntuProvTests {
@EnabledOnOs(OS.LINUX) @EnabledOnOs(OS.LINUX)
fun that_cmd_works() { fun that_cmd_works() {
// given // given
val a = Prov.defaultInstance() val a = testLocal()
// when // when
val res1 = a.cmd("pwd") val res1 = a.cmd("pwd")
@ -50,7 +49,7 @@ internal class UbuntuProvTests {
@NonCi @NonCi
fun that_cmd_works_with_sudo() { fun that_cmd_works_with_sudo() {
// given // given
val a = Prov.defaultInstance() val a = testLocal()
// when // when
val res1 = a.cmd("echo abc", "/root", sudo = true) val res1 = a.cmd("echo abc", "/root", sudo = true)
@ -64,7 +63,7 @@ internal class UbuntuProvTests {
@EnabledOnOs(OS.LINUX) @EnabledOnOs(OS.LINUX)
fun that_nested_shells_work() { fun that_nested_shells_work() {
// given // given
val a = Prov.defaultInstance() val a = testLocal()
// when // when
val res1 = a.cmd("pwd") val res1 = a.cmd("pwd")
@ -81,7 +80,7 @@ internal class UbuntuProvTests {
@EnabledOnOs(OS.LINUX) @EnabledOnOs(OS.LINUX)
fun that_xec_works() { fun that_xec_works() {
// given // given
val a = Prov.defaultInstance() val a = testLocal()
// when // when
val res1 = a.xec("/usr/bin/printf", "hi") val res1 = a.xec("/usr/bin/printf", "hi")

@ -1,6 +1,7 @@
package io.provs.platformTest package io.provs.platformTest
import io.provs.Prov import io.provs.Prov
import io.provs.test.testLocal
import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.condition.EnabledOnOs import org.junit.jupiter.api.condition.EnabledOnOs
@ -8,19 +9,17 @@ import org.junit.jupiter.api.condition.OS
internal class WinProvTests { internal class WinProvTests {
private val prov = Prov.defaultInstance() private fun Prov.ping(url: String) = def {
private fun ping(url: String) = prov.def {
cmd("ping $url") cmd("ping $url")
} }
private fun outerPing() = prov.def { ping("nu.nl") } private fun Prov.outerPing() = def { ping("nu.nl") }
@Test @Test
@EnabledOnOs(OS.WINDOWS) @EnabledOnOs(OS.WINDOWS)
fun def_definesPing_function() { fun def_definesPing_function() {
// when // when
val res = outerPing() val res = testLocal().outerPing()
// then // then
assert(res.success) assert(res.success)
@ -30,7 +29,7 @@ internal class WinProvTests {
@EnabledOnOs(OS.WINDOWS) @EnabledOnOs(OS.WINDOWS)
fun cmd_executesCommand() { fun cmd_executesCommand() {
// given // given
val a = Prov.defaultInstance() val a = testLocal()
// when // when
val res1 = a.cmd("echo %cd%") val res1 = a.cmd("echo %cd%")

@ -4,6 +4,7 @@ import io.provs.platforms.SHELL
import io.provs.test.DEFAULT_START_MODE_TEST_CONTAINER import io.provs.test.DEFAULT_START_MODE_TEST_CONTAINER
import io.provs.test.tags.ContainerTest import io.provs.test.tags.ContainerTest
import io.provs.test.testDockerWithSudo import io.provs.test.testDockerWithSudo
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.condition.EnabledOnOs import org.junit.jupiter.api.condition.EnabledOnOs
import org.junit.jupiter.api.condition.OS.LINUX import org.junit.jupiter.api.condition.OS.LINUX
@ -14,9 +15,16 @@ class ContainerUbuntuHostProcessorTest {
@Test @Test
@EnabledOnOs(LINUX) @EnabledOnOs(LINUX)
@ContainerTest @ContainerTest
fun test() { fun test_execution() {
// given
val processor = val processor =
ContainerUbuntuHostProcessor("provs_ubuntuhost_test", "ubuntu", DEFAULT_START_MODE_TEST_CONTAINER, sudo = testDockerWithSudo) ContainerUbuntuHostProcessor("provs_ubuntuhost_test", "ubuntu", DEFAULT_START_MODE_TEST_CONTAINER, sudo = testDockerWithSudo)
processor.x(SHELL, "-c", "'cd /home && mkdir blabla'")
// when
val res = processor.x(SHELL, "-c", "echo -n abc")
// then
assertEquals(0, res.exitCode)
assertEquals("abc", res.out)
} }
} }

@ -1,10 +1,10 @@
package io.provs.test package io.provs.test
import io.provs.ProgressType
import io.provs.Prov import io.provs.Prov
import io.provs.docker.dockerImageExists import io.provs.docker.dockerImageExists
import io.provs.docker.dockerProvideImage import io.provs.docker.dockerProvideImage
import io.provs.docker.images.UbuntuPlusUser import io.provs.docker.images.UbuntuPlusUser
import io.provs.local
import io.provs.processors.ContainerStartMode import io.provs.processors.ContainerStartMode
import io.provs.processors.ContainerUbuntuHostProcessor import io.provs.processors.ContainerUbuntuHostProcessor
@ -16,7 +16,7 @@ const val defaultTestContainerName = "provs_test"
fun defaultTestContainer(): Prov { fun defaultTestContainer(): Prov {
val image = UbuntuPlusUser() val image = UbuntuPlusUser()
val prov = local() val prov = testLocal()
if (!prov.dockerImageExists(image.imageName(), testDockerWithSudo)) { if (!prov.dockerImageExists(image.imageName(), testDockerWithSudo)) {
prov.dockerProvideImage(image, sudo = testDockerWithSudo) prov.dockerProvideImage(image, sudo = testDockerWithSudo)
} }
@ -27,6 +27,11 @@ fun defaultTestContainer(): Prov {
startMode = DEFAULT_START_MODE_TEST_CONTAINER, startMode = DEFAULT_START_MODE_TEST_CONTAINER,
sudo = testDockerWithSudo, sudo = testDockerWithSudo,
dockerImage = image.imageName() dockerImage = image.imageName()
) ),
progressType = ProgressType.NONE
) )
} }
fun testLocal(): Prov {
return Prov.newInstance(name = "testing", progressType = ProgressType.NONE)
}
Loading…
Cancel
Save