fix todos in class Prov & method names refactorings
This commit is contained in:
parent
d8ff355893
commit
1836b9efdb
12 changed files with 73 additions and 65 deletions
|
@ -1,6 +1,5 @@
|
||||||
package org.domaindrivenarchitecture.provs.framework.core
|
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.platforms.UbuntuProv
|
||||||
import org.domaindrivenarchitecture.provs.framework.core.processors.LocalProcessor
|
import org.domaindrivenarchitecture.provs.framework.core.processors.LocalProcessor
|
||||||
import org.domaindrivenarchitecture.provs.framework.core.processors.Processor
|
import org.domaindrivenarchitecture.provs.framework.core.processors.Processor
|
||||||
|
@ -13,11 +12,13 @@ enum class OS { LINUX }
|
||||||
|
|
||||||
|
|
||||||
private const val RESULT_PREFIX = "> "
|
private const val RESULT_PREFIX = "> "
|
||||||
|
private const val NOT_IMPLEMENTED = "Not implemented"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This main class offers methods to execute shell commands.
|
* This main class offers methods to execute shell commands.
|
||||||
* The commands are executed locally, remotely (via ssh) or in a docker container
|
* The commands are executed locally, remotely (via ssh) or in a docker container depending on
|
||||||
* depending on the processor which is passed to the constructor.
|
* the processor which is passed to the constructor.
|
||||||
*/
|
*/
|
||||||
open class Prov protected constructor(
|
open class Prov protected constructor(
|
||||||
private val processor: Processor,
|
private val processor: Processor,
|
||||||
|
@ -59,14 +60,12 @@ open class Prov protected constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private val internalResults = arrayListOf<ResultLine>()
|
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
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a task with a custom name instead of the name of the calling function.
|
* 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).
|
* 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() }
|
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
|
runInContainerWithName = containerName
|
||||||
val res = handle(ResultMode.ALL) { a() }
|
val res = handle(ResultMode.ALL) { task() }
|
||||||
runInContainerWithName = null
|
runInContainerWithName = null
|
||||||
return res
|
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 {
|
fun exec(vararg args: String): ProvResult {
|
||||||
val cmd = runInContainerWithName?.let { cmdInContainer(it, *s) } ?: s
|
val cmd = runInContainerWithName?.let { execInContainer(it, *args) } ?: args
|
||||||
val result = processor.x(*cmd)
|
val result = processor.exec(*cmd)
|
||||||
return ProvResult(
|
return ProvResult(
|
||||||
success = (result.exitCode == 0),
|
success = (result.exitCode == 0),
|
||||||
cmd = result.argsToString(),
|
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 {
|
fun execNoLog(vararg s: String): ProvResult {
|
||||||
val cmd = runInContainerWithName?.let { cmdInContainer(it, *s) } ?: s
|
val cmd = runInContainerWithName?.let { execInContainer(it, *s) } ?: s
|
||||||
val result = processor.xNoLog(*cmd)
|
val result = processor.execNoLog(*cmd)
|
||||||
return ProvResult(
|
return ProvResult(
|
||||||
success = (result.exitCode == 0),
|
success = (result.exitCode == 0),
|
||||||
cmd = "***",
|
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.
|
* Executes a command by using the shell.
|
||||||
|
@ -233,23 +240,6 @@ open class Prov protected constructor(
|
||||||
ProvResult(success)
|
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
|
* Provides result handling, e.g. gather results for result summary
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -76,7 +76,7 @@ fun UbuntuProv.dockerProvideImagePlatform(image: DockerImage, skipIfExisting: Bo
|
||||||
|
|
||||||
val path = hostUserHome() + "tmp_docker_img" + fileSeparator()
|
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")
|
cmd("cd ${hostUserHome()} && mkdir tmp_docker_img")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,15 +24,29 @@ class UbuntuProv internal constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
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))
|
exec(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun cmdNoLog(cmd: String, dir: String?, sudo: Boolean): ProvResult {
|
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 {
|
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 = " ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,17 +40,17 @@ open class ContainerUbuntuHostProcessor(
|
||||||
|
|
||||||
private val hostShell = "/bin/bash"
|
private val hostShell = "/bin/bash"
|
||||||
|
|
||||||
override fun x(vararg args: String): ProcessResult {
|
override fun exec(vararg args: String): ProcessResult {
|
||||||
return localExecution.x(hostShell, "-c", dockerCmd + "exec $containerName " + buildCommand(*args))
|
return localExecution.exec(hostShell, "-c", dockerCmd + "exec $containerName " + buildCommand(*args))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun xNoLog(vararg args: String): ProcessResult {
|
override fun execNoLog(vararg args: String): ProcessResult {
|
||||||
return localExecution.xNoLog(hostShell, "-c", dockerCmd + "exec $containerName " + buildCommand(*args))
|
return localExecution.execNoLog(hostShell, "-c", dockerCmd + "exec $containerName " + buildCommand(*args))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun exitAndRm() {
|
private fun exitAndRm() {
|
||||||
localExecution.x(hostShell, "-c", dockerCmd + "stop $containerName")
|
localExecution.exec(hostShell, "-c", dockerCmd + "stop $containerName")
|
||||||
localExecution.x(hostShell, "-c", dockerCmd + "rm $containerName")
|
localExecution.exec(hostShell, "-c", dockerCmd + "rm $containerName")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun quoteString(s: String): String {
|
private fun quoteString(s: String): String {
|
||||||
|
|
|
@ -3,12 +3,12 @@ package org.domaindrivenarchitecture.provs.framework.core.processors
|
||||||
|
|
||||||
class DummyProcessor : Processor {
|
class DummyProcessor : Processor {
|
||||||
|
|
||||||
override fun x(vararg args: String): ProcessResult
|
override fun exec(vararg args: String): ProcessResult
|
||||||
{
|
{
|
||||||
return ProcessResult(0, args = args)
|
return ProcessResult(0, args = args)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun xNoLog(vararg args: String): ProcessResult
|
override fun execNoLog(vararg args: String): ProcessResult
|
||||||
{
|
{
|
||||||
return ProcessResult(0, args = args)
|
return ProcessResult(0, args = args)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,12 +29,12 @@ open class LocalProcessor : Processor {
|
||||||
return System.getProperty("user.home") ?: File.separator
|
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)
|
return execute(true, *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun xNoLog(vararg args: String): ProcessResult {
|
override fun execNoLog(vararg args: String): ProcessResult {
|
||||||
return execute(false, *args)
|
return execute(false, *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ package org.domaindrivenarchitecture.provs.framework.core.processors
|
||||||
@Suppress("unused") // used externally
|
@Suppress("unused") // used externally
|
||||||
class PrintOnlyProcessor : Processor {
|
class PrintOnlyProcessor : Processor {
|
||||||
|
|
||||||
override fun x(vararg args: String): ProcessResult
|
override fun exec(vararg args: String): ProcessResult
|
||||||
{
|
{
|
||||||
print("PrintOnlyProcessor >>> ")
|
print("PrintOnlyProcessor >>> ")
|
||||||
for (n in args) print("\"$n\" ")
|
for (n in args) print("\"$n\" ")
|
||||||
|
@ -12,7 +12,7 @@ class PrintOnlyProcessor : Processor {
|
||||||
return ProcessResult(0, args = args)
|
return ProcessResult(0, args = args)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun xNoLog(vararg args: String): ProcessResult
|
override fun execNoLog(vararg args: String): ProcessResult
|
||||||
{
|
{
|
||||||
print("PrintOnlyProcessor >>> ********")
|
print("PrintOnlyProcessor >>> ********")
|
||||||
return ProcessResult(0, args = args)
|
return ProcessResult(0, args = args)
|
||||||
|
|
|
@ -2,8 +2,8 @@ package org.domaindrivenarchitecture.provs.framework.core.processors
|
||||||
|
|
||||||
|
|
||||||
interface Processor {
|
interface Processor {
|
||||||
fun x(vararg args: String): ProcessResult
|
fun exec(vararg args: String): ProcessResult
|
||||||
fun xNoLog(vararg args: String): ProcessResult
|
fun execNoLog(vararg args: String): ProcessResult
|
||||||
fun close() {
|
fun close() {
|
||||||
// no action needed for most processors; if action is needed when closing, this method must be overwritten in the subclass
|
// no action needed for most processors; if action is needed when closing, this method must be overwritten in the subclass
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,11 @@ import java.net.InetAddress
|
||||||
import java.util.concurrent.TimeUnit
|
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 {
|
companion object {
|
||||||
@Suppress("JAVA_CLASS_ON_COMPANION")
|
@Suppress("JAVA_CLASS_ON_COMPANION")
|
||||||
|
@ -28,13 +32,13 @@ class RemoteProcessor(ip: InetAddress, user: String, password: Secret? = null) :
|
||||||
|
|
||||||
init {
|
init {
|
||||||
try {
|
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()
|
ssh.loadKnownHosts()
|
||||||
|
|
||||||
// todo: replace PromiscuousVerifier by more secure solution
|
// Attention: host key is not verified
|
||||||
ssh.addHostKeyVerifier(PromiscuousVerifier())
|
ssh.addHostKeyVerifier(PromiscuousVerifier())
|
||||||
ssh.connect(ip)
|
ssh.connect(host)
|
||||||
|
|
||||||
if (password != null) {
|
if (password != null) {
|
||||||
ssh.authPassword(user, password.plain())
|
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)
|
return execute(true, *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun xNoLog(vararg args: String): ProcessResult {
|
override fun execNoLog(vararg args: String): ProcessResult {
|
||||||
return execute(false, *args)
|
return execute(false, *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -477,7 +477,7 @@ internal class ProvTest {
|
||||||
|
|
||||||
// then
|
// then
|
||||||
fun Prov.outer() = def {
|
fun Prov.outer() = def {
|
||||||
inContainer(containerName) {
|
taskInContainer(containerName) {
|
||||||
inner()
|
inner()
|
||||||
cmd("echo testfile > testfile.txt")
|
cmd("echo testfile > testfile.txt")
|
||||||
}
|
}
|
||||||
|
@ -503,7 +503,7 @@ internal class ProvTest {
|
||||||
// then
|
// then
|
||||||
val res = remote(host, remoteUser).def {
|
val res = remote(host, remoteUser).def {
|
||||||
inner() // executed on the remote host
|
inner() // executed on the remote host
|
||||||
inContainer("prov_default") {
|
taskInContainer("prov_default") {
|
||||||
inner() // executed in the container on the remote host
|
inner() // executed in the container on the remote host
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,8 +69,8 @@ internal class UbuntuProvTest {
|
||||||
val a = testLocal()
|
val a = testLocal()
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val res1 = a.xec("/usr/bin/printf", "hi")
|
val res1 = a.exec("/usr/bin/printf", "hi")
|
||||||
val res2 = a.xec("/bin/bash", "-c", "echo echoed")
|
val res2 = a.exec("/bin/bash", "-c", "echo echoed")
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert(res1.success)
|
assert(res1.success)
|
||||||
|
|
|
@ -18,7 +18,7 @@ class ContainerUbuntuHostProcessorTest {
|
||||||
ContainerUbuntuHostProcessor("provs_ubuntuhost_test", "ubuntu", DEFAULT_START_MODE_TEST_CONTAINER, sudo = testDockerWithSudo)
|
ContainerUbuntuHostProcessor("provs_ubuntuhost_test", "ubuntu", DEFAULT_START_MODE_TEST_CONTAINER, sudo = testDockerWithSudo)
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val res = processor.x(SHELL, "-c", "echo -n abc")
|
val res = processor.exec(SHELL, "-c", "echo -n abc")
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals(0, res.exitCode)
|
assertEquals(0, res.exitCode)
|
||||||
|
|
Loading…
Reference in a new issue