You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
provs/src/main/kotlin/io/provs/Utils.kt

108 lines
4.1 KiB
Kotlin

package io.provs
import io.provs.docker.provideContainer
import io.provs.processors.ContainerStartMode
import io.provs.processors.ContainerUbuntuHostProcessor
import io.provs.processors.RemoteProcessor
import java.io.File
/**
* 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.
*/
@Suppress("unused") // used by other libraries resp. KotlinScript
fun remote(host: String, remoteUser: String, password: Secret? = null, platform: String? = null): Prov {
return Prov.newInstance(RemoteProcessor(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.
*/
@Suppress("unused") // 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)
}
}