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:
commit
5a7e5a8535
9 changed files with 106 additions and 44 deletions
55
README.md
55
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
|
||||
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
|
||||
|
|
|
@ -18,7 +18,7 @@ apply plugin: "kotlinx-serialization"
|
|||
|
||||
|
||||
group = "org.domaindrivenarchitecture.provs"
|
||||
version = "0.15.3-SNAPSHOT"
|
||||
version = "0.15.4-SNAPSHOT"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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."
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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
|
||||
) {
|
||||
|
||||
}
|
||||
)
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue