diff --git a/README.md b/README.md index a60697b..55d1a73 100644 --- a/README.md +++ b/README.md @@ -5,17 +5,12 @@ ## Purpose -provs provides cli-based tooling for provisioning desktop or server resp. perform system checks. -* provs-desktop minimal - provides a minimal setup (e.g. swappiness / randomutils) e.g. for setup on a VirtualBox -* provs-desktop office - provides enhancements like zim / gopass / fakturama -* provs-desktop ide - provides development environments for java / kotlin / python / clojure / terraform -* provs-server k3s - provides a production ready & k3s setup with dualstack option -* provs-syspec - verifies a system according to the provided system spec config file - -In general provs combines -* being able to use the power of shell commands -* a clear and detailed result summary of the built-in execution handling (incl. failure handling and reporting) -* the convenience and robustness of a modern programming language +provs provides cli-based tools for +* provisioning a desktop (various kinds) +* provisioning a k3s server +* performing system checks + +Tasks can be run locally or remotely. ## Status @@ -26,11 +21,24 @@ under development - we are working hard on setting up our environments using pro * A **Java Virtual machine** (JVM) is required. * Install `jarwrapper` (e.g. `sudo apt install jarwrapper`) -* Download the latest `provs-desktop.jar` from: https://gitlab.com/domaindrivenarchitecture/provs/-/releases -* Make the jar-file executable by `chmod +x provs-desktop.jar` -* For server functionality (e.g. k3s) download the latest `provs-server.jar` from: https://gitlab.com/domaindrivenarchitecture/provs/-/releases +* Then either download the binaries or build them yourself + +#### Download the binaries + +* 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` + +#### Build the binaries + +Instead of downloading the binaries you can build them yourself + +* Clone this repository +* In the repository's root folder execute: `./gradlew install`. This will install the binaries in `/usr/local/bin` + +### Provision a desktop -### provs-desktop +After having installed `provs-desktop.jar` (see prerequisites) execute: `provs-desktop.jar []` @@ -41,7 +49,9 @@ under development - we are working hard on setting up our environments using pro **target** can be: * `local` -* `user123:mypassword@myhost.com` - general format is: - +* remote, e.g. `user123:mypassword@myhost.com` - general format is: - + * be sure to have openssh-server installed + * add your preferred public key to known_hosts on the target machine * if password is omitted, then ssh-keys will be used for authentication * if password is omitted but option `-p` is provided, then the password will be prompted interactively @@ -49,7 +59,7 @@ under development - we are working hard on setting up our environments using pro * `-p` for interactive password question -#### Provision a desktop +#### Example ```bash provs-desktop.jar basic local @@ -57,9 +67,9 @@ provs-desktop.jar basic local provs-desktop.jar office myuser@myhost.com -p ``` -In the last case you'll be prompted for the password of the remote user due to option `-p`. +In the second case you'll be prompted for the password of the remote user due to option `-p`. -### Provision k3s +### Provision a k3s Server ```bash provs-server.jar k3s local @@ -67,7 +77,8 @@ provs-server.jar k3s local provs-server.jar k3s myuser@myhost.com # using ssh-authentication - alternatively use option -p for password authentication ``` -For the remote server please configure a config file (default file name: server-config.yaml) +For the remote server please configure a config file (default file name: server-config.yaml). +It has to be in the same folder where you execute the provs-server.jar command. ```yaml fqdn: "myhostname.com" node: @@ -94,14 +105,14 @@ provs-server.jar k3s myuser@myhost.com -o grafana -### Performing a system check +### Perform a system check The default config-file for the system check is `syspec-config.yaml`, you can specify a different file with option `-c `. ```bash provs-syspec.jar local -# or remote: -provs-syspec.jar myuser@myhost.com +# or remote with a custom config filename +provs-syspec.jar myuser@myhost.com -c my-syspec-config.yaml ``` ## Get help diff --git a/build.gradle b/build.gradle index 0358d86..c12808c 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,7 @@ apply plugin: "kotlinx-serialization" group = "org.domaindrivenarchitecture.provs" -version = "0.15.3-SNAPSHOT" +version = "0.15.4-SNAPSHOT" repositories { mavenCentral() diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/application/CliArgumentsParser.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/application/CliArgumentsParser.kt index 4277c59..b2a3605 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/application/CliArgumentsParser.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/application/CliArgumentsParser.kt @@ -24,7 +24,7 @@ open class CliArgumentsParser(name: String) : CliTargetParser(name) { val module = modules.first { it.parsed } return DesktopCliCommand( - DesktopType.returnIfExists(module.name.uppercase()), + DesktopType.valueOf(module.name.uppercase()), TargetCliCommand( target, passwordInteractive diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopType.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopType.kt index 2f1b72c..13edb9c 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopType.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopType.kt @@ -4,9 +4,8 @@ package org.domaindrivenarchitecture.provs.desktop.domain /** * Provides desktop types. For each type a different set of software and packages is installed, see README.md. */ -open class DesktopType(val name: String) { - - // A regular class is used rather than enum class in order to allow extending DesktopType by subclassing. +// Uses a regular class instead of an enum class in order to allow subclasses which can add new DesktopTypes +open class DesktopType protected constructor(val name: String) { companion object { @@ -17,7 +16,11 @@ open class DesktopType(val name: String) { @JvmStatic protected val values = listOf(BASIC, OFFICE, IDE) - fun returnIfExists(value: String, valueList: List = values): DesktopType { + @JvmStatic + fun valueOf(value: String): DesktopType = valueOf(value, values) + + @JvmStatic + protected fun valueOf(value: String, valueList: List): DesktopType { for (type in valueList) { if (value.uppercase().equals(type.name)) { return type @@ -31,4 +34,3 @@ open class DesktopType(val name: String) { return name } } - diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/GopassBridge.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/GopassBridge.kt index 1095c33..edabfb9 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/GopassBridge.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/GopassBridge.kt @@ -11,7 +11,7 @@ import org.domaindrivenarchitecture.provs.framework.ubuntu.web.base.downloadFrom fun Prov.downloadGopassBridge() = task { - val version = "0.8.0" + val version = "0.9.0" val filename = "gopass_bridge-${version}-fx.xpi" val downloadDir = "${userHome()}Downloads/" @@ -25,10 +25,10 @@ fun Prov.downloadGopassBridge() = task { fun Prov.installGopassBridgeJsonApi() = task { // 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 gopassJsonApiVersion = "1.14.3" + val requiredGopassVersion = "1.14.4" + 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" val installedJsonApiVersion = gopassJsonApiVersion()?.trim() @@ -55,13 +55,13 @@ fun Prov.installGopassBridgeJsonApi() = task { ) } } else { - if (installedJsonApiVersion.startsWith("gopass-jsonapi version " + gopassBridgeVersion)) { - addResultToEval(ProvResult(true, out = "Version $gopassBridgeVersion of gopass-jsonapi is already installed")) + if (installedJsonApiVersion.startsWith("gopass-jsonapi version " + gopassJsonApiVersion)) { + addResultToEval(ProvResult(true, out = "Version $gopassJsonApiVersion of gopass-jsonapi is already installed")) } else { addResultToEval( ProvResult( false, - err = "gopass-jsonapi (version $gopassBridgeVersion) cannot be installed as version $installedJsonApiVersion is already installed." + + err = "gopass-jsonapi (version $gopassJsonApiVersion) cannot be installed as version $installedJsonApiVersion is already installed." + " Upgrading gopass-jsonapi is currently not supported by provs." ) ) diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/application/CliArgumentsParser.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/application/CliArgumentsParser.kt index 8171052..f6e5b3e 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/application/CliArgumentsParser.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/application/CliArgumentsParser.kt @@ -34,7 +34,7 @@ class CliArgumentsParser(name: String) : CliTargetParser(name) { ), module.configFileName, module.applicationFileName, - module.submodules, + module.submodules ) else -> return ServerCliCommand( ServerType.valueOf(module.name.uppercase()), @@ -73,6 +73,7 @@ class CliArgumentsParser(name: String) : CliTargetParser(name) { "o", "provisions only parts ", ) + override fun execute() { super.configFileName = cliConfigFileName?.let { ConfigFileName(it) } super.applicationFileName = cliApplicationFileName?.let { ApplicationFileName(it) } diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/K3sCliCommand.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/K3sCliCommand.kt index 9da2784..827d4a6 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/K3sCliCommand.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/K3sCliCommand.kt @@ -4,18 +4,15 @@ import org.domaindrivenarchitecture.provs.configuration.domain.ConfigFileName import org.domaindrivenarchitecture.provs.configuration.domain.TargetCliCommand import org.domaindrivenarchitecture.provs.server.domain.ServerCliCommand import org.domaindrivenarchitecture.provs.server.domain.ServerType -import org.domaindrivenarchitecture.provs.server.infrastructure.genericFileExistenceCheck class K3sCliCommand( serverType: ServerType, target: TargetCliCommand, configFileName: ConfigFileName?, val applicationFileName: ApplicationFileName?, - val submodules: List? = null, + val submodules: List? = null ) : ServerCliCommand( serverType, target, configFileName -) { - -} \ No newline at end of file +) \ No newline at end of file diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/K3sService.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/K3sService.kt index 015b673..64ca5dd 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/K3sService.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/K3sService.kt @@ -63,7 +63,7 @@ private fun Prov.provisionGrafanaSanitized( submodules: List?, grafanaConfigResolved: GrafanaAgentConfigResolved?) = task { - if (submodules!!.contains(ServerSubmodule.GRAFANA.name.lowercase())) { + if (submodules != null && submodules.contains(ServerSubmodule.GRAFANA.name.lowercase())) { if (grafanaConfigResolved == null) { println("ERROR: Could not find grafana config.") exitProcess(7) diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopTypeTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopTypeTest.kt new file mode 100644 index 0000000..715ede7 --- /dev/null +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopTypeTest.kt @@ -0,0 +1,51 @@ +package org.domaindrivenarchitecture.provs.desktop.domain + +import org.domaindrivenarchitecture.provs.desktop.domain.DesktopType.Companion.BASIC +import org.domaindrivenarchitecture.provs.desktop.domain.DesktopType.Companion.IDE +import org.domaindrivenarchitecture.provs.desktop.domain.SubDesktopType.Companion.SUBTYPE +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* + +// tests subclassing of DesktopType +internal open class SubDesktopType protected constructor(name: String) : DesktopType(name) { + + companion object { + + // defines a new DesktopType + val SUBTYPE = SubDesktopType("SUBTYPE") + + private val values = DesktopType.values + SUBTYPE + + fun valueOf(value: String): DesktopType { + return valueOf(value, values) + } + } +} + +internal class DesktopTypeTest { + + @Test + fun test_valueOf() { + assertEquals(BASIC, DesktopType.valueOf("basic")) + assertEquals(BASIC, DesktopType.valueOf("Basic")) + assertEquals(IDE, DesktopType.valueOf("IDE")) + + val exception = assertThrows(RuntimeException::class.java) { + DesktopType.valueOf("subtype") + } + assertEquals("No DesktopType found for value: subtype", exception.message) + } + + @Test + fun test_valueOf_in_subclass() { + assertEquals(SUBTYPE, SubDesktopType.valueOf("subtype")) + assertEquals(BASIC, SubDesktopType.valueOf("basic")) + assertNotEquals(SUBTYPE, DesktopType.valueOf("basic")) + + val exception = assertThrows(RuntimeException::class.java) { + DesktopType.valueOf("subtype2") + } + assertEquals("No DesktopType found for value: subtype2", exception.message) + } +}