add installKubectlAndTools

merge-requests/1/merge
az 3 years ago
parent 73a40498a0
commit 1493977672

@ -40,22 +40,25 @@ fun getCallingMethodName(): String? {
}
fun String.escapeNewline(): String = this.replace("\r", "\\r").replace("\n", "\\n")
fun String.escapeControlChars(): String = this.replace("\r", "\\r").replace("\n", "\\n").replace("\t", "\\t").replace("[\\p{Cntrl}]".toRegex(), "\\?")
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("%", "%%")
fun String.escapeNewline(): String = replace("\r", "\\r").replace("\n", "\\n")
fun String.escapeControlChars(): String = replace("\r", "\\r").replace("\n", "\\n").replace("\t", "\\t").replace("[\\p{Cntrl}]".toRegex(), "\\?")
fun String.escapeBackslash(): String = replace("\\", "\\\\")
fun String.escapeDoubleQuote(): String = replace("\"", "\\\"")
fun String.escapeSingleQuote(): String = replace("'", "\'")
fun String.escapeSingleQuoteForShell(): String = replace("'", "'\"'\"'")
fun String.escapeProcentForPrintf(): String = replace("%", "%%")
fun String.endingWithFileSeparator(): String = if (length > 0 && (last() != fileSeparatorChar())) this + fileSeparator() else this
// 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
fun fileSeparatorChar(): Char = File.separatorChar
fun newline(): String = System.getProperty("line.separator")
fun hostUserHome(): String = System.getProperty("user.home") + fileSeparator()
fun getResourceAsText(path: String): String {
val resource = Thread.currentThread().contextClassLoader.getResource(path)

@ -10,6 +10,22 @@ fun Prov.fileExists(file: String, sudo: Boolean = false): Boolean {
}
fun Prov.createFileFromResource(
fullyQualifiedFilename: String,
resourceFilename: String,
resourcePath: String = "",
posixFilePermission: String? = null,
sudo: Boolean = false
): ProvResult {
return createFile(
fullyQualifiedFilename,
getResourceAsText(resourcePath.endingWithFileSeparator() + resourceFilename),
posixFilePermission,
sudo
)
}
fun Prov.createFile(
fullyQualifiedFilename: String,
text: String?,
@ -69,6 +85,14 @@ fun Prov.fileContent(file: String, sudo: Boolean = false): String? {
}
fun Prov.addTextToFile(
text: String,
file: String,
doNotAddIfExisting: Boolean = true,
sudo: Boolean = false
): ProvResult = addTextToFile(text, File(file), doNotAddIfExisting, sudo)
fun Prov.addTextToFile(
text: String,
file: File,

@ -2,19 +2,16 @@ package org.domaindrivenarchitecture.provs.workplace.infrastructure
import org.domaindrivenarchitecture.provs.core.Prov
import org.domaindrivenarchitecture.provs.core.ProvResult
import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDirs
import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createFile
import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.dirExists
import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.fileExists
import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.*
import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall
import org.domaindrivenarchitecture.provs.ubuntu.web.base.downloadFromURL
fun Prov.installDevOps() = def {
installTerraform()
//installAwsCredentials("", "") // TODO: get credentials from gopass
installKubectl()
installKubectlAndTools()
installYq()
installAwsCredentials()
}
@ -22,10 +19,10 @@ fun Prov.installYq(
version: String = "4.13.2",
sha256sum: String = "d7c89543d1437bf80fee6237eadc608d1b121c21a7cbbe79057d5086d74f8d79"
): ProvResult = def {
var path = "/usr/bin/"
var filename = "yq"
if(!fileExists(path + filename)) {
val result = downloadFromURL(
val path = "/usr/bin/"
val filename = "yq"
if (!fileExists(path + filename)) {
downloadFromURL(
"https://github.com/mikefarah/yq/releases/download/v$version/yq_linux_amd64",
filename,
path,
@ -38,97 +35,82 @@ fun Prov.installYq(
}
}
fun Prov.installKubectl(): ProvResult = def {
var kubeConfigFile = "~/.bashrc.d/kubectl.sh"
if(!fileExists(kubeConfigFile)) {
aptInstall("kubectl")
cmd("kubectl completion bash >> /etc/bash_completion.d/kubernetes", sudo = true)
// TODO: externalize to file - trippeld escaping is realy ugly & does not work
/*var kubeConfig = """
# Set the default kube context if present
DEFAULT_KUBE_CONTEXTS="$HOME/.kube/config"
if test -f "${DEFAULT_KUBE_CONTEXTS}"
then
export KUBECONFIG="$DEFAULT_KUBE_CONTEXTS"
fi
# Additional contexts should be in ~/.kube/custom-contexts/
CUSTOM_KUBE_CONTEXTS="$HOME/.kube/custom-contexts"
mkdir -p "${CUSTOM_KUBE_CONTEXTS}"
OIFS="$IFS"
IFS=$'\n'
for contextFile in `find "${CUSTOM_KUBE_CONTEXTS}" -type f -name "*.yml"`
do
export KUBECONFIG="$contextFile:$KUBECONFIG"
done
IFS="$OIFS"
""".trimIndent()
*/
fun Prov.installKubectlAndTools(): ProvResult = def {
val resourcePath = "workplace/infrastructure/"
task("installKubectl") {
val kubeConfigFile = "~/.bashrc.d/kubectl.sh"
if (!fileExists(kubeConfigFile)) {
// prerequisites -- see https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/
cmd("sudo apt-get update")
aptInstall("apt-transport-https ca-certificates curl")
cmd("sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg")
cmd("echo \"deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main\" | sudo tee /etc/apt/sources.list.d/kubernetes.list")
// kubectl and bash completion
cmd("sudo apt-get update")
aptInstall("kubectl")
addTextToFile("\nkubectl completion bash\n", "/etc/bash_completion.d/kubernetes", sudo = true)
createFileFromResource(kubeConfigFile, "kubectl.sh", resourcePath)
} else {
ProvResult(true, out = "Kubectl already installed")
}
}
val tunnelAliasFile = "~/.bashrc.d/ssh_alias.sh"
if(!fileExists(tunnelAliasFile)) {
var tunnelAlias = """
alias sshu='ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
alias ssht='ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -L 8002:localhost:8002 -L 6443:192.168.5.1:6443'
""".trimIndent()
createFile(tunnelAliasFile, tunnelAlias, "640")
task("install tunnel alias") {
val tunnelAliasFile = "~/.bashrc.d/ssh_alias.sh"
if (!fileExists(tunnelAliasFile)) {
val tunnelAlias = """
alias sshu='ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
alias ssht='ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -L 8002:localhost:8002 -L 6443:192.168.5.1:6443'
""".trimIndent()
createFile(tunnelAliasFile, tunnelAlias, "640")
} else {
ProvResult(true, out = "tunnel alias already installed")
}
}
val k8sContextFile = "/usr/local/bin/k8s-create-context.sh"
if(!fileExists(k8sContextFile)) {
// TODO: externalize to file - trippeld escaping is realy ugly & does not work
var k8sContext = """
function main() {
local cluster_name="${1}"; shift
ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@\$\{cluster_name}.meissa-gmbh.de \
"cat /etc/kubernetes/admin.conf" | \
yq e ".clusters[0].name=\"\$\{cluster_name}\" \
| .clusters[0].cluster.server=\"https://kubernetes:6443\" \
| .contexts[0].context.cluster=\"\$\{cluster_name}\" \
| .contexts[0].context.user=\"\$\{cluster_name}\" \
| .contexts[0].name=\"\$\{cluster_name}\" \
| del(.current-context) \
| del(.preferences) \
| .users[0].name=\"\$\{cluster_name}\"" - \
> ~/.kube/custom-contexts/\$\{cluster_name}.yml
task("install k8sCreateContext") {
val k8sContextFile = "/usr/local/bin/k8s-create-context.sh"
if (!fileExists(k8sContextFile)) {
createFileFromResource(
k8sContextFile,
"k8s-create-context.sh",
resourcePath,
"555",
sudo = true
)
} else {
ProvResult(true)
}
main $1
""".trimIndent()
createFile(k8sContextFile, k8sContext, "555", sudo = true)
} else {
ProvResult(true)
}
}
fun Prov.installTerraform(): ProvResult = def {
val dir = "/usr/lib/tfenv/"
if(!dirExists(dir)) {
if (!dirExists(dir)) {
createDirs(dir, sudo = true)
cmd("git clone https://github.com/tfutils/tfenv.git " + dir, sudo = true)
cmd("rm " + dir + ".git/ -rf", sudo = true)
cmd("ln -s " + dir + "bin/* /usr/local/bin", sudo = true)
}
cmd ("tfenv install", sudo = true)
cmd ("tfenv install latest:^0.13", sudo = true)
cmd ("tfenv use latest:^0.13", sudo = true)
cmd("tfenv install", sudo = true)
cmd("tfenv install latest:^1.0.8", sudo = true)
cmd("tfenv use latest:^1.0.8", sudo = true)
}
fun Prov.installAwsCredentials(id:String, key:String): ProvResult = def {
// -------------------------------------------- AWS credentials file -----------------------------------------------
fun Prov.installAwsCredentials(id: String = "REPLACE_WITH_YOUR_ID", key: String = "REPLACE_WITH_YOUR_KEY"): ProvResult = def {
val dir = "~/.aws"
if(!dirExists(dir)) {
if (!dirExists(dir)) {
createDirs(dir)
createFile("~/.aws/config", awsConfig())
createFile("~/.aws/credentials", awsCredentials(id, key))
} else {
ProvResult(true, "aws credential file already installed")
ProvResult(true, "aws credential folder already installed")
}
}
@ -140,7 +122,7 @@ fun awsConfig(): String {
""".trimIndent()
}
fun awsCredentials(id:String, key:String): String {
fun awsCredentials(id: String, key: String): String {
return """
[default]
aws_access_key_id = $id

@ -0,0 +1,17 @@
function main() {
local cluster_name="${1}"; shift
ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@${cluster_name}.meissa-gmbh.de \
"cat /etc/kubernetes/admin.conf" | \
yq e ".clusters[0].name=\"${cluster_name}\" \
| .clusters[0].cluster.server=\"https://kubernetes:6443\" \
| .contexts[0].context.cluster=\"${cluster_name}\" \
| .contexts[0].context.user=\"${cluster_name}\" \
| .contexts[0].name=\"${cluster_name}\" \
| del(.current-context) \
| del(.preferences) \
| .users[0].name=\"${cluster_name}\"" - \
> ~/.kube/custom-contexts/${cluster_name}.yml
}
main $1

@ -0,0 +1,18 @@
# Set the default kube context if present
DEFAULT_KUBE_CONTEXTS="$HOME/.kube/config"
if test -f "${DEFAULT_KUBE_CONTEXTS}"
then
export KUBECONFIG="$DEFAULT_KUBE_CONTEXTS"
fi
# Additional contexts should be in ~/.kube/custom-contexts/
CUSTOM_KUBE_CONTEXTS="$HOME/.kube/custom-contexts"
mkdir -p "${CUSTOM_KUBE_CONTEXTS}"
OIFS="$IFS"
IFS=$'\n'
for contextFile in $(find "${CUSTOM_KUBE_CONTEXTS}" -type f -name "*.yml")
do
export KUBECONFIG="$contextFile:$KUBECONFIG"
done
IFS="$OIFS"

@ -0,0 +1,39 @@
package org.domaindrivenarchitecture.provs.workplace.infrastructure
import org.domaindrivenarchitecture.provs.core.getResourceAsText
import org.domaindrivenarchitecture.provs.test.defaultTestContainer
import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDir
import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDirs
import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.fileContainsText
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
internal class DevOpsKtTest {
@Test
fun installKubectlAndTools() {
// given
defaultTestContainer().def {
createDirs("/etc/bash_completion.d", sudo = true)
createDir(".bashrc.d")
}
//when
val res = defaultTestContainer().installKubectlAndTools()
// then
assertTrue(res.success)
assertTrue(
defaultTestContainer().fileContainsText(
"~/.bashrc.d/kubectl.sh",
getResourceAsText("workplace/infrastructure/kubectl.sh")
)
)
assertTrue(
defaultTestContainer().fileContainsText(
"/etc/bash_completion.d/kubernetes",
"\nkubectl completion bash\n"
)
)
}
}
Loading…
Cancel
Save