Merge branch 'main' of ssh://repo.prod.meissa.de:2222/meissa/provs

This commit is contained in:
patdyn 2024-08-06 14:39:22 +02:00
commit 43b7e83187
13 changed files with 90 additions and 72 deletions

View file

@ -12,9 +12,6 @@ provs provides cli-based tools for
Tasks can be run locally or remotely.
## Status
under development - though we already set up a few IDEs and servers with provs.
## Try out
### Prerequisites
@ -28,8 +25,9 @@ under development - though we already set up a few IDEs and servers with provs.
* Download the latest `provs-desktop.jar`,`provs-server.jar` and/or `provs-syspec.jar` from: https://gitlab.com/domaindrivenarchitecture/provs/-/releases
* Preferably into `/usr/local/bin` or any other folder where executables can be found by the system
* Make the jar-file executable e.g. by `chmod +x provs-desktop.jar`
* Check with `provs-desktop.jar -h` to show help information
#### Build the binaries
###### Build the binaries
Instead of downloading the binaries you can build them yourself

View file

@ -2,8 +2,6 @@ This repository holds the documentation of the provs framework.
# Design principles
For usage examples it is recommended to have a look at [provs-scripts](https://gitlab.com/domaindrivenarchitecture/provs-scripts) or [provs-ubuntu-extensions](https://gitlab.com/domaindrivenarchitecture/provs-ubuntu-extensions).
## "Implarative"
Configuration management tools are usually classified as either **imperative** or **declarative**.

View file

@ -134,7 +134,7 @@ fun Prov.provisionOfficeDesktop() {
installDeltaChat()
aptInstall(OFFICE_SUITE)
installZimWiki()
installNextcloudClient()
// installNextcloudClient() might not install - might need fix and working test
aptInstall(COMPARE_TOOLS)
// optional, as installation of these tools often fail and as they are not considered mandatory

View file

@ -15,8 +15,37 @@ fun Prov.installDevOps() = task {
installTerraform()
installKubectlAndTools()
installYq()
installGraalVM()
}
fun Prov.installGraalVM():ProvResult = task{
val version = "21.0.2"
val tmpDir = "~/tmp"
val filename = "graalvm-community-jdk-"
val additionalPartFilename = "_linux-x64_bin"
val packedFilename = "$filename$version$additionalPartFilename.tar.gz"
val extractedFilenameHunch = "graalvm-community-openjdk-"
val installationPath = "/usr/lib/jvm/"
if ( !chk("/usr/local/bin/native-image --version") || version != cmd("/usr/local/bin/native-image --version|awk 'NR==1 {print $2}").out?.trim() || !chk("ls -d $installationPath$extractedFilenameHunch$version*")) {
downloadFromURL(
"https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-$version/$packedFilename",
path = tmpDir,
sha256sum = "b048069aaa3a99b84f5b957b162cc181a32a4330cbc35402766363c5be76ae48"
)
if (!chk("ls -d $installationPath"))
cmd("sudo mkdir $installationPath")
else {
ProvResult(true, out = "$installationPath just exists, mkdir not necessary.")
}
cmd("sudo tar -C $installationPath -xzf $packedFilename", tmpDir)
val graalInstPath = installationPath + (cmd("ls /usr/lib/jvm/|grep -e graalvm-community-openjdk-$version").out?.replace("\n", ""))
cmd("sudo ln -s $graalInstPath/lib/svm/bin/native-image /usr/local/bin/native-image")
cmd("/usr/local/bin/native-image --version")
} else {
ProvResult(true, out = "GraalVM $version already installed")
}
}
fun Prov.installYq(
version: String = "4.13.2",
@ -91,8 +120,8 @@ fun Prov.installKubectl(): ProvResult = task {
downloadFromURL(
"https://dl.k8s.io/release/v$kubectlVersion/bin/linux/amd64/kubectl",
path = tmpDir,
// from https://dl.k8s.io/v1.23.0/bin/linux/amd64/kubectl.sha256
sha256sum = "2d0f5ba6faa787878b642c151ccb2c3390ce4c1e6c8e2b59568b3869ba407c4f"
// from https://dl.k8s.io/v1.27.4/bin/linux/amd64/kubectl.sha256
sha256sum = "4685bfcf732260f72fce58379e812e091557ef1dfc1bc8084226c7891dd6028f"
)
cmd("sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl", dir = tmpDir)
}
@ -158,34 +187,3 @@ fun Prov.installTerraform(): ProvResult = task {
cmd("tfenv install latest:^1.4.6", sudo = true)
cmd("tfenv use latest:^1.4.6", sudo = true)
}
// -------------------------------------------- AWS credentials file -----------------------------------------------
fun Prov.installAwsCredentials(id: String = "REPLACE_WITH_YOUR_ID", key: String = "REPLACE_WITH_YOUR_KEY"): ProvResult =
task {
val dir = "~/.aws"
if (!checkDir(dir)) {
createDirs(dir)
createFile("~/.aws/config", awsConfig())
createFile("~/.aws/credentials", awsCredentials(id, key))
} else {
ProvResult(true, "aws credential folder already installed")
}
}
fun awsConfig(): String {
return """
[default]
region = eu-central-1
output = json
""".trimIndent()
}
fun awsCredentials(id: String, key: String): String {
return """
[default]
aws_access_key_id = $id
aws_secret_access_key = $key
""".trimIndent()
}

View file

@ -11,9 +11,10 @@ import org.domaindrivenarchitecture.provs.framework.ubuntu.web.base.downloadFrom
fun Prov.installGopass(
version: String = "1.15.5",
version: String = "1.15.13", // NOTE: when adjusting, pls also adjust checksum below and version of gopass bridge json api
enforceVersion: Boolean = false,
sha256sum: String = "23ec10015c2643f22cb305859eb36d671094d463d2eb1798cc675e7bb06f4b39"
// from https://github.com/gopasspw/gopass/releases/tag/v1.15.13
sha256sum: String = "409ed5617e64fa2c781d5e2807ba7fcd65bc383a4e110f410f90b590e51aec55"
) = taskWithResult {
if (isPackageInstalled("gopass") && !enforceVersion) {

View file

@ -22,10 +22,10 @@ fun Prov.downloadGopassBridge() = task {
}
fun Prov.installGopassJsonApi() = taskWithResult {
// see https://github.com/gopasspw/gopass-jsonapi
val sha256sum = "ec9976e39a468428ae2eb1e2e0b9ceccba7f60d66b8097e2425b0c07f4fed108"
val gopassJsonApiVersion = "1.15.5"
val requiredGopassVersion = "1.15.5"
// from https://github.com/gopasspw/gopass-jsonapi/releases/tag/v1.15.13
val sha256sum = "3162ab558301645024325ce2e419c1d67900e1faf95dc1774a36f1ebfc76389f"
val gopassJsonApiVersion = "1.15.13"
val requiredGopassVersion = "1.15.13"
val filename = "gopass-jsonapi_${gopassJsonApiVersion}_linux_amd64.deb"
val downloadUrl = "-L https://github.com/gopasspw/gopass-jsonapi/releases/download/v$gopassJsonApiVersion/$filename"
val downloadDir = "${userHome()}Downloads"

View file

@ -30,7 +30,7 @@ val OPENCONNECT = "openconnect network-manager-openconnect network-manager-openc
val VPNC = "vpnc network-manager-vpnc network-manager-vpnc-gnome vpnc-scripts"
val JAVA = "openjdk-8-jdk openjdk-11-jdk openjdk-17-jdk jarwrapper"
val JAVA = "openjdk-17-jdk jarwrapper"
val DRAWING_TOOLS = "inkscape dia openboard graphviz"

View file

@ -24,7 +24,7 @@ class ProvWithSudoKtTest {
fun test_ensureSudoWithoutPassword_local_Prov() {
mockkStatic(::getPasswordToConfigureSudoWithoutPassword)
every { getPasswordToConfigureSudoWithoutPassword() } returns Secret("testuserpw")
every { getPasswordToConfigureSudoWithoutPassword() } returns Secret("testuser")
// given
val containerName = "prov-test-sudo-no-pw"
@ -58,7 +58,7 @@ class ProvWithSudoKtTest {
// given
val containerName = "prov-test-sudo-no-pw-ssh"
val password = Secret("testuserpw")
val password = Secret("testuser")
val prov = Prov.newInstance(
ContainerUbuntuHostProcessor(

View file

@ -1,6 +1,7 @@
package org.domaindrivenarchitecture.provs.desktop.domain
import io.mockk.*
import org.domaindrivenarchitecture.provs.configuration.domain.TargetCliCommand
import org.domaindrivenarchitecture.provs.desktop.infrastructure.installPpaFirefox
import org.domaindrivenarchitecture.provs.desktop.infrastructure.verifyIdeSetup
import org.domaindrivenarchitecture.provs.desktop.infrastructure.verifyOfficeSetup
@ -37,10 +38,8 @@ internal class DesktopServiceKtTest {
// when
Assertions.assertThrows(Exception::class.java) {
prov.provisionDesktop(
DesktopType.BASIC,
gitUserName = "testuser",
gitEmail = "testuser@test.org",
prov.provisionDesktopCommand(
DesktopCliCommand(DesktopType.BASIC, TargetCliCommand("testuser@somehost"), null), DesktopConfig() // dummy data
)
}
}

View file

@ -1,10 +1,7 @@
package org.domaindrivenarchitecture.provs.desktop.infrastructure
import org.domaindrivenarchitecture.provs.framework.core.getResourceAsText
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.checkFile
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.createDir
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.createDirs
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.fileContainsText
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.*
import org.domaindrivenarchitecture.provs.test.defaultTestContainer
import org.domaindrivenarchitecture.provs.test.tags.ContainerTest
import org.domaindrivenarchitecture.provs.test.tags.ExtensiveContainerTest
@ -62,4 +59,17 @@ internal class DevOpsKtTest {
assertTrue(res.success)
assertTrue(prov.checkFile("/usr/local/bin/kubeconform"))
}
@ContainerTest
fun installGraalVM() {
// given
val prov = defaultTestContainer()
// when
val res = prov.installGraalVM()
// then
assertTrue(res.success)
assertTrue(prov.checkFile("/usr/local/bin/native-image"))
}
}

View file

@ -1,17 +1,21 @@
package org.domaindrivenarchitecture.provs.desktop.infrastructure
import org.domaindrivenarchitecture.provs.framework.core.Secret
import org.domaindrivenarchitecture.provs.framework.core.remote
import org.domaindrivenarchitecture.provs.test.defaultTestContainer
import org.domaindrivenarchitecture.provs.test.tags.ContainerTest
import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.KeyPair
import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.base.configureGpgKeys
import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.base.gpgFingerprint
import org.domaindrivenarchitecture.provs.framework.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.framework.ubuntu.filesystem.base.*
import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.privateGPGSnakeoilKey
import org.domaindrivenarchitecture.provs.framework.ubuntu.secret.secretSources.PromptSecretSource
import org.domaindrivenarchitecture.provs.framework.ubuntu.user.base.makeCurrentUserSudoerWithoutPasswordRequired
import org.domaindrivenarchitecture.provs.test.tags.ExtensiveContainerTest
import org.domaindrivenarchitecture.provs.test_keys.publicGPGSnakeoilKey
import org.junit.jupiter.api.Assertions.assertFalse
@ -56,24 +60,32 @@ internal class GopassKtTest {
}
@Test
@Disabled // Integrationtest; change user, host and keys, then remove this line to run this test
@Disabled // This is an integration test, which needs preparation:
// Pls change user, host and remote connection (choose connection either by password or by ssh key)
// then remove tag @Disabled to be able to run this test.
// PREREQUISITE: remote machine needs openssh-server installed
fun test_install_and_configure_Gopass_and_GopassBridgeJsonApi() {
// settings to change
val host = "192.168.56.135"
// host and user
val host = "192.168.56.154"
val user = "xxx"
val pubKey = GopassSecretSource("path-to/pub.key").secret()
val privateKey = GopassSecretSource("path-to/priv.key").secret()
// given
val prov = remote(host, user)
// connection by password
val pw = PromptSecretSource("Pw for $user").secret()
val prov = remote(host, user, pw)
prov.makeCurrentUserSudoerWithoutPasswordRequired(pw) // may be commented out if user can already sudo without password
// or alternatively use connection by ssh key if the public key is already available remotely
// val prov = remote(host, user)
val pubKey = Secret(publicGPGSnakeoilKey())
val privateKey = Secret(privateGPGSnakeoilKey())
// when
val res = prov.task {
configureGpgKeys(
KeyPair(
pubKey,
privateKey
),
KeyPair(pubKey, privateKey),
trust = true,
skipIfExistin = true
)

View file

@ -3,8 +3,10 @@ package org.domaindrivenarchitecture.provs.desktop.infrastructure
import org.domaindrivenarchitecture.provs.test.defaultTestContainer
import org.domaindrivenarchitecture.provs.test.tags.ExtensiveContainerTest
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Disabled
internal class NextcloudClientTest {
@Disabled // test is hanging sometimes
@ExtensiveContainerTest
fun test_installNextcloudClient() {
// when

View file

@ -34,7 +34,7 @@ class ContainerUbuntuHostProcessorTest {
// given
val containerName = "prov-test-ssh-with-container"
val password = Secret("testuserpw")
val password = Secret("testuser")
val prov = Prov.newInstance(
ContainerUbuntuHostProcessor(
@ -57,8 +57,8 @@ class ContainerUbuntuHostProcessorTest {
val remoteProvBySsh = remote(ipOfContainer, "testuser", password)
// when
val firstSessionResult = remoteProvBySsh.cmd("echo 1")
val secondSessionResult = remoteProvBySsh.cmd("echo 1")
val firstSessionResult = remoteProvBySsh.cmd("echo 1") // connect (to container) by ssh via ip
val secondSessionResult = remoteProvBySsh.cmd("echo 2") // second connect after first connection has been closed
// then
assertTrue(firstSessionResult.success)