make progress info level configurable

This commit is contained in:
ansgarz 2021-05-15 19:33:56 +02:00
parent 2d4607964f
commit 122fa68850
17 changed files with 236 additions and 133 deletions

View file

@ -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

View file

@ -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

View file

@ -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()
} }
@ -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 object ProgressBar { private fun initProgress() {
fun init() { if ((progressType == ProgressType.DOTS) || (progressType == ProgressType.BASIC)) {
print("Processing started ...\n") println("---------- Processing started ----------")
}
fun progress() {
print(".")
System.out.flush() System.out.flush()
} }
}
fun end() { private fun progress(line: ResultLine) {
println("processing completed.") 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 ----------")
}
}
}
internal data class ResultLine(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 ... "
}
fun inProgress(): String {
return prefix(level) + "executing... -- " + method
}
private fun prefix(level: Int): String {
return "---".repeat(level) + "> "
}
}
fun Prov.myfu() = def {
cmd("echo asdf222")
}
fun main() {
local().def {
cmd("echo asdfasdf")
myfu()
} }
} }

View file

@ -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() }
}
}

View file

@ -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 != "")
} }

View file

@ -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))

View file

@ -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"

View file

@ -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)

View file

@ -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

View file

@ -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>

View file

@ -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)

View file

@ -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)))

View file

@ -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")
} }
} }

View file

@ -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")

View file

@ -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%")

View file

@ -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)
} }
} }

View file

@ -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)
}