diff --git a/.classpath b/.classpath deleted file mode 100644 index fc44fba..0000000 --- a/.classpath +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.project b/.project deleted file mode 100644 index 2820e02..0000000 --- a/.project +++ /dev/null @@ -1,34 +0,0 @@ - - - provs-core - Project provs-core created by Buildship. - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.buildship.core.gradleprojectnature - - - - 1628357951205 - - 30 - - org.eclipse.core.resources.regexFilterMatcher - node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ - - - - diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs deleted file mode 100644 index 2b6d83b..0000000 --- a/.settings/org.eclipse.buildship.core.prefs +++ /dev/null @@ -1,13 +0,0 @@ -arguments= -auto.sync=false -build.scans.enabled=false -connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) -connection.project.dir= -eclipse.preferences.version=1 -gradle.user.home= -java.home=/usr/lib/jvm/java-11-openjdk-amd64 -jvm.arguments= -offline.mode=false -override.workspace.settings=true -show.console.view=true -show.executions.view=true diff --git a/bin/main/logback.xml b/bin/main/logback.xml deleted file mode 100644 index 2dd0fdb..0000000 --- a/bin/main/logback.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - System.err - - WARN - - - %d{HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{35}) - %msg %n - - - - - System.out - - DEBUG - - - %d{HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{35}) - %msg %n - - - - - ./logs/provs-${byTime}.log - - ./logs/provs-%d{yyyy-MM-dd}.%i.log - 10MB - 3 - 1GB - - true - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/core/Prov.kt b/bin/main/org/domaindrivenarchitecture/provs/core/Prov.kt deleted file mode 100644 index ca7d06b..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/core/Prov.kt +++ /dev/null @@ -1,439 +0,0 @@ -package org.domaindrivenarchitecture.provs.core - -import org.domaindrivenarchitecture.provs.core.platforms.SHELL -import org.domaindrivenarchitecture.provs.core.platforms.UbuntuProv -import org.domaindrivenarchitecture.provs.core.platforms.WinProv -import org.domaindrivenarchitecture.provs.core.processors.LocalProcessor -import org.domaindrivenarchitecture.provs.core.processors.Processor -import org.slf4j.LoggerFactory - - -enum class ProgressType { NONE, DOTS, BASIC, FULL_LOG } -enum class ResultMode { NONE, LAST, ALL, FAILEXIT } -enum class OS { WINDOWS, LINUX } - - -/** - * 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. - */ -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 { - - private lateinit var defaultProvInstance: Prov - - fun defaultInstance(platform: String? = null): Prov { - return if (Factory::defaultProvInstance.isInitialized) { - defaultProvInstance - } else { - defaultProvInstance = newInstance(platform = platform, name = "default instance") - defaultProvInstance - } - } - - fun newInstance( - processor: Processor = LocalProcessor(), - platform: String? = null, - name: String? = null, - progressType: ProgressType = ProgressType.BASIC - ): Prov { - - val os = platform ?: System.getProperty("os.name") - - return when { - os.toUpperCase().contains(OS.LINUX.name) -> UbuntuProv(processor, name, progressType) - os.toUpperCase().contains(OS.WINDOWS.name) -> WinProv(processor, name, progressType) - else -> throw Exception("OS not supported") - } - } - } - - - 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 default success behavior, i.e. returns success if all subtasks finished with success. - * Same as requireAll. - */ - fun def(a: Prov.() -> ProvResult): ProvResult { - 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 { - return handle(ResultMode.LAST) { a() } - } - - /** - * defines a task, which always returns success - */ - fun optional(a: Prov.() -> ProvResult): ProvResult { - return handle(ResultMode.NONE) { a() } - } - - /** - * defines a task, which returns success if all subtasks finished with success - */ - fun requireAll(a: Prov.() -> ProvResult): ProvResult { - return handle(ResultMode.ALL) { a() } - } - - /** - * defines a task, which exits the overall execution on failure - */ - fun exitOnFailure(a: Prov.() -> ProvResult): ProvResult { - return handle(ResultMode.FAILEXIT) { a() } - } - - // todo: add sudo and update test - fun inContainer(containerName: String, a: Prov.() -> ProvResult): ProvResult { - runInContainerWithName = containerName - val res = handle(ResultMode.ALL) { a() } - runInContainerWithName = null - return res - } - - - /** - * execute program with parameters - */ - fun xec(vararg s: String): ProvResult { - val cmd = runInContainerWithName?.let { cmdInContainer(it, *s) } ?: s - val result = processor.x(*cmd) - return ProvResult( - success = (result.exitCode == 0), - cmd = result.argsToString(), - out = result.out, - err = result.err - ) - } - - /** - * execute program with parameters without logging (to be used if secrets are involved) - */ - fun xecNoLog(vararg s: String): ProvResult { - val cmd = runInContainerWithName?.let { cmdInContainer(it, *s) } ?: s - val result = processor.xNoLog(*cmd) - return ProvResult( - success = (result.exitCode == 0), - cmd = "***", - out = result.out, - err = "***" - ) - } - - - /** - * Executes a command by using the shell. - * Be aware: Executing shell commands that incorporate unsanitized input from an untrusted source - * makes a program vulnerable to shell injection, a serious security flaw which can result in arbitrary command execution. - * Thus, the use of this method is strongly discouraged in cases where the command string is constructed from external input. - */ - open fun cmd(cmd: String, dir: String? = null, sudo: Boolean = false): ProvResult { - throw Exception("Not implemented") - } - - - /** - * Same as method cmd but without logging of the result/output, should be used e.g. if secrets are involved. - * Attention: only result is NOT logged the executed command still is. - */ - open fun cmdNoLog(cmd: String, dir: String? = null, sudo: Boolean = false): ProvResult { - throw Exception("Not implemented") - } - - - /** - * Same as method cmd but without evaluating the result for the overall success. - * Can be used e.g. for checks which might succeed or fail but where failure should not influence overall success - */ - open fun cmdNoEval(cmd: String, dir: String? = null, sudo: Boolean = false): ProvResult { - throw Exception("Not implemented") - } - - - /** - * Executes command cmd and returns true in case of success else false. - * The success resp. failure is not evaluated, i.e. it is not taken into account for the overall success. - */ - fun chk(cmd: String, dir: String? = null): Boolean { - return cmdNoEval(cmd, dir).success - } - - - /** - * Retrieve a secret by executing the given command. - * Returns the result of the command as secret. - */ - fun getSecret(command: String): Secret? { - val result = cmdNoLog(command) - return if (result.success && result.out != null) { - addResultToEval(ProvResult(true, getCallingMethodName())) - Secret(result.out) - } else { - addResultToEval(ProvResult(false, getCallingMethodName(), err = result.err, exception = result.exception)) - null - } - } - - - /** - * Adds a ProvResult to the overall success evaluation. - * Intended for use in methods which do not automatically add results. - */ - fun addResultToEval(result: ProvResult) = requireAll { - result - } - - /** - * Executes multiple shell commands. Each command must be in its own line. - * Multi-line commands within the script are not supported. - * Empty lines and comments (all text behind # in a line) are supported, i.e. they are ignored. - */ - fun sh(script: String, dir: String? = null, sudo: Boolean = false) = def { - val lines = script.trimIndent().replace("\r\n", "\n").split("\n") - val linesWithoutComments = lines.stream().map { it.split("#")[0] } - val linesNonEmpty = linesWithoutComments.filter { it.trim().isNotEmpty() } - - var success = true - - for (cmd in linesNonEmpty) { - if (success) { - success = success && cmd(cmd, dir, sudo).success - } - } - 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 - */ - private fun handle(mode: ResultMode, a: Prov.() -> ProvResult): ProvResult { - - // init - if (level == 0) { - internalResults.clear() - previousLevel = -1 - exit = false - initProgress() - } - - // pre-handling - val resultIndex = internalResults.size - val method = getCallingMethodName() - val internalResult = ResultLine(level, method, null) - internalResults.add(internalResult) - - previousLevel = level - - level++ - - // call the actual function - val res = if (!exit) { - progress(internalResult) - @Suppress("UNUSED_EXPRESSION") // false positive - a() - } else { - ProvResult(false, out = "Exiting due to failure and mode FAILEXIT") - } - - level-- - - // post-handling - val returnValue = - if (mode == ResultMode.LAST) { - if (internalResultIsLeaf(resultIndex) || method == "cmd") - res.copy() else ProvResult(res.success) - } else if (mode == ResultMode.ALL) { - // leaf - if (internalResultIsLeaf(resultIndex)) res.copy() - // evaluate subcalls' results - else ProvResult(cumulativeSuccessSublevel(resultIndex) ?: false) - } else if (mode == ResultMode.NONE) { - ProvResult(true) - } else if (mode == ResultMode.FAILEXIT) { - return if (res.success) { - ProvResult(true) - } else { - exit = true - ProvResult(false) - } - } else { - ProvResult(false, err = "mode unknown") - } - - previousLevel = level - - internalResults[resultIndex].provResult = returnValue - - if (level == 0) { - endProgress() - processor.close() - printResults() - } - - return returnValue - } - - - private fun internalResultIsLeaf(resultIndex: Int): Boolean { - return !(resultIndex < internalResults.size - 1 && internalResults[resultIndex + 1].level > internalResults[resultIndex].level) - } - - - private fun cumulativeSuccessSublevel(resultIndex: Int): Boolean? { - val currentLevel = internalResults[resultIndex].level - var res: Boolean? = null - var i = resultIndex + 1 - while (i < internalResults.size && internalResults[i].level > currentLevel) { - if (internalResults[i].level == currentLevel + 1) { - res = - if (res == null) internalResults[i].provResult?.success else res && (internalResults[i].provResult?.success - ?: false) - } - i++ - } - return res - } - - - private val ANSI_RESET = "\u001B[0m" - private val ANSI_BRIGHT_RED = "\u001B[91m" - private val ANSI_BRIGHT_GREEN = "\u001B[92m" - // uncomment if needed - // val ANSI_BLACK = "\u001B[30m" - // val ANSI_RED = "\u001B[31m" - // val ANSI_GREEN = "\u001B[32m" - // val ANSI_YELLOW = "\u001B[33m" - // val ANSI_BLUE = "\u001B[34m" - // val ANSI_PURPLE = "\u001B[35m" - // val ANSI_CYAN = "\u001B[36m" - // val ANSI_WHITE = "\u001B[37m" - val ANSI_GRAY = "\u001B[90m" - - private fun printResults() { - println( - "============================================== SUMMARY " + (if (name != null) "(" + name + ") " else "") + - "============================================== " - ) - for (result in internalResults) { - println( - result.toString().escapeNewline() - .replace("Success --", ANSI_BRIGHT_GREEN + "Success" + ANSI_RESET + " --") - .replace("FAILED --", ANSI_BRIGHT_RED + "FAILED" + ANSI_RESET + " --") - ) - } - if (internalResults.size > 1) { - println("----------------------------------------------------------------------------------------------------- ") - println( - "Overall " + internalResults[0].toString().take(10) - .replace("Success", ANSI_BRIGHT_GREEN + "Success" + ANSI_RESET) - .replace("FAILED", ANSI_BRIGHT_RED + "FAILED" + ANSI_RESET) - ) - } - 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 ----------") - } - } - -} - - -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() - } -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/core/ProvResult.kt b/bin/main/org/domaindrivenarchitecture/provs/core/ProvResult.kt deleted file mode 100644 index e625d68..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/core/ProvResult.kt +++ /dev/null @@ -1,26 +0,0 @@ -package org.domaindrivenarchitecture.provs.core - - -data class ProvResult(val success: Boolean, - val cmd: String? = null, - val out: String? = null, - val err: String? = null, - val exception: Exception? = null, - val exit: String? = null) { - - constructor(returnCode : Int) : this(returnCode == 0) - - override fun toString(): String { - return "ProvResult:: ${if (success) "Succeeded" else "FAILED"} -- ${if (!cmd.isNullOrEmpty()) "Name: " + - cmd.escapeNewline() + ", " else ""}${if (!out.isNullOrEmpty()) "Details: $out" else ""}" + - (exception?.run { " Exception: " + toString() } ?: "") - } - - @Suppress("unused") - fun toShortString() : String { - return "ProvResult:: ${if (success) "Succeeded" else "FAILED"} -- " + - if (!success) - (if (out != null) "Details: $out " else "" + - if (err != null) " Error: " + err else "") else "" - } -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/core/Secret.kt b/bin/main/org/domaindrivenarchitecture/provs/core/Secret.kt deleted file mode 100644 index 5772373..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/core/Secret.kt +++ /dev/null @@ -1,14 +0,0 @@ -package org.domaindrivenarchitecture.provs.core - - -open class Secret(private val value: String) { - override fun toString(): String { - return "********" - } - fun plain() : String { - return value - } -} - - -class Password(plainPassword: String) : Secret(plainPassword) \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/core/Utils.kt b/bin/main/org/domaindrivenarchitecture/provs/core/Utils.kt deleted file mode 100644 index 878ea9e..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/core/Utils.kt +++ /dev/null @@ -1,112 +0,0 @@ -package org.domaindrivenarchitecture.provs.core - -import org.domaindrivenarchitecture.provs.core.docker.provideContainer -import org.domaindrivenarchitecture.provs.core.processors.ContainerStartMode -import org.domaindrivenarchitecture.provs.core.processors.ContainerUbuntuHostProcessor -import org.domaindrivenarchitecture.provs.core.processors.RemoteProcessor -import org.domaindrivenarchitecture.provs.core.tags.Api -import java.io.File -import java.net.InetAddress - -/** - * Returns the name of the calling function but excluding some functions of the prov framework - * in order to return the "real" calling function. - * Note: names of inner functions (i.e. which are defined inside other functions) are not - * supported in the sense that always the name of the outer function is returned instead. - */ -fun getCallingMethodName(): String? { - val offsetVal = 1 - val exclude = arrayOf("def", "record", "invoke", "invoke0", "handle", "def\$default", "addResultToEval") - // suffixes are also ignored as method names but will be added as suffix in the evaluation results - val suffixes = arrayOf("optional", "requireAll", "requireLast", "inContainer") - - var suffix = "" - val callingFrame = Thread.currentThread().stackTrace - for (i in 0 until (callingFrame.size - 1)) { - if (callingFrame[i].methodName == "getCallingMethodName") { - var method = callingFrame[i + offsetVal].methodName - var inc = 0 - while ((method in exclude) or (method in suffixes)) { - if (method in suffixes && suffix == "") { - suffix = method - } - inc++ - method = callingFrame[i + offsetVal + inc].methodName - } - return method + if (suffix.isBlank()) "" else " ($suffix)" - } - } - return null -} - - -fun String.escapeNewline(): String = this.replace("\r\n", "\\n").replace("\n", "\\n") -fun String.escapeBackslash(): String = this.replace("\\", "\\\\") -fun String.escapeDoubleQuote(): String = this.replace("\"", "\\\"") -fun String.escapeSingleQuote(): String = this.replace("'", "\'") -fun String.escapeSingleQuoteForShell(): String = this.replace("'", "'\"'\"'") -fun String.escapeProcentForPrintf(): String = this.replace("%", "%%") - -// see https://www.shellscript.sh/escape.html -fun String.escapeAndEncloseByDoubleQuoteForShell(): String { - return "\"" + this.escapeBackslash().replace("`", "\\`").escapeDoubleQuote().replace("$", "\\$") + "\"" -} - -fun hostUserHome(): String = System.getProperty("user.home") + fileSeparator() -fun newline(): String = System.getProperty("line.separator") -fun fileSeparator(): String = File.separator - - -/** - * Returns default local Prov instance. - */ -@Suppress("unused") // used by other libraries resp. KotlinScript -fun local(): Prov { - return Prov.defaultInstance() -} - - -/** - * Returns Prov instance for remote host with remote user with provided password. - * If password is null, connection is done by ssh-key. - * Platform (Linux, Windows) must be provided if different from local platform. - */ -@Api // used by other libraries resp. KotlinScript -fun remote(host: String, remoteUser: String, password: Secret? = null, platform: String? = null): Prov { - require(host.isNotEmpty(), { "Host must not be empty." }) - require(remoteUser.isNotEmpty(), { "Remote user must not be empty." }) - - return Prov.newInstance(RemoteProcessor(InetAddress.getByName(host), remoteUser, password), platform) -} - - -/** - * Returns Prov instance running in a local docker container with name containerName. - * A potentially existing container with the same name is reused by default resp. if - * parameter useExistingContainer is set to true. - * If a new container needs to be created, on Linux systems the image _ubuntu_ is used. - */ -@Api // used by other libraries resp. KotlinScript -fun docker(containerName: String = "provs_default", useExistingContainer: Boolean = true): Prov { - - val os = System.getProperty("os.name") - - if ("Linux".equals(os)) { - val defaultDockerImage = "ubuntu" - - local().provideContainer(containerName, defaultDockerImage) - - return Prov.newInstance( - ContainerUbuntuHostProcessor( - containerName, - defaultDockerImage, - if (useExistingContainer) - ContainerStartMode.USE_RUNNING_ELSE_CREATE - else - ContainerStartMode.CREATE_NEW_KILL_EXISTING - ) - ) - } else { - throw RuntimeException("ERROR: method docker() is currently not supported for " + os) - } -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/core/docker/HostDocker.kt b/bin/main/org/domaindrivenarchitecture/provs/core/docker/HostDocker.kt deleted file mode 100644 index 550234a..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/core/docker/HostDocker.kt +++ /dev/null @@ -1,84 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.docker - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.core.docker.dockerimages.DockerImage -import org.domaindrivenarchitecture.provs.core.docker.platforms.* -import org.domaindrivenarchitecture.provs.core.platforms.UbuntuProv -import org.domaindrivenarchitecture.provs.core.processors.ContainerStartMode - -/** - * Builds a docker image if not yet existing. - */ -fun Prov.dockerProvideImage(image: DockerImage, skipIfExisting: Boolean = true, sudo: Boolean = true) : ProvResult { - if (this is UbuntuProv) { - return this.dockerProvideImagePlatform(image, skipIfExisting, sudo) - } else { - throw RuntimeException("docker not yet supported for " + (this as UbuntuProv).javaClass) - } -} - -/** - * Returns true if the specified docker image exists. - */ -fun Prov.dockerImageExists(imageName: String, sudo: Boolean = true) : Boolean { - if (this is UbuntuProv) { - return this.dockerImageExistsPlatform(imageName, sudo) - } else { - throw RuntimeException("docker not yet supported for " + (this as UbuntuProv).javaClass) - } -} - -/** - * Creates and runs a new container with name _containerName_ for image _imageName_ if not yet existing. - * In case the container already exists, the parameter _startMode_ determines - * if the running container is just kept (default behavior) - * or if the running container is stopped and removed and a new container is created - * or if the method results in a failure result. - */ -fun Prov.provideContainer( - containerName: String, - imageName: String = "ubuntu", - startMode: ContainerStartMode = ContainerStartMode.USE_RUNNING_ELSE_CREATE, - sudo: Boolean = true -) : ProvResult { - if (this is UbuntuProv) { - return this.provideContainerPlatform(containerName, imageName, startMode, sudo) - } else { - throw RuntimeException("docker not yet supported for " + (this as UbuntuProv).javaClass) - } -} - - -fun Prov.containerRuns(containerName: String, sudo: Boolean = true) : Boolean { - if (this is UbuntuProv) { - return this.containerRunsPlatform(containerName, sudo) - } else { - throw RuntimeException("docker not yet supported for " + (this as UbuntuProv).javaClass) - } -} - - -fun Prov.runContainer( - containerName: String = "provs_default", - imageName: String = "ubuntu", - sudo: Boolean = true -) : ProvResult { - if (this is UbuntuProv) { - return this.runContainerPlatform(containerName, imageName, sudo) - } else { - throw RuntimeException("docker not yet supported for " + (this as UbuntuProv).javaClass) - } -} - - -fun Prov.exitAndRmContainer( - containerName: String, - sudo: Boolean = true -) : ProvResult { - if (this is UbuntuProv) { - return this.exitAndRmContainerPlatform(containerName, sudo) - } else { - throw RuntimeException("docker not yet supported for " + (this as UbuntuProv).javaClass) - } -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/core/docker/dockerimages/DockerImages.kt b/bin/main/org/domaindrivenarchitecture/provs/core/docker/dockerimages/DockerImages.kt deleted file mode 100644 index 1efbc40..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/core/docker/dockerimages/DockerImages.kt +++ /dev/null @@ -1,33 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.docker.dockerimages - - -interface DockerImage { - fun imageName() : String - fun imageText() : String -} - -/** - * Provides a docker image based on ubuntu additionally with a non-root default user and sudo isntalled - */ -class UbuntuPlusUser(private val userName: String = "testuser") : DockerImage { - - override fun imageName(): String { - return "ubuntu_plus_user" - } - - override fun imageText(): String { - return """ -FROM ubuntu:18.04 - -ARG DEBIAN_FRONTEND=noninteractive - -RUN apt-get update && apt-get -y install sudo -RUN useradd -m $userName && echo "$userName:$userName" | chpasswd && adduser $userName sudo -RUN echo "$userName ALL=(ALL:ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/$userName - -USER $userName -CMD /bin/bash -WORKDIR /home/$userName -""" - } -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/core/docker/platforms/UbuntuHostDocker.kt b/bin/main/org/domaindrivenarchitecture/provs/core/docker/platforms/UbuntuHostDocker.kt deleted file mode 100644 index db33835..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/core/docker/platforms/UbuntuHostDocker.kt +++ /dev/null @@ -1,101 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.docker.platforms - -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.core.docker.containerRuns -import org.domaindrivenarchitecture.provs.core.docker.dockerImageExists -import org.domaindrivenarchitecture.provs.core.docker.exitAndRmContainer -import org.domaindrivenarchitecture.provs.core.docker.dockerimages.DockerImage -import org.domaindrivenarchitecture.provs.core.escapeSingleQuote -import org.domaindrivenarchitecture.provs.core.fileSeparator -import org.domaindrivenarchitecture.provs.core.hostUserHome -import org.domaindrivenarchitecture.provs.core.platforms.UbuntuProv -import org.domaindrivenarchitecture.provs.core.processors.ContainerStartMode - - -fun UbuntuProv.provideContainerPlatform( - containerName: String, - imageName: String = "ubuntu", - startMode: ContainerStartMode = ContainerStartMode.USE_RUNNING_ELSE_CREATE, - sudo: Boolean = true -): ProvResult = requireLast { - val dockerCmd = if (sudo) "sudo docker " else "docker " - - if (startMode == ContainerStartMode.CREATE_NEW_KILL_EXISTING) { - exitAndRmContainer(containerName) - } - if ((startMode == ContainerStartMode.CREATE_NEW_KILL_EXISTING) || (startMode == ContainerStartMode.CREATE_NEW_FAIL_IF_EXISTING)) { - if (!cmd(dockerCmd + "run -dit --name=$containerName $imageName").success) { - throw RuntimeException("could not start docker") - } - } else if (startMode == ContainerStartMode.USE_RUNNING_ELSE_CREATE) { - val runCheckResult = cmdNoEval(dockerCmd + "inspect -f '{{.State.Running}}' $containerName") - - // if either container not found or container found but not running - if (!runCheckResult.success || "false\n" == runCheckResult.out) { - cmdNoEval(dockerCmd + "rm -f $containerName") - cmd(dockerCmd + "run -dit --name=$containerName $imageName") - } - } - ProvResult(containerRuns(containerName, sudo)) -} - - -fun UbuntuProv.containerRunsPlatform(containerName: String, sudo: Boolean = true): Boolean { - val dockerCmd = if (sudo) "sudo docker " else "docker " - return cmdNoEval(dockerCmd + "inspect -f '{{.State.Running}}' $containerName").out?.equals("true\n") ?: false -} - - -fun UbuntuProv.runContainerPlatform( - containerName: String = "defaultProvContainer", - imageName: String = "ubuntu", - sudo: Boolean = true -) = def { - val dockerCmd = if (sudo) "sudo docker " else "docker " - cmd(dockerCmd + "run -dit --name=$containerName $imageName") -} - - -fun UbuntuProv.containerExecPlatform(containerName: String, cmd: String, sudo: Boolean = true) = def { - val dockerCmd = if (sudo) "sudo docker " else "docker " - cmd(dockerCmd + "exec $containerName $cmd") -} - - -fun UbuntuProv.dockerProvideImagePlatform(image: DockerImage, skipIfExisting: Boolean, sudo: Boolean): ProvResult { - val dockerCmd = if (sudo) "sudo docker " else "docker " - - if (skipIfExisting && dockerImageExists(image.imageName())) { - return ProvResult(true) - } - - val path = hostUserHome() + "tmp_docker_img" + fileSeparator() - - if (!xec("test", "-d", path).success) { - cmd("cd ${hostUserHome()} && mkdir tmp_docker_img") - } - - cmd("cd $path && printf '${image.imageText().escapeSingleQuote()}' > Dockerfile") - - return cmd("cd $path && "+dockerCmd+"build --tag ${image.imageName()} .") -} - - -fun UbuntuProv.dockerImageExistsPlatform(imageName: String, sudo: Boolean): Boolean { - val dockerCmd = if (sudo) "sudo docker " else "docker " - - return (cmdNoEval(dockerCmd + "images $imageName -q").out != "") -} - - -fun UbuntuProv.exitAndRmContainerPlatform( - containerName: String, - sudo: Boolean -) = requireAll { - val dockerCmd = if (sudo) "sudo docker " else "docker " - - if (containerRuns(containerName)) { - cmd(dockerCmd + "stop $containerName") - } - cmd(dockerCmd + "rm $containerName") -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/core/entry/Entry.kt b/bin/main/org/domaindrivenarchitecture/provs/core/entry/Entry.kt deleted file mode 100644 index c329021..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/core/entry/Entry.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.entry - -/** - * Calls a static method of a class. - * Only methods are supported with either no parameters or with one vararg parameter of type String. - * Methods with a vararg parameter must be called with at least one argument. - * - * @param args specify class and (optionally) method and parameters, in detail: - * @param args[0] fully-qualified class name of the class to be called - * @param args[1] (optional) static method of the class with a vararg parameter of type String; if not specified, the "main" method is used - * @param args[2...] (optional) String parameters that are passed to the method; can be only used if method name (args[1]) is provided - */ -fun main(vararg args: String) { - - if (args.isNotEmpty()) { - val className = args[0] - - val jClass = Class.forName(className) - - val parameterTypeStringArray = arrayOf>( - Array::class.java - ) - val method = if (args.size == 1) { - jClass.getMethod("main", *parameterTypeStringArray) - } else { - jClass.getMethod(args[1], *parameterTypeStringArray) - } - - if (args.size <= 2) { - method.invoke(null, emptyArray()) - } else { - method.invoke(null, args.drop(2).toTypedArray()) - } - } else { - println("Usage: ") - } -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/core/platforms/UbuntuProv.kt b/bin/main/org/domaindrivenarchitecture/provs/core/platforms/UbuntuProv.kt deleted file mode 100644 index 67fae5b..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/core/platforms/UbuntuProv.kt +++ /dev/null @@ -1,36 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.platforms - -import org.domaindrivenarchitecture.provs.core.ProgressType -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.core.escapeAndEncloseByDoubleQuoteForShell -import org.domaindrivenarchitecture.provs.core.processors.LocalProcessor -import org.domaindrivenarchitecture.provs.core.processors.Processor - -const val SHELL = "/bin/bash" - - -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 { - xec(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo)) - } - - override fun cmdNoLog(cmd: String, dir: String?, sudo: Boolean) : ProvResult { - return xecNoLog(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo)) - } - - override fun cmdNoEval(cmd: String, dir: String?, sudo: Boolean) : ProvResult { - return xec(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo)) - } -} - -private fun commandWithDirAndSudo(cmd: String, dir: String?, sudo: Boolean): String { - val cmdWithDir= if (dir == null) cmd else "cd $dir && $cmd" - return if (sudo) cmdWithDir.sudoize() else cmdWithDir -} - -private fun String.sudoize(): String { - return "sudo " + SHELL + " -c " + this.escapeAndEncloseByDoubleQuoteForShell() -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/core/platforms/WinProv.kt b/bin/main/org/domaindrivenarchitecture/provs/core/platforms/WinProv.kt deleted file mode 100644 index 66b787e..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/core/platforms/WinProv.kt +++ /dev/null @@ -1,30 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.platforms - -import org.domaindrivenarchitecture.provs.core.ProgressType -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.core.processors.LocalProcessor -import org.domaindrivenarchitecture.provs.core.processors.Processor - - -class WinProv internal constructor(processor : Processor = LocalProcessor(), name: String? = null, progressType: ProgressType) - : Prov(processor, name, progressType) { - - private val SHELL = "cmd.exe" - - override fun cmd(cmd: String, dir: String?, sudo: Boolean) : ProvResult = def { - require(!sudo, {"sudo not supported"}) - xec(SHELL, "/c", if (dir == null) cmd else "cd $dir && $cmd") - } - - override fun cmdNoLog(cmd: String, dir: String?, sudo: Boolean) : ProvResult = def { - require(!sudo, {"sudo not supported"}) - xecNoLog(SHELL, "/c", if (dir == null) cmd else "cd $dir && $cmd") - } - - - override fun cmdNoEval(cmd: String, dir: String?, sudo: Boolean) : ProvResult { - require(!sudo, {"sudo not supported"}) - return xec(SHELL, "/c", if (dir == null) cmd else "cd $dir && $cmd") - } -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/core/processors/ContainerUbuntuHostProcessor.kt b/bin/main/org/domaindrivenarchitecture/provs/core/processors/ContainerUbuntuHostProcessor.kt deleted file mode 100644 index d1e219c..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/core/processors/ContainerUbuntuHostProcessor.kt +++ /dev/null @@ -1,69 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.processors - -import org.domaindrivenarchitecture.provs.core.ProgressType -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.docker.provideContainer -import org.domaindrivenarchitecture.provs.core.escapeAndEncloseByDoubleQuoteForShell -import org.domaindrivenarchitecture.provs.core.platforms.SHELL -import org.domaindrivenarchitecture.provs.core.tags.Api - -enum class ContainerStartMode { - USE_RUNNING_ELSE_CREATE, - CREATE_NEW_KILL_EXISTING, - CREATE_NEW_FAIL_IF_EXISTING -} - -enum class ContainerEndMode { - EXIT_AND_REMOVE, - KEEP_RUNNING -} - -open class ContainerUbuntuHostProcessor( - private val containerName: String = "default_provs_container", - @Api // suppress false positive warning - private val dockerImage: String = "ubuntu", - @Api // suppress false positive warning - private val startMode: ContainerStartMode = ContainerStartMode.USE_RUNNING_ELSE_CREATE, - private val endMode: ContainerEndMode = ContainerEndMode.KEEP_RUNNING, - @Api // suppress false positive warning - private val sudo: Boolean = true -) : Processor { - private val dockerCmd = if (sudo) "sudo docker " else "docker " - private var localExecution = LocalProcessor() - private var a = Prov.newInstance(name = "LocalProcessor for Docker operations", progressType = ProgressType.NONE) - - init { - val r = a.provideContainer(containerName, dockerImage, startMode, sudo) - if (!r.success) - throw RuntimeException("Could not start docker image: " + r.toString(), r.exception) - } - - override fun x(vararg args: String): ProcessResult { - return localExecution.x("sh", "-c", dockerCmd + "exec $containerName " + buildCommand(*args)) - } - - override fun xNoLog(vararg args: String): ProcessResult { - return localExecution.xNoLog("sh", "-c", dockerCmd + "exec $containerName " + buildCommand(*args)) - } - - private fun exitAndRm() { - localExecution.x(SHELL, "-c", dockerCmd + "stop $containerName") - localExecution.x(SHELL, "-c", dockerCmd + "rm $containerName") - } - - private fun quoteString(s: String): String { - return s.escapeAndEncloseByDoubleQuoteForShell() - } - - private fun buildCommand(vararg args: String) : String { - return if (args.size == 1) quoteString(args[0]) else - if (args.size == 3 && SHELL == args[0] && "-c" == args[1]) SHELL + " -c " + quoteString(args[2]) - else args.joinToString(separator = " ") - } - - protected fun finalize() { - if (endMode == ContainerEndMode.EXIT_AND_REMOVE) { - exitAndRm() - } - } -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/core/processors/LocalProcessor.kt b/bin/main/org/domaindrivenarchitecture/provs/core/processors/LocalProcessor.kt deleted file mode 100644 index 06e245d..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/core/processors/LocalProcessor.kt +++ /dev/null @@ -1,77 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.processors - -import org.domaindrivenarchitecture.provs.core.escapeNewline -import org.slf4j.LoggerFactory -import java.io.File -import java.io.IOException -import java.nio.charset.Charset - - -private fun getOsName(): String { - return System.getProperty("os.name") -} - -open class LocalProcessor : Processor { - - companion object { - @Suppress("JAVA_CLASS_ON_COMPANION") - private val log = LoggerFactory.getLogger(javaClass.enclosingClass) - - var charset: Charset = if (getOsName().contains("Windows")) Charset.forName("Windows-1252") else Charset.defaultCharset() - init { - log.info("os.name: " + getOsName()) - log.info("user.home: " + System.getProperty("user.home")) - } - } - - private fun workingDir() : String - { - return System.getProperty("user.home") ?: File.separator - } - - override fun x(vararg args: String): ProcessResult { - return execute(true, *args) - } - - - override fun xNoLog(vararg args: String): ProcessResult { - return execute(false, *args) - } - - private fun execute(logging: Boolean, vararg args: String): ProcessResult { - try { - var prefix = "******************** Prov: " - if (logging) { - for (arg in args) { - prefix += " \"${arg.escapeNewline()}\"" - } - } else { - prefix += "\"xxxxxxxx\"" - } - log.info(prefix) - - val proc = ProcessBuilder(args.toList()) - .directory(File(workingDir())) - .redirectOutput(ProcessBuilder.Redirect.PIPE) - .redirectError(ProcessBuilder.Redirect.PIPE) - .start() - - val c = proc.waitFor() - - val r = ProcessResult( - c, - proc.inputStream.bufferedReader(charset).readText(), - proc.errorStream.bufferedReader(charset).readText(), - args = args - ) - if (logging) { - log.info(r.toString()) - } - return r - - } catch (e: IOException) { - e.printStackTrace() - return ProcessResult(-1, ex = e) - } - } -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/core/processors/PrintOnlyProcessor.kt b/bin/main/org/domaindrivenarchitecture/provs/core/processors/PrintOnlyProcessor.kt deleted file mode 100644 index 868d0ef..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/core/processors/PrintOnlyProcessor.kt +++ /dev/null @@ -1,20 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.processors - - -@Suppress("unused") // used externally -class PrintOnlyProcessor : Processor { - - override fun x(vararg args: String): ProcessResult - { - print("PrintOnlyProcessor >>> ") - for (n in args) print("\"$n\" ") - println() - return ProcessResult(0, args = args) - } - - override fun xNoLog(vararg args: String): ProcessResult - { - print("PrintOnlyProcessor >>> ********") - return ProcessResult(0, args = args) - } -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/core/processors/Processor.kt b/bin/main/org/domaindrivenarchitecture/provs/core/processors/Processor.kt deleted file mode 100644 index c868066..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/core/processors/Processor.kt +++ /dev/null @@ -1,56 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.processors - - -interface Processor { - fun x(vararg args: String): ProcessResult - fun xNoLog(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 - } -} - - -data class ProcessResult(val exitCode: Int, val out: String? = null, val err: String? = null, val ex: Exception? = null, val args: Array = emptyArray()) { - - private fun success(): Boolean { - return (exitCode == 0) - } - - fun argsToString() : String { - return args.joinToString( - separator = ", ", - prefix = "[", - postfix = "]", - limit = 4, - truncated = " ..." - ) - } - - override fun toString(): String { - return "--->>> ProcessResult: ${if (success()) "Succeeded" else "FAILED"} -- Code: $exitCode, ${if (!out.isNullOrEmpty()) "Out: $out, " else ""}${if (!err.isNullOrEmpty()) "Err: $err" else ""}" + argsToString() - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as ProcessResult - - if (exitCode != other.exitCode) return false - if (out != other.out) return false - if (err != other.err) return false - if (ex != other.ex) return false - if (!args.contentEquals(other.args)) return false - - return true - } - - override fun hashCode(): Int { - var result = exitCode - result = 31 * result + (out?.hashCode() ?: 0) - result = 31 * result + (err?.hashCode() ?: 0) - result = 31 * result + ex.hashCode() - result = 31 * result + args.contentHashCode() - return result - } -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/core/processors/RemoteUbuntuProcessor.kt b/bin/main/org/domaindrivenarchitecture/provs/core/processors/RemoteUbuntuProcessor.kt deleted file mode 100644 index eae5792..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/core/processors/RemoteUbuntuProcessor.kt +++ /dev/null @@ -1,127 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.processors - -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.core.escapeAndEncloseByDoubleQuoteForShell -import org.domaindrivenarchitecture.provs.core.escapeNewline -import org.domaindrivenarchitecture.provs.core.platforms.SHELL -import net.schmizz.sshj.SSHClient -import net.schmizz.sshj.connection.channel.direct.Session -import net.schmizz.sshj.connection.channel.direct.Session.Command -import net.schmizz.sshj.transport.verification.PromiscuousVerifier -import org.slf4j.LoggerFactory -import java.io.BufferedReader -import java.io.File -import java.io.IOException -import java.io.InputStreamReader -import java.net.InetAddress -import java.util.concurrent.TimeUnit - - -class RemoteProcessor(ip: InetAddress, user: String, password: Secret? = null) : Processor { - - companion object { - @Suppress("JAVA_CLASS_ON_COMPANION") - private val log = LoggerFactory.getLogger(javaClass.enclosingClass) - } - - private val ssh = SSHClient() - - init { - try { - log.info("Connecting to $ip with user: $user with " + if (password != null) "password" else "ssh-key") - - ssh.loadKnownHosts() - - // todo: replace PromiscuousVerifier by more secure solution - ssh.addHostKeyVerifier(PromiscuousVerifier()) - ssh.connect(ip) - - if (password != null) { - ssh.authPassword(user, password.plain()) - } else { - val base = System.getProperty("user.home") + File.separator + ".ssh" + File.separator - ssh.authPublickey(user, base + "id_rsa", base + "id_dsa", base + "id_ed25519", base + "id_ecdsa") - } - } catch (e: Exception) { - try { - ssh.disconnect() - } finally { - log.error("Got exception when initializing ssh: " + e.message) - throw RuntimeException("Error when initializing ssh", e) - } - } - } - - override fun x(vararg args: String): ProcessResult { - return execute(true, *args) - } - - override fun xNoLog(vararg args: String): ProcessResult { - return execute(false, *args) - } - - private fun execute(logging: Boolean, vararg args: String): ProcessResult { - var prefix = "******************** Prov: " - if (logging) { - for (arg in args) { - prefix += " \"${arg.escapeNewline()}\"" - } - } else { - prefix += "\"xxxxxxxx\"" - } - log.info(prefix) - - val cmdString: String = - if (args.size == 1) - args[0].escapeAndEncloseByDoubleQuoteForShell() - else - if (args.size == 3 && SHELL == args[0] && "-c" == args[1]) - SHELL + " -c " + args[2].escapeAndEncloseByDoubleQuoteForShell() - else - args.joinToString(separator = " ") - - var session: Session? = null - - try { - session = ssh.startSession() - - val cmd: Command = session!!.exec(cmdString) - val out = BufferedReader(InputStreamReader(cmd.inputStream)).use { it.readText() } - val err = BufferedReader(InputStreamReader(cmd.errorStream)).use { it.readText() } - cmd.join(100, TimeUnit.SECONDS) - - val cmdRes = ProcessResult(cmd.exitStatus, out, err, args = args) - if (logging) { - log.info(cmdRes.toString()) - } - session.close() - - return cmdRes - - } catch (e: Exception) { - try { - session?.close() - } finally { - // nothing to do - } - return ProcessResult( - -1, - err = "Error when opening or executing remote ssh session (Pls check host, user, password resp. ssh key) - ", - ex = e - ) - } - } - - override fun close() { - try { - log.info("Disconnecting ssh.") - ssh.disconnect() - } catch (e: IOException) { - // No prov required - } - } - - protected fun finalize() { - close() - } -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/core/tags/Api.kt b/bin/main/org/domaindrivenarchitecture/provs/core/tags/Api.kt deleted file mode 100644 index 9d9bd08..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/core/tags/Api.kt +++ /dev/null @@ -1,6 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.tags - -@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION) -@Retention(AnnotationRetention.SOURCE) -@Suppress("unused") // element is offered to be used externally -annotation class Api \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/demos/HelloWorld.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/demos/HelloWorld.kt deleted file mode 100644 index 8b3b7d8..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/demos/HelloWorld.kt +++ /dev/null @@ -1,14 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.demos - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.local - - -fun Prov.helloWorld() = def { - cmd("echo Hello world!") -} - - -fun main() { - local().helloWorld() -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/demos/SystemInfos.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/demos/SystemInfos.kt deleted file mode 100644 index 2488d52..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/demos/SystemInfos.kt +++ /dev/null @@ -1,54 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.demos - -import org.domaindrivenarchitecture.provs.core.* - - -/** - * Prints some information and settings of the operating system and environment. - * - * For running locally no arguments are required. - * For running remotely either 2 or 3 arguments must be provided: - * either host and user for connection by ssh key () - * or host, user and password for password-authenticated connection. - * E.g. 172.0.0.123 username or 172.0.0.123 username password - */ -fun main(vararg args: String) { - if (args.isEmpty()) { - local().printInfos() - } else { - if (args.size !in 2..3) { - println("Wrong number of arguments. Please specify either host and user if connection is done by ssh key or otherwise host, user and password. E.g. 172.0.0.123 username password") - } else { - val password = if (args.size == 2) null else Secret(args[3]) - remote(args[0], args[1], password = password).printInfos() - } - } -} - - -fun Prov.printInfos() = def { - println("\nUbuntu Version:\n${ubuntuVersion()}") - println("\nCurrent directory:\n${currentDir()}") - println("\nTime zone:\n${timeZone()}") - - val dir = cmd("pwd").out - println("\nCurrent directory: $dir") - - ProvResult(true) -} - - -fun Prov.ubuntuVersion(): String? { - return cmd("lsb_release -a").out -} - - -fun Prov.currentDir(): String? { - return cmd("pwd").out -} - - -fun Prov.timeZone(): String? { - return cmd("cat /etc/timezone").out -} - diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_compounds/monitoring/ProvisionMonitoring.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/server_compounds/monitoring/ProvisionMonitoring.kt deleted file mode 100644 index 8c85888..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_compounds/monitoring/ProvisionMonitoring.kt +++ /dev/null @@ -1,18 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_compounds.monitoring - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.base.NginxConf -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.base.nginxHttpConf -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.provisionNginxStandAlone -import org.domaindrivenarchitecture.provs.extensions.server_software.prometheus.base.configurePrometheusDocker -import org.domaindrivenarchitecture.provs.extensions.server_software.prometheus.base.runPrometheusDocker - - -@Suppress("unused") // used externally -fun Prov.provisionMonitoring() = requireAll { - configurePrometheusDocker() - runPrometheusDocker() - provisionNginxStandAlone(NginxConf.nginxHttpConf()) -} - - diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_compounds/monitoring/ProvisionNginxAndMonitoring.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/server_compounds/monitoring/ProvisionNginxAndMonitoring.kt deleted file mode 100644 index 9320da8..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_compounds/monitoring/ProvisionNginxAndMonitoring.kt +++ /dev/null @@ -1,20 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_compounds.monitoring - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.base.NginxConf -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.base.nginxAddLocation -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.base.nginxCreateSelfSignedCertificate -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.base.nginxHttpsConfWithLocationFiles -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.provisionNginxStandAlone -import org.domaindrivenarchitecture.provs.extensions.server_software.prometheus.base.prometheusNginxConfig -import org.domaindrivenarchitecture.provs.extensions.server_software.prometheus.provisionPrometheusDocker - - -@Suppress("unused") // used externally -fun Prov.provisionNginxMonitoring(nginxHost: String = "localhost") = def { - provisionPrometheusDocker(nginxHost) - nginxCreateSelfSignedCertificate() - provisionNginxStandAlone(NginxConf.nginxHttpsConfWithLocationFiles()) - nginxAddLocation("443", nginxHost, "/prometheus", prometheusNginxConfig) -} - diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/certbot/ProvisionCertbot.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/certbot/ProvisionCertbot.kt deleted file mode 100644 index ad66362..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/certbot/ProvisionCertbot.kt +++ /dev/null @@ -1,28 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.certbot - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.fileExists -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall - - -/** - * Provisions a certbot for the specified serverName and email to obtain and renew letsencrypt certificates - * Parameter can be used to specify certbot options e.g. "--nginx" to configure nginx, see https://certbot.eff.org/docs/using.html#certbot-command-line-options - */ -fun Prov.provisionCertbot(serverName: String, email: String?, additionalOptions: String? = "") = requireAll { - aptInstall("snapd") - sh(""" - sudo snap install core; sudo snap refresh core - sudo snap install --classic certbot - """.trimIndent()) - - if (!fileExists("/usr/bin/certbot")) { - cmd("sudo ln -s /snap/bin/certbot /usr/bin/certbot") - val emailOption = email?.let { " -m $it" } ?: "--register-unsafely-without-email" - cmd("sudo certbot $additionalOptions -n --agree-tos $emailOption -d $serverName") - } else { - ProvResult(true) - } - -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/firewall/ProvisionFirewall.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/firewall/ProvisionFirewall.kt deleted file mode 100644 index 1cc8ed2..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/firewall/ProvisionFirewall.kt +++ /dev/null @@ -1,143 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.firewall - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall - - -fun Prov.saveIpTables() = requireAll { - sh(""" - iptables-save > /etc/iptables/rules.v4 - ip6tables-save > /etc/iptables/rules.v6 - - netfilter-persistent save""", - sudo = true) -} - - -fun Prov.makeIpTablesPersistent() = requireAll { - // inspired by https://gist.github.com/alonisser/a2c19f5362c2091ac1e7 - // enables iptables-persistent to be installed without manual input - sh(""" - echo iptables-persistent iptables-persistent/autosave_v4 boolean true | sudo debconf-set-selections - echo iptables-persistent iptables-persistent/autosave_v6 boolean true | sudo debconf-set-selections - """.trimIndent()) - - aptInstall("iptables-persistent netfilter-persistent") - saveIpTables() -} - - -fun Prov.resetFirewall() = requireAll { - sh(""" - #!/bin/bash - sudo iptables -F - sudo iptables -X - sudo iptables -t nat -F - sudo iptables -t nat -X - sudo iptables -t mangle -F - sudo iptables -t mangle -X - - # the rules allow us to reconnect by opening up all traffic. - sudo iptables -P INPUT ACCEPT - sudo iptables -P FORWARD ACCEPT - sudo iptables -P OUTPUT ACCEPT - - # print out all rules to the console after running this file. - sudo iptables -nL - """, sudo = true - ) -} - - -fun Prov.provisionFirewall(addNetworkProtections: Boolean = false) = requireAll { - if (addNetworkProtections) { - networkProtections() - } - - // inspired by: https://github.com/ChrisTitusTech/firewallsetup/blob/master/firewall - sh(""" - # Firewall - - # Accept all traffic first to avoid ssh lockdown via iptables firewall rules # - iptables -P INPUT ACCEPT - iptables -P FORWARD ACCEPT - iptables -P OUTPUT ACCEPT - - # Flush all chains - iptables --flush - - # Allow unlimited traffic on the loopback interface - iptables -A INPUT -i lo -j ACCEPT - iptables -A OUTPUT -o lo -j ACCEPT - - # Previously initiated and accepted exchanges bypass rule checking - # Allow unlimited outbound traffic - iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT - iptables -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT - - #Ratelimit SSH for attack protection - iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP - iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set - iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT - - # Allow http/https ports to be accessible from the outside - iptables -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT # http - iptables -A INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT # https - - # UDP packet rule. This is just a random udp packet rule as an example only - # iptables -A INPUT -p udp --dport 5021 -m state --state NEW -j ACCEPT - - # Allow pinging of your server - iptables -A INPUT -p icmp --icmp-type 8 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT - - - # Drop all other traffic - iptables -A INPUT -j DROP - - # print the activated rules to the console when script is completed - iptables -nL - - # Set default policies - iptables --policy INPUT DROP - iptables --policy OUTPUT DROP - iptables --policy FORWARD DROP - """, sudo = true) - if (chk("docker -v")) { - ipTablesRecreateDockerRules() - } else { - ProvResult(true, "No need to create iptables docker rules as no docker installed.") - } -} - - -fun Prov.networkProtections() = def { - sh(""" - # Drop ICMP echo-request messages sent to broadcast or multicast addresses - echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts - - # Drop source routed packets - echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route - - # Enable TCP SYN cookie protection from SYN floods - echo 1 > /proc/sys/net/ipv4/tcp_syncookies - - # Don't accept ICMP redirect messages - echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects - - # Don't send ICMP redirect messages - echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects - - # Enable source address spoofing protection - echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter - - # Log packets with impossible source addresses - echo 1 > /proc/sys/net/ipv4/conf/all/log_martians - """.trimIndent()) -} - - -fun Prov.ipTablesRecreateDockerRules() = requireAll { - // see https://stackoverflow.com/questions/25917941/docker-how-to-re-create-dockers-additional-iptables-rules - cmd("sudo service docker restart") -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/firewall/base/FirewallBackup.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/firewall/base/FirewallBackup.kt deleted file mode 100644 index f4b6068..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/firewall/base/FirewallBackup.kt +++ /dev/null @@ -1,21 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.firewall.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import java.time.LocalDateTime -import java.time.format.DateTimeFormatter - - -fun Prov.saveIpTablesToFile() = def { - val dateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("-yyyy-MM-dd--HH:mm:ss")) - val file = "savedrules$dateTime.txt" - sh(""" - sudo iptables-save > $file - cat $file""") -} - -fun Prov.restoreIpTablesFromFile(file: String? = null) = def { - val fileName = file ?: cmd("ls -r a* | head -1\n").out - fileName?.let { cmd("sudo iptables-restore < $file") } - ?: ProvResult(false, err = "File to restore not found.") -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nexus/ProvisionNexus.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nexus/ProvisionNexus.kt deleted file mode 100644 index 5a2f65f..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nexus/ProvisionNexus.kt +++ /dev/null @@ -1,92 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.nexus - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.core.docker.containerRuns -import org.domaindrivenarchitecture.provs.core.remote -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.fileExists -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.domaindrivenarchitecture.provs.ubuntu.user.base.createUser -import org.domaindrivenarchitecture.provs.extensions.server_software.certbot.provisionCertbot -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.base.NginxConf -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.base.nginxReverseProxyHttpConfig -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.provisionNginxStandAlone - - -/** - * Provisions sonatype nexus in a docker container. - * If you would want nexus to be accessible directly from the internet (e.g. for test or demo reasons) - * set parameter portAccessibleFromNetwork to true. - */ -fun Prov.provisionNexusWithDocker(portAccessibleFromNetwork: Boolean = false) = requireAll { - // https://blog.sonatype.com/sonatype-nexus-installation-using-docker - // https://medium.com/@AhGh/how-to-setup-sonatype-nexus-3-repository-manager-using-docker-7ff89bc311ce - aptInstall("docker.io") - - if (!containerRuns("nexus")) { - val volume = "nexus-data" - if (!cmdNoEval("docker volume inspect $volume").success) { - cmd("docker volume create --name $volume") - } - cmd("sudo docker run -d --restart unless-stopped -p 8081:8081 --name nexus -v nexus-data:/nexus-data sonatype/nexus3") - - for (n in 0..3) { - if (fileExists("/var/lib/docker/volumes/$volume/_data/admin.password", sudo = true)) { - val res = cmd("sudo cat /var/lib/docker/volumes/$volume/_data/admin.password") - println("Admin Password:" + res.out) - break - } - Thread.sleep(20000) - } - } - if (!portAccessibleFromNetwork) { - val netIf = getDefaultNetworkingInterface() - netIf?.also { - val iptablesParameters = "DOCKER-USER -i $it ! -s 127.0.0.1 -j DROP" - if (!cmdNoEval("sudo iptables -C $iptablesParameters").success) { - cmd("sudo iptables -I $iptablesParameters") - } - } - } - ProvResult(true) // dummy -} - -private fun Prov.getDefaultNetworkingInterface(): String? { - return cmd("route | grep \"^default\" | grep -o \"[^ ]*\$\"\n").out?.trim() -} - - -/** - * Provisions sonatype nexus on the specified host. - * Creates user "nexus" on the remote system. - * Installs nexus in a docker container behind an nginx reverse proxy with ssl using letsencrypt certificates. - * - * To run this method it is required to have ssl root access to the host. - */ -@Suppress("unused") // to be used externally -fun provisionNexusServer(serverName: String, certbotEmail: String) { - val userName = "nexus" + 7 - remote(serverName, "root").def { - createUser(userName, copyAuthorizedKeysFromCurrentUser = true, sudo = true) - } - remote(serverName, userName).requireAll { - provisionNexusWithDocker() - - if (provisionNginxStandAlone(NginxConf.nginxReverseProxyHttpConfig(serverName)).success) { - - cmd("sudo cat /etc/nginx/nginx.conf") - - provisionCertbot(serverName, certbotEmail, "--nginx") - - optional { - cmd("sudo cat /etc/nginx/nginx.conf") - cmd("sudo sed -i 's/X-Forwarded-Proto \"http\"/X-Forwarded-Proto \"https\"/g' /etc/nginx/nginx.conf") - cmd("sudo systemctl reload nginx") - } - } else { - ProvResult(true) - } - } -} - - diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nexus/base/NginxConf.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nexus/base/NginxConf.kt deleted file mode 100644 index 25e3b58..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nexus/base/NginxConf.kt +++ /dev/null @@ -1,83 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.nexus.base - -fun reverseProxyConfigHttpPort80(serverName: String): String { - // see https://help.sonatype.com/repomanager3/installation/run-behind-a-reverse-proxy - return """ - events {} # event context have to be defined to consider config valid - - http { - - proxy_send_timeout 120; - proxy_read_timeout 300; - proxy_buffering off; - keepalive_timeout 5 5; - tcp_nodelay on; - - server { - listen 80; - server_name $serverName; - - # allow large uploads of files - client_max_body_size 1G; - - # optimize downloading files larger than 1G - #proxy_max_temp_file_size 2G; - - location / { - # Use IPv4 upstream address instead of DNS name to avoid attempts by nginx to use IPv6 DNS lookup - proxy_pass http://127.0.0.1:8081/; - proxy_set_header Host ${'$'}host; - proxy_set_header X-Real-IP ${'$'}remote_addr; - proxy_set_header X-Forwarded-For ${'$'}proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto "http"; - } - } - } - """.trimIndent() -} - - -fun reverseProxyConfigSsl(serverName: String, ssl_certificate: String? = null, ssl_certificate_key: String? = null): String { - // see https://help.sonatype.com/repomanager3/installation/run-behind-a-reverse-proxy - - val sslCertificateEntry = ssl_certificate?.let { "ssl_certificate $ssl_certificate;" } ?: "ssl_certificate /etc/letsencrypt/live/$serverName/fullchain.pem;" - val sslCertificateKeyEntry = ssl_certificate?.let { "ssl_certificate_key $ssl_certificate_key;" } ?: "ssl_certificate_key /etc/letsencrypt/live/$serverName/privkey.pem" - - return """ -events {} # event context have to be defined to consider config valid - -http { - - proxy_send_timeout 120; - proxy_read_timeout 300; - proxy_buffering off; - keepalive_timeout 5 5; - tcp_nodelay on; - - server { - listen *:443 ssl; - server_name $serverName; - - # allow large uploads of files - client_max_body_size 1G; - - # optimize downloading files larger than 1G - # proxy_max_temp_file_size 2G; - - $sslCertificateEntry - $sslCertificateKeyEntry - - location / { - # Use IPv4 upstream address instead of DNS name to avoid attempts by nginx to use IPv6 DNS lookup - proxy_pass http://127.0.0.1:8081/; - proxy_set_header Host ${'$'}host; - proxy_set_header X-Real-IP ${'$'}remote_addr; - proxy_set_header X-Forwarded-For ${'$'}proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto "https"; - } - } -} - """ -} - - diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/ProvisionNginx.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/ProvisionNginx.kt deleted file mode 100644 index 51714ad..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/ProvisionNginx.kt +++ /dev/null @@ -1,46 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.nginx - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.core.remote -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createFile -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.fileExists -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.base.NginxConf -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.base.createNginxLocationFolders -import kotlin.system.exitProcess - - -internal const val configFile = "/etc/nginx/nginx.conf" - - -fun Prov.provisionNginxStandAlone(config: NginxConf? = null) = requireAll { - - aptInstall("nginx") - - createNginxLocationFolders() - - if (config != null) { - if (fileExists(configFile)) { - cmd("sudo mv $configFile $configFile-orig") - } - createFile(configFile, config.conf, sudo = true) - val configCheck = cmd("sudo nginx -t") - if (configCheck.success) { - cmd("sudo service nginx restart") - } else { - ProvResult(false, err = "Nginx config is incorrect:\n" + configCheck.err) - } - } else { - ProvResult(true) // dummy - } -} - - -fun provisionRemote(vararg args: String) { - if (args.size != 2) { - println("Pls specify host and user for remote installation of nginx.") - exitProcess(1) - } - remote(args[0], args[1]).provisionNginxStandAlone() -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/base/BasicAuth.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/base/BasicAuth.kt deleted file mode 100644 index d9d48d2..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/base/BasicAuth.kt +++ /dev/null @@ -1,12 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.nginx.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall - -fun Prov.nginxAddBasicAuth(user: String, password: Secret) = requireAll { - aptInstall("apache2-utils") - val passwordFile = "/etc/nginx/.htpasswd" - cmdNoLog("sudo htpasswd -b -c $passwordFile $user ${password.plain()}") -} - diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/base/Configs.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/base/Configs.kt deleted file mode 100644 index 40be12d..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/base/Configs.kt +++ /dev/null @@ -1,162 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.nginx.base - -class NginxConf(val conf: String = NGINX_MINIMAL_CONF) { - companion object {} -} - - -const val NGINX_MINIMAL_CONF = """ -events {} - -http { - server { - listen 80; - - location / { - return 200 'Hi from nginx!'; - } - } -} -""" - - -@Suppress("unused") // use later -fun NginxConf.Companion.nginxHttpConf( - serverName: String = "localhost" -): NginxConf { - return NginxConf( - """ -events {} - -http { - server { - listen 80; - server_name $serverName; - - include /etc/nginx/locations-enabled/port80*$locationsFileExtension; - } -} -""" - ) -} - - -fun NginxConf.Companion.nginxHttpsConfWithLocationFiles( - sslCertificate: String = "/etc/nginx/ssl/cert/selfsigned.crt", - sslCertificateKey: String = "/etc/nginx/ssl/private/selfsigned.key" -): NginxConf { - return NginxConf( - """ -events {} - -http { - server { - listen 443 ssl; - server_name localhost; - - ssl_certificate $sslCertificate; - ssl_certificate_key $sslCertificateKey; - - include /etc/nginx/locations-enabled/port443*$locationsFileExtension; - } -} -""" - ) -} - - -@Suppress("unused") // use later -fun NginxConf.Companion.nginxReverseProxySslConfig( - serverName: String, - ssl_certificate: String? = null, - ssl_certificate_key: String? = null -): NginxConf { - // see https://help.sonatype.com/repomanager3/installation/run-behind-a-reverse-proxy - - val sslCertificateEntry = ssl_certificate?.let { "ssl_certificate $ssl_certificate;" } - ?: "ssl_certificate /etc/letsencrypt/live/$serverName/fullchain.pem;" - val sslCertificateKeyEntry = ssl_certificate?.let { "ssl_certificate_key $ssl_certificate_key;" } - ?: "ssl_certificate_key /etc/letsencrypt/live/$serverName/privkey.pem" - - return NginxConf( - """ -events {} # event context have to be defined to consider config valid - -http { - - proxy_send_timeout 120; - proxy_read_timeout 300; - proxy_buffering off; - keepalive_timeout 5 5; - tcp_nodelay on; - - server { - listen *:443 ssl; - server_name $serverName; - - # allow large uploads of files - client_max_body_size 1G; - - # optimize downloading files larger than 1G - #proxy_max_temp_file_size 2G; - - $sslCertificateEntry - $sslCertificateKeyEntry - - location / { - # Use IPv4 upstream address instead of DNS name to avoid attempts by nginx to use IPv6 DNS lookup - proxy_pass http://127.0.0.1:8081/; - proxy_set_header Host ${'$'}host; - proxy_set_header X-Real-IP ${'$'}remote_addr; - proxy_set_header X-Forwarded-For ${'$'}proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto "https"; - } - } -} - """ - ) -} - - -@Suppress("unused") // use later -fun NginxConf.Companion.nginxReverseProxyHttpConfig( - serverName: String -): NginxConf { - // see https://help.sonatype.com/repomanager3/installation/run-behind-a-reverse-proxy - - return NginxConf( - """ -events {} # event context have to be defined to consider config valid - -http { - - proxy_send_timeout 120; - proxy_read_timeout 300; - proxy_buffering off; - keepalive_timeout 5 5; - tcp_nodelay on; - - server { - listen *:80; - server_name $serverName; - - # allow large uploads of files - client_max_body_size 1G; - - # optimize downloading files larger than 1G - #proxy_max_temp_file_size 2G; - - location / { - # Use IPv4 upstream address instead of DNS name to avoid attempts by nginx to use IPv6 DNS lookup - proxy_pass http://127.0.0.1:8081/; - proxy_set_header Host ${'$'}host; - proxy_set_header X-Real-IP ${'$'}remote_addr; - proxy_set_header X-Forwarded-For ${'$'}proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto "https"; - } - } -} - """ - ) -} - diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/base/Locations.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/base/Locations.kt deleted file mode 100644 index cf14cc7..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/base/Locations.kt +++ /dev/null @@ -1,44 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.nginx.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.* - - -internal const val locationsAvailableDir = "/etc/nginx/locations-available/" -internal const val locationsEnabledDir = "/etc/nginx/locations-enabled/" -internal const val locationsFileExtension = ".locations" - - -fun Prov.createNginxLocationFolders() = requireAll { - createDirs(locationsEnabledDir, sudo = true) - createDirs(locationsAvailableDir, sudo = true) -} - - -fun Prov.nginxIncludeLocationFolders() = requireAll { - replaceTextInFile("/etc/nginx/nginx.conf", "listen 80;\n", - """listen 80; - include ${locationsAvailableDir}port80*$locationsFileExtension; - include ${locationsEnabledDir}port443*$locationsFileExtension; - """) -} - - -fun Prov.nginxAddLocation(port: String, locationFileName: String, urlPath: String, content: String) = requireAll { - - val locationConf = """location $urlPath {""" + - content + - "\n}" - - if (!dirExists(locationsAvailableDir, sudo = true)) { - createNginxLocationFolders() - } - - createFile("${locationsAvailableDir}port${port}_$locationFileName$locationsFileExtension", locationConf, sudo = true) - if (!fileExists("${locationsEnabledDir}port${port}_$locationFileName$locationsFileExtension", sudo = true)) { - cmd("sudo ln -s ${locationsAvailableDir}port${port}_$locationFileName$locationsFileExtension ${locationsEnabledDir}port${port}_$locationFileName$locationsFileExtension ") - } else { - ProvResult(true) - } -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/base/SelfSignedCertificate.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/base/SelfSignedCertificate.kt deleted file mode 100644 index 196aad7..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/base/SelfSignedCertificate.kt +++ /dev/null @@ -1,36 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.nginx.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDirs -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.provisionNginxStandAlone - - -internal val certificateName = "selfsigned" -internal val sslDays = 365 -val dirSslCert="/etc/nginx/ssl/cert" -val dirSslKey="/etc/nginx/ssl/private" - - -fun Prov.nginxCreateSelfSignedCertificate( - country: String = "DE", - state: String = "test", - locality: String = "test", - organization: String = "test", - organizationalUnit: String = "test", - commonName: String = "test", - email : String = "test@test.net" -) = def { - // inspired by https://gist.github.com/adrianorsouza/2bbfe5e197ce1c0b97c8 - createDirs(dirSslCert, sudo = true) - createDirs(dirSslKey, sudo = true) - cmd("cd $dirSslKey && sudo openssl req -x509 -nodes -newkey rsa:2048 -keyout $certificateName.key -out $certificateName.crt -days $sslDays -subj \"/C=$country/ST=$state/L=$locality/O=$organization/OU=$organizationalUnit/CN=$commonName/emailAddress=$email\"") - cmd("sudo mv $dirSslKey/$certificateName.crt $dirSslCert/") -} - - -fun Prov.configureNginxWithSelfSignedCertificate() = def { - // todo: should not call provisionNginxStandAlone, which is defined in the package above - provisionNginxStandAlone(NginxConf.nginxReverseProxySslConfig("localhost", - dirSslCert+"/"+ certificateName + ".crt", - dirSslKey + "/" + certificateName + ".key")) -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/prometheus/ProvisionPrometheus.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/prometheus/ProvisionPrometheus.kt deleted file mode 100644 index d138fb0..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/prometheus/ProvisionPrometheus.kt +++ /dev/null @@ -1,19 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.prometheus - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.extensions.server_software.prometheus.base.* - -/** - * Provisions prometheus monitoring. - * If running behind an nginx, pls specify the hostname in parameter nginxHost (e.g. mydomain.com). - * To run it without nodeExporter (which provides system data to prometheus), set withNodeExporter to false. - */ -fun Prov.provisionPrometheusDocker(nginxHost: String? = null, withNodeExporter: Boolean = true) = def { - configurePrometheusDocker() - if (withNodeExporter) { - installNodeExporter() - runNodeExporter() - addNodeExporterToPrometheusConf() - } - runPrometheusDocker(nginxHost) -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/prometheus/base/NodeExporter.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/prometheus/base/NodeExporter.kt deleted file mode 100644 index be205d4..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/prometheus/base/NodeExporter.kt +++ /dev/null @@ -1,84 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.prometheus.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDir -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createFile -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.fileContainsText -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.replaceTextInFile -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.domaindrivenarchitecture.provs.ubuntu.user.base.whoami - - -internal val defaultInstallationDir = "/usr/local/bin/" - - -fun Prov.installNodeExporter() = requireAll { - // inspired by https://devopscube.com/monitor-linux-servers-prometheus-node-exporter/ and - // https://www.howtoforge.com/tutorial/how-to-install-prometheus-and-node-exporter-on-centos-8/#step-install-and-configure-nodeexporter - val downloadFileBasename = "node_exporter-1.0.1.linux-amd64" - val downloadFile = "$downloadFileBasename.tar.gz" - val downloadPath = "~/tmp/" - val fqFile = downloadPath + downloadFile - - aptInstall("curl") - createDir("tmp") - sh( - """ - cd tmp && curl -LO https://github.com/prometheus/node_exporter/releases/download/v1.0.1/$downloadFile --output $downloadFile - cd tmp && tar -xvf $fqFile -C $downloadPath - - sudo mv $downloadPath$downloadFileBasename/node_exporter $defaultInstallationDir""" - ) - -} - - -fun Prov.runNodeExporter() = def { - createFile("/etc/systemd/system/node_exporter.service", nodeExporterServiceConf(whoami()?:"nouserfound"), sudo = true) - - sh(""" - sudo systemctl daemon-reload - - # start the node_exporter service and enable it to launch everytime at system startup. - sudo systemctl start node_exporter - sudo systemctl enable node_exporter - - # check if running - sudo systemctl status node_exporter --no-pager -l - """) -} - - -fun Prov.addNodeExporterToPrometheusConf ( - prometheusConf: String = "/etc/prometheus/prometheus.yml", - sudo: Boolean = true -) = requireAll { - val prometheusConfNodeExporter = """ -scrape_configs: - - job_name: 'node_exporter' - static_configs: - - targets: ['172.17.0.1:9100'] -""" - if (!fileContainsText(prometheusConf, "- job_name: 'node_exporter'", sudo)) { - replaceTextInFile(prometheusConf, "\nscrape_configs:\n", prometheusConfNodeExporter) - } - // cmd("sudo systemctl restart prometheus") for standalone - cmd("sudo docker restart prometheus") -} - - -fun nodeExporterServiceConf(user: String, installationDir: String = defaultInstallationDir): String { - return """ -[Unit] -Description=Node Exporter -Wants=network-online.target -After=network-online.target - -[Service] -User=$user -ExecStart=${installationDir}node_exporter - -[Install] -WantedBy=default.target -""" -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/prometheus/base/Prometheus.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/prometheus/base/Prometheus.kt deleted file mode 100644 index 5b3fea4..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/prometheus/base/Prometheus.kt +++ /dev/null @@ -1,75 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.prometheus.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.docker.containerRuns -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDirs -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createFile -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall - - -internal val configDir = "/etc/prometheus/" -internal val configFile = "prometheus.yml" - - -fun Prov.configurePrometheusDocker(config: String = prometheusDefaultConfig) = requireAll { - createDirs(configDir, sudo = true) - createFile(configDir + configFile, config, sudo = true) -} - - -fun Prov.runPrometheusDocker(nginxHost: String? = null) = requireAll { - aptInstall("docker.io") - - val containerName = "prometheus" - - if (containerRuns(containerName)) { - cmd("sudo docker restart $containerName") - } else { - if (nginxHost == null) { - cmd( - "sudo docker run -d -p 9090:9090 " + - " --name $containerName " + - " --restart on-failure:1" + - " -v prometheus-data:/prometheus" + - " -v $configDir$configFile:/etc/prometheus/prometheus.yml " + - " prom/prometheus" - ) - } else { - cmd( - "sudo docker run -d -p 9090:9090 " + - " --name $containerName " + - " --restart on-failure:1" + - " -v prometheus-data:/prometheus" + - " -v $configDir$configFile:/etc/prometheus/prometheus.yml " + - " prom/prometheus --config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus " + - "--web.console.libraries=/usr/share/prometheus/console_libraries " + - "--web.console.templates=/usr/share/prometheus/consoles " + - "--web.external-url=http://$nginxHost/prometheus" - ) - } - } -} - - -private const val prometheusDefaultConfig = - """ -global: - scrape_interval: 15s # By default, scrape targets every 15 seconds. - - # Attach these labels to any time series or alerts when communicating with - # external systems (federation, remote storage, Alertmanager). - external_labels: - monitor: 'codelab-monitor' - -# A scrape configuration containing exactly one endpoint to scrape: -# Here it's Prometheus itself. -scrape_configs: - # The job name is added as a label `job=` to any timeseries scraped from this config. - - job_name: 'prometheus' - - # Override the global default and scrape targets from this job every 5 seconds. - scrape_interval: 5s - - static_configs: - - targets: ['localhost:9090'] -""" diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/prometheus/base/PrometheusNginxConfig.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/prometheus/base/PrometheusNginxConfig.kt deleted file mode 100644 index 39fdb22..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/server_software/prometheus/base/PrometheusNginxConfig.kt +++ /dev/null @@ -1,5 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.prometheus.base - -val prometheusNginxConfig = """ - proxy_pass http://localhost:9090/prometheus; -""" \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/ProvisionWorkplace.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/ProvisionWorkplace.kt deleted file mode 100644 index c5146c4..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/ProvisionWorkplace.kt +++ /dev/null @@ -1,155 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace - -import org.domaindrivenarchitecture.provs.core.* -import org.domaindrivenarchitecture.provs.core.processors.RemoteProcessor -import org.domaindrivenarchitecture.provs.extensions.workplace.base.* -import org.domaindrivenarchitecture.provs.ubuntu.git.provisionGit -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstallFromPpa -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptPurge -import org.domaindrivenarchitecture.provs.ubuntu.keys.KeyPair -import org.domaindrivenarchitecture.provs.ubuntu.keys.base.gpgFingerprint -import org.domaindrivenarchitecture.provs.ubuntu.keys.provisionKeysCurrentUser -import org.domaindrivenarchitecture.provs.ubuntu.secret.secretSources.PromptSecretSource -import org.domaindrivenarchitecture.provs.ubuntu.user.base.currentUserCanSudo -import org.domaindrivenarchitecture.provs.ubuntu.user.base.makeUserSudoerWithNoSudoPasswordRequired -import org.domaindrivenarchitecture.provs.ubuntu.user.base.whoami -import java.net.InetAddress -import kotlin.system.exitProcess - - -enum class WorkplaceType { - MINIMAL, OFFICE, IDE -} - - -/** - * Provisions software and configurations for a personal workplace. - * Offers the possibility to choose between different types. - * Type OFFICE installs office-related software like Thunderbird, LibreOffice, and much more. - * Type IDE provides additional software for a development environment, such as Visual Studio Code, IntelliJ, etc. - * - * Prerequisites: user must be sudoer. If password is required for user to execute sudo, then also parameter userPassword must be provided - * - * @param workplaceType - * @param userPassword only needs to be provided if user cannot sudo without password - */ -fun Prov.provisionWorkplace( - workplaceType: WorkplaceType = WorkplaceType.MINIMAL, - ssh: KeyPair? = null, - gpg: KeyPair? = null, - gitUserName: String? = null, - gitEmail: String? = null, - userPassword: Secret? = null -) = requireAll { - - userPassword?.also { makeUserSudoerWithNoSudoPasswordRequired(it) } - - if (!currentUserCanSudo()) { - throw Exception("Current user ${whoami()} cannot execute sudo without a password, but he must be able to in order to provisionWorkplace") - } - - aptInstall("ssh gnupg curl git") - - provisionKeysCurrentUser(gpg, ssh) - provisionGit(gitUserName ?: whoami(), gitEmail, gpg?.let { gpgFingerprint(it.publicKey.plain()) }) - - installVirtualBoxGuestAdditions() - - aptPurge("remove-power-management xfce4-power-manager " + - "xfce4-power-manager-plugins xfce4-power-manager-data") - aptPurge("abiword gnumeric") - aptPurge("popularity-contest") - - configureNoSwappiness() - - if (workplaceType == WorkplaceType.OFFICE || workplaceType == WorkplaceType.IDE) { - aptInstall("seahorse") - aptInstall(BASH_UTILS) - aptInstall(OS_ANALYSIS) - aptInstall(ZIP_UTILS) - - aptInstall("firefox chromium-browser") - aptInstall("thunderbird libreoffice") - aptInstall("xclip") - - installZimWiki() - installGopass() - aptInstallFromPpa("nextcloud-devs", "client", "nextcloud-client") - - aptInstall("inkscape") - aptInstall("dia") - - aptInstall(SPELLCHECKING_DE) - - installRedshift() - configureRedshift() - } - - if (workplaceType == WorkplaceType.IDE) { - - aptInstall(JAVA_JDK) - - aptInstall(OPEN_VPM) - aptInstall(OPENCONNECT) - aptInstall(VPNC) - - installDocker() - - // IDEs - cmd("sudo snap install intellij-idea-community --classic") - installVSC("python", "clojure") - } - - ProvResult(true) // dummy -} - - -/** - * Provisions a workplace on a remote machine. - * Prerequisite: you have built the uberjar by ./gradlew uberJarLatest - * The remote host and remote user are specified by args parameters. - * The first argument specifies hostName or IP-Address of the remote machine, - * the second argument defines the user on the remote machine for whom the workplace is provisioned; - * You can invoke this method e.g. using the jar-file from the project root by: - * java -jar build/libs/provs-extensions-uber.jar org.domaindrivenarchitecture.provs.ubuntu.extensions.workplace.ProvisionWorkplaceKt provisionRemote - * You will be prompted for the password of the remote user. - * - * @param args host and userName of the remote machine as the first resp. second argument - */ -fun provisionRemote(args: Array) { - if (args.size != 2) { - println("Please specify host and user.") - exitProcess(1) - } - - val host = InetAddress.getByName(args[0]) - val userName = args[1] - val pwSecret = PromptSecretSource("Password for user $userName on $host").secret() - val pwFromSecret = Password(pwSecret.plain()) - - val config = readWorkplaceConfigFromFile() ?: WorkplaceConfig() - Prov.newInstance(RemoteProcessor(host, userName, pwFromSecret), OS.LINUX.name).provisionWorkplace( - config.type, - config.ssh?.keyPair(), - config.gpg?.keyPair(), - config.gitUserName, - config.gitEmail, - pwFromSecret - ) -} - - -/** - * Provisions a workplace on a remote machine by calling method provisionRemote. - * - * @ see #provisionRemote(args: Array) - * - * You can invoke this method e.g. using the jar-file from the project root by: - * java -jar build/libs/provs-ext-latest.jar workplace.WorkplaceKt main - * - * @param args host and userName of the remote machine as first resp. second argument - */ -fun main(args: Array) { - provisionRemote(args = args) -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/WorkplaceConfig.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/WorkplaceConfig.kt deleted file mode 100644 index de75195..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/WorkplaceConfig.kt +++ /dev/null @@ -1,38 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace - -import org.domaindrivenarchitecture.provs.ubuntu.keys.KeyPairSource -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.Json -import java.io.* - - -@Serializable -class WorkplaceConfig( - val type: WorkplaceType = WorkplaceType.MINIMAL, - val ssh: KeyPairSource? = null, - val gpg: KeyPairSource? = null, - val gitUserName: String? = null, - val gitEmail: String? = null, -) - - -// -------------------------------------------- file methods ------------------------------------ -fun readWorkplaceConfigFromFile(filename: String = "WorkplaceConfig.json"): WorkplaceConfig? { - val file = File(filename) - return if (file.exists()) - try { - // read from file - val inputAsString = BufferedReader(FileReader(filename)).use { it.readText() } - - return Json.decodeFromString(WorkplaceConfig.serializer(), inputAsString) - } catch (e: FileNotFoundException) { - null - } else null -} - - -fun writeWorkplaceConfigToFile(config: WorkplaceConfig) { - val fileName = "WorkplaceConfig.json" - - FileWriter(fileName).use { it.write(Json.encodeToString(WorkplaceConfig.serializer(), config)) } -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/Docker.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/Docker.kt deleted file mode 100644 index 1892f4f..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/Docker.kt +++ /dev/null @@ -1,12 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall - -fun Prov.installDocker() = def { - aptInstall("containerd docker.io") - if (!chk("getent group docker")) { - cmd("sudo groupadd docker") - } - cmd("sudo gpasswd -a \$USER docker") -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/Fakturama.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/Fakturama.kt deleted file mode 100644 index 06a9440..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/Fakturama.kt +++ /dev/null @@ -1,17 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDir -import org.domaindrivenarchitecture.provs.ubuntu.web.base.downloadFromURL - - -fun Prov.installFakturama() = def { - createDir("/tmp", sudo = true) - downloadFromURL( "https://files.fakturama.info/release/v2.1.1/Installer_Fakturama_linux_x64_2.1.1b.deb", "fakturama.deb", "/tmp") - cmd("sudo dpkg -i fakturama.deb", "/tmp") - - createDir("/opt/fakturama", sudo = true) - val filename = "Handbuch-Fakturama_2.1.1.pdf" - downloadFromURL( "https://files.fakturama.info/release/v2.1.1/Handbuch-Fakturama_2.1.1.pdf", filename, "/tmp") - cmd("sudo mv /tmp/$filename /opt/fakturama") -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/Gopass.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/Gopass.kt deleted file mode 100644 index c5050fd..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/Gopass.kt +++ /dev/null @@ -1,91 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDir -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDirs -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createFile -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.userHome -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.domaindrivenarchitecture.provs.ubuntu.install.base.isPackageInstalled - - -fun Prov.installGopass(version: String = "1.12.7", enforceVersion: Boolean = false) = def { - if (isPackageInstalled("gopass") && !enforceVersion) { - ProvResult(true) - } else { - // install required dependencies - aptInstall("rng-tools gnupg2 git") - aptInstall("curl") - - sh( - """ - curl -L https://github.com/gopasspw/gopass/releases/download/v${version}/gopass_${version}_linux_amd64.deb -o gopass_${version}_linux_amd64.deb - sudo dpkg -i gopass_${version}_linux_amd64.deb - """ - ) - gopassEnsureVersion(version) - } -} - - -fun Prov.configureGopass(gopassRootFolder: String? = null) = def { - val defaultRootFolder = userHome() + ".password-store" - val rootFolder = gopassRootFolder ?: defaultRootFolder - // use default - createDir(rootFolder) - createDirs(".config/gopass") - createFile("~/.config/gopass/config.yml", gopassConfig(rootFolder)) -} - - -fun Prov.gopassMountStore(storeName: String, path: String, indexOfRecepientKey: Int = 0) = def { - cmd("printf \"$indexOfRecepientKey\\n\" | gopass mounts add $storeName $path") -} - - -internal fun gopassConfig(gopassRoot: String): String { - return """ -root: - askformore: false - autoclip: true - autoprint: false - autoimport: true - autosync: false - check_recipient_hash: false - cliptimeout: 45 - concurrency: 1 - editrecipients: false - exportkeys: true - nocolor: false - noconfirm: true - nopager: false - notifications: true - path: gpgcli-gitcli-fs+file://$gopassRoot - recipient_hash: - .gpg-id: 3078303637343130344341383141343930350aa69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26 - safecontent: false - usesymbols: false -mounts: {} - """.trim() + "\n" -} - - -/** - * Returns true if gopass is installed and has the given version. - * - * @param version that is checked; specifies left part of text of installed version, e.g. both "1" and "1.12" will return true if installed version is "1.12.6+8d7a311b9273846bbb618e4bd9ddbae51b1db7b8" - */ -internal fun Prov.gopassEnsureVersion(version: String) = def { - val installedGopassVersion = gopassVersion() - if (installedGopassVersion != null && installedGopassVersion.startsWith("gopass " + version)) { - ProvResult(true, out = "Required gopass version ($version) matches installed version ($installedGopassVersion)") - } else { - ProvResult(false, err = "Wrong gopass version. Expected $version but found $installedGopassVersion") - } -} - -internal fun Prov.gopassVersion(): String? { - val result = cmdNoEval("gopass -v") - return if (!result.success) null else result.out -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassBridge.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassBridge.kt deleted file mode 100644 index 92f1531..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassBridge.kt +++ /dev/null @@ -1,90 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDir -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDirs -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.userHome -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.domaindrivenarchitecture.provs.ubuntu.install.base.isPackageInstalled -import org.domaindrivenarchitecture.provs.ubuntu.web.base.downloadFromURL - - -fun Prov.downloadGopassBridge() = def { - val version = "0.8.0" - val filename = "gopass_bridge-${version}-fx.xpi" - val downloadDir = "${userHome()}Downloads/" - - createDirs(downloadDir) - downloadFromURL( - "-L https://addons.mozilla.org/firefox/downloads/file/3630534/" + filename, - downloadDir + filename - ) - // needs manual install with: firefox Downloads/gopass_bridge-0.8.0-fx.xpi -} - -fun Prov.installGopassBridgeJsonApi() = def { - // see https://github.com/gopasspw/gopass-jsonapi - val gopassBridgeVersion = "1.11.1" - val requiredGopassVersion = "1.12" - val filename = "gopass-jsonapi_${gopassBridgeVersion}_linux_amd64.deb" - val downloadUrl = "-L https://github.com/gopasspw/gopass-jsonapi/releases/download/v$gopassBridgeVersion/$filename" - val downloadDir = "${userHome()}Downloads" - val installedJsonApiVersion = gopassJsonApiVersion()?.trim() - - if (installedJsonApiVersion == null) { - if (chk("gopass ls")) { - if (gopassEnsureVersion(requiredGopassVersion).success) { - aptInstall("git gnupg2") // required dependencies - createDir(downloadDir) - downloadFromURL(downloadUrl, filename, downloadDir) - cmd("dpkg -i " + downloadDir + "/" + filename, sudo = true) - } else { - ProvResult( - false, - "Version of currently installed gopass (" + gopassVersion() + ") is incompatible with gopass-jsonapi version to be installed. " + - "Please upgrade gopass to version: " + requiredGopassVersion - ) - } - } else { - addResultToEval( - ProvResult( - false, - "gopass not initialized correctly. You can initialize gopass with: \"gopass init\"" - ) - ) - } - } else { - if (installedJsonApiVersion.startsWith("gopass-jsonapi version " + gopassBridgeVersion)) { - addResultToEval(ProvResult(true, out = "Version $gopassBridgeVersion of gopass-jsonapi is already installed")) - } else { - addResultToEval( - ProvResult( - false, - err = "gopass-jsonapi (version $gopassBridgeVersion) cannot be installed as version $installedJsonApiVersion is already installed." + - " Upgrading gopass-jsonapi is currently not supported by provs." - ) - ) - } - } -} - -fun Prov.configureGopassBridgeJsonApi() = def { - if (isPackageInstalled("gopass-jsonapi")) { - // configure for firefox and choose default for each: - // "Install for all users? [y/N/q]", - // "In which path should gopass_wrapper.sh be installed? [/home/testuser/.config/gopass]" - // "Wrapper Script for gopass_wrapper.sh ..." - cmd("printf \"\\n\\n\\n\" | gopass-jsonapi configure --browser firefox") - } else { - ProvResult( - false, - err = "gopass-jsonapi is missing. Gopass-jsonapi must be installed to be able to configure it." - ) - } -} - -internal fun Prov.gopassJsonApiVersion(): String? { - val result = cmdNoEval("gopass-jsonapi -v") - return if (!result.success) null else result.out -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/NoSwappiness.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/NoSwappiness.kt deleted file mode 100644 index ba63836..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/NoSwappiness.kt +++ /dev/null @@ -1,10 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.addTextToFile -import java.io.File - -fun Prov.configureNoSwappiness() = def { - // set swappiness to 0 - addTextToFile("vm.swappiness=0", File("/etc/sysctl.conf"), sudo = true) -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/PackageBundles.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/PackageBundles.kt deleted file mode 100644 index 2d9e984..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/PackageBundles.kt +++ /dev/null @@ -1,17 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base - -val OS_ANALYSIS = "lsof strace ncdu iptraf htop iotop iftop" - -val ZIP_UTILS = "p7zip-rar p7zip-full rar unrar zip unzip" - -val BASH_UTILS = "bash-completion" - -val SPELLCHECKING_DE = "hyphen-de hunspell hunspell-de-de" - -val OPEN_VPM = "openvpn network-manager-openvpn network-manager-openvpn-gnome" - -val OPENCONNECT = "openconnect network-manager-openconnect network-manager-openconnect-gnome" - -val VPNC = "vpnc network-manager-vpnc network-manager-vpnc-gnome vpnc-scripts" - -val JAVA_JDK = "openjdk-8-jdk openjdk-11-jdk openjdk-14-jdk" \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/Redshift.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/Redshift.kt deleted file mode 100644 index 8541da4..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/Redshift.kt +++ /dev/null @@ -1,35 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDir -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createFile -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall - - -fun Prov.installRedshift() = def { - aptInstall("redshift redshift-gtk") -} - - -fun Prov.configureRedshift() = def { - aptInstall("redshift redshift-gtk") - - createDir(".config") - createFile("~/.config/redshift.conf", config) -} - - -val config = """ - [redshift] - temp-day=5500 - temp-night=2700 - brightness-day=1 - brightness-night=0.6 - fade=1 - - location-provider=manual - - [manual] - lat=48.783333 - lon=9.1833334 -""".trimIndent() diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/VSCode.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/VSCode.kt deleted file mode 100644 index fc70a3d..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/VSCode.kt +++ /dev/null @@ -1,75 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall - - -fun Prov.installVSC(vararg options: String) = requireAll { - val clojureExtensions = - arrayListOf("betterthantomorrow.calva", "martinklepsch.clojure-joker-linter", "DavidAnson.vscode-markdownlint") - val pythonExtensions = arrayListOf("ms-python.python") - - prerequisitesVSCinstall() - - installVSCPackage() - - if (options.contains("clojure")) { - installExtensions(clojureExtensions) - } - if (options.contains("python")) { - installExtensions(pythonExtensions) - } - - provisionAdditionalTools() -} - - -private fun Prov.prerequisitesVSCinstall() = def { - aptInstall("curl gpg unzip apt-transport-https") -} - - -@Suppress("unused") // only required for installation of vscode via apt -private fun Prov.configurePackageManagerForVsc() = requireAll { - // see https://code.visualstudio.com/docs/setup/linux - // alternatively install with snapd (but this cannot be tested within docker as snapd within docker is not working/supported) - - sh( - """ - curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg - sudo install -o root -g root -m 644 packages.microsoft.gpg /etc/apt/trusted.gpg.d/ - sudo sh -c 'echo \"deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/packages.microsoft.gpg] https://packages.microsoft.com/repos/vscode stable main\" > /etc/apt/sources.list.d/vscode.list' - """ - ) - aptInstall("apt-transport-https") - aptInstall("code") -} - - -private fun Prov.installVSCPackage() = def { - cmd("sudo snap install code --classic") - - // to install via apt use: - // configurePackageManagerForVsc() - // aptInstall("code") - -} - - -private fun Prov.installExtensions(extensions: List) = optional { - var res = ProvResult(true) - for (ext in extensions) { - res = cmd("code --install-extension $ext") - } - res - // Settings can be found at $HOME/.config/Code/User/settings.json -} - - -private fun Prov.provisionAdditionalTools() = requireAll { - // Joker - cmd("curl -Lo joker-0.12.2-linux-amd64.zip https://github.com/candid82/joker/releases/download/v0.12.2/joker-0.12.2-linux-amd64.zip") - cmd("unzip joker-0.12.2-linux-amd64.zip") - cmd("sudo mv joker /usr/local/bin/") -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/VirtualBoxGuest.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/VirtualBoxGuest.kt deleted file mode 100644 index 45763d6..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/VirtualBoxGuest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.domaindrivenarchitecture.provs.ubuntu.user.base.whoami - -fun Prov.installVirtualBoxGuestAdditions() = def { - // if running in a VirtualBox vm - if (!chk("lspci | grep VirtualBox")) { - return@def ProvResult(true, "Not running in a VirtualBox") - } - - if (chk("VBoxService --version")) { - return@def ProvResult(true, "VBoxService already installed") - } - - // install guest additions - cmd("sudo add-apt-repository multiverse") - aptInstall("virtualbox-guest-x11") // virtualbox-guest-dkms") - // and add user to group vboxsf e.g. to be able to use shared folders - whoami()?.let { cmd("sudo usermod -G vboxsf -a " + it) } - ?: ProvResult(true) -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/Zim.kt b/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/Zim.kt deleted file mode 100644 index 1c4295a..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/extensions/workplace/base/Zim.kt +++ /dev/null @@ -1,17 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstallFromPpa -import org.domaindrivenarchitecture.provs.ubuntu.install.base.isPackageInstalled - - -fun Prov.installZimWiki() = def { - if (isPackageInstalled("zim")) { - ProvResult(true, out = "zim already installed.") - } else { - aptInstallFromPpa("jaap.karssenberg", "zim", "zim") - aptInstall("python3-gtkspellcheck") - } -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/filesystem/base/Filesystem.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/filesystem/base/Filesystem.kt deleted file mode 100644 index d97e4bd..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/filesystem/base/Filesystem.kt +++ /dev/null @@ -1,197 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.filesystem.base - -import org.domaindrivenarchitecture.provs.core.* -import org.domaindrivenarchitecture.provs.core.platforms.SHELL -import java.io.File - - -fun Prov.fileExists(file: String, sudo: Boolean = false): Boolean { - return cmdNoEval((if (sudo) "sudo " else "") + "test -e " + file).success -} - - -fun Prov.createFile( - fullyQualifiedFilename: String, - text: String?, - posixFilePermission: String? = null, - sudo: Boolean = false -): ProvResult = - def { - val withSudo = if (sudo) "sudo " else "" - posixFilePermission?.let { - ensureValidPosixFilePermission(posixFilePermission) - cmd(withSudo + "install -m $posixFilePermission /dev/null $fullyQualifiedFilename") - } - if (text != null) { - if (sudo) { - cmd( - "printf " + text.escapeProcentForPrintf() - .escapeAndEncloseByDoubleQuoteForShell() + " | sudo tee $fullyQualifiedFilename > /dev/null" - ) - } else { - cmd( - "printf " + text.escapeProcentForPrintf() - .escapeAndEncloseByDoubleQuoteForShell() + " > $fullyQualifiedFilename" - ) - } - } else { - cmd(withSudo + "touch $fullyQualifiedFilename") - } - } - - -fun Prov.createSecretFile( - fullyQualifiedFilename: String, - secret: Secret, - posixFilePermission: String? = null -): ProvResult = - def { - posixFilePermission?.let { - ensureValidPosixFilePermission(posixFilePermission) - cmd("install -m $posixFilePermission /dev/null $fullyQualifiedFilename") - } - cmdNoLog("echo '" + secret.plain().escapeSingleQuote() + "' > $fullyQualifiedFilename") - } - - -fun Prov.deleteFile(file: String, sudo: Boolean = false): ProvResult = def { - cmd((if (sudo) "sudo " else "") + "rm $file") -} - - -fun Prov.fileContainsText(file: String, content: String, sudo: Boolean = false): Boolean { - return cmdNoEval((if (sudo) "sudo " else "") + "grep '${content.escapeSingleQuote()}' $file").success -} - - -fun Prov.fileContent(file: String, sudo: Boolean = false): String? { - return cmd((if (sudo) "sudo " else "") + "cat $file").out -} - - -fun Prov.addTextToFile( - text: String, - file: File, - doNotAddIfExisting: Boolean = true, - sudo: Boolean = false -): ProvResult = - def { - // TODO find solution without trim handling spaces, newlines, etc correctly - val findCmd = "grep '${text.trim().escapeSingleQuote()}' ${file}" - val findResult = cmdNoEval(if (sudo) findCmd.sudoizeCommand() else findCmd) - if (!findResult.success || !doNotAddIfExisting) { - val addCmd = "printf \"" + text.escapeDoubleQuote() + "\" >> " + file - cmd(if (sudo) addCmd.sudoizeCommand() else addCmd) - } else { - ProvResult(true) - } - } - - -fun Prov.replaceTextInFile(file: String, oldText: String, replacement: String) = def { - replaceTextInFile(file, Regex.fromLiteral(oldText), Regex.escapeReplacement(replacement)) -} - - -fun Prov.replaceTextInFile(file: String, oldText: Regex, replacement: String) = def { - // todo: only use sudo for root or if owner different from current - val content = fileContent(file, true) - if (content != null) { - cmd("sudo truncate -s 0 $file") - addTextToFile(content.replace(oldText, Regex.escapeReplacement(replacement)), File(file), sudo = true) - } else { - ProvResult(false) - } -} - - -fun Prov.insertTextInFile(file: String, textBehindWhichToInsert: Regex, textToInsert: String) = def { - // todo: only use sudo for root or if owner different from current - val content = fileContent(file, true) - if (content != null) { - val match = textBehindWhichToInsert.find(content) - if (match != null) { - cmd("sudo truncate -s 0 $file") - addTextToFile( - content.replace(textBehindWhichToInsert, match.value + Regex.escapeReplacement(textToInsert)), - File(file), - sudo = true - ) - } else { - ProvResult(false, err = "Text not found") - } - } else { - ProvResult(false) - } -} - - -fun Prov.dirExists(dir: String, path: String? = null, sudo: Boolean = false): Boolean { - val effectivePath = if (path != null) path else - (if (dir.startsWith(File.separator)) File.separator else "~" + File.separator) - val cmd = "cd $effectivePath && test -d $dir" - return cmdNoEval(if (sudo) cmd.sudoizeCommand() else cmd).success -} - - -fun Prov.createDir( - dir: String, - path: String = "~/", - failIfExisting: Boolean = false, - sudo: Boolean = false -): ProvResult = def { - if (!failIfExisting && dirExists(dir, path, sudo)) { - ProvResult(true) - } else { - val cmd = "cd $path && mkdir $dir" - cmd(if (sudo) cmd.sudoizeCommand() else cmd) - } -} - - -fun Prov.createDirs( - dirs: String, - path: String = "~/", - failIfExisting: Boolean = false, - sudo: Boolean = false -): ProvResult = def { - if (!failIfExisting && dirExists(dirs, path, sudo)) { - ProvResult(true) - } else { - val cmd = "cd $path && mkdir -p $dirs" - cmd(if (sudo) cmd.sudoizeCommand() else cmd) - } -} - - -fun Prov.deleteDir(dir: String, path: String, sudo: Boolean = false): ProvResult { - if ("" == path) - throw RuntimeException("In deleteDir: path must not be empty.") - val cmd = "cd $path && rmdir $dir" - return if (!sudo) { - cmd(cmd) - } else { - cmd(cmd.sudoizeCommand()) - } -} - - -fun Prov.userHome(): String { - val user = cmd("whoami").out - if (user == null) { - throw RuntimeException("Could not determine user with whoami") - } else { - // assume default home folder - return "/home/" + user.trim() + "/" - } -} - - -private fun ensureValidPosixFilePermission(posixFilePermission: String) { - if (!Regex("^[0-7]{3}$").matches(posixFilePermission)) throw RuntimeException("Wrong file permission ($posixFilePermission), permission must consist of 3 digits as e.g. 664 ") -} - - -private fun String.sudoizeCommand(): String { - return "sudo " + SHELL + " -c " + this.escapeAndEncloseByDoubleQuoteForShell() -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/git/ProvisionGit.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/git/ProvisionGit.kt deleted file mode 100644 index f96b57a..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/git/ProvisionGit.kt +++ /dev/null @@ -1,22 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.git - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall - - -fun Prov.provisionGit( - userName: String? = null, - email: String? = null, - signingKey: String? = null, - diffTool: String? = null -): ProvResult = def { - - aptInstall("git") - - cmd("git config --global push.default simple") - userName?.let { cmd("git config --global user.name $it") } - email?.let { cmd("git config --global user.email $it") } - signingKey?.let { cmd("git config --global user.signingkey $it") } - diffTool?.let { cmd("git config --global --add diff.tool $it") } ?: ProvResult(true) -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/git/base/Git.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/git/base/Git.kt deleted file mode 100644 index ab127b7..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/git/base/Git.kt +++ /dev/null @@ -1,80 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.git.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.addTextToFile -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDir -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.dirExists -import org.domaindrivenarchitecture.provs.ubuntu.keys.base.isHostKnown -import org.domaindrivenarchitecture.provs.ubuntu.utils.printToShell -import java.io.File - - -/** - * @param host name or ip - * @param rsaFingerprints - */ -private fun Prov.trustHost(host: String, rsaFingerprints: Set) = def { - if (!isHostKnown(host)) { - // logic based on https://serverfault.com/questions/447028/non-interactive-git-clone-ssh-fingerprint-prompt - val key = cmd("ssh-keyscan $host").out - if (key == null) { - ProvResult(false, "No key retrieved for $host") - } else { - val c = printToShell(key).trim() - val fpr = cmd(c + " | ssh-keygen -lf -").out - if (rsaFingerprints.contains(fpr) - ) { - createDir(".ssh", "~/") - cmd(printToShell(key) + " >> ~/.ssh/known_hosts") - } else { - ProvResult(false, "Fingerprint $fpr not valid for $host") - } - } - } else { - ProvResult(true) - } -} - - -fun Prov.gitClone(repo: String, path: String, pullIfExisting: Boolean = true): ProvResult = def { - val dir = cmdNoEval("basename $repo .git").out?.trim() - if (dir == null) { - ProvResult(false, err = "$repo is not a valid git repository") - } else { - val pathToDir = if (path.endsWith("/")) path + dir else path + "/" + dir - if (dirExists(pathToDir + "/.git/")) { - if (pullIfExisting) { - cmd("cd $pathToDir && git pull") - } else { - ProvResult(true, out = "Repo $repo is already existing") - } - } else { - cmd("cd $path && git clone $repo") - } - } -} - - -fun Prov.trustGithub() = def { - // current see https://docs.github.com/en/github/authenticating-to-github/githubs-ssh-key-fingerprints - val fingerprints = setOf( - "2048 SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8 github.com (RSA)\n", - "2048 SHA256:br9IjFspm1vxR3iA35FWE+4VTyz1hYVLIE2t1/CeyWQ github.com (RSA)\n" - ) - - trustHost("github.com", fingerprints) -} - - -fun Prov.trustGitlab() = def { - // from https://docs.gitlab.com/ee/user/gitlab_com/ - val gitlabFingerprints = """ - gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf - gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9 - gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY= - """.trimIndent() - addTextToFile("\n" + gitlabFingerprints+ "\n", File("~/.ssh/known_hosts")) -} - - diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/install/base/Install.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/install/base/Install.kt deleted file mode 100644 index 83c09af..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/install/base/Install.kt +++ /dev/null @@ -1,60 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.install.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult - - -private var aptInit = false - -/** - * Installs package(s) by using package manager "apt". - * - * @param packages the packages to be installed, packages separated by space if there are more than one - */ -fun Prov.aptInstall(packages: String): ProvResult = def { - if (!aptInit) { - cmd("sudo apt-get update") - cmd("sudo apt-get install -qy apt-utils") - aptInit = true - } - - val packageList = packages.split(" ") - for (packg in packageList) { - // see https://superuser.com/questions/164553/automatically-answer-yes-when-using-apt-get-install - cmd("sudo DEBIAN_FRONTEND=noninteractive apt-get install -qy $packg") - } - ProvResult(true) // dummy -} - - -/** - * Installs a package from a ppa (personal package archive) by using package manager "apt". - * - * @param packageName the package to install - */ -fun Prov.aptInstallFromPpa(launchPadUser: String, ppaName: String, packageName: String): ProvResult = def { - aptInstall("software-properties-common") // for being able to use add-apt-repository - cmd("sudo add-apt-repository -y ppa:$launchPadUser/$ppaName") - aptInstall(packageName) -} - - -/** - * Checks if a program is installed - * - * @param packageName to check - * @return true if program is installed - */ -@Suppress("unused") // used externally -fun Prov.isPackageInstalled(packageName: String): Boolean { - return chk("timeout 2 dpkg -l $packageName") -} - - -/** - * Removes a package including its configuration and data files - */ -@Suppress("unused") // used externally -fun Prov.aptPurge(packageName: String): Boolean { - return chk("sudo apt-get purge -qy $packageName") -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/keys/ProvisionKeys.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/keys/ProvisionKeys.kt deleted file mode 100644 index 7b4bf0d..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/keys/ProvisionKeys.kt +++ /dev/null @@ -1,33 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.keys - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.ubuntu.keys.base.configureGpgKeys -import org.domaindrivenarchitecture.provs.ubuntu.keys.base.configureSshKeys -import org.domaindrivenarchitecture.provs.ubuntu.secret.SecretSourceType -import kotlinx.serialization.Serializable - - -open class KeyPair(val publicKey: Secret, val privateKey: Secret) - - -@Serializable -class KeyPairSource(val sourceType: SecretSourceType, val publicKey: String, val privateKey: String) { - fun keyPair() : KeyPair { - val pub = sourceType.secret(publicKey) - val priv = sourceType.secret(privateKey) - return KeyPair(pub, priv) - } -} - - -/** - * provisions gpg and/or ssh keys for the current user - */ -fun Prov.provisionKeysCurrentUser(gpgKeys: KeyPair? = null, sshKeys: KeyPair? = null) = requireAll { - gpgKeys?.let { configureGpgKeys(it, true) } - sshKeys?.let { configureSshKeys(it) } - ProvResult(true) // dummy -} - diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/keys/base/Gpg.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/keys/base/Gpg.kt deleted file mode 100644 index 701ffd8..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/keys/base/Gpg.kt +++ /dev/null @@ -1,74 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.keys.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDir -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createFile -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createSecretFile -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.dirExists -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.domaindrivenarchitecture.provs.ubuntu.keys.KeyPair -import org.domaindrivenarchitecture.provs.ubuntu.utils.printToShell - - -/** - * Installs a gpg key pair for the current user. - * - * @param gpgKeys - * @param trust whether to trust keys with trust-level 5 (ultimate) - */ -fun Prov.configureGpgKeys(gpgKeys: KeyPair, trust: Boolean = false, skipIfExistin: Boolean = true) = requireAll { - aptInstall("gnupg") - val fingerprint = gpgFingerprint(gpgKeys.publicKey.plain()) - if (fingerprint == null) { - ProvResult(false, err = "Fingerprint of key could not be determined") - } else { - if (gpgKeysInstalled(fingerprint) && skipIfExistin) { - ProvResult(true, out = "Keys were already installed") - } else { - val pubkeyFile = "~/pub-key.asc" - val privkeyFile = "~/priv-key.asc" - - createSecretFile(pubkeyFile, gpgKeys.publicKey) - createSecretFile(privkeyFile, gpgKeys.privateKey) - - cmd("gpg --import $pubkeyFile") - - // using option --batch for older keys; see https://superuser.com/questions/1135812/gpg2-asking-for-passphrase-when-importing-secret-keys - cmd("gpg --batch --import $privkeyFile") - - if (trust) { - cmd("printf \"5\\ny\\n\" | gpg --no-tty --command-fd 0 --expert --edit-key $fingerprint trust") - } - - cmd("shred $pubkeyFile") - cmd("shred $privkeyFile") - - configureGPGAgent() - } - } -} - - -private fun Prov.configureGPGAgent() = def { - if (dirExists(".gnupg")) { - createDir(".gnupg", "~/") - } - val content = """ - allow-preset-passphrase - allow-loopback-pinentry - """.trimIndent() - createFile("~/.gnupg/gpg-agent.conf", content) -} - - -private fun Prov.gpgKeysInstalled(fingerprint: String): Boolean { - return cmdNoLog("gpg --list-keys $fingerprint").success -} - - -fun Prov.gpgFingerprint(pubKey: String): String? { - val result = - cmdNoLog(" " + printToShell(pubKey) + " | gpg --with-colons --import-options show-only --import --fingerprint") - return result.out?.let { """^fpr:*([A-Z0-9]*):$""".toRegex(RegexOption.MULTILINE).find(it)?.groupValues?.get(1) } -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/keys/base/Ssh.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/keys/base/Ssh.kt deleted file mode 100644 index ac84160..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/keys/base/Ssh.kt +++ /dev/null @@ -1,46 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.keys.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDir -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createSecretFile -import org.domaindrivenarchitecture.provs.ubuntu.keys.KeyPair - - -/** - * installs ssh keys for active user - */ -fun Prov.configureSshKeys(sshKeys: KeyPair) = def { - createDir(".ssh", "~/") - createSecretFile("~/.ssh/id_rsa.pub", sshKeys.publicKey, "644") - createSecretFile("~/.ssh/id_rsa", sshKeys.privateKey, "600") - configureSSHClient() -} - -fun Prov.configureSSHClient() = def { - // TODO("Not yet implemented") - ProvResult(true) -} - - -/** - * Specifies a host or Ip to be trusted - * - * ATTENTION: - * This method is NOT secure as a man-in-the-middle could compromise the connection. - * Don't use this for critical systems resp. environments - */ -fun Prov.trustServer(hostOrIp: String) = def { - cmd("ssh-keyscan $hostOrIp >> ~/.ssh/known_hosts") -} - - -/** - * Checks if the specified hostname or Ip is in a known_hosts file - * - * @return whether if was found - */ -fun Prov.isHostKnown(hostOrIp: String) : Boolean { - return cmdNoEval("ssh-keygen -F $hostOrIp").out?.isNotEmpty() ?: false -} - diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/SecretSource.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/SecretSource.kt deleted file mode 100644 index 438cf4e..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/SecretSource.kt +++ /dev/null @@ -1,39 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.secret - -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.ubuntu.secret.secretSources.* -import kotlinx.serialization.Serializable - - -@Serializable -abstract class SecretSource(protected val input: String) { - abstract fun secret() : Secret - abstract fun secretNullable() : Secret? -} - - -@Serializable -enum class SecretSourceType() { - - PLAIN, FILE, PROMPT, PASS, GOPASS; - - fun secret(input: String) : Secret { - return when (this) { - PLAIN -> PlainSecretSource(input).secret() - FILE -> FileSecretSource(input).secret() - PROMPT -> PromptSecretSource().secret() - PASS -> PassSecretSource(input).secret() - GOPASS -> GopassSecretSource(input).secret() - } - } -} - - -@Serializable -@Suppress("unused") // for use in other projects -class SecretSupplier(private val source: SecretSourceType, val parameter: String) { - fun secret(): Secret { - return source.secret(parameter) - } -} - diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/FileSecretSource.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/FileSecretSource.kt deleted file mode 100644 index be188d6..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/FileSecretSource.kt +++ /dev/null @@ -1,22 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.secret.secretSources - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.ubuntu.secret.SecretSource - - -/** - * Retrieve secret from a file - */ -class FileSecretSource(fqFileName: String) : SecretSource(fqFileName) { - - override fun secret(): Secret { - val p = Prov.newInstance(name = "FileSecretSource") - return p.getSecret("cat " + input) ?: throw Exception("Failed to get secret.") - } - - override fun secretNullable(): Secret? { - val p = Prov.newInstance(name = "FileSecretSource") - return p.getSecret("cat " + input) - } -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/GopassSecretSource.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/GopassSecretSource.kt deleted file mode 100644 index e05fb52..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/GopassSecretSource.kt +++ /dev/null @@ -1,19 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.secret.secretSources - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.ubuntu.secret.SecretSource - - -/** - * Retrieve secret from gopass - */ -class GopassSecretSource(path: String) : SecretSource(path) { - override fun secret(): Secret { - return secretNullable() ?: throw Exception("Failed to get \"$input\" secret from gopass.") - } - override fun secretNullable(): Secret? { - val p = Prov.newInstance(name = "GopassSecretSource for $input") - return p.getSecret("gopass show -f " + input) - } -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/PassSecretSource.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/PassSecretSource.kt deleted file mode 100644 index ac537de..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/PassSecretSource.kt +++ /dev/null @@ -1,20 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.secret.secretSources - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.ubuntu.secret.SecretSource - - -/** - * Retrieve secret from passwordstore on Unix - */ -class PassSecretSource(path: String) : SecretSource(path) { - override fun secret(): Secret { - val p = Prov.newInstance(name = "PassSecretSource") - return p.getSecret("pass " + input) ?: throw Exception("Failed to get secret.") - } - override fun secretNullable(): Secret? { - val p = Prov.newInstance(name = "PassSecretSource") - return p.getSecret("pass " + input) - } -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/PlainSecretSource.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/PlainSecretSource.kt deleted file mode 100644 index cf6f795..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/PlainSecretSource.kt +++ /dev/null @@ -1,14 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.secret.secretSources - -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.ubuntu.secret.SecretSource - - -class PlainSecretSource(plainSecret: String) : SecretSource(plainSecret) { - override fun secret(): Secret { - return Secret(input) - } - override fun secretNullable(): Secret { - return Secret(input) - } -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/PromptSecretSource.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/PromptSecretSource.kt deleted file mode 100644 index a2ab4cd..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/PromptSecretSource.kt +++ /dev/null @@ -1,67 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.secret.secretSources - -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.ubuntu.secret.SecretSource -import java.awt.FlowLayout -import javax.swing.* - - -class PasswordPanel : JPanel(FlowLayout()) { - - private val passwordField = JPasswordField(20) - private var entered = false - - val enteredPassword - get() = if (entered) String(passwordField.password) else null - - init { - add(JLabel("Password: ")) - add(passwordField) - passwordField.setActionCommand("OK") - passwordField.addActionListener { - if (it.actionCommand == "OK") { - entered = true - - SwingUtilities.getWindowAncestor(it.source as JComponent) - .dispose() - } - } - } - - private fun request(passwordIdentifier: String) = apply { - JOptionPane.showOptionDialog(null, this@PasswordPanel, - "Enter $passwordIdentifier", - JOptionPane.DEFAULT_OPTION, - JOptionPane.INFORMATION_MESSAGE, - null, emptyArray(), null) - } - - companion object { - - fun requestPassword(passwordIdentifier: String) = PasswordPanel() - .request(passwordIdentifier) - .enteredPassword - } -} - -class PromptSecretSource(text: String = "Secret/Password") : SecretSource(text) { - - override fun secret(): Secret { - val password = PasswordPanel.requestPassword(input) - if (password == null) { - throw IllegalArgumentException("Failed to retrieve secret from prompting.") - } else { - return Secret(password) - } - } - - override fun secretNullable(): Secret? { - val password = PasswordPanel.requestPassword(input) - - return if(password == null) { - null - }else { - Secret(password) - } - } -} \ No newline at end of file diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/user/UserConfig.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/user/UserConfig.kt deleted file mode 100644 index 746dc46..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/user/UserConfig.kt +++ /dev/null @@ -1,29 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.user - -import org.domaindrivenarchitecture.provs.ubuntu.keys.KeyPairSource -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.Json -import java.io.BufferedReader -import java.io.FileReader -import java.io.FileWriter - - -@Serializable -class UserConfig(val userName: String, val gitEmail: String? = null, val gpg: KeyPairSource? = null, val ssh: KeyPairSource? = null) - - -// -------------------------------------------- file methods ------------------------------------ -@Suppress("unused") -fun readUserConfigFromFile(filename: String = "UserConfig.json") : UserConfig { - // read from file - val inputAsString = BufferedReader(FileReader(filename)).use { it.readText() } - - // serializing objects - return Json.decodeFromString(UserConfig.serializer(), inputAsString) -} - -fun writeUserConfigToFile(config: UserConfig) { - val fileName = "UserConfig.json" - - FileWriter(fileName).use { it.write(Json.encodeToString(UserConfig.serializer(), config)) } -} diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/user/base/User.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/user/base/User.kt deleted file mode 100644 index 4d80dc3..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/user/base/User.kt +++ /dev/null @@ -1,166 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.user.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.core.processors.RemoteProcessor -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDirs -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.fileExists -import org.domaindrivenarchitecture.provs.ubuntu.git.provisionGit -import org.domaindrivenarchitecture.provs.ubuntu.keys.base.gpgFingerprint -import org.domaindrivenarchitecture.provs.ubuntu.keys.provisionKeysCurrentUser -import org.domaindrivenarchitecture.provs.ubuntu.user.UserConfig -import java.net.InetAddress - - -fun Prov.userExists(userName: String): Boolean { - return cmdNoEval("grep -c '^$userName:' /etc/passwd").success -} - - -/** - * Creates a new user. - */ -fun Prov.createUser( - userName: String, - password: Secret? = null, - sudo: Boolean = false, - copyAuthorizedKeysFromCurrentUser: Boolean = false -): ProvResult = requireAll { - if (!userExists(userName)) { - cmd("sudo adduser --gecos \"First Last,RoomNumber,WorkPhone,HomePhone\" --disabled-password --home /home/$userName $userName") - } - password?.let { cmdNoLog("sudo echo \"$userName:${password.plain()}\" | sudo chpasswd") } ?: ProvResult(true) - if (sudo) { - makeUserSudoerWithNoSudoPasswordRequired(userName) - } - val authorizedKeysFile = "~/.ssh/authorized_keys" - if (copyAuthorizedKeysFromCurrentUser && fileExists(authorizedKeysFile)) { - createDirs("/home/$userName/.ssh") - val newAuthorizedKeysFile = "/home/$userName/.ssh/authorized_keys" - cmd("sudo cp $authorizedKeysFile $newAuthorizedKeysFile") - cmd("chown $userName $newAuthorizedKeysFile") - - } - ProvResult(true) // dummy -} - - -/** - * Configures gpg and ssh keys for the current if keys are provided in the config. - * Installs and configures git for the user if gitEmail is provided in the config. - * Does NOT CREATE the user. - */ -fun Prov.configureUser(config: UserConfig) = requireAll { - provisionKeysCurrentUser( - config.gpg?.keyPair(), - config.ssh?.keyPair() - ) - - config.gitEmail?.run { - provisionGit( - config.userName, - config.gitEmail, - config.gpg?.keyPair()?.let { gpgFingerprint(it.publicKey.plain()) }) - } ?: ProvResult(true) -} - - -@Suppress("unused") -// todo create test -fun Prov.deleteUser(userName: String, deleteHomeDir: Boolean = false): ProvResult = requireAll { - val flagToDeleteHomeDir = if (deleteHomeDir) " -r " else "" - if (userExists(userName)) { - cmd("sudo userdel $flagToDeleteHomeDir $userName") - } else { - ProvResult(false, err = "User $userName cannot be deleted as it does not exist.") - } -} - - -/** - * Makes userName a sudoer who does not need a password to sudo. - * The current (executing) user must already be a sudoer. If he is a sudoer with password required then - * his password must be provided. - */ -fun Prov.makeUserSudoerWithNoSudoPasswordRequired( - userName: String, - password: Secret? = null, - overwriteFile: Boolean = false -): ProvResult = def { - val userSudoFile = "/etc/sudoers.d/$userName" - if (!fileExists(userSudoFile) || overwriteFile) { - val sudoPrefix = if (password == null) "sudo" else "echo ${password.plain()} | sudo -S" - // see https://stackoverflow.com/questions/323957/how-do-i-edit-etc-sudoers-from-a-script - val result = cmdNoLog(sudoPrefix + " sh -c \"echo '$userName ALL=(ALL) NOPASSWD:ALL' | (sudo su -c 'EDITOR=\"tee\" visudo -f " + userSudoFile + "')\"") - // don't log the command (containing the password) resp. don't include it in the ProvResult, just include success and err - ProvResult(result.success, err = result.err) - } else { - ProvResult(true, out = "File already exists") - } -} - - -/** - * Makes the current (executing) user be able to sudo without password. - * IMPORTANT: Current user must already by sudoer when calling this function. - */ -@Suppress("unused") // used externally -fun Prov.makeUserSudoerWithNoSudoPasswordRequired(password: Secret) = def { - val currentUser = whoami() - if (currentUser != null) { - makeUserSudoerWithNoSudoPasswordRequired(currentUser, password, overwriteFile = true) - } else { - ProvResult(false, "Current user could not be determined.") - } -} - - -/** - * Checks if user is in group sudo. - */ -@Suppress("unused") -fun Prov.userIsInGroupSudo(userName: String): Boolean { - return cmd("getent group sudo | grep -c '$userName'").success -} - - -/** - * Checks if current user can execute sudo commands. - */ -@Suppress("unused") -fun Prov.currentUserCanSudo(): Boolean { - return cmd("timeout 1 sudo id").success -} - - -/** - * Returns username of current user if it can be determined - */ -fun Prov.whoami(): String? { - return cmd("whoami").run { if (success) out?.trim() else null } -} - - -/** - * Creates a new user on the specified host. - * - * @host hostname or ip-address - * @hostUser user on the remote system, which is used to create the new user, - * hostUser must be sudoer - * @hostPassword pw of hostUser on the remote system; - * ssh-key authentication will be used if hostPassword is null - */ -@Suppress("api") // use externally -fun createRemoteUser( - host: InetAddress, - hostUser: String, - hostPassword: Secret?, - newUserName: String, - newUserPW: Secret, - makeNewUserSudoer: Boolean = false -) { - Prov.newInstance(RemoteProcessor(host, hostUser, hostPassword), name = "createRemoteUser") - .createUser(newUserName, newUserPW, makeNewUserSudoer) -} - diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/utils/Utils.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/utils/Utils.kt deleted file mode 100644 index bad65f7..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/utils/Utils.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.utils - -import org.domaindrivenarchitecture.provs.core.escapeBackslash -import org.domaindrivenarchitecture.provs.core.escapeDoubleQuote - - -// todo: investigate to use .escapeAndEncloseByDoubleQuoteForShell() or similar instead (?) -internal fun printToShell(text: String): String { - return "echo -n \"${text.escapeBackslash().escapeDoubleQuote()}\"" -} - diff --git a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/web/base/Web.kt b/bin/main/org/domaindrivenarchitecture/provs/ubuntu/web/base/Web.kt deleted file mode 100644 index 5336d9d..0000000 --- a/bin/main/org/domaindrivenarchitecture/provs/ubuntu/web/base/Web.kt +++ /dev/null @@ -1,26 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.web.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.domaindrivenarchitecture.provs.ubuntu.install.base.isPackageInstalled - - -/** - * Downloads a file from the given URL using curl - * - * @param path where to download to - * @param url file to download - * @param filename filename after download - */ -@Suppress("unused") // used externally -fun Prov.downloadFromURL(url: String, filename: String? = null, path: String? = null, sudo: Boolean = false) : ProvResult = def { - - if (!isPackageInstalled("curl")) aptInstall("curl") - - if (filename == null) { - cmd("curl $url", path, sudo) - } else { - cmd("curl $url -o $filename", path, sudo) - } -} \ No newline at end of file diff --git a/bin/test/WorkplaceConfigExample.json b/bin/test/WorkplaceConfigExample.json deleted file mode 100644 index 5ea87e4..0000000 --- a/bin/test/WorkplaceConfigExample.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "MINIMAL", - "ssh": null, - "gpg": null, - "gitUserName": "mygitusername", - "gitEmail": "my@git.email" -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/core/ProvTest.kt b/bin/test/org/domaindrivenarchitecture/provs/core/ProvTest.kt deleted file mode 100644 index 365cf31..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/core/ProvTest.kt +++ /dev/null @@ -1,478 +0,0 @@ -package org.domaindrivenarchitecture.provs.core - -import org.domaindrivenarchitecture.provs.core.docker.provideContainer -import org.domaindrivenarchitecture.provs.test.tags.ContainerTest -import org.domaindrivenarchitecture.provs.test.tags.NonCi -import org.domaindrivenarchitecture.provs.test.testLocal -import org.junit.jupiter.api.Assertions.* -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.condition.EnabledOnOs -import org.junit.jupiter.api.condition.OS -import java.io.ByteArrayOutputStream -import java.io.PrintStream - - -internal class ProvTest { - - private fun Prov.def_returnungFalse() = def { - ProvResult(false) - } - - private fun Prov.def_returningTrue() = def { - ProvResult(true) - } - - - @Test - @EnabledOnOs(OS.LINUX) - fun cmd_onLinux() { - // when - val res = Prov.newInstance(name = "testing").cmd("echo --testing--").success - - // then - assert(res) - } - - @Test - @EnabledOnOs(OS.LINUX) - @ContainerTest - fun sh_onLinux() { - // given - val script = """ - # test some script commands - - ping -c1 nu.nl - echo something - ping -c1 github.com - """ - - // when - val res = Prov.newInstance(name = "testing").sh(script).success - - // then - assert(res) - } - - @Test - @EnabledOnOs(OS.LINUX) - @ContainerTest - @NonCi - fun sh_onLinux_with_dir_and_sudo() { - // given - val script = """ - # test some script commands - - ping -c1 google.com - echo something - ping -c1 github.com - echo 1 # comment behind command - """ - - // when - val res = Prov.newInstance(name = "provs_test").sh(script, "/root", true).success - - // then - assert(res) - } - - - @Test - @EnabledOnOs(OS.WINDOWS) - fun cmd_onWindows() { - // when - val res = Prov.newInstance(name = "testing").cmd("echo --testing--").success - - // then - assert(res) - } - - @Test - @EnabledOnOs(OS.WINDOWS) - fun sh_onWindows() { - // given - val script = """ - # test some script commands - - ping -n 1 nu.nl - echo something - ping -n 1 github.com - """ - - // when - val res = Prov.newInstance(name = "testing").sh(script).success - - // then - assert(res) - } - - @Test - fun def_modeOptional_result_true() { - // given - fun Prov.tst_def() = optional { - def_returnungFalse() - def_returningTrue() - def_returnungFalse() - } - - // when - val res = testLocal().tst_def().success - - // then - assert(res) - } - - @Test - fun def_modeLast_result_true() { - // given - fun Prov.tst_def() = requireLast { - def_returnungFalse() - def_returningTrue() - } - - // when - val res = testLocal().tst_def().success - - // then - assert(res) - } - - @Test - fun def_modeLast_result_false() { - // given - fun Prov.tst_def() = requireLast { - def_returningTrue() - def_returnungFalse() - } - - // when - val res = testLocal().tst_def().success - - // then - assert(!res) - } - - @Test - fun def_mode_ALL_result_true() { - // given - fun Prov.tst_def_all_true_mode_ALL() = requireAll { - def_returningTrue() - def_returningTrue() - } - - // when - val res = testLocal().tst_def_all_true_mode_ALL().success - - // then - assert(res) - } - - // given - fun Prov.tst_def_one_false_mode_ALL() = requireAll { - def_returningTrue() - def_returnungFalse() - def_returningTrue() - } - - @Test - fun def_modeALL_resultFalse() { - // when - val res = testLocal().tst_def_one_false_mode_ALL().success - - // then - assert(!res) - } - - // given - fun Prov.tst_def_one_false_mode_ALL_nested() = requireAll { - def_returningTrue() - tst_def_one_false_mode_ALL() - def_returningTrue() - tst_ALL_returningTrue() - } - - // given - fun Prov.tst_ALL_returningTrue() = requireAll { - ProvResult(true) - } - - @Test - fun def_modeALLnested_resultFalse() { - // when - val res = testLocal().tst_def_one_false_mode_ALL_nested().success - - // then - assert(!res) - } - - @Test - fun def_mode_ALL_LAST_NONE_nested() { - // given - fun Prov.tst_def_last() = def { - def_returningTrue() - def_returnungFalse() - } - - fun Prov.tst_def_one_false_mode_ALL() = requireAll { - tst_def_last() - def_returningTrue() - } - - // when - val res = testLocal().tst_def_one_false_mode_ALL().success - - // then - assert(!res) - } - - @Test - fun def_mode_FAILEXIT_nested_false() { - // given - fun Prov.tst_def_failexit_inner() = exitOnFailure { - def_returningTrue() - def_returnungFalse() - } - - fun Prov.tst_def_failexit_outer() = exitOnFailure { - tst_def_failexit_inner() - def_returningTrue() - } - - // when - val res = testLocal().tst_def_failexit_outer().success - - // then - assert(!res) - } - - @Test - fun def_mode_FAILEXIT_nested_true() { - // given - fun Prov.tst_def_failexit_inner() = exitOnFailure { - def_returningTrue() - def_returningTrue() - } - - fun Prov.tst_def_failexit_outer() = exitOnFailure { - tst_def_failexit_inner() - def_returningTrue() - } - - // when - val res = testLocal().tst_def_failexit_outer().success - - // then - assert(res) - } - - @Test - fun def_mode_multiple_nested() { - // given - fun Prov.tst_nested() = def { - requireAll { - def_returningTrue() - def { - def_returnungFalse() - def_returningTrue() - } - def_returnungFalse() - def_returningTrue() - optional { - def_returnungFalse() - } - } - } - - // when - val res = testLocal().tst_nested().success - - // then - assert(!res) - } - - - // given - fun Prov.checkPrereq_evaluateToFailure() = requireLast { - ProvResult(false, err = "This is a test error.") - } - - fun Prov.methodThatProvidesSomeOutput() = requireLast { - - if (!checkPrereq_evaluateToFailure().success) { - sh( - """ - echo -Start test- - echo Some output - """ - ) - } - - sh("echo -End test-") - } - - @Test - fun runProv_printsCorrectOutput() { - - // given - val outContent = ByteArrayOutputStream() - val errContent = ByteArrayOutputStream() - val originalOut = System.out - val originalErr = System.err - - System.setOut(PrintStream(outContent)) - System.setErr(PrintStream(errContent)) - - // when - Prov.newInstance(name = "test instance", progressType = ProgressType.NONE).methodThatProvidesSomeOutput() - - // then - System.setOut(originalOut) - System.setErr(originalErr) - - println(outContent.toString()) - - val expectedOutput = if (OS.WINDOWS.isCurrentOs) "\n" + - "============================================== SUMMARY (test Instance) ============================================== \n" + - "> Success -- methodThatProvidesSomeOutput (requireLast) \n" + - "---> FAILED -- checkPrereq_evaluateToFailure (requireLast) -- Error: This is a test error.\n" + - "---> Success -- sh \n" + - "------> Success -- cmd [cmd.exe, /c, echo -Start test-]\n" + - "------> Success -- cmd [cmd.exe, /c, echo Some output]\n" + - "---> Success -- sh \n" + - "------> Success -- cmd [cmd.exe, /c, echo -End test-]\n" + - "============================================ SUMMARY END ============================================ \n" - else if (OS.LINUX.isCurrentOs()) { - "============================================== SUMMARY (test instance) ============================================== \n" + - "> \u001B[92mSuccess\u001B[0m -- methodThatProvidesSomeOutput (requireLast) \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 -- cmd [/bin/bash, -c, echo -Start test-]\n" + - "------> \u001B[92mSuccess\u001B[0m -- cmd [/bin/bash, -c, echo Some output]\n" + - "---> \u001B[92mSuccess\u001B[0m -- sh \n" + - "------> \u001B[92mSuccess\u001B[0m -- cmd [/bin/bash, -c, echo -End test-]\n" + - "----------------------------------------------------------------------------------------------------- \n" + - "Overall > \u001B[92mSuccess\u001B[0m\n" + - "============================================ SUMMARY END ============================================ \n" + - "\n" - } else { - "OS " + System.getProperty("os.name") + " not yet supported" - } - - assertEquals(expectedOutput, outContent.toString().replace("\r", "")) - } - - @Test - fun check_returnsTrue() { - // when - val res = testLocal().chk("echo 123") - - // then - assertTrue(res) - } - - @Test - fun check_returnsFalse() { - // when - val res = testLocal().chk("cmddoesnotexist") - - // then - assertFalse(res) - } - - @Test - fun getSecret_returnsSecret() { - // when - val res = testLocal().getSecret("echo 123") - - // then - assertEquals("123", res?.plain()?.trim()) - } - - @Test - fun addResultToEval_success() { - // given - fun Prov.inner() { - addResultToEval(ProvResult(true)) - } - - fun Prov.outer() = requireAll { - inner() - ProvResult(true) - } - - // when - val res = testLocal().outer() - - //then - assertEquals(ProvResult(true), res) - } - - @Test - fun addResultToEval_failure() { - // given - fun Prov.inner() { - addResultToEval(ProvResult(false)) - } - - fun Prov.outer() = requireAll { - inner() - ProvResult(true) - } - - // when - val res = testLocal().outer() - - //then - assertEquals(ProvResult(false), res) - } - - @Test - @EnabledOnOs(OS.LINUX) - @NonCi - fun inContainer_locally() { - // given - val containerName = "provs_test" - testLocal().provideContainer(containerName, "ubuntu") - - fun Prov.inner() = def { - cmd("echo in container") - } - - // then - fun Prov.outer() = def { - inContainer(containerName) { - inner() - cmd("echo testfile > testfile.txt") - } - } - - val res = testLocal().def { outer() } - - // then - assertEquals(true, res.success) - } - - @Test - @EnabledOnOs(OS.LINUX) - @Disabled // run manually after updating host and remoteUser - fun inContainer_remotely() { - // given - val host = "192.168.56.135" - val remoteUser = "az" - - fun Prov.inner() = def { - cmd("echo 'in testfile' > testfile.txt") - } - - // then - val res = remote(host, remoteUser).def { - inner() // executed on the remote host - inContainer("prov_default") { - inner() // executed in the container on the remote host - } - } - - // then - assertEquals(true, res.success) - } -} diff --git a/bin/test/org/domaindrivenarchitecture/provs/core/UtilsKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/core/UtilsKtTest.kt deleted file mode 100644 index a0f7865..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/core/UtilsKtTest.kt +++ /dev/null @@ -1,49 +0,0 @@ -package org.domaindrivenarchitecture.provs.core - -import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.domaindrivenarchitecture.provs.test.tags.ContainerTest -import org.junit.jupiter.api.Assertions.* -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test -import java.net.UnknownHostException - -internal class UtilsKtTest { - - @Test - fun test_getCallingMethodName() { - // when - val s = getCallingMethodName() - - // then - assertEquals("test_getCallingMethodName", s) - } - - @Test - @ContainerTest - fun runCmdInContainer() { - // when - val res = defaultTestContainer().cmd("echo something") - - // then - assertTrue(res.success) - } - - @Test - fun remote_emptyHost() { - assertThrows(IllegalArgumentException::class.java, - { remote("", "user") }) - } - - @Test - fun remote_invalidHost() { - assertThrows( - UnknownHostException::class.java, - { remote("invalid_host", "user") }) - } - - @Test - @Disabled // run manually after having updated user - fun test_remote() { - assertTrue(remote("127.0.0.1", "user").cmd("echo sth").success) - } -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/core/docker/platforms/UbuntuHostDockerKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/core/docker/platforms/UbuntuHostDockerKtTest.kt deleted file mode 100644 index c5bb42b..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/core/docker/platforms/UbuntuHostDockerKtTest.kt +++ /dev/null @@ -1,32 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.docker.platforms - -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.core.docker.containerRuns -import org.domaindrivenarchitecture.provs.core.docker.exitAndRmContainer -import org.domaindrivenarchitecture.provs.core.docker.runContainer -import org.domaindrivenarchitecture.provs.test.tags.NonCi -import org.domaindrivenarchitecture.provs.test.testLocal -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.condition.EnabledOnOs -import org.junit.jupiter.api.condition.OS - -internal class UbuntuHostDockerKtTest { - - @Test - @EnabledOnOs(OS.LINUX) - @NonCi - fun runAndCheckAndExitContainer() { - // when - val containerName = "testContainer" - val result = testLocal().requireAll { - runContainer(containerName) - addResultToEval(ProvResult(containerRuns(containerName))) - - exitAndRmContainer(containerName) - } - - // then - assertEquals(ProvResult(true), result) - } -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/core/entry/EntryTest.kt b/bin/test/org/domaindrivenarchitecture/provs/core/entry/EntryTest.kt deleted file mode 100644 index fca7e30..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/core/entry/EntryTest.kt +++ /dev/null @@ -1,85 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.entry - -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import java.io.ByteArrayOutputStream -import java.io.PrintStream - - -@Suppress("unused") -fun testfun(args: Array) { - println("test is fun " + args.joinToString(" ")) -} - -@Suppress("unused") -fun main(args: Array) { - println("main is fun " + args.joinToString(" ")) -} - - -internal class EntryKtTest { - - private var outContent = ByteArrayOutputStream() - private var originalOut = System.out - - @BeforeEach - fun redirectSystemOutStream() { - originalOut = System.out - - // given - outContent = ByteArrayOutputStream() - System.setOut(PrintStream(outContent)) - } - - @AfterEach - fun restoreSystemOutStream() { - System.setOut(originalOut) - } - - @Test - fun test_without_method_argument() { - // when - main("org.domaindrivenarchitecture.provs.core.entry.EntryTestKt") - - // then - assertEquals("main is fun \n", outContent.toString()) - } - - @Test - fun test_method_main_without_args() { - // when - main("org.domaindrivenarchitecture.provs.core.entry.EntryTestKt", "main") - - // then - assertEquals("main is fun \n", outContent.toString()) - } - - @Test - fun test_named_method_without_args() { - // when - main("org.domaindrivenarchitecture.provs.core.entry.EntryTestKt", "testfun") - - // then - assertEquals("test is fun \n", outContent.toString()) - } - - @Test - fun test_method_main_with_args() { - // when - main("org.domaindrivenarchitecture.provs.core.entry.EntryTestKt", "main", "arg1", "arg2") - - // then - assertEquals("main is fun arg1 arg2\n", outContent.toString()) - } - - @Test - fun test_named_method_with_args() { - // when - main("org.domaindrivenarchitecture.provs.core.entry.EntryTestKt", "testfun", "arg1", "arg2") - - // then - assertEquals("test is fun arg1 arg2\n", outContent.toString()) - } -} diff --git a/bin/test/org/domaindrivenarchitecture/provs/core/platformTest/UbuntuProvTests.kt b/bin/test/org/domaindrivenarchitecture/provs/core/platformTest/UbuntuProvTests.kt deleted file mode 100644 index b7f5bf0..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/core/platformTest/UbuntuProvTests.kt +++ /dev/null @@ -1,99 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.platformTest - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.test.tags.NonCi -import org.domaindrivenarchitecture.provs.test.testLocal -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.condition.EnabledOnOs -import org.junit.jupiter.api.condition.OS - -internal class UbuntuProvTests { - - private fun Prov.ping(url: String) = def { - xec("ping", "-c", "4", url) - } - - private fun Prov.outerPing() = def { - ping("gitlab.com") - } - - @Test - @EnabledOnOs(OS.LINUX) - fun that_ping_works() { - // when - val res = testLocal().outerPing() - - // then - assert(res.success) - } - - @Test - @EnabledOnOs(OS.LINUX) - fun that_cmd_works() { - // given - val a = testLocal() - - // when - val res1 = a.cmd("pwd") - val dir = res1.out?.trim() - val res2 = a.cmd("echo abc", dir) - - // then - assert(res1.success) - assert(res2.success) - assert(res2.out?.trim() == "abc") - } - - @Test - @EnabledOnOs(OS.LINUX) - @NonCi - fun that_cmd_works_with_sudo() { - // given - val a = testLocal() - - // when - val res1 = a.cmd("echo abc", "/root", sudo = true) - - // then - assert(res1.success) - assert(res1.out?.trim() == "abc") - } - - @Test - @EnabledOnOs(OS.LINUX) - fun that_nested_shells_work() { - // given - val a = testLocal() - - // when - val res1 = a.cmd("pwd") - val dir = res1.out?.trim() - val res2 = a.cmd("echo abc", dir) - - // then - assert(res1.success) - assert(res2.success) - assert(res2.out?.trim() == "abc") - } - - @Test - @EnabledOnOs(OS.LINUX) - fun that_xec_works() { - // given - val a = testLocal() - - // when - val res1 = a.xec("/usr/bin/printf", "hi") - val res2 = a.xec("/bin/ping", "-c", "2", "gitlab.com") - val res3 = a.xec("/bin/bash", "-c", "echo echoed") - - // then - assert(res1.success) - assert(res1.out?.trim() == "hi") - assert(res2.success) - assert(res3.success) - assert(res3.out?.trim() == "echoed") - } - -} - diff --git a/bin/test/org/domaindrivenarchitecture/provs/core/platformTest/WinProvTests.kt b/bin/test/org/domaindrivenarchitecture/provs/core/platformTest/WinProvTests.kt deleted file mode 100644 index 9ed2d6d..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/core/platformTest/WinProvTests.kt +++ /dev/null @@ -1,45 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.platformTest - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.test.testLocal -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.condition.EnabledOnOs -import org.junit.jupiter.api.condition.OS - -internal class WinProvTests { - - private fun Prov.ping(url: String) = def { - cmd("ping $url") - } - - private fun Prov.outerPing() = def { ping("nu.nl") } - - @Test - @EnabledOnOs(OS.WINDOWS) - fun def_definesPing_function() { - // when - val res = testLocal().outerPing() - - // then - assert(res.success) - } - - @Test - @EnabledOnOs(OS.WINDOWS) - fun cmd_executesCommand() { - // given - val a = testLocal() - - // when - val res1 = a.cmd("echo %cd%") - val dir = res1.out?.trim() - val res2 = a.cmd("echo abc", dir) - - // then - assert(res1.success) - assert(res1.success) - assertEquals( "abc", res2.out?.trim()) - } -} - diff --git a/bin/test/org/domaindrivenarchitecture/provs/core/processors/ContainerProcessorTest.kt b/bin/test/org/domaindrivenarchitecture/provs/core/processors/ContainerProcessorTest.kt deleted file mode 100644 index 26fd034..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/core/processors/ContainerProcessorTest.kt +++ /dev/null @@ -1,47 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.processors - -import org.domaindrivenarchitecture.provs.core.newline -import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.domaindrivenarchitecture.provs.test.tags.ContainerTest -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.condition.EnabledOnOs -import org.junit.jupiter.api.condition.OS - -@EnabledOnOs(OS.LINUX) -internal class ContainerProcessorTest { - - @Test - @ContainerTest - fun cmd_works_with_echo() { - - // given - val prov = defaultTestContainer() - val text = "abc123!§$%&/#äöü" - - // when - val res = prov.cmd("echo '${text}'") - - // then - assert(res.success) - assertEquals(text + newline(), res.out) - } - - - @Test - @ContainerTest - fun cmdNoLog_works_with_echo() { - // given - val prov = defaultTestContainer() - val text = "abc123!§$%&/#äöü" - - // when - val res = prov.cmdNoLog("echo '${text}'") - - // then - assert(res.success) - assertEquals(text + newline(), res.out) - - // todo add check that cmd was not logged - } -} diff --git a/bin/test/org/domaindrivenarchitecture/provs/core/processors/ContainerUbuntuHostProcessorTest.kt b/bin/test/org/domaindrivenarchitecture/provs/core/processors/ContainerUbuntuHostProcessorTest.kt deleted file mode 100644 index b055d63..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/core/processors/ContainerUbuntuHostProcessorTest.kt +++ /dev/null @@ -1,30 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.processors - -import org.domaindrivenarchitecture.provs.core.platforms.SHELL -import org.domaindrivenarchitecture.provs.test.tags.ContainerTest -import org.domaindrivenarchitecture.provs.test.testDockerWithSudo -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.condition.EnabledOnOs -import org.junit.jupiter.api.condition.OS.LINUX - -val DEFAULT_START_MODE_TEST_CONTAINER = ContainerStartMode.USE_RUNNING_ELSE_CREATE - -class ContainerUbuntuHostProcessorTest { - - @Test - @EnabledOnOs(LINUX) - @ContainerTest - fun test_execution() { - // given - val processor = - ContainerUbuntuHostProcessor("provs_ubuntuhost_test", "ubuntu", DEFAULT_START_MODE_TEST_CONTAINER, sudo = testDockerWithSudo) - - // when - val res = processor.x(SHELL, "-c", "echo -n abc") - - // then - assertEquals(0, res.exitCode) - assertEquals("abc", res.out) - } -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/core/processors/LocalProcessorTest.kt b/bin/test/org/domaindrivenarchitecture/provs/core/processors/LocalProcessorTest.kt deleted file mode 100644 index f6e6dc5..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/core/processors/LocalProcessorTest.kt +++ /dev/null @@ -1,97 +0,0 @@ -package org.domaindrivenarchitecture.provs.core.processors - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.escapeAndEncloseByDoubleQuoteForShell -import org.domaindrivenarchitecture.provs.core.escapeProcentForPrintf -import org.domaindrivenarchitecture.provs.core.escapeSingleQuoteForShell -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.condition.EnabledOnOs -import org.junit.jupiter.api.condition.OS - - -internal class LocalProcessorTest { - - @Test - @EnabledOnOs(OS.LINUX) - fun cmd_with_printf_on_Linux() { - // given - val prov = Prov.newInstance() - val text = "abc123!§\\\$%%&/\"\\äöü'" - - // when - val res = prov.cmd("printf '${text.replace("%", "%%").escapeSingleQuoteForShell()}'") - - // then - assert(res.success) - assert(res.out == text) - } - - - @Test - @EnabledOnOs(OS.LINUX) - fun cmd_with_nested_shell_and_printf_on_Linux() { - // given - val prov = Prov.newInstance() - val text = "abc123!§\\$%%&/\"\\äöü'" - - // when - val res = prov.cmd("sh -c " + ("sh -c " + ("printf ${text.escapeProcentForPrintf().escapeAndEncloseByDoubleQuoteForShell()}").escapeAndEncloseByDoubleQuoteForShell()).escapeAndEncloseByDoubleQuoteForShell()) - - // then - assertTrue(res.success) - assertEquals(text, res.out) - } - - - @Test - @EnabledOnOs(OS.WINDOWS) - fun cmd_with_echo_on_Windows() { - // given - val prov = Prov.newInstance() - val text = "abc123!\"#" - - // when - val res = prov.cmd("echo $text") - - // then - assert(res.success) - assertEquals( text + "\r\n", res.out) - } - - - @Test - @EnabledOnOs(OS.LINUX) - fun cmdNoLog_linux() { - // given - val prov = Prov.newInstance() - val text = "abc123!#" - val osSpecificText = if (OS.WINDOWS.isCurrentOs) text else "'$text'" - - - // when - val res = prov.cmdNoLog("echo $osSpecificText") - - // then - assert(res.success) - assertEquals( text + System.lineSeparator(), res.out) - - // todo add check that cmd was not logged - } - - - @Test - fun cmd_forUnkownCommand_resultWithError() { - // given - val prov = Prov.newInstance() - - // when - val res = prov.cmd("iamanunknowncmd") - - // then - assert(!res.success) - assert(res.out.isNullOrEmpty()) - assert(!res.err.isNullOrEmpty()) - } -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/extensions/server_software/firewall/ProvisionFirewallKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/extensions/server_software/firewall/ProvisionFirewallKtTest.kt deleted file mode 100644 index 8014d3f..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/extensions/server_software/firewall/ProvisionFirewallKtTest.kt +++ /dev/null @@ -1,46 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.firewall - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.docker.dockerProvideImage -import org.domaindrivenarchitecture.provs.core.docker.dockerimages.UbuntuPlusUser -import org.domaindrivenarchitecture.provs.core.docker.exitAndRmContainer -import org.domaindrivenarchitecture.provs.core.local -import org.domaindrivenarchitecture.provs.core.processors.ContainerEndMode -import org.domaindrivenarchitecture.provs.core.processors.ContainerStartMode -import org.domaindrivenarchitecture.provs.core.processors.ContainerUbuntuHostProcessor -import org.domaindrivenarchitecture.provs.test.tags.NonCi -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test - - -internal class ProvisionFirewallKtTest { - - @Test - @NonCi - fun configureFirewall() { - // given - val dockerImage = UbuntuPlusUser() - local().dockerProvideImage(dockerImage) - val containerName = "firewall_test" - local().exitAndRmContainer(containerName) - local().cmd("sudo docker run --cap-add=NET_ADMIN -dit --name $containerName ${dockerImage.imageName()}") - val a = Prov.newInstance( - ContainerUbuntuHostProcessor( - containerName, - dockerImage.imageName(), - ContainerStartMode.USE_RUNNING_ELSE_CREATE, // already started in previous statement - ContainerEndMode.EXIT_AND_REMOVE - )) - - // when - val res = a.requireAll { - aptInstall("iptables") - provisionFirewall() - } - local().exitAndRmContainer(containerName) - - // then - assertTrue(res.success) - } -} diff --git a/bin/test/org/domaindrivenarchitecture/provs/extensions/server_software/nexus/ProvisionNexusKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/extensions/server_software/nexus/ProvisionNexusKtTest.kt deleted file mode 100644 index 797f472..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/extensions/server_software/nexus/ProvisionNexusKtTest.kt +++ /dev/null @@ -1,25 +0,0 @@ -package nexus - -import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.domaindrivenarchitecture.provs.extensions.server_software.nexus.provisionNexusWithDocker -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test - -internal class ProvisionNexusKtTest { - - @Test - @Disabled("Find out how to run docker in docker") - fun provisionNexusWithDocker() { - // given - val a = defaultTestContainer() - - // when - val res = a.requireAll { - provisionNexusWithDocker() - } - - // then - assertTrue(res.success) - } -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/ProvisionNginxKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/ProvisionNginxKtTest.kt deleted file mode 100644 index a020a35..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/ProvisionNginxKtTest.kt +++ /dev/null @@ -1,89 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.nginx - -import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.domaindrivenarchitecture.provs.test.tags.NonCi -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.replaceTextInFile -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.base.* -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.fileExists -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test - - -internal class ProvisionNginxKtTest { - - @Test - @NonCi - fun provisionNginxStandAlone_customConfig() { - // given - val a = defaultTestContainer() - val config = """ - events {} # event context have to be defined to consider config valid - - http { - server { - listen 80; - server_name localhost; - - return 200 "Hello"; - } - } - """.trimIndent() - a.aptInstall("curl") - - // when - val res = a.requireAll { - provisionNginxStandAlone(NginxConf(config)) - cmd("curl localhost") - } - - // then - assertTrue(res.success) - } - - @Test - @NonCi - fun provisionNginxStandAlone_defaultConfig() { - // given - val a = defaultTestContainer() - - // when - val res = a.requireAll { - provisionNginxStandAlone() - } - - // then - assertTrue(res.success) - } - - @Test - @NonCi - fun provisionNginxStandAlone_sslConfig() { - // given - val a = defaultTestContainer() - a.def { - val file = "/etc/ssl/openssl.cnf" - if (fileExists(file)) { - replaceTextInFile(file, "RANDFILE", "#RANDFILE") - } - aptInstall("openssl") - } - - // when - val res = a.def { - nginxCreateSelfSignedCertificate() - - provisionNginxStandAlone( - NginxConf.nginxReverseProxySslConfig( - "localhost", - dirSslCert + "/" + certificateName + ".crt", - dirSslKey + "/" + certificateName + ".key" - ) - ) - } - - // then - assertTrue(res.success) - } -} - diff --git a/bin/test/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/base/LocationsKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/base/LocationsKtTest.kt deleted file mode 100644 index e1e1a24..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/extensions/server_software/nginx/base/LocationsKtTest.kt +++ /dev/null @@ -1,35 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_software.nginx.base - -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createFile -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.fileContainsText -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.configFile -import org.domaindrivenarchitecture.provs.extensions.server_software.nginx.provisionNginxStandAlone -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test -import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.domaindrivenarchitecture.provs.test.tags.NonCi - -internal class LocationsKtTest { - - @Test - @NonCi - fun nginxIncludeLocationFolders() { - // given - val a = defaultTestContainer() - a.provisionNginxStandAlone() - a.createFile(configFile, NGINX_MINIMAL_CONF, sudo = true) - - // when - val res = a.nginxIncludeLocationFolders() - - // then - assertTrue(res.success) - assertTrue(a.fileContainsText( - configFile, """listen 80; - include /etc/nginx/locations-enabled/port80*.conf - include /etc/nginx/locations-enabled/port443*.conf""")) - // just 1 occurrence - assertEquals("1", a.cmd("grep -o 'listen 80;' $configFile | wc -l").out?.trim()) - } -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/extensions/test_keys/TestKeys.kt b/bin/test/org/domaindrivenarchitecture/provs/extensions/test_keys/TestKeys.kt deleted file mode 100644 index 8e66bcb..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/extensions/test_keys/TestKeys.kt +++ /dev/null @@ -1,166 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.test_keys - - -fun publicGPGSnakeoilKey(): String { - return """-----BEGIN PGP PUBLIC KEY BLOCK----- - -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 -KpkCQg== -=cS1b ------END PGP PUBLIC KEY BLOCK----- """ -} - -fun privateGPGSnakeoilKey(): String { - return """-----BEGIN PGP PRIVATE KEY BLOCK----- - -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 -i+XV3Dazj3nq/DxUB0neLU/r1afAEiqZAkI= -=h5SJ ------END PGP PRIVATE KEY BLOCK-----""".trimIndent() -} - -fun publicSSHSnakeoilKey(): String { - return """ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDOtQOq8a/Z7SdZVPrh+Icaq5rr+Qg1TZP4IPuRoFgfujUztQ2dy5DfTEbabJ0qHyo+PKwBDQorVohrW7CwvCEVQQh2NLuGgnukBN2ut5Lam7a/fZBoMjAyTvD4bXyEsUr/Bl5CLoBDkKM0elUxsc19ndzSofnDWeGyQjJIWlkNkVk/ybErAnIHVE+D+g3UxwA+emd7BF72RPqdVN39Eu4ntnxYzX0eepc8rkpFolVn6+Ai4CYHE4FaJ7bJ9WGPbwLuDl0pw/Cp3ps17cB+JlQfJ2spOq0tTVk+GcdGnt+mq0WaOnvVeQsGJ2O1HpY3VqQd1AsC2UOyHhAQ00pw7Pi9 snake@oil.com""" -} - -fun privateSSHSnakeoilKey(): String { - return """ - -----BEGIN RSA PRIVATE KEY----- - MIIEowIBAAKCAQEAzrUDqvGv2e0nWVT64fiHGqua6/kINU2T+CD7kaBYH7o1M7UN - ncuQ30xG2mydKh8qPjysAQ0KK1aIa1uwsLwhFUEIdjS7hoJ7pATdrreS2pu2v32Q - aDIwMk7w+G18hLFK/wZeQi6AQ5CjNHpVMbHNfZ3c0qH5w1nhskIySFpZDZFZP8mx - KwJyB1RPg/oN1McAPnpnewRe9kT6nVTd/RLuJ7Z8WM19HnqXPK5KRaJVZ+vgIuAm - BxOBWie2yfVhj28C7g5dKcPwqd6bNe3AfiZUHydrKTqtLU1ZPhnHRp7fpqtFmjp7 - 1XkLBidjtR6WN1akHdQLAtlDsh4QENNKcOz4vQIDAQABAoIBAGrgAsZ28gJOcSLq - IlGF62zpv0800n6k3tXTT98qtYWqBGn4udKVdxFNYfD7aYNm27OUMSbV9CUWN7Cy - lre6fax8lIBxoWfZvU2/ylLUzZREIIf/xxNop6zLTiJUkaYV+P3E8CVt35mPhiLT - AYuRL/s8DPnHD9lmdqBxQ4hPVm4Bg7JZxbyN8in3PP1UkdWKxg91O1LYewIZHszq - y9BdklKyxQ+fcYP5DD9KkULAjdab48GIxQETrZKp7zV0KiGrjF4Axf5y5yT2jmFT - nZ1uZrC1MJTMYyKTBR7wsSpVBMSMUsh5XtxdJo4FuP6g9Kn6AkeQ/Y1shcWVfQgw - 6009o8ECgYEA8J1PtnVCHxMLiVKZznzvgCe+EV0RkvuB9PGPdfpLfkHa1DKS+FzH - 80D+Vqe0rQNLudG5Qj53MPghNirGyrjXwTYFW9xCqq9hrzfxEI4xIYOd4gHoPMMQ - pfWZylP9GYQp/uoa+e/fcdXRSv1IDLRwJZ5XpMtWAIfvMOyDhbfjehECgYEA2+yp - poey1y6RWuaIQd2a/PKuYk9jvLEETiz6q7t63MFd6e9cUYX02cG/6yzz6piTWUtx - pk9e9IjclLUgV/twVz8SUgSw5TcqBrMnuIT4yQ5rQNZqiEvpCfgb5itcW7I3ADGy - dsz2kgaAm7QVZlndQKIy7xRYBCnCD3VQ+TiWh+0CgYAT3qnKg3xmXIhDWtLgvmh4 - yM9lV64v2R0uQRR7xaOeVYngpByG7gKFEATw2wCMmQ0T10HZOpdVL+huNLId443N - osxmfZXzym/irFf36gYcomXTWBz5h5JEYjfFAZKRHNzq9CIuKaTmHaYe7zOX+P6Z - 3K2YKkJ74L3b6GwkCr96QQKBgQC6n0iTTSGg4h5skaXcpq2HqnP6br4G9/vcTuTk - Z/JpdBk6k2i2sULGqlguu/W8BH89Tf0CEOZWAfGUq2Ln5jE9iAMG4H4v9DDQgKTb - OtNW4cp3uburLydw0z7xgagdE80CeCmmEGXIIoZuGlHyiZ1r5HfuU0ghOEI6FeaB - pdhvPQKBgEpmHV66wqSzzxmYxKjUu8gl9rIniG8SWXHlvcoGVwt1qdOMtNtvwDgB - DnbUbANSjzIfFSqVwlx7nXG1e1yN7F1YuyUa3I5QEm4+5URoTSDghk03LTFH+kfM - OUxwE8Su4WnoQc7WjkTG0M3FECAu7TEcF9uqdcEsW+4+JMAhE5oo - -----END RSA PRIVATE KEY----- - """.trimIndent() -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/extensions/workplace/ProvisionWorkplaceKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/extensions/workplace/ProvisionWorkplaceKtTest.kt deleted file mode 100644 index 752a210..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/extensions/workplace/ProvisionWorkplaceKtTest.kt +++ /dev/null @@ -1,51 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace - -import org.domaindrivenarchitecture.provs.core.Password -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test -import org.domaindrivenarchitecture.provs.test.defaultTestContainer - -internal class ProvisionWorkplaceKtTest { - - @Test - fun provisionWorkplace() { - // given - val a = defaultTestContainer() - - // when - // in order to test WorkplaceType.OFFICE: fix installing libreoffice for a fresh container as it hangs the first time but succeeds 2nd time - val res = a.provisionWorkplace( - WorkplaceType.MINIMAL, - gitUserName = "testuser", - gitEmail = "testuser@test.org", - userPassword = Password("testuser") - ) - - // then - assertTrue(res.success) - } - - - @Test - fun provisionWorkplaceFromConfigFile() { - // given - val a = defaultTestContainer() - - // when - // in order to test WorkplaceType.OFFICE: fix installing libreoffice for a fresh container as it hangs the first time but succeeds 2nd time - val config = readWorkplaceConfigFromFile("src/test/resources/WorkplaceConfigExample.json") - ?: throw Exception("Could not read WorkplaceConfig") - val res = a.provisionWorkplace( - config.type, - config.ssh?.keyPair(), - config.gpg?.keyPair(), - config.gitUserName, - config.gitEmail, - ) - - // then - assertTrue(res.success) - } -} - - diff --git a/bin/test/org/domaindrivenarchitecture/provs/extensions/workplace/base/FakturamaKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/extensions/workplace/base/FakturamaKtTest.kt deleted file mode 100644 index 4d3e47a..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/extensions/workplace/base/FakturamaKtTest.kt +++ /dev/null @@ -1,18 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base - -import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test - -internal class FakturamaKtTest { - - @Test - fun installFakturama() { - // given - val a = defaultTestContainer() - // when - val res = a.def { installFakturama() } - // then - assertTrue(res.success) - } -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassBridgeKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassBridgeKtTest.kt deleted file mode 100644 index 7add4bc..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassBridgeKtTest.kt +++ /dev/null @@ -1,143 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.ProvResult -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.core.docker.exitAndRmContainer -import org.domaindrivenarchitecture.provs.core.local -import org.domaindrivenarchitecture.provs.core.processors.ContainerStartMode -import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.domaindrivenarchitecture.provs.test.tags.ContainerTest -import org.domaindrivenarchitecture.provs.test.tags.NonCi -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.domaindrivenarchitecture.provs.ubuntu.keys.KeyPair -import org.domaindrivenarchitecture.provs.ubuntu.keys.base.configureGpgKeys -import org.junit.jupiter.api.Assertions.assertFalse -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test -import org.domaindrivenarchitecture.provs.extensions.test_keys.privateGPGSnakeoilKey -import org.domaindrivenarchitecture.provs.extensions.test_keys.publicGPGSnakeoilKey - - -internal class GopassBridgeKtTest { - - @ContainerTest - @Test - fun test_downloadGopassBridge() { - // given - local().exitAndRmContainer("provs_test") - val a = defaultTestContainer() - a.aptInstallCurl() - - // when - val res = a.downloadGopassBridge() - - // then - assertTrue(res.success) - } - - @ContainerTest - @Test - fun test_install_and_configure_GopassBridgeJsonApi() { - // given - local().exitAndRmContainer("provs_test") - val a = defaultTestContainer() - val preparationResult = a.def { - aptInstallCurl() - configureGpgKeys( - KeyPair(Secret(publicGPGSnakeoilKey()), Secret(privateGPGSnakeoilKey())), - trust = true, - skipIfExistin = false - ) - installGopass() - if (!chk("gopass ls")) { - // configure/init gopass in default location with gpg-key-fingerprint of snakeoil keys - cmd("printf \"\\ntest\\ntest@test.org\\n\" | gopass init 0x0674104CA81A4905") - } else { - ProvResult(true, out = "gopass already configured") - } - } - assertTrue(preparationResult.success) - - // when - val res = a.def { - installGopassBridgeJsonApi() - configureGopassBridgeJsonApi() - } - - // then - assertTrue(res.success) - } - - @ContainerTest - @Test - @NonCi - fun test_install_GopassBridgeJsonApi_with_incompatible_gopass_jsonapi_version_installed() { - // given - val a = defaultTestContainer(ContainerStartMode.CREATE_NEW_KILL_EXISTING) - val preparationResult = a.def { - aptInstallCurl() - - configureGpgKeys( - KeyPair(Secret(publicGPGSnakeoilKey()), Secret(privateGPGSnakeoilKey())), - trust = true, - skipIfExistin = false - ) - installGopass("1.11.0", enforceVersion = true) - if (!chk("gopass ls")) { - // configure gopass in default location with gpg-key-fingerprint of snakeoil keys - cmd("printf \"\\ntest\\ntest@test.org\\n\" | gopass init 0x0674104CA81A4905") - } else { - ProvResult(true, out = "gopass already configured") - } - } - assertTrue(preparationResult.success) - - // when - val res = a.def { - installGopassBridgeJsonApi() - configureGopassBridgeJsonApi() - } - - // then - assertFalse(res.success) - } - - @ContainerTest - @Test - @NonCi - fun test_install_GopassBridgeJsonApi_with_incompatible_gopass_version_installed() { - // given - val a = defaultTestContainer(ContainerStartMode.CREATE_NEW_KILL_EXISTING) - val preparationResult = a.def { - aptInstallCurl() - configureGpgKeys( - KeyPair(Secret(publicGPGSnakeoilKey()), Secret(privateGPGSnakeoilKey())), - trust = true, - skipIfExistin = false - ) - installGopass("1.9.0", enforceVersion = true) - if (!chk("gopass ls")) { - // configure gopass in default location with gpg-key-fingerprint of snakeoil keys - cmd("printf \"\\ntest\\ntest@test.org\\n\" | gopass init 0x0674104CA81A4905") - } else { - ProvResult(true, out = "gopass already configured") - } - } - assertTrue(preparationResult.success) - - // when - val res = a.def { - installGopassBridgeJsonApi() - configureGopassBridgeJsonApi() - } - - // then - assertFalse(res.success) - } - - private fun Prov.aptInstallCurl() = def { - cmd("apt-get update", sudo = true) - aptInstall("curl") - } -} diff --git a/bin/test/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassKtTest.kt deleted file mode 100644 index 98880b9..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassKtTest.kt +++ /dev/null @@ -1,90 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base - -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.core.remote -import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.domaindrivenarchitecture.provs.test.tags.ContainerTest -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.* -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.domaindrivenarchitecture.provs.ubuntu.keys.KeyPair -import org.domaindrivenarchitecture.provs.ubuntu.keys.base.configureGpgKeys -import org.domaindrivenarchitecture.provs.ubuntu.keys.base.gpgFingerprint -import org.domaindrivenarchitecture.provs.ubuntu.secret.secretSources.GopassSecretSource -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test -import org.domaindrivenarchitecture.provs.extensions.test_keys.privateGPGSnakeoilKey -import org.domaindrivenarchitecture.provs.extensions.test_keys.publicGPGSnakeoilKey - - -internal class GopassKtTest { - - @ContainerTest - @Test - fun test_installAndConfigureGopassAndMountStore() { - // given - val a = defaultTestContainer() - val gopassRootDir = ".password-store" - a.aptInstall("wget git gnupg") - a.createDir(gopassRootDir, "~/") - a.cmd("git init", "~/$gopassRootDir") - val fpr = a.gpgFingerprint(publicGPGSnakeoilKey()) - println("+++++++++++++++++++++++++++++++++++++ $fpr +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++") - a.createFile("~/" + gopassRootDir + "/.gpg-id", fpr) - - a.createDir("exampleStoreFolder", "~/") - a.createFile("~/exampleStoreFolder/.gpg-id", fpr) - - a.configureGpgKeys(KeyPair(Secret(publicGPGSnakeoilKey()), Secret(privateGPGSnakeoilKey())), true) - - // when - val res = a.installGopass() - val res2 = a.configureGopass(a.userHome() + gopassRootDir) - val res3 = a.gopassMountStore("exampleStore", "~/exampleStoreFolder") - - // then - a.fileContent("~/.config/gopass/config.yml") // displays the content in the logs - assertTrue(res.success) - assertTrue(res2.success) - assertTrue(res3.success) - assertTrue(a.fileContainsText("~/.config/gopass/config.yml", "/home/testuser/.password-store")) - assertTrue(a.fileContainsText("~/.config/gopass/config.yml", "exampleStore")) - } - - @Test - @Disabled // Integrationtest; change user, host and keys, then remove this line to run this test - fun test_install_and_configure_Gopass_and_GopassBridgeJsonApi() { - // settings to change - val host = "192.168.56.135" - val user = "xxx" - val pubKey = GopassSecretSource("path-to/pub.key").secret() - val privateKey = GopassSecretSource("path-to/priv.key").secret() - - // given - val a = remote(host, user) - - // when - val res = a.def { - configureGpgKeys( - KeyPair( - pubKey, - privateKey - ), - trust = true, - skipIfExistin = true - ) - installGopass() - - if (!chk("gopass ls")) { - // configure (=init) gopass - cmd("printf \"\\ntest\\ntest@test.org\\n\" | gopass init " + gpgFingerprint(pubKey.plain())) // gopass init in default location with gpg-key-fingerprint of given key - } - downloadGopassBridge() - installGopassBridgeJsonApi() - configureGopassBridgeJsonApi() - } - - // then - assertTrue(res.success) - } -} diff --git a/bin/test/org/domaindrivenarchitecture/provs/extensions/workplace/base/VSCodeKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/extensions/workplace/base/VSCodeKtTest.kt deleted file mode 100644 index 8e22383..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/extensions/workplace/base/VSCodeKtTest.kt +++ /dev/null @@ -1,25 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base - -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test -import org.domaindrivenarchitecture.provs.test.defaultTestContainer - - -internal class VSCodeKtTest { - - @Test - @Disabled("Test currently not working, needs fix. VSC is installed by snapd which is not currently supported to run inside docker") - fun installVSC() { - // given - val a = defaultTestContainer() - a.aptInstall("xvfb libgbm-dev libasound2") - - // when - val res = a.installVSC("python", "clojure") - - // then - assertTrue(res.success) - } -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/filesystem/base/FilesystemKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/ubuntu/filesystem/base/FilesystemKtTest.kt deleted file mode 100644 index df29d52..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/filesystem/base/FilesystemKtTest.kt +++ /dev/null @@ -1,194 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.filesystem.base - -import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.domaindrivenarchitecture.provs.test.tags.ContainerTest -import org.junit.jupiter.api.Assertions.* -import org.junit.jupiter.api.Test - - -internal class FilesystemKtTest { - - @Test - @ContainerTest - fun checkingCreatingDeletingFile() { - // given - val prov = defaultTestContainer() - - // when - val res1 = prov.fileExists("testfile") - val res2 = prov.createFile("testfile", "some content") - val res3 = prov.fileExists("testfile") - val res4a = prov.fileContainsText("testfile", "some content") - val res4b = prov.fileContainsText("testfile", "some non-existing content") - val res5 = prov.deleteFile("testfile") - val res6 = prov.fileExists("testfile") - - // then - assertFalse(res1) - assertTrue(res2.success) - assertTrue(res3) - assertTrue(res4a) - assertFalse(res4b) - assertTrue(res5.success) - assertFalse(res6) - } - - - @Test - @ContainerTest - fun checkingCreatingDeletingFileWithSudo() { - // given - val prov = defaultTestContainer() - - // when - val file = "/testfile" - val res1 = prov.fileExists(file) - val res2 = prov.createFile(file, "some content", sudo = true) - val res3 = prov.fileExists(file) - val res4a = prov.fileContainsText(file, "some content") - val res4b = prov.fileContainsText(file, "some non-existing content") - val res5 = prov.deleteFile(file) - val res6 = prov.fileExists(file) - val res7 = prov.deleteFile(file, true) - val res8 = prov.fileExists(file) - - // then - assertFalse(res1) - assertTrue(res2.success) - assertTrue(res3) - assertTrue(res4a) - assertFalse(res4b) - assertFalse(res5.success) - assertTrue(res6) - assertTrue(res7.success) - assertFalse(res8) - } - - - @Test - @ContainerTest - fun checkingCreatingDeletingDir() { - // given - val prov = defaultTestContainer() - - // when - val res1 = prov.dirExists("testdir") - val res2 = prov.createDir("testdir", "~/") - val res3 = prov.dirExists("testdir") - val res4 = prov.deleteDir("testdir", "~/") - val res5 = prov.dirExists("testdir") - - val res6 = prov.dirExists("testdir", "~/test") - val res7 = prov.createDirs("test/testdir") - val res8 = prov.dirExists("testdir", "~/test") - prov.deleteDir("testdir", "~/test/") - - // then - assertFalse(res1) - assertTrue(res2.success) - assertTrue(res3) - assertTrue(res4.success) - assertFalse(res5) - assertFalse(res6) - assertTrue(res7.success) - assertTrue(res8) - } - - - @Test - @ContainerTest - fun checkingCreatingDeletingDirWithSudo() { - // given - val prov = defaultTestContainer() - - // when - val res1 = prov.dirExists("/testdir", sudo = true) - val res2 = prov.createDir("testdir", "/", sudo = true) - val res3 = prov.dirExists("/testdir", sudo = true) - val res4 = prov.deleteDir("testdir", "/", true) - val res5 = prov.dirExists("testdir", sudo = true) - - // then - assertFalse(res1) - assertTrue(res2.success) - assertTrue(res3) - assertTrue(res4.success) - assertFalse(res5) - } - - - @Test - fun userHome() { - // given - val prov = defaultTestContainer() - - // when - val res1 = prov.userHome() - - // then - assertEquals("/home/testuser/", res1) - } - - - @Test - @ContainerTest - fun replaceTextInFile() { - // given - val prov = defaultTestContainer() - - // when - val file = "replaceTest" - val res1 = prov.createFile(file, "a\nb\nc\nd") - val res2 = prov.replaceTextInFile(file,"b", "hi\nho") - val res3 = prov.fileContent(file).equals("a\nhi\nho\nc\nd") - val res4 = prov.deleteFile(file) - - // then - assertTrue(res1.success) - assertTrue(res2.success) - assertTrue(res3) - assertTrue(res4.success) - } - - - @Test - @ContainerTest - fun replaceTextInFileRegex() { - // given - val prov = defaultTestContainer() - - // when - val file = "replaceTest" - val res1 = prov.createFile(file, "a\nbananas\nc\nd") - val res2 = prov.replaceTextInFile(file, Regex("b.*n?nas\n"), "hi\nho\n") - val res3 = prov.fileContent(file) - val res4 = prov.deleteFile(file) - - // then - assertTrue(res1.success) - assertTrue(res2.success) - assertEquals("a\nhi\nho\nc\nd",res3) - assertTrue(res4.success) - } - - - @Test - @ContainerTest - fun insertTextInFile() { - // given - val prov = defaultTestContainer() - - // when - val file = "insertTest" - val res1 = prov.createFile(file, "a\nbananas\nc\nd") - val res2 = prov.insertTextInFile(file, Regex("b.*n.nas\n"), "hi\n") - val res3 = prov.fileContent(file) - val res4 = prov.deleteFile(file) - - // then - assertTrue(res1.success) - assertTrue(res2.success) - assertEquals("a\nbananas\nhi\nc\nd", res3) - assertTrue(res4.success) - } -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/git/base/GitKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/ubuntu/git/base/GitKtTest.kt deleted file mode 100644 index feee9e5..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/git/base/GitKtTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.git.base - -import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.domaindrivenarchitecture.provs.ubuntu.keys.base.isHostKnown -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test - - -internal class GitKtTest { - - @Test - fun trustGitServers(){ - // given - val a = defaultTestContainer() - a.aptInstall("openssh-client") - - // when - val res = a.trustGithub() - val known = a.isHostKnown("github.com") - val res2 = a.trustGitlab() - val known2 = a.isHostKnown("gitlab.com") - - // then - assertTrue(res.success) - assertTrue(known) - assertTrue(res2.success) - assertTrue(known2) - } - - @Test - fun gitClone() { - // given - val prov = defaultTestContainer() - prov.aptInstall("openssh-client ssh git") - - // when - prov.trustGithub() - prov.gitClone("https://github.com/DomainDrivenArchitecture/dda-git-crate.git", "~/") - val res = prov.gitClone("https://github.com/DomainDrivenArchitecture/dda-git-crate.git", "~/") - - // then - assertTrue(res.success) - } -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/install/base/InstallKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/ubuntu/install/base/InstallKtTest.kt deleted file mode 100644 index a70853f..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/install/base/InstallKtTest.kt +++ /dev/null @@ -1,40 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.install.base - -import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.domaindrivenarchitecture.provs.test.tags.ContainerTest -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test - - -internal class InstallKtTest { - - @ContainerTest - @Test - fun aptInstall_installsPackage() { - // given - val a = defaultTestContainer() - - // when - val res = a.aptInstall("rolldice") - - // then - assertTrue(res.success) - } - - @ContainerTest - @Test - @Disabled // run manually if needed; - // todo: replace zim by a smaller repo - fun aptInstallFromPpa_installsPackage() { - // given - val a = defaultTestContainer() - a.aptInstall("software-properties-common") // prereq for adding a repo to apt - - // when - val res = a.aptInstallFromPpa("jaap.karssenberg", "zim", "zim") - - // then - assertTrue(res.success) - } -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/keys/ProvisionKeysTest.kt b/bin/test/org/domaindrivenarchitecture/provs/ubuntu/keys/ProvisionKeysTest.kt deleted file mode 100644 index da62673..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/keys/ProvisionKeysTest.kt +++ /dev/null @@ -1,27 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.keys - -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.condition.EnabledOnOs -import org.junit.jupiter.api.condition.OS - -internal class ProvisionKeysTest { - - @Test - @EnabledOnOs(OS.LINUX) - fun provisionKeysCurrentUser() { - // given - val a = defaultTestContainer() - - // when - val res = a.provisionKeysCurrentUser( - KeyPair(Secret(publicGPGSnakeoilKey()), Secret(privateGPGSnakeoilKey())), - KeyPair(Secret(publicSSHSnakeoilKey()), Secret(privateSSHSnakeoilKey())) - ) - - // then - assert(res.success) - } -} - diff --git a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/keys/TestKeys.kt b/bin/test/org/domaindrivenarchitecture/provs/ubuntu/keys/TestKeys.kt deleted file mode 100644 index 1140588..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/keys/TestKeys.kt +++ /dev/null @@ -1,166 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.keys - - -fun publicGPGSnakeoilKey(): String { - return """-----BEGIN PGP PUBLIC KEY BLOCK----- - -mQGNBF5tPEsBDADaHpW0//tcPnliBJP65gOil/WvIDi3GLGmBKN5tNmocoD9bj7C -0yK9RVmwS6rXdf5h/CdNL33+yFyHfUyHtT68By+jYHVvakHVWKE9ac7GL6ToLMRV -3AJKXjQYs+r+BClVShC24ipOEc+t/MJSie1mi+yr0CsrHhfcvD3WWxfZnL8DRxs6 -0UTpDxjZyA9TOHP/uLqxKLW+iwSo9TG0gEcRhfYfeejVBaWXhXmaA4iTYTO6yqvy -BC6HInOVs654oBBrxVNyNJNhu6IPjKd7DbM42vKxSezXHEVuYggDRz8Hi3gzvfxp -5gPdcHCoifjJdvOcN+WDh/NRhJC5frnu+yAQxf/OJF1VsTh/ezpG0TUsTagig1jF -0tTYNZZuDjLEtW6xFEJHvRu07kx57RI3rzfJAFk2q8S1VuZvmYhxC6CQDIoZMSgi -wxK/mkEhMW1jesfz49JPdYzTFtjtLElkGXUJ1YaCpDLrU9C9KaoKVuxx483tT6HU -b28X37laHwNC3xMAEQEAAbQYc25ha2VvaWwgPHNuYWtlQG9pbC5jb20+iQHOBBMB -CgA4FiEEhQUsaVQmLWHU6Zd+BnQQTKgaSQUFAl5tPEsCGwMFCwkIBwIGFQoJCAsC -BBYCAwECHgECF4AACgkQBnQQTKgaSQW/rAwAhH0h8CTbXo8CWv0u4HbNAfx0wQf1 -/a7mQyNsSHmfenZEJjabF2s81A06+aw1hejz+QLxnklQWaz7NxVgIbfm3ArwXidB -LQJ8PYjl8y4fxu+6+xsEdFqJXfLgaDTOUV8e2gxin5W4fbiTmGyW1kq7yZ8mhIzF -pJ0W59GqkIKpowdQ+Sj6C8JkPn25+AQwh71LZWU/3dGakfyn/9gamgoYQgtDLzF7 -EA2zIUhBItVj44W1jv9xfpsxnoqyVZWGKqk/iOgZ9pe4kVKzCee1YkGRAnNwgB1B -Brb5ujUcfZeem1GlA1WFzuMvtKLkk1KdfrcanJHI93SlcmZyoLsju6j2pJW6zu+H -vEy3/uCx7LFhMVwvGAq8kWG6yWFUjQprc68sW+082/zztR2IUc8AzW3fdoCx8LPX -4CKQt1aByYk6H8+PaRYnA8e1DuWH4dtrN3hYJBfCYmhI3WRoz+puNx3AZID31fSx -ekBcw1lCH2c3jt7J6KB7hbovQ9J45XhKtCNkuQGNBF5tPEsBDAC2WoZBjHF+5Q7V -0EhS6DODA5/1hbxbGvZa7QS+gHFeQDeI2QCKg/Hnesd2bjmBA7UiAzHTBDO6HuYi -qG+K/usJdWbxGbSFThnkimc5TZ25Kvm2PglcMcxsCV/IKr+60j9Kp345X6Pp/f/L -SuUd/Or/VJnZDWJc9vcPk3TPA5Raw+nS9pzpbROqtWPD7JjbHnA894ZgqLTbHRg/ -aO8QG7ZF/7cw+92eJ+valM1XbHdpD2VNh8P8p9IjVemL3Hsu2fyIchCkOtE9FUqt -1HlAfIp0CW9iZnO+9kIbtfIMADb1xZjPfm1KJifjbzvRiKxAUuBw9EomhhW0hnJf -fArgE1ceDzrHXxFw0o4TMVZSDyOjSTOAy1a8fEW6qqRVTrXWb1JTSBCur6vGT1D3 -nOontlC2fVo61cHl1M1M71iTn9kbeJwicFXoMgG948PpNIQxx+b8TJrFTv57cvbZ -NKuldTcJcX1JZ2X9OLEh40VZUFMeVloF0M8fsvq+tA8mxkhL9yEAEQEAAYkBtgQY -AQoAIBYhBIUFLGlUJi1h1OmXfgZ0EEyoGkkFBQJebTxLAhsMAAoJEAZ0EEyoGkkF -dVIL/AmZZEKwo0db2nNG4SgbiGkvqYBwvDTKc9z+29a0ll32F6mfCI9efEx3KzvU -cCOL+nRC3/cmYHEyCP1wJ8Bfg9DnJz2Df3K3P7pK2jdBsLwHIOqe+d/z7mF+IDiC -en07VwfNyTxyqtX5WGocf2I9URRwrmOIpWZjB3Z9SODmM5k0iPnJ0d4cHg6kaUPM -ftKszvOqrsub0yc788df3ajIlRcfNsTBs8Ba3PuzauX4DtoNbjqCY8aVbTvasYjZ -Vnok+5aVwvltxDAkxYRUDApwH2IQNxUO/FdvkeSYWJjjrmeR2z0HOyDk7zZmCTSu -L+JBNIfBqXaZuzTItR3bOUvwkRIodCgHp7CwrWlvtaX741uQNWQXVrFUU/Dgj8ts -sfptcoSbXxdor4VQRCQVvclNStsEMqiqj1AafP6SmK1eYMe8U2b4TIyhSIxvgICF -onKkzP4DFnouGGIQg99NOJP4oF2hmQslusiL5dXcNrOPeer8PFQHSd4tT+vVp8AS -KpkCQg== -=cS1b ------END PGP PUBLIC KEY BLOCK----- """ -} - -fun privateGPGSnakeoilKey(): String { - return """-----BEGIN PGP PRIVATE KEY BLOCK----- - -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 -i+XV3Dazj3nq/DxUB0neLU/r1afAEiqZAkI= -=h5SJ ------END PGP PRIVATE KEY BLOCK-----""".trimIndent() -} - -fun publicSSHSnakeoilKey(): String { - return """ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDOtQOq8a/Z7SdZVPrh+Icaq5rr+Qg1TZP4IPuRoFgfujUztQ2dy5DfTEbabJ0qHyo+PKwBDQorVohrW7CwvCEVQQh2NLuGgnukBN2ut5Lam7a/fZBoMjAyTvD4bXyEsUr/Bl5CLoBDkKM0elUxsc19ndzSofnDWeGyQjJIWlkNkVk/ybErAnIHVE+D+g3UxwA+emd7BF72RPqdVN39Eu4ntnxYzX0eepc8rkpFolVn6+Ai4CYHE4FaJ7bJ9WGPbwLuDl0pw/Cp3ps17cB+JlQfJ2spOq0tTVk+GcdGnt+mq0WaOnvVeQsGJ2O1HpY3VqQd1AsC2UOyHhAQ00pw7Pi9 snake@oil.com""" -} - -fun privateSSHSnakeoilKey(): String { - return """ - -----BEGIN RSA PRIVATE KEY----- - MIIEowIBAAKCAQEAzrUDqvGv2e0nWVT64fiHGqua6/kINU2T+CD7kaBYH7o1M7UN - ncuQ30xG2mydKh8qPjysAQ0KK1aIa1uwsLwhFUEIdjS7hoJ7pATdrreS2pu2v32Q - aDIwMk7w+G18hLFK/wZeQi6AQ5CjNHpVMbHNfZ3c0qH5w1nhskIySFpZDZFZP8mx - KwJyB1RPg/oN1McAPnpnewRe9kT6nVTd/RLuJ7Z8WM19HnqXPK5KRaJVZ+vgIuAm - BxOBWie2yfVhj28C7g5dKcPwqd6bNe3AfiZUHydrKTqtLU1ZPhnHRp7fpqtFmjp7 - 1XkLBidjtR6WN1akHdQLAtlDsh4QENNKcOz4vQIDAQABAoIBAGrgAsZ28gJOcSLq - IlGF62zpv0800n6k3tXTT98qtYWqBGn4udKVdxFNYfD7aYNm27OUMSbV9CUWN7Cy - lre6fax8lIBxoWfZvU2/ylLUzZREIIf/xxNop6zLTiJUkaYV+P3E8CVt35mPhiLT - AYuRL/s8DPnHD9lmdqBxQ4hPVm4Bg7JZxbyN8in3PP1UkdWKxg91O1LYewIZHszq - y9BdklKyxQ+fcYP5DD9KkULAjdab48GIxQETrZKp7zV0KiGrjF4Axf5y5yT2jmFT - nZ1uZrC1MJTMYyKTBR7wsSpVBMSMUsh5XtxdJo4FuP6g9Kn6AkeQ/Y1shcWVfQgw - 6009o8ECgYEA8J1PtnVCHxMLiVKZznzvgCe+EV0RkvuB9PGPdfpLfkHa1DKS+FzH - 80D+Vqe0rQNLudG5Qj53MPghNirGyrjXwTYFW9xCqq9hrzfxEI4xIYOd4gHoPMMQ - pfWZylP9GYQp/uoa+e/fcdXRSv1IDLRwJZ5XpMtWAIfvMOyDhbfjehECgYEA2+yp - poey1y6RWuaIQd2a/PKuYk9jvLEETiz6q7t63MFd6e9cUYX02cG/6yzz6piTWUtx - pk9e9IjclLUgV/twVz8SUgSw5TcqBrMnuIT4yQ5rQNZqiEvpCfgb5itcW7I3ADGy - dsz2kgaAm7QVZlndQKIy7xRYBCnCD3VQ+TiWh+0CgYAT3qnKg3xmXIhDWtLgvmh4 - yM9lV64v2R0uQRR7xaOeVYngpByG7gKFEATw2wCMmQ0T10HZOpdVL+huNLId443N - osxmfZXzym/irFf36gYcomXTWBz5h5JEYjfFAZKRHNzq9CIuKaTmHaYe7zOX+P6Z - 3K2YKkJ74L3b6GwkCr96QQKBgQC6n0iTTSGg4h5skaXcpq2HqnP6br4G9/vcTuTk - Z/JpdBk6k2i2sULGqlguu/W8BH89Tf0CEOZWAfGUq2Ln5jE9iAMG4H4v9DDQgKTb - OtNW4cp3uburLydw0z7xgagdE80CeCmmEGXIIoZuGlHyiZ1r5HfuU0ghOEI6FeaB - pdhvPQKBgEpmHV66wqSzzxmYxKjUu8gl9rIniG8SWXHlvcoGVwt1qdOMtNtvwDgB - DnbUbANSjzIfFSqVwlx7nXG1e1yN7F1YuyUa3I5QEm4+5URoTSDghk03LTFH+kfM - OUxwE8Su4WnoQc7WjkTG0M3FECAu7TEcF9uqdcEsW+4+JMAhE5oo - -----END RSA PRIVATE KEY----- - """.trimIndent() -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/keys/base/GpgKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/ubuntu/keys/base/GpgKtTest.kt deleted file mode 100644 index f76e6e4..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/keys/base/GpgKtTest.kt +++ /dev/null @@ -1,80 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.keys.base - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.core.processors.ContainerStartMode -import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.domaindrivenarchitecture.provs.test.tags.ContainerTest -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.domaindrivenarchitecture.provs.ubuntu.keys.KeyPair -import org.domaindrivenarchitecture.provs.ubuntu.keys.privateGPGSnakeoilKey -import org.domaindrivenarchitecture.provs.ubuntu.keys.publicGPGSnakeoilKey -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test - -internal class GpgKtTest { - - @Test - @ContainerTest - fun gpgFingerprint_returnsCorrectFingerprint() { - // given - val a = defaultTestContainer() - a.aptInstall("gpg") - a.cmd("gpg --version") // just for info reasons - - // when - val fingerprint = a.gpgFingerprint(publicGPGSnakeoilKey()) - - // then - assertEquals("85052C6954262D61D4E9977E0674104CA81A4905", fingerprint) - } - - - @Test - @ContainerTest - fun configureGpgKeys() { - // given - val a = defaultTestContainer() - - // when - val res = a.configureGpgKeys(KeyPair(Secret(publicGPGSnakeoilKey()), Secret(privateGPGSnakeoilKey()))) - - // then - assertTrue(res.success) - } - - - @Test - @ContainerTest - fun configureGpgKeysTrusted() { - // given - val a = defaultTestContainer() - - // when - val res = a.configureGpgKeys(KeyPair(Secret(publicGPGSnakeoilKey()), Secret(privateGPGSnakeoilKey())), true) - - // then - assertTrue(res.success) - val trustedKey = a.cmd("gpg -K | grep ultimate").out - assertEquals("uid [ultimate] snakeoil ", trustedKey?.trim()) - } - - - @Test - @ContainerTest - fun configureGpgKeysIsIdempotent() { - // given - val a = defaultTestContainer() - - // when - val res = a.configureGpgKeys(KeyPair(Secret(publicGPGSnakeoilKey()), Secret(privateGPGSnakeoilKey()))) - val res2 = a.configureGpgKeys(KeyPair(Secret(publicGPGSnakeoilKey()), Secret(privateGPGSnakeoilKey()))) - - // then - assertTrue(res.success) - assertTrue(res2.success) - } -} - - diff --git a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/keys/base/SshKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/ubuntu/keys/base/SshKtTest.kt deleted file mode 100644 index 88b542c..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/keys/base/SshKtTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.keys.base - -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.domaindrivenarchitecture.provs.ubuntu.keys.* -import org.junit.jupiter.api.Test - -import org.junit.jupiter.api.Assertions.* - -internal class SshKtTest { - - @Test - fun configureSshKeys() { - // given - val a = defaultTestContainer() - - // when - val res = a.configureSshKeys(KeyPair(Secret(publicSSHSnakeoilKey()), Secret(privateSSHSnakeoilKey()))) - - // then - assertTrue(res.success) - - } -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/PromptSecretSourceTest.kt b/bin/test/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/PromptSecretSourceTest.kt deleted file mode 100644 index 3374435..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/secret/secretSources/PromptSecretSourceTest.kt +++ /dev/null @@ -1,13 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.secret.secretSources - -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test - -internal class PromptSecretSourceTest { - - @Test - @Disabled // run manually - fun secret() { - println("Secret: " + PromptSecretSource().secret().plain()) - } -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/user/ProvisionUserKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/ubuntu/user/ProvisionUserKtTest.kt deleted file mode 100644 index be3f1db..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/user/ProvisionUserKtTest.kt +++ /dev/null @@ -1,33 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.user - -import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.domaindrivenarchitecture.provs.ubuntu.keys.* -import org.domaindrivenarchitecture.provs.ubuntu.secret.SecretSourceType -import org.domaindrivenarchitecture.provs.ubuntu.user.base.configureUser -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.condition.EnabledOnOs -import org.junit.jupiter.api.condition.OS - - -internal class ProvisionUserKtTest { - - @Test - @EnabledOnOs(OS.LINUX) - fun configureUser() { - // given - val a = defaultTestContainer() - - // when - val res = a.configureUser( - UserConfig( - "testuser", - "test@mail.com", - KeyPairSource(SecretSourceType.PLAIN, publicGPGSnakeoilKey(), privateGPGSnakeoilKey()), - KeyPairSource(SecretSourceType.PLAIN, publicSSHSnakeoilKey(), privateSSHSnakeoilKey()) - ) - ) - - // then - assert(res.success) - } -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/utils/UtilsKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/ubuntu/utils/UtilsKtTest.kt deleted file mode 100644 index 8c39d98..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/utils/UtilsKtTest.kt +++ /dev/null @@ -1,23 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.utils - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.test.tags.ContainerTest -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test - -internal class UtilsKtTest { - - @ContainerTest - @Test - fun printToShell_escapes_successfully() { - // given - val a = Prov.defaultInstance() - - // when - val testString = "test if newline \n and apostrophe's ' \" and special chars !§$%[]\\ äöüß are handled correctly" - val res = a.cmd(printToShell(testString)).out - - // then - assertEquals(testString, res) - } -} \ No newline at end of file diff --git a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/web/base/WebKtTest.kt b/bin/test/org/domaindrivenarchitecture/provs/ubuntu/web/base/WebKtTest.kt deleted file mode 100644 index 07f5879..0000000 --- a/bin/test/org/domaindrivenarchitecture/provs/ubuntu/web/base/WebKtTest.kt +++ /dev/null @@ -1,30 +0,0 @@ -package org.domaindrivenarchitecture.provs.ubuntu.web.base - -import org.domaindrivenarchitecture.provs.test.defaultTestContainer -import org.domaindrivenarchitecture.provs.test.tags.ContainerTest -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createFile -import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.fileContent -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test - -internal class WebKtTest { - - @ContainerTest - @Test - fun downloadFromURL_downloadsFile() { - // given - val a = defaultTestContainer() - val file = "file1" - a.createFile("/tmp/" + file, "hello") - - // when - val res = a.downloadFromURL("file:///tmp/" + file, "file2", "/tmp") - - // then - val res2 = a.fileContent("/tmp/file2") - - assertTrue(res.success) - assertEquals("hello", res2) - } -} \ No newline at end of file diff --git a/bin/testFixtures/logback-test.xml b/bin/testFixtures/logback-test.xml deleted file mode 100644 index a43a2a2..0000000 --- a/bin/testFixtures/logback-test.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - System.err - - - %d{HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{35}) - %msg %n - - - - - - - - - - \ No newline at end of file diff --git a/bin/testFixtures/org/domaindrivenarchitecture/provs/test/TestSetup.kt b/bin/testFixtures/org/domaindrivenarchitecture/provs/test/TestSetup.kt deleted file mode 100644 index 5cf6261..0000000 --- a/bin/testFixtures/org/domaindrivenarchitecture/provs/test/TestSetup.kt +++ /dev/null @@ -1,35 +0,0 @@ -package org.domaindrivenarchitecture.provs.test - -import org.domaindrivenarchitecture.provs.core.ProgressType -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.docker.dockerImageExists -import org.domaindrivenarchitecture.provs.core.docker.dockerProvideImage -import org.domaindrivenarchitecture.provs.core.docker.dockerimages.UbuntuPlusUser -import org.domaindrivenarchitecture.provs.core.processors.ContainerStartMode -import org.domaindrivenarchitecture.provs.core.processors.ContainerUbuntuHostProcessor - -val testDockerWithSudo = !"true".equals(System.getProperty("testdockerwithoutsudo")?.toLowerCase()) - -const val defaultTestContainerName = "provs_test" - -fun defaultTestContainer(startMode: ContainerStartMode = ContainerStartMode.USE_RUNNING_ELSE_CREATE): Prov { - val image = UbuntuPlusUser() - val prov = testLocal() - if (!prov.dockerImageExists(image.imageName(), testDockerWithSudo)) { - prov.dockerProvideImage(image, sudo = testDockerWithSudo) - } - - return Prov.newInstance( - ContainerUbuntuHostProcessor( - defaultTestContainerName, - startMode = startMode, - sudo = testDockerWithSudo, - dockerImage = image.imageName() - ), - progressType = ProgressType.NONE - ) -} - -fun testLocal(): Prov { - return Prov.newInstance(name = "testing", progressType = ProgressType.NONE) -} \ No newline at end of file diff --git a/bin/testFixtures/org/domaindrivenarchitecture/provs/test/tags/Tags.kt b/bin/testFixtures/org/domaindrivenarchitecture/provs/test/tags/Tags.kt deleted file mode 100644 index bc24bc5..0000000 --- a/bin/testFixtures/org/domaindrivenarchitecture/provs/test/tags/Tags.kt +++ /dev/null @@ -1,21 +0,0 @@ -package org.domaindrivenarchitecture.provs.test.tags - -import org.junit.jupiter.api.Tag -import org.junit.jupiter.api.Test - -private const val CONTAINER_TEST = "containertest" -private const val CONTAINER_TEST_NON_CI = "containernonci" - - -@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) -@kotlin.annotation.Retention -@Tag(CONTAINER_TEST) -@Test -annotation class ContainerTest - - -@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) -@kotlin.annotation.Retention -@Tag(CONTAINER_TEST_NON_CI) -@Test -annotation class NonCi \ No newline at end of file