diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/Prov.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/Prov.kt index f17a589..b627a59 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/Prov.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/Prov.kt @@ -1,6 +1,5 @@ package org.domaindrivenarchitecture.provs.framework.core -import org.domaindrivenarchitecture.provs.framework.core.platforms.SHELL import org.domaindrivenarchitecture.provs.framework.core.platforms.UbuntuProv import org.domaindrivenarchitecture.provs.framework.core.processors.LocalProcessor import org.domaindrivenarchitecture.provs.framework.core.processors.Processor @@ -13,11 +12,13 @@ enum class OS { LINUX } private const val RESULT_PREFIX = "> " +private const val NOT_IMPLEMENTED = "Not implemented" + /** * 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. + * The commands are executed locally, remotely (via ssh) or in a docker container depending on + * the processor which is passed to the constructor. */ open class Prov protected constructor( private val processor: Processor, @@ -59,14 +60,12 @@ open class Prov protected constructor( } } - private val internalResults = arrayListOf() private var level = 0 private var previousLevel = 0 private var exit = false private var runInContainerWithName: String? = null - /** * Defines a task with a custom name instead of the name of the calling function. * Returns success if all subtasks finished with success (same as requireAll). @@ -111,21 +110,23 @@ open class Prov protected constructor( return handle(ResultMode.FAILEXIT) { a() } } - // todo: add sudo and update test - fun inContainer(containerName: String, a: Prov.() -> ProvResult): ProvResult { + /** + * Runs the provided task in the specified (running) container + */ + fun taskInContainer(containerName: String, task: Prov.() -> ProvResult): ProvResult { runInContainerWithName = containerName - val res = handle(ResultMode.ALL) { a() } + val res = handle(ResultMode.ALL) { task() } runInContainerWithName = null return res } - /** - * execute program with parameters + * Executes a program with (optional) parameters. + * args[0] contains the program name, the other args (if provided) specify the parameters. */ - fun xec(vararg s: String): ProvResult { - val cmd = runInContainerWithName?.let { cmdInContainer(it, *s) } ?: s - val result = processor.x(*cmd) + fun exec(vararg args: String): ProvResult { + val cmd = runInContainerWithName?.let { execInContainer(it, *args) } ?: args + val result = processor.exec(*cmd) return ProvResult( success = (result.exitCode == 0), cmd = result.argsToString(), @@ -135,11 +136,12 @@ open class Prov protected constructor( } /** - * execute program with parameters without logging (to be used if secrets are involved) + * Executes a program with (optional) parameters without logging (e.g. to be used if secrets are involved) + * args[0] contains the program name, the other args (if provided) specify the parameters. */ - fun xecNoLog(vararg s: String): ProvResult { - val cmd = runInContainerWithName?.let { cmdInContainer(it, *s) } ?: s - val result = processor.xNoLog(*cmd) + fun execNoLog(vararg s: String): ProvResult { + val cmd = runInContainerWithName?.let { execInContainer(it, *s) } ?: s + val result = processor.execNoLog(*cmd) return ProvResult( success = (result.exitCode == 0), cmd = "***", @@ -148,8 +150,13 @@ open class Prov protected constructor( ) } - - private val NOT_IMPLEMENTED = "Not implemented" + /** + * Executes a program with (optional) parameters in the specified container. + * args[0] contains the program name, the other args (if provided) specify the parameters. + */ + protected open fun execInContainer(containerName: String, vararg args: String): Array { + throw Exception(NOT_IMPLEMENTED) + } /** * Executes a command by using the shell. @@ -233,23 +240,6 @@ open class Prov protected constructor( ProvResult(success) } - - // todo: put logic in subclasses, such as UbuntuProv - private fun cmdInContainer(containerName: String, vararg args: String): Array { - 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 */ diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/docker/platforms/UbuntuHostDocker.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/docker/platforms/UbuntuHostDocker.kt index 3bc0649..11d6636 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/docker/platforms/UbuntuHostDocker.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/docker/platforms/UbuntuHostDocker.kt @@ -76,7 +76,7 @@ fun UbuntuProv.dockerProvideImagePlatform(image: DockerImage, skipIfExisting: Bo val path = hostUserHome() + "tmp_docker_img" + fileSeparator() - if (!xec("test", "-d", path).success) { + if (!exec("test", "-d", path).success) { cmd("cd ${hostUserHome()} && mkdir tmp_docker_img") } diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/platforms/UbuntuProv.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/platforms/UbuntuProv.kt index 17d53a4..9d59e7e 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/platforms/UbuntuProv.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/platforms/UbuntuProv.kt @@ -24,15 +24,29 @@ class UbuntuProv internal constructor( } override fun cmd(cmd: String, dir: String?, sudo: Boolean): ProvResult = def { - xec(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo)) + exec(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo)) } override fun cmdNoLog(cmd: String, dir: String?, sudo: Boolean): ProvResult { - return xecNoLog(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo)) + return execNoLog(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo)) } override fun cmdNoEval(cmd: String, dir: String?, sudo: Boolean): ProvResult { - return xec(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo)) + return exec(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo)) + } + + override fun execInContainer(containerName: String, vararg args: String): Array { + 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 = " ") } } diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/ContainerUbuntuHostProcessor.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/ContainerUbuntuHostProcessor.kt index 5df69db..9c8a880 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/ContainerUbuntuHostProcessor.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/ContainerUbuntuHostProcessor.kt @@ -40,17 +40,17 @@ open class ContainerUbuntuHostProcessor( private val hostShell = "/bin/bash" - override fun x(vararg args: String): ProcessResult { - return localExecution.x(hostShell, "-c", dockerCmd + "exec $containerName " + buildCommand(*args)) + override fun exec(vararg args: String): ProcessResult { + return localExecution.exec(hostShell, "-c", dockerCmd + "exec $containerName " + buildCommand(*args)) } - override fun xNoLog(vararg args: String): ProcessResult { - return localExecution.xNoLog(hostShell, "-c", dockerCmd + "exec $containerName " + buildCommand(*args)) + override fun execNoLog(vararg args: String): ProcessResult { + return localExecution.execNoLog(hostShell, "-c", dockerCmd + "exec $containerName " + buildCommand(*args)) } private fun exitAndRm() { - localExecution.x(hostShell, "-c", dockerCmd + "stop $containerName") - localExecution.x(hostShell, "-c", dockerCmd + "rm $containerName") + localExecution.exec(hostShell, "-c", dockerCmd + "stop $containerName") + localExecution.exec(hostShell, "-c", dockerCmd + "rm $containerName") } private fun quoteString(s: String): String { diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/DummyProcessor.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/DummyProcessor.kt index a1680d9..b646d12 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/DummyProcessor.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/DummyProcessor.kt @@ -3,12 +3,12 @@ package org.domaindrivenarchitecture.provs.framework.core.processors class DummyProcessor : Processor { - override fun x(vararg args: String): ProcessResult + override fun exec(vararg args: String): ProcessResult { return ProcessResult(0, args = args) } - override fun xNoLog(vararg args: String): ProcessResult + override fun execNoLog(vararg args: String): ProcessResult { return ProcessResult(0, args = args) } diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/LocalProcessor.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/LocalProcessor.kt index 1449d2d..6ab774d 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/LocalProcessor.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/LocalProcessor.kt @@ -29,12 +29,12 @@ open class LocalProcessor : Processor { return System.getProperty("user.home") ?: File.separator } - override fun x(vararg args: String): ProcessResult { + override fun exec(vararg args: String): ProcessResult { return execute(true, *args) } - override fun xNoLog(vararg args: String): ProcessResult { + override fun execNoLog(vararg args: String): ProcessResult { return execute(false, *args) } diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/PrintOnlyProcessor.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/PrintOnlyProcessor.kt index bbde5ed..8095b71 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/PrintOnlyProcessor.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/PrintOnlyProcessor.kt @@ -4,7 +4,7 @@ package org.domaindrivenarchitecture.provs.framework.core.processors @Suppress("unused") // used externally class PrintOnlyProcessor : Processor { - override fun x(vararg args: String): ProcessResult + override fun exec(vararg args: String): ProcessResult { print("PrintOnlyProcessor >>> ") for (n in args) print("\"$n\" ") @@ -12,7 +12,7 @@ class PrintOnlyProcessor : Processor { return ProcessResult(0, args = args) } - override fun xNoLog(vararg args: String): ProcessResult + override fun execNoLog(vararg args: String): ProcessResult { print("PrintOnlyProcessor >>> ********") return ProcessResult(0, args = args) diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/Processor.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/Processor.kt index 6f34551..7138d8f 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/Processor.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/Processor.kt @@ -2,8 +2,8 @@ package org.domaindrivenarchitecture.provs.framework.core.processors interface Processor { - fun x(vararg args: String): ProcessResult - fun xNoLog(vararg args: String): ProcessResult + fun exec(vararg args: String): ProcessResult + fun execNoLog(vararg args: String): ProcessResult fun close() { // no action needed for most processors; if action is needed when closing, this method must be overwritten in the subclass } diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/RemoteUbuntuProcessor.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/RemoteUbuntuProcessor.kt index b0b4f96..f6e08ff 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/RemoteUbuntuProcessor.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/RemoteUbuntuProcessor.kt @@ -17,7 +17,11 @@ import java.net.InetAddress import java.util.concurrent.TimeUnit -class RemoteProcessor(ip: InetAddress, user: String, password: Secret? = null) : Processor { +/** + * Executes task on a remote machine. + * Attention: host key is currently not being verified + */ +class RemoteProcessor(host: InetAddress, user: String, password: Secret? = null) : Processor { companion object { @Suppress("JAVA_CLASS_ON_COMPANION") @@ -28,13 +32,13 @@ class RemoteProcessor(ip: InetAddress, user: String, password: Secret? = null) : init { try { - log.info("Connecting to $ip with user: $user with " + if (password != null) "password" else "ssh-key") + log.info("Connecting to $host with user: $user with " + if (password != null) "password" else "ssh-key") ssh.loadKnownHosts() - // todo: replace PromiscuousVerifier by more secure solution + // Attention: host key is not verified ssh.addHostKeyVerifier(PromiscuousVerifier()) - ssh.connect(ip) + ssh.connect(host) if (password != null) { ssh.authPassword(user, password.plain()) @@ -52,11 +56,11 @@ class RemoteProcessor(ip: InetAddress, user: String, password: Secret? = null) : } } - override fun x(vararg args: String): ProcessResult { + override fun exec(vararg args: String): ProcessResult { return execute(true, *args) } - override fun xNoLog(vararg args: String): ProcessResult { + override fun execNoLog(vararg args: String): ProcessResult { return execute(false, *args) } diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/ProvTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/ProvTest.kt index 0474458..8dd55ee 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/ProvTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/ProvTest.kt @@ -477,7 +477,7 @@ internal class ProvTest { // then fun Prov.outer() = def { - inContainer(containerName) { + taskInContainer(containerName) { inner() cmd("echo testfile > testfile.txt") } @@ -503,7 +503,7 @@ internal class ProvTest { // then val res = remote(host, remoteUser).def { inner() // executed on the remote host - inContainer("prov_default") { + taskInContainer("prov_default") { inner() // executed in the container on the remote host } } diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/platformTest/UbuntuProvTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/platformTest/UbuntuProvTest.kt index bf2fff7..bca33f9 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/platformTest/UbuntuProvTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/platformTest/UbuntuProvTest.kt @@ -69,8 +69,8 @@ internal class UbuntuProvTest { val a = testLocal() // when - val res1 = a.xec("/usr/bin/printf", "hi") - val res2 = a.xec("/bin/bash", "-c", "echo echoed") + val res1 = a.exec("/usr/bin/printf", "hi") + val res2 = a.exec("/bin/bash", "-c", "echo echoed") // then assert(res1.success) diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/ContainerUbuntuHostProcessorTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/ContainerUbuntuHostProcessorTest.kt index a50b311..fc98156 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/ContainerUbuntuHostProcessorTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/ContainerUbuntuHostProcessorTest.kt @@ -18,7 +18,7 @@ class ContainerUbuntuHostProcessorTest { ContainerUbuntuHostProcessor("provs_ubuntuhost_test", "ubuntu", DEFAULT_START_MODE_TEST_CONTAINER, sudo = testDockerWithSudo) // when - val res = processor.x(SHELL, "-c", "echo -n abc") + val res = processor.exec(SHELL, "-c", "echo -n abc") // then assertEquals(0, res.exitCode)