add installKubectlAndTools
This commit is contained in:
parent
73a40498a0
commit
1493977672
6 changed files with 172 additions and 89 deletions
|
@ -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"
|
||||
val path = "/usr/bin/"
|
||||
val filename = "yq"
|
||||
if (!fileExists(path + filename)) {
|
||||
val result = downloadFromURL(
|
||||
downloadFromURL(
|
||||
"https://github.com/mikefarah/yq/releases/download/v$version/yq_linux_amd64",
|
||||
filename,
|
||||
path,
|
||||
|
@ -38,73 +35,56 @@ fun Prov.installYq(
|
|||
}
|
||||
}
|
||||
|
||||
fun Prov.installKubectl(): ProvResult = def {
|
||||
var kubeConfigFile = "~/.bashrc.d/kubectl.sh"
|
||||
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")
|
||||
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()
|
||||
*/
|
||||
addTextToFile("\nkubectl completion bash\n", "/etc/bash_completion.d/kubernetes", sudo = true)
|
||||
createFileFromResource(kubeConfigFile, "kubectl.sh", resourcePath)
|
||||
} else {
|
||||
ProvResult(true, out = "Kubectl already installed")
|
||||
}
|
||||
}
|
||||
|
||||
task("install tunnel alias") {
|
||||
val tunnelAliasFile = "~/.bashrc.d/ssh_alias.sh"
|
||||
if (!fileExists(tunnelAliasFile)) {
|
||||
var tunnelAlias = """
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
task("install k8sCreateContext") {
|
||||
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
|
||||
}
|
||||
|
||||
main $1
|
||||
|
||||
""".trimIndent()
|
||||
createFile(k8sContextFile, k8sContext, "555", sudo = true)
|
||||
createFileFromResource(
|
||||
k8sContextFile,
|
||||
"k8s-create-context.sh",
|
||||
resourcePath,
|
||||
"555",
|
||||
sudo = true
|
||||
)
|
||||
} else {
|
||||
ProvResult(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Prov.installTerraform(): ProvResult = def {
|
||||
val dir = "/usr/lib/tfenv/"
|
||||
|
@ -116,11 +96,13 @@ fun Prov.installTerraform(): ProvResult = def {
|
|||
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 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)) {
|
||||
|
@ -128,7 +110,7 @@ fun Prov.installAwsCredentials(id:String, key:String): ProvResult = def {
|
|||
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")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
18
src/main/resources/workplace/infrastructure/kubectl.sh
Normal file
18
src/main/resources/workplace/infrastructure/kubectl.sh
Normal file
|
@ -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…
Reference in a new issue