fix todos in class Prov & method names refactorings

This commit is contained in:
ansgarz 2022-03-12 18:41:07 +01:00
parent d8ff355893
commit 1836b9efdb
12 changed files with 73 additions and 65 deletions

View file

@ -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<ResultLine>()
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<String> {
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<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
*/

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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