Merge branch 'master' into improve-input-validation

# Conflicts:
#	src/main/kotlin/org/domaindrivenarchitecture/provs/server/application/CliArgumentsParser.kt
#	src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/K3sCliCommand.kt
#	src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/K3sService.kt
This commit is contained in:
az 2022-08-30 15:40:28 +02:00
commit 5a7e5a8535
9 changed files with 106 additions and 44 deletions

View file

@ -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
provs provides cli-based tools for
* provisioning a desktop (various kinds)
* provisioning a k3s server
* performing system checks
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
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
### provs-desktop
#### 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
After having installed `provs-desktop.jar` (see prerequisites) execute:
`provs-desktop.jar <type> <target> [<options>]`
@ -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: <user[:password]@host> -
* remote, e.g. `user123:mypassword@myhost.com` - general format is: <user[:password]@host> -
* 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 <config-file>`.
```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

View file

@ -18,7 +18,7 @@ apply plugin: "kotlinx-serialization"
group = "org.domaindrivenarchitecture.provs"
version = "0.15.3-SNAPSHOT"
version = "0.15.4-SNAPSHOT"
repositories {
mavenCentral()

View file

@ -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

View file

@ -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<DesktopType> = values): DesktopType {
@JvmStatic
fun valueOf(value: String): DesktopType = valueOf(value, values)
@JvmStatic
protected fun valueOf(value: String, valueList: List<DesktopType>): 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
}
}

View file

@ -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."
)
)

View file

@ -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) }

View file

@ -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<String>? = null,
val submodules: List<String>? = null
) : ServerCliCommand(
serverType,
target,
configFileName
) {
}
)

View file

@ -63,7 +63,7 @@ private fun Prov.provisionGrafanaSanitized(
submodules: List<String>?,
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)

View file

@ -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)
}
}