diff --git a/build.gradle b/build.gradle index 1db101e..eb70088 100644 --- a/build.gradle +++ b/build.gradle @@ -83,7 +83,7 @@ dependencies { api "ch.qos.logback:logback-core:1.2.5" testFixturesApi group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.5.2' -// testImplementation("io.mockk:mockk:1.12.0") + testImplementation("io.mockk:mockk:1.12.0") testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2' } diff --git a/docs/CliApplication.puml b/docs/CliApplication.puml new file mode 100644 index 0000000..24f6d91 --- /dev/null +++ b/docs/CliApplication.puml @@ -0,0 +1,52 @@ +@startuml + +autonumber + +skinparam sequenceBox { + borderColor White +} + +participant User + +box "application" #LightBlue + +participant CliWorkplace +participant WorkplaceCliCommand +participant Application + +end box + +box "domain" #LightGreen + +participant ProvisionWorkplace +participant WorkplaceConfig + +end box + +box "infrastructure" #CornSilk + +participant ConfigRepository +participant InfrastructureModules + +end box + + +User -> CliWorkplace ++ : main(args...) + +CliWorkplace -> WorkplaceCliCommand : parseWorkplaceArguments + +CliWorkplace -> WorkplaceCliCommand : isValid + +CliWorkplace -> ConfigRepository : getConfig +WorkplaceConfig <- ConfigRepository : create +WorkplaceConfig --> ConfigRepository : config +CliWorkplace <-- ConfigRepository : config + +CliWorkplace -> Application : provision +Application -> ProvisionWorkplace : provisionWorkplace + +ProvisionWorkplace -> InfrastructureModules: Various calls like: +ProvisionWorkplace -> InfrastructureModules: installVirtualBoxGuestAdditions +ProvisionWorkplace -> InfrastructureModules: configureNoSwappiness, ... + +@enduml diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/core/cli/TargetCliCommand.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/core/cli/CliTargetCommand.kt similarity index 96% rename from src/main/kotlin/org/domaindrivenarchitecture/provs/core/cli/TargetCliCommand.kt rename to src/main/kotlin/org/domaindrivenarchitecture/provs/core/cli/CliTargetCommand.kt index c4947af..4330fd8 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/core/cli/TargetCliCommand.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/core/cli/CliTargetCommand.kt @@ -31,7 +31,7 @@ fun parseTarget( programName: String = "java -jar provs.jar", args: Array ): TargetCliCommand { - val parser = TargetParser(programName) + val parser = CliTargetParser(programName) parser.parse(args) return TargetCliCommand( diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/core/cli/TargetParser.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/core/cli/CliTargetParser.kt similarity index 94% rename from src/main/kotlin/org/domaindrivenarchitecture/provs/core/cli/TargetParser.kt rename to src/main/kotlin/org/domaindrivenarchitecture/provs/core/cli/CliTargetParser.kt index 8314682..1460c8d 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/core/cli/TargetParser.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/core/cli/CliTargetParser.kt @@ -4,7 +4,7 @@ import kotlinx.cli.ArgParser import kotlinx.cli.ArgType import kotlinx.cli.default -open class TargetParser(name: String) : ArgParser(name) { +open class CliTargetParser(name: String) : ArgParser(name) { val remoteHost by option( ArgType.String, shortName = "r", description = "provision to remote host - either localHost or remoteHost must be specified" diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/server_compounds/monitoring/ProvisionMonitoring.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/server_compounds/monitoring/ProvisionMonitoring.kt deleted file mode 100644 index 56b204a..0000000 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/server_compounds/monitoring/ProvisionMonitoring.kt +++ /dev/null @@ -1,18 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_compounds.monitoring - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.extensions.server_software.standalone_server.nginx.base.NginxConf -import org.domaindrivenarchitecture.provs.extensions.server_software.standalone_server.nginx.base.nginxHttpConf -import org.domaindrivenarchitecture.provs.extensions.server_software.standalone_server.nginx.provisionNginxStandAlone -import org.domaindrivenarchitecture.provs.extensions.server_software.standalone_server.prometheus.base.configurePrometheusDocker -import org.domaindrivenarchitecture.provs.extensions.server_software.standalone_server.prometheus.base.runPrometheusDocker - - -@Suppress("unused") // used externally -fun Prov.provisionMonitoring() = requireAll { - configurePrometheusDocker() - runPrometheusDocker() - provisionNginxStandAlone(NginxConf.nginxHttpConf()) -} - - diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/server_compounds/monitoring/ProvisionNginxAndMonitoring.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/server_compounds/monitoring/ProvisionNginxAndMonitoring.kt deleted file mode 100644 index 1f34c0f..0000000 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/server_compounds/monitoring/ProvisionNginxAndMonitoring.kt +++ /dev/null @@ -1,20 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.server_compounds.monitoring - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.extensions.server_software.standalone_server.nginx.base.NginxConf -import org.domaindrivenarchitecture.provs.extensions.server_software.standalone_server.nginx.base.nginxAddLocation -import org.domaindrivenarchitecture.provs.extensions.server_software.standalone_server.nginx.base.nginxCreateSelfSignedCertificate -import org.domaindrivenarchitecture.provs.extensions.server_software.standalone_server.nginx.base.nginxHttpsConfWithLocationFiles -import org.domaindrivenarchitecture.provs.extensions.server_software.standalone_server.nginx.provisionNginxStandAlone -import org.domaindrivenarchitecture.provs.extensions.server_software.standalone_server.prometheus.base.prometheusNginxConfig -import org.domaindrivenarchitecture.provs.extensions.server_software.standalone_server.prometheus.provisionPrometheusDocker - - -@Suppress("unused") // used externally -fun Prov.provisionNginxMonitoring(nginxHost: String = "localhost") = def { - provisionPrometheusDocker(nginxHost) - nginxCreateSelfSignedCertificate() - provisionNginxStandAlone(NginxConf.nginxHttpsConfWithLocationFiles()) - nginxAddLocation("443", nginxHost, "/prometheus", prometheusNginxConfig) -} - diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/server_software/k3s/application/CliK3sArgumentsParser.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/server_software/k3s/application/CliK3sArgumentsParser.kt index b405b73..5c60bbe 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/server_software/k3s/application/CliK3sArgumentsParser.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/server_software/k3s/application/CliK3sArgumentsParser.kt @@ -2,9 +2,9 @@ package org.domaindrivenarchitecture.provs.extensions.server_software.k3s.applic import kotlinx.cli.ArgType import kotlinx.cli.default -import org.domaindrivenarchitecture.provs.core.cli.TargetParser +import org.domaindrivenarchitecture.provs.core.cli.CliTargetParser -class CliK3sArgumentsParser(name: String) : TargetParser(name) { +class CliK3sArgumentsParser(name: String) : CliTargetParser(name) { enum class K3sType { K3S, K3D diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/ProvisionWorkplace.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/ProvisionWorkplace.kt deleted file mode 100644 index ff2c932..0000000 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/ProvisionWorkplace.kt +++ /dev/null @@ -1,155 +0,0 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace - -import org.domaindrivenarchitecture.provs.core.* -import org.domaindrivenarchitecture.provs.core.processors.RemoteProcessor -import org.domaindrivenarchitecture.provs.workplace.domain.WorkplaceType -import org.domaindrivenarchitecture.provs.extensions.workplace.base.* -import org.domaindrivenarchitecture.provs.workplace.infrastructure.getConfig -import org.domaindrivenarchitecture.provs.ubuntu.git.provisionGit -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstallFromPpa -import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptPurge -import org.domaindrivenarchitecture.provs.ubuntu.keys.KeyPair -import org.domaindrivenarchitecture.provs.ubuntu.keys.base.gpgFingerprint -import org.domaindrivenarchitecture.provs.ubuntu.keys.provisionKeys -import org.domaindrivenarchitecture.provs.ubuntu.secret.secretSources.PromptSecretSource -import org.domaindrivenarchitecture.provs.ubuntu.user.base.currentUserCanSudo -import org.domaindrivenarchitecture.provs.ubuntu.user.base.makeUserSudoerWithNoSudoPasswordRequired -import org.domaindrivenarchitecture.provs.ubuntu.user.base.whoami -import org.domaindrivenarchitecture.provs.workplace.infrastructure.installDevOps -import java.net.InetAddress -import kotlin.system.exitProcess - - -/** - * Provisions software and configurations for a personal workplace. - * Offers the possibility to choose between different types. - * Type OFFICE installs office-related software like Thunderbird, LibreOffice, and much more. - * Type IDE provides additional software for a development environment, such as Visual Studio Code, IntelliJ, etc. - * - * Prerequisites: user must be sudoer. If password is required for user to execute sudo, then also parameter userPassword must be provided - * - * @param workplaceType - * @param userPassword only needs to be provided if user cannot sudo without password - */ -fun Prov.provisionWorkplace( - workplaceType: WorkplaceType = WorkplaceType.MINIMAL, - ssh: KeyPair? = null, - gpg: KeyPair? = null, - gitUserName: String? = null, - gitEmail: String? = null, - userPassword: Secret? = null -) = requireAll { - - userPassword?.also { makeUserSudoerWithNoSudoPasswordRequired(it) } - - if (!currentUserCanSudo()) { - throw Exception("Current user ${whoami()} cannot execute sudo without entering a password! This is necessary to execute provisionWorkplace") - } - - aptInstall("ssh gnupg curl git") - - provisionKeys(gpg, ssh) - provisionGit(gitUserName ?: whoami(), gitEmail, gpg?.let { gpgFingerprint(it.publicKey.plain()) }) - - installVirtualBoxGuestAdditions() - - aptPurge("remove-power-management xfce4-power-manager " + - "xfce4-power-manager-plugins xfce4-power-manager-data") - aptPurge("abiword gnumeric") - aptPurge("popularity-contest") - - configureNoSwappiness() - - if (workplaceType == WorkplaceType.OFFICE || workplaceType == WorkplaceType.IDE) { - aptInstall("seahorse") - aptInstall(BASH_UTILS) - aptInstall(OS_ANALYSIS) - aptInstall(ZIP_UTILS) - - aptInstall("firefox chromium-browser") - aptInstall("thunderbird libreoffice") - aptInstall("xclip") - - installZimWiki() - installGopass() - aptInstallFromPpa("nextcloud-devs", "client", "nextcloud-client") - - aptInstall("inkscape") - aptInstall("dia") - - aptInstall(SPELLCHECKING_DE) - - installRedshift() - configureRedshift() - } - - if (workplaceType == WorkplaceType.IDE) { - - aptInstall(JAVA_JDK) - - aptInstall(OPEN_VPM) - aptInstall(OPENCONNECT) - aptInstall(VPNC) - - installDocker() - - // IDEs - cmd("sudo snap install intellij-idea-community --classic") - installVSC("python", "clojure") - - installDevOps() - } - - ProvResult(true) // dummy -} - - -/** - * Provisions a workplace on a remote machine. - * Prerequisite: you have built the uberjar by ./gradlew uberJarLatest - * The remote host and remote user are specified by args parameters. - * The first argument specifies hostName or IP-Address of the remote machine, - * the second argument defines the user on the remote machine for whom the workplace is provisioned; - * You can invoke this method e.g. using the jar-file from the project root by: - * java -jar build/libs/provs-extensions-uber.jar org.domaindrivenarchitecture.provs.ubuntu.extensions.workplace.ProvisionWorkplaceKt provisionRemote - * You will be prompted for the password of the remote user. - * - * @param args host and userName of the remote machine as the first resp. second argument - */ -fun provisionRemote(args: Array) { - if (args.size != 2) { - println("Please specify host and user.") - exitProcess(1) - } - - val host = InetAddress.getByName(args[0]) - val userName = args[1] - val pwSecret = PromptSecretSource("Password for user $userName on $host").secret() - val pwFromSecret = Password(pwSecret.plain()) - - val config = getConfig() - Prov.newInstance(RemoteProcessor(host, userName, pwFromSecret)).provisionWorkplace( - config.type, - config.ssh?.keyPair(), - config.gpg?.keyPair(), - config.gitUserName, - config.gitEmail, - pwFromSecret - ) -} - - -/** - * Provisions a workplace on a remote machine by calling method provisionRemote. - * - * @ see #provisionRemote(args: Array) - * - * You can invoke this method e.g. using the jar-file from the project root by: - * java -jar build/libs/provs-ext-latest.jar workplace.WorkplaceKt main - * - * @param args host and userName of the remote machine as first resp. second argument - */ -fun main(args: Array) { - provisionRemote(args = args) -} \ No newline at end of file diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/Application.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/Application.kt index 2176f11..3d9b9da 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/Application.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/Application.kt @@ -1,15 +1,14 @@ package org.domaindrivenarchitecture.provs.workplace.application import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.extensions.workplace.provisionWorkplace +import org.domaindrivenarchitecture.provs.workplace.domain.provisionWorkplace import org.domaindrivenarchitecture.provs.workplace.domain.WorkplaceConfig /** * Use case for provisioning a workplace */ -fun Prov.provision(conf: WorkplaceConfig, password: Secret?) = def { +fun Prov.provision(conf: WorkplaceConfig) = def { with (conf) { - provisionWorkplace(type, ssh?.keyPair(), gpg?.keyPair(), gitUserName, gitEmail, password) + provisionWorkplace(type, ssh?.keyPair(), gpg?.keyPair(), gitUserName, gitEmail) } } diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/Cli.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/Cli.kt deleted file mode 100644 index 82a9069..0000000 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/Cli.kt +++ /dev/null @@ -1,83 +0,0 @@ -package org.domaindrivenarchitecture.provs.workplace.application - -import org.domaindrivenarchitecture.provs.core.Prov -import org.domaindrivenarchitecture.provs.core.Secret -import org.domaindrivenarchitecture.provs.core.local -import org.domaindrivenarchitecture.provs.core.remote -import org.domaindrivenarchitecture.provs.ubuntu.secret.secretSources.GopassSecretSource -import org.domaindrivenarchitecture.provs.ubuntu.secret.secretSources.PromptSecretSource -import org.domaindrivenarchitecture.provs.workplace.infrastructure.getConfig -import java.io.File - -/** - * Provisions according to the options either a meissa workplace, reposOnly or gopassOnly. - * Locally or on a remote machine. If remotely, the remote host and remote user are specified by args parameters. - */ -fun main(args: Array) { - val cliCommand = parseCli(args) - if (cliCommand.isValid()) { - provision(cliCommand) - } else { - println("Invalid command line options.\nPlease use option -h for help.") - System.exit(1) - } -} - -private fun provision(cliCommand: CliCommand) { - val filename = cliCommand.configFileName - - // TODO: improve exceptions - try { - val conf = getConfig(filename) - val password: Secret? = retrievePassword(cliCommand) - val prov: Prov = createProvInstance(cliCommand, password) - - prov.provision(conf, password) - } catch (e: IllegalArgumentException) { - println( - "Error: File\u001b[31m $filename \u001b[0m was not found.\n" + - "Pls copy file \u001B[31m WorkplaceConfigExample.yaml \u001B[0m to file \u001B[31m $filename \u001B[0m " + - "and change the content according to your needs.\n" - ) - - // provide example config - File("WorkplaceConfigExample.yaml").writeText("type: \"MINIMAL\"\n") - } -} - -private fun createProvInstance( - cliCommand: CliCommand, - password: Secret? -): Prov { - if (cliCommand.isValid()) { - if (cliCommand.isValidRemote()) { - val host = cliCommand.remoteHost!! - val remoteUser = cliCommand.userName!! - if (cliCommand.sshWithKey) { - return remote(host, remoteUser) - } else { - require( - password != null, - { "No password available for provisioning without ssh keys. Either specify provisioning by ssh-keys or provide password." }) - return remote(host, remoteUser, password) - } - } else { - return local() - } - } else { - throw RuntimeException("Invalid cliCommand") - } -} - -private fun retrievePassword(cliCommand: CliCommand): Secret? { - var password: Secret? = null - if (cliCommand.isValidRemote()) { - if (cliCommand.sshWithPasswordPrompt) { - password = - PromptSecretSource("Password for user ${cliCommand.userName!!} on ${cliCommand.remoteHost!!}").secret() - } else if (cliCommand.sshWithGopassPath != null) { - password = GopassSecretSource(cliCommand.sshWithGopassPath).secret() - } - } - return password -} \ No newline at end of file diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/CliCommand.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/CliCommand.kt deleted file mode 100644 index 1999670..0000000 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/CliCommand.kt +++ /dev/null @@ -1,83 +0,0 @@ -package org.domaindrivenarchitecture.provs.workplace.application - -import kotlinx.cli.ArgParser -import kotlinx.cli.ArgType -import kotlinx.cli.default -import kotlinx.cli.optional - -class CliCommand( - val remoteHost: String?, - val localHost: Boolean?, - val userName: String?, - val sshWithGopassPath: String?, - val sshWithPasswordPrompt: Boolean, - val sshWithKey: Boolean, - _configFileName: String? -) { - val configFileName: String - - init { - configFileName = _configFileName ?: "WorkplaceConfig.yaml" - } - - fun isValidLocalhost(): Boolean { - return (localHost ?: false) && remoteHost == null && userName == null && sshWithGopassPath == null && - !sshWithPasswordPrompt && !sshWithKey - } - - fun hasValidPasswordOption(): Boolean { - return (sshWithGopassPath != null) xor sshWithPasswordPrompt xor sshWithKey - } - - fun isValidRemote(): Boolean { - return remoteHost != null && userName != null && hasValidPasswordOption() - } - - fun isValid(): Boolean { - return (isValidLocalhost() || isValidRemote()) - } -} - -fun parseCli(args: Array): CliCommand { - val parser = ArgParser("java -jar provs.jar") - - val remoteHost by parser.option( - ArgType.String, shortName = - "r", description = "provision to remote host - either localHost or remoteHost must be specified" - ) - val localHost by parser.option( - ArgType.Boolean, shortName = - "l", description = "provision to local machine - either localHost or remoteHost must be specified" - ) - val configFileName by parser.option( - ArgType.String, - shortName = "c", - description = "the config file name to apply" - ).default("WorkplaceConfig.yaml") - val userName by parser.option( - ArgType.String, - shortName = "u", - description = "user for remote provisioning." - ) - val sshWithGopassPath by parser.option( - ArgType.String, - shortName = "p", - description = "password stored at gopass path" - ) - val sshWithPasswordPrompt by parser.option( - ArgType.Boolean, - shortName = "i", - description = "prompt for password interactive" - ).default(false) - val sshWithKey by parser.option( - ArgType.Boolean, - shortName = "k", - description = "provision over ssh using user & ssh key" - ).default(false) - parser.parse(args) - val cliCommand = - CliCommand( - remoteHost, localHost, userName, sshWithGopassPath, sshWithPasswordPrompt, sshWithKey, configFileName - ) - return cliCommand -} diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/CliWorkplace.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/CliWorkplace.kt new file mode 100644 index 0000000..f772067 --- /dev/null +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/CliWorkplace.kt @@ -0,0 +1,45 @@ +package org.domaindrivenarchitecture.provs.workplace.application + +import org.domaindrivenarchitecture.provs.core.cli.createProvInstance +import org.domaindrivenarchitecture.provs.workplace.application.WorkplaceCliCommand.Companion.parseWorkplaceArguments +import org.domaindrivenarchitecture.provs.workplace.infrastructure.getConfig +import java.io.File +import kotlin.system.exitProcess + + +/** + * Provisions according to the options either a meissa workplace, reposOnly or gopassOnly. + * Locally or on a remote machine. If remotely, the remote host and remote user are specified by args parameters. + */ +fun main(args: Array) { + + val cmd = parseWorkplaceArguments("java -jar provs.jar", args) + if (!cmd.isValid()) { + println("Arguments are not valid, pls try -h for help.") + exitProcess(1) + } + + provisionWorkplace(cmd) +} + + +private fun provisionWorkplace(cliCommand: WorkplaceCliCommand) { + val filename = cliCommand.configFile + + try { + val conf = getConfig(filename) + + val prov = createProvInstance(cliCommand.target) + prov.provision(conf) + + } catch (e: IllegalArgumentException) { + println( + "Error: File\u001b[31m $filename \u001b[0m was not found.\n" + + "Pls copy file \u001B[31m WorkplaceConfigExample.yaml \u001B[0m to file \u001B[31m $filename \u001B[0m " + + "and change the content according to your needs.\n" + ) + + // provide example config + File("WorkplaceConfigExample.yaml").writeText("type: \"MINIMAL\"\n") + } +} diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/CliWorkplaceCommand.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/CliWorkplaceCommand.kt new file mode 100644 index 0000000..e4def42 --- /dev/null +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/CliWorkplaceCommand.kt @@ -0,0 +1,33 @@ +package org.domaindrivenarchitecture.provs.workplace.application + +import org.domaindrivenarchitecture.provs.core.cli.TargetCliCommand + + +class WorkplaceCliCommand(val configFile: String, val target: TargetCliCommand) { + companion object { + fun parseWorkplaceArguments( + programName: String = "java -jar provs.jar", + args: Array + ): WorkplaceCliCommand { + val parser = CliWorkplaceParser(programName) + parser.parse(args) + + return WorkplaceCliCommand( + parser.configFileName ?: "WorkplaceConfig.yaml", + TargetCliCommand( + parser.localHost, + parser.remoteHost, + parser.userName, + parser.sshWithPasswordPrompt, + parser.sshWithGopassPath, + parser.sshWithKey + ) + ) + } + } + + fun isValid(): Boolean { + return target.isValid() + } +} + diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/CliWorkplaceParser.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/CliWorkplaceParser.kt new file mode 100644 index 0000000..893e25f --- /dev/null +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/application/CliWorkplaceParser.kt @@ -0,0 +1,13 @@ +package org.domaindrivenarchitecture.provs.workplace.application + +import kotlinx.cli.ArgType +import kotlinx.cli.optional +import org.domaindrivenarchitecture.provs.core.cli.CliTargetParser + +class CliWorkplaceParser(name: String) : CliTargetParser(name) { + val configFileName by argument( + ArgType.String, + "configFilename", + "the filename containing the yaml config for the workplace" + ).optional() +} \ No newline at end of file diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/domain/ProvisionWorkplace.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/domain/ProvisionWorkplace.kt new file mode 100644 index 0000000..cffe877 --- /dev/null +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/domain/ProvisionWorkplace.kt @@ -0,0 +1,94 @@ +package org.domaindrivenarchitecture.provs.workplace.domain + +import org.domaindrivenarchitecture.provs.core.Prov +import org.domaindrivenarchitecture.provs.core.ProvResult +import org.domaindrivenarchitecture.provs.ubuntu.git.provisionGit +import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall +import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstallFromPpa +import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptPurge +import org.domaindrivenarchitecture.provs.ubuntu.keys.KeyPair +import org.domaindrivenarchitecture.provs.ubuntu.keys.base.gpgFingerprint +import org.domaindrivenarchitecture.provs.ubuntu.keys.provisionKeys +import org.domaindrivenarchitecture.provs.ubuntu.user.base.currentUserCanSudo +import org.domaindrivenarchitecture.provs.ubuntu.user.base.whoami +import org.domaindrivenarchitecture.provs.workplace.infrastructure.* + + +/** + * Provisions software and configurations for a personal workplace. + * Offers the possibility to choose between different types. + * Type OFFICE installs office-related software like Thunderbird, LibreOffice, and much more. + * Type IDE provides additional software for a development environment, such as Visual Studio Code, IntelliJ, etc. + * + * Prerequisites: user must be able to sudo without entering the password + */ +fun Prov.provisionWorkplace( + workplaceType: WorkplaceType = WorkplaceType.MINIMAL, + ssh: KeyPair? = null, + gpg: KeyPair? = null, + gitUserName: String? = null, + gitEmail: String? = null +) = requireAll { + + if (!currentUserCanSudo()) { + throw Exception("Current user ${whoami()} cannot execute sudo without entering a password! This is necessary to execute provisionWorkplace") + } + + aptInstall("ssh gnupg curl git") + + provisionKeys(gpg, ssh) + provisionGit(gitUserName ?: whoami(), gitEmail, gpg?.let { gpgFingerprint(it.publicKey.plain()) }) + + installVirtualBoxGuestAdditions() + + aptPurge( + "remove-power-management xfce4-power-manager " + + "xfce4-power-manager-plugins xfce4-power-manager-data" + ) + aptPurge("abiword gnumeric") + aptPurge("popularity-contest") + + configureNoSwappiness() + + if (workplaceType == WorkplaceType.OFFICE || workplaceType == WorkplaceType.IDE) { + aptInstall("seahorse") + aptInstall(BASH_UTILS) + aptInstall(OS_ANALYSIS) + aptInstall(ZIP_UTILS) + + aptInstall("firefox chromium-browser") + aptInstall("thunderbird libreoffice") + aptInstall("xclip") + + installZimWiki() + installGopass() + aptInstallFromPpa("nextcloud-devs", "client", "nextcloud-client") + + aptInstall("inkscape") + aptInstall("dia") + + aptInstall(SPELLCHECKING_DE) + + installRedshift() + configureRedshift() + } + + if (workplaceType == WorkplaceType.IDE) { + + aptInstall(JAVA_JDK) + + aptInstall(OPEN_VPM) + aptInstall(OPENCONNECT) + aptInstall(VPNC) + + installDocker() + + // IDEs + cmd("sudo snap install intellij-idea-community --classic") + installVSC("python", "clojure") + + installDevOps() + } + + ProvResult(true) // dummy +} diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/Docker.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/Docker.kt similarity index 82% rename from src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/Docker.kt rename to src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/Docker.kt index 1892f4f..9bb592a 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/Docker.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/Docker.kt @@ -1,4 +1,4 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base +package org.domaindrivenarchitecture.provs.workplace.infrastructure import org.domaindrivenarchitecture.provs.core.Prov import org.domaindrivenarchitecture.provs.ubuntu.install.base.aptInstall diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/Fakturama.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/Fakturama.kt similarity index 91% rename from src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/Fakturama.kt rename to src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/Fakturama.kt index 06a9440..d8461a0 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/Fakturama.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/Fakturama.kt @@ -1,4 +1,4 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base +package org.domaindrivenarchitecture.provs.workplace.infrastructure import org.domaindrivenarchitecture.provs.core.Prov import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDir diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/Gopass.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/Gopass.kt index b20edf5..4f454d5 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/Gopass.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/Gopass.kt @@ -1,4 +1,4 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base +package org.domaindrivenarchitecture.provs.workplace.infrastructure import org.domaindrivenarchitecture.provs.core.Prov import org.domaindrivenarchitecture.provs.core.ProvResult diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassBridge.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/GopassBridge.kt similarity index 98% rename from src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassBridge.kt rename to src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/GopassBridge.kt index ad63092..042de71 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassBridge.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/GopassBridge.kt @@ -1,4 +1,4 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base +package org.domaindrivenarchitecture.provs.workplace.infrastructure import org.domaindrivenarchitecture.provs.core.Prov import org.domaindrivenarchitecture.provs.core.ProvResult diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/NoSwappiness.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/NoSwappiness.kt similarity index 81% rename from src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/NoSwappiness.kt rename to src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/NoSwappiness.kt index ba63836..0207cf4 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/NoSwappiness.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/NoSwappiness.kt @@ -1,4 +1,4 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base +package org.domaindrivenarchitecture.provs.workplace.infrastructure import org.domaindrivenarchitecture.provs.core.Prov import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.addTextToFile diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/PackageBundles.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/PackageBundles.kt similarity index 88% rename from src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/PackageBundles.kt rename to src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/PackageBundles.kt index 2d9e984..0201304 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/PackageBundles.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/PackageBundles.kt @@ -1,4 +1,4 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base +package org.domaindrivenarchitecture.provs.workplace.infrastructure val OS_ANALYSIS = "lsof strace ncdu iptraf htop iotop iftop" diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/Redshift.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/Redshift.kt similarity index 91% rename from src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/Redshift.kt rename to src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/Redshift.kt index 8541da4..67ea7d4 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/Redshift.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/Redshift.kt @@ -1,4 +1,4 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base +package org.domaindrivenarchitecture.provs.workplace.infrastructure import org.domaindrivenarchitecture.provs.core.Prov import org.domaindrivenarchitecture.provs.ubuntu.filesystem.base.createDir diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/VSCode.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/VSCode.kt similarity index 97% rename from src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/VSCode.kt rename to src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/VSCode.kt index 752b4c6..ef5e69e 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/VSCode.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/VSCode.kt @@ -1,4 +1,4 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base +package org.domaindrivenarchitecture.provs.workplace.infrastructure import org.domaindrivenarchitecture.provs.core.Prov import org.domaindrivenarchitecture.provs.core.ProvResult diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/VirtualBoxGuest.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/VirtualBoxGuest.kt similarity index 92% rename from src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/VirtualBoxGuest.kt rename to src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/VirtualBoxGuest.kt index 45763d6..b8bc39f 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/VirtualBoxGuest.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/VirtualBoxGuest.kt @@ -1,4 +1,4 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base +package org.domaindrivenarchitecture.provs.workplace.infrastructure import org.domaindrivenarchitecture.provs.core.Prov import org.domaindrivenarchitecture.provs.core.ProvResult diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/Zim.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/Zim.kt similarity index 89% rename from src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/Zim.kt rename to src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/Zim.kt index 1c4295a..caad15f 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/Zim.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/workplace/infrastructure/Zim.kt @@ -1,4 +1,4 @@ -package org.domaindrivenarchitecture.provs.extensions.workplace.base +package org.domaindrivenarchitecture.provs.workplace.infrastructure import org.domaindrivenarchitecture.provs.core.Prov import org.domaindrivenarchitecture.provs.core.ProvResult diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/core/cli/CliCommandKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/core/cli/CliCommandKtTest.kt index 0a964f2..f521b47 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/core/cli/CliCommandKtTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/core/cli/CliCommandKtTest.kt @@ -1,61 +1,75 @@ -//package org.domaindrivenarchitecture.provs.core.cli -// -//import io.mockk.every -//import io.mockk.mockkStatic -//import io.mockk.verify -//import org.domaindrivenarchitecture.provs.core.Prov -//import org.domaindrivenarchitecture.provs.core.Secret -//import org.domaindrivenarchitecture.provs.core.local -//import org.domaindrivenarchitecture.provs.core.processors.PrintOnlyProcessor -//import org.domaindrivenarchitecture.provs.core.remote -//import org.junit.jupiter.api.Test -// -//internal class CliCommandKtTest { -// -// @Test -// fun createProvInstance_local() { -// mockkStatic(::local) -// -// // given -// val cliCommand = CliCommand(true, null, null, false, null, false) -// -// // when -// createProvInstance(cliCommand) -// -// // then -// verify { local() } -// } -// -// @Test -// fun createProvInstance_remote_with_sshKey() { -// mockkStatic(::remote) -// every { remote(any(), any(), any(), any()) } returns Prov.newInstance(PrintOnlyProcessor()) -// -// // given -// val cliCommand = CliCommand(false, "host123", "user123", false, null, true) -// -// // when -// createProvInstance(cliCommand) -// -// // then -// verify { remote("host123", "user123", null, any()) } -// } -// -// @Test -// fun createProvInstance_remote_with_interactive_password_retrieval() { -// mockkStatic(::remote) -// every { remote(any(), any(), any(), any()) } returns Prov.newInstance(PrintOnlyProcessor()) -// -// mockkStatic(::retrievePassword) -// every { retrievePassword(any()) } returns Secret("sec") -// -// // given -// val cliCommand = CliCommand(false, "host123", "user123", true, null, false) -// -// // when -// createProvInstance(cliCommand) -// -// // then -// verify { remote("host123", "user123", Secret("sec"), any()) } -// } -//} \ No newline at end of file +package org.domaindrivenarchitecture.provs.core.cli + +import io.mockk.every +import io.mockk.mockkStatic +import io.mockk.unmockkStatic +import io.mockk.verify +import org.domaindrivenarchitecture.provs.core.Prov +import org.domaindrivenarchitecture.provs.core.Secret +import org.domaindrivenarchitecture.provs.core.local +import org.domaindrivenarchitecture.provs.core.processors.PrintOnlyProcessor +import org.domaindrivenarchitecture.provs.core.remote +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.Test + +internal class CliTargetCommandKtTest { + + companion object { + @BeforeAll + @JvmStatic + internal fun beforeAll() { + mockkStatic(::local) + mockkStatic(::remote) + every { remote(any(), any(), any(), any()) } returns Prov.newInstance(PrintOnlyProcessor()) + + mockkStatic(::retrievePassword) + every { retrievePassword(any()) } returns Secret("sec") + } + + @AfterAll + @JvmStatic + internal fun afterAll() { + unmockkStatic(::local) + unmockkStatic(::remote) + unmockkStatic(::retrievePassword) + } + } + + + @Test + fun createProvInstance_local() { + // given + val cliCommand = TargetCliCommand(true, null, null, false, null, false) + + // when + createProvInstance(cliCommand) + + // then + verify { local() } + } + + @Test + fun createProvInstance_remote_with_sshKey() { + // given + val cliCommand = TargetCliCommand(false, "host123", "user123", false, null, true) + + // when + createProvInstance(cliCommand) + + // then + verify { remote("host123", "user123", null, any()) } + } + + @Test + fun createProvInstance_remote_with_interactive_password_retrieval() { + // given + val cliCommand = TargetCliCommand(false, "host123", "user123", true, null, false) + + // when + createProvInstance(cliCommand) + + // then + verify { remote("host123", "user123", Secret("sec"), any()) } + } +} \ No newline at end of file diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/ProvisionWorkplaceKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/ProvisionWorkplaceKtTest.kt index d300ac1..0fb7db7 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/ProvisionWorkplaceKtTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/ProvisionWorkplaceKtTest.kt @@ -1,12 +1,12 @@ package org.domaindrivenarchitecture.provs.extensions.workplace -import org.domaindrivenarchitecture.provs.core.Password -import org.domaindrivenarchitecture.provs.workplace.domain.WorkplaceType -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test import org.domaindrivenarchitecture.provs.test.defaultTestContainer import org.domaindrivenarchitecture.provs.test.tags.ContainerTest +import org.domaindrivenarchitecture.provs.workplace.domain.WorkplaceType +import org.domaindrivenarchitecture.provs.workplace.domain.provisionWorkplace import org.domaindrivenarchitecture.provs.workplace.infrastructure.getConfig +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test internal class ProvisionWorkplaceKtTest { @@ -21,8 +21,7 @@ internal class ProvisionWorkplaceKtTest { val res = a.provisionWorkplace( WorkplaceType.MINIMAL, gitUserName = "testuser", - gitEmail = "testuser@test.org", - userPassword = Password("testuser") + gitEmail = "testuser@test.org" ) // then diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/FakturamaKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/FakturamaKtTest.kt index b2ce77a..43ae296 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/FakturamaKtTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/FakturamaKtTest.kt @@ -2,6 +2,7 @@ package org.domaindrivenarchitecture.provs.extensions.workplace.base import org.domaindrivenarchitecture.provs.test.defaultTestContainer import org.domaindrivenarchitecture.provs.test.tags.ContainerTest +import org.domaindrivenarchitecture.provs.workplace.infrastructure.installFakturama import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassBridgeKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassBridgeKtTest.kt index 78065e3..53eb597 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassBridgeKtTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassBridgeKtTest.kt @@ -17,6 +17,10 @@ import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test import org.domaindrivenarchitecture.provs.extensions.test_keys.privateGPGSnakeoilKey import org.domaindrivenarchitecture.provs.extensions.test_keys.publicGPGSnakeoilKey +import org.domaindrivenarchitecture.provs.workplace.infrastructure.configureGopassBridgeJsonApi +import org.domaindrivenarchitecture.provs.workplace.infrastructure.downloadGopassBridge +import org.domaindrivenarchitecture.provs.workplace.infrastructure.installGopass +import org.domaindrivenarchitecture.provs.workplace.infrastructure.installGopassBridgeJsonApi internal class GopassBridgeKtTest { diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassKtTest.kt index 98880b9..3a94164 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassKtTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/GopassKtTest.kt @@ -15,6 +15,7 @@ import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.domaindrivenarchitecture.provs.extensions.test_keys.privateGPGSnakeoilKey import org.domaindrivenarchitecture.provs.extensions.test_keys.publicGPGSnakeoilKey +import org.domaindrivenarchitecture.provs.workplace.infrastructure.* internal class GopassKtTest { diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/VSCodeKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/VSCodeKtTest.kt index 8e22383..aada005 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/VSCodeKtTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/extensions/workplace/base/VSCodeKtTest.kt @@ -5,6 +5,7 @@ import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.domaindrivenarchitecture.provs.test.defaultTestContainer +import org.domaindrivenarchitecture.provs.workplace.infrastructure.installVSC internal class VSCodeKtTest { diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/workplace/application/CliWorkplaceKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/workplace/application/CliWorkplaceKtTest.kt new file mode 100644 index 0000000..900507a --- /dev/null +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/workplace/application/CliWorkplaceKtTest.kt @@ -0,0 +1,74 @@ +package org.domaindrivenarchitecture.provs.workplace.application + +import io.mockk.every +import io.mockk.mockkStatic +import io.mockk.unmockkStatic +import io.mockk.verify +import org.domaindrivenarchitecture.provs.core.* +import org.domaindrivenarchitecture.provs.core.cli.retrievePassword +import org.domaindrivenarchitecture.provs.core.processors.PrintOnlyProcessor +import org.domaindrivenarchitecture.provs.workplace.domain.WorkplaceConfig +import org.domaindrivenarchitecture.provs.workplace.domain.WorkplaceType +import org.domaindrivenarchitecture.provs.workplace.domain.provisionWorkplace +import org.domaindrivenarchitecture.provs.workplace.infrastructure.getConfig +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.Test + +internal class CliWorkplaceKtTest { + + companion object { + + val printOnlyProv = Prov.newInstance(PrintOnlyProcessor()) + val testConfig = WorkplaceConfig(WorkplaceType.MINIMAL, gitUserName = "gittestuser", gitEmail = "git@test.mail") + + @BeforeAll + @JvmStatic + internal fun beforeAll() { + mockkStatic(::local) + every { local() } returns printOnlyProv + + mockkStatic(::remote) + every { remote(any(), any(), any(), any()) } returns printOnlyProv + + mockkStatic(::getConfig) + every { getConfig("testconfig.yaml") } returns testConfig + + mockkStatic(Prov::provisionWorkplace) + every { any().provisionWorkplace(any(), any(), any(), any(), any()) } returns ProvResult(true, cmd = "mocked command") + + mockkStatic(::retrievePassword) + every { retrievePassword(any()) } returns Secret("sec") + } + + @AfterAll + @JvmStatic + internal fun afterAll() { + unmockkStatic(::local) + unmockkStatic(::remote) + unmockkStatic(::getConfig) + unmockkStatic(Prov::provisionWorkplace) + unmockkStatic(::retrievePassword) + } + } + + @Test + fun provision_workplace_locally() { + // when + main(arrayOf("-l", "testconfig.yaml")) + + // then + verify { any().provisionWorkplace(WorkplaceType.MINIMAL, null, null, testConfig.gitUserName, testConfig.gitEmail) } + } + + @Test + fun provision_workplace_remotely() { + + // when + main(arrayOf("-i", "-r", "host123", "-u", "user123", "testconfig.yaml")) + + // then + verify { remote("host123", "user123", Secret("sec"), any()) } + verify { any().provisionWorkplace(WorkplaceType.MINIMAL, null, null, testConfig.gitUserName, testConfig.gitEmail) } + } +} \ No newline at end of file