add prov installation for desktop

This commit is contained in:
jem 2022-02-03 21:11:36 +01:00
parent 89c0fba39e
commit 83d590f1c9
12 changed files with 150 additions and 80 deletions

View file

@ -0,0 +1,11 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="provs-desktop" type="JetRunConfigurationType">
<option name="MAIN_CLASS_NAME" value="org.domaindrivenarchitecture.provs.desktop.application.ApplicationKt" />
<module name="provs.main" />
<option name="PROGRAM_PARAMETERS" value="-s provs -l myIdeConfig.yaml" />
<shortenClasspath name="NONE" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View file

@ -2,7 +2,7 @@
<configuration default="false" name="provs-server statistics.prod" type="JetRunConfigurationType">
<option name="MAIN_CLASS_NAME" value="org.domaindrivenarchitecture.provs.server.application.ApplicationKt" />
<module name="provs.main" />
<option name="PROGRAM_PARAMETERS" value="k3s -r statistics.prod.meissa-gmbh.de -u root -k myServerKonfig.yaml" />
<option name="PROGRAM_PARAMETERS" value="k3s -r statistics.prod.meissa-gmbh.de -u root -k myK3sServerConfig.yaml" />
<shortenClasspath name="NONE" />
<method v="2">
<option name="Make" enabled="true" />

View file

@ -1,9 +1,12 @@
package org.domaindrivenarchitecture.provs.desktop.application
import kotlinx.cli.ArgType
import kotlinx.cli.default
import kotlinx.cli.multiple
import org.domaindrivenarchitecture.provs.configuration.application.CliTargetParser
import org.domaindrivenarchitecture.provs.configuration.domain.ConfigFileName
import org.domaindrivenarchitecture.provs.configuration.domain.TargetCliCommand
import org.domaindrivenarchitecture.provs.desktop.domain.Scope
open class CliArgumentsParser(name: String) : CliTargetParser(name) {
@ -14,12 +17,19 @@ open class CliArgumentsParser(name: String) : CliTargetParser(name) {
"the filename containing the yaml config for the desktop"
)
val scopes by option (
type = ArgType.Choice<Scope>(),
shortName = "s",
fullName = "scope",
description = "only provision component in scope."
).multiple()
fun parseWorkplaceArguments(args: Array<String>): DesktopCliCommand {
super.parse(args)
return DesktopCliCommand(
ConfigFileName(configFileName),
scopes,
TargetCliCommand(
localHost,
remoteHost,

View file

@ -2,12 +2,20 @@ package org.domaindrivenarchitecture.provs.desktop.application
import org.domaindrivenarchitecture.provs.configuration.domain.ConfigFileName
import org.domaindrivenarchitecture.provs.configuration.domain.TargetCliCommand
import org.domaindrivenarchitecture.provs.desktop.domain.Scope
class DesktopCliCommand(val configFile: ConfigFileName, val target: TargetCliCommand) {
class DesktopCliCommand(
val configFile: ConfigFileName,
val scopes: List<Scope>,
val target: TargetCliCommand, ) {
fun isValid(): Boolean {
return configFile.fileName.isNotEmpty() && target.isValid()
}
fun haScope(): Boolean {
return scopes.isNotEmpty()
}
}

View file

@ -14,12 +14,13 @@ import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.base.gpgFingerpr
import org.domaindrivenarchitecture.provs.framework.ubuntu.keys.provisionKeys
import org.domaindrivenarchitecture.provs.framework.ubuntu.user.base.currentUserCanSudo
import org.domaindrivenarchitecture.provs.framework.ubuntu.user.base.whoami
import org.domaindrivenarchitecture.provs.framework.ubuntu.web.base.downloadFromURL
fun provisionDesktop(prov: Prov, cmd: DesktopCliCommand) {
// retrieve config
val conf = getConfig(cmd.configFile.fileName)
with(conf) {
prov.provisionWorkplace(type, ssh?.keyPair(), gpg?.keyPair(), gitUserName, gitEmail)
prov.provisionWorkplace(type, ssh?.keyPair(), gpg?.keyPair(), gitUserName, gitEmail, cmd)
}
}
@ -36,13 +37,35 @@ fun Prov.provisionWorkplace(
ssh: KeyPair? = null,
gpg: KeyPair? = null,
gitUserName: String? = null,
gitEmail: String? = null
gitEmail: String? = null,
cmd: DesktopCliCommand
) = requireAll {
if (!currentUserCanSudo()) {
throw Exception("Current user ${whoami()} cannot execute sudo without entering a password! This is necessary to execute provisionWorkplace")
}
if (cmd.haScope()) {
if (cmd.scopes.contains(Scope.PROVS)) {
downloadFromURL(
url="https://gitlab.com/domaindrivenarchitecture/provs/-/jobs/2046149473/artifacts/file/build/libs/provs-server.jar",
filename = "provs-server.jar",
path = "/usr/local/bin/",
sha256sum = "cec1c8762ce310694bacef587ad26b3bb7b8482a8548330ccaf9c9d3eb052409",
sudo = true
)
downloadFromURL(
url="https://gitlab.com/domaindrivenarchitecture/provs/-/jobs/2046149473/artifacts/file/build/libs/provs-desktop.jar",
filename = "provs-desktop.jar",
path = "/usr/local/bin/",
sha256sum = "61bad1380809325aca95bfbcb7cf27928ee070ed886c5de7e300797961d1fa58",
sudo = true
)
cmd("chmod 755 /usr/local/bin/provs-server.jar" , sudo = true)
cmd("chmod 755 /usr/local/bin/provs-desktop.jar", sudo = true)
}
ProvResult(true)
} else {
aptInstall(KEY_MANAGEMENT)
aptInstall(VERSION_MANAGEMENT)
aptInstall(NETWORK_TOOLS)
@ -108,6 +131,6 @@ fun Prov.provisionWorkplace(
installPython()
}
ProvResult(true) // dummy
ProvResult(true)
}
}

View file

@ -0,0 +1,5 @@
package org.domaindrivenarchitecture.provs.desktop.domain
enum class Scope {
PROVS
}

View file

@ -13,12 +13,15 @@ import org.domaindrivenarchitecture.provs.server.infrastructure.k3s.getK3sConfig
fun Prov.provisionK3s(configFileName: ConfigFileName?) = task {
val k3sConfig: K3sConfig = getK3sConfig(configFileName!!)
provisionNetwork(loopbackIpv4 = k3sConfig.loopback.ipv4, loopbackIpv6 = k3sConfig.loopback.ipv6!!)
provisionNetwork(loopbackIpv4 = k3sConfig.loopback.ipv4, loopbackIpv6 = k3sConfig.loopback.ipv6)
if (k3sConfig.reprovision && testConfigExists()) {
deprovisionK3sInfra()
}
provisionK3sInfra(tlsName = k3sConfig.fqdn, nodeIpv4 = k3sConfig.node.ipv4, nodeIpv6 = k3sConfig.node.ipv6,
loopbackIpv4 = k3sConfig.loopback.ipv4, loopbackIpv6 = k3sConfig.loopback.ipv6)
provisionK3sInfra(
tlsName = k3sConfig.fqdn, nodeIpv4 = k3sConfig.node.ipv4, nodeIpv6 = k3sConfig.node.ipv6,
loopbackIpv4 = k3sConfig.loopback.ipv4, loopbackIpv6 = k3sConfig.loopback.ipv6
)
provisionK3sCertManager(k3sConfig.letsencryptEndpoint)
provisionK3sApple(k3sConfig.fqdn, k3sConfig.letsencryptEndpoint)
}

View file

@ -36,18 +36,19 @@ fun Prov.deprovisionK3sInfra() = task {
* If docker is true, then docker will be installed (may conflict if docker is already existing) and k3s will be installed with docker option.
* If tlsHost is specified, then tls (if configured) also applies to the specified host.
*/
fun Prov.provisionK3sInfra(tlsName: String, nodeIpv4: String, loopbackIpv4: String, loopbackIpv6: String,
fun Prov.provisionK3sInfra(tlsName: String, nodeIpv4: String, loopbackIpv4: String, loopbackIpv6: String?,
nodeIpv6: String? = null) = task {
val isDualStack = nodeIpv6?.isNotEmpty() ?: false
val isDualStack = nodeIpv6 != null && loopbackIpv6 != null
if (!testConfigExists()) {
createDirs(k3sAutomatedManifestsDir, sudo = true)
createDirs(k3sManualManifestsDir, sudo = true)
var k3sConfigFileName = "config"
var k3sConfigMap: Map<String, String> = mapOf("loopback_ipv4" to loopbackIpv4, "loopback_ipv6" to loopbackIpv6,
var k3sConfigMap: Map<String, String> = mapOf("loopback_ipv4" to loopbackIpv4,
"node_ipv4" to nodeIpv4, "tls_name" to tlsName)
if (isDualStack) {
k3sConfigFileName += ".dual.template.yaml"
k3sConfigMap = k3sConfigMap.plus("node_ipv6" to nodeIpv6!!)
.plus("loopback_ipv6" to loopbackIpv6!!)
} else {
k3sConfigFileName += ".ipv4.template.yaml"
}

View file

@ -12,16 +12,21 @@ fun Prov.testNetworkExists(): Boolean {
return fileExists(loopbackFile)
}
fun Prov.provisionNetwork(loopbackIpv4: String, loopbackIpv6: String) = task {
fun Prov.provisionNetwork(loopbackIpv4: String, loopbackIpv6: String?) = task {
val isDualStack = loopbackIpv6?.isNotEmpty() ?: false
if(!testNetworkExists()) {
if(isDualStack) {
createFileFromResourceTemplate(
loopbackFile,
"99-loopback.yaml.template",
resourcePath,
mapOf("loopback_ipv4" to loopbackIpv4, "loopback_ipv6" to loopbackIpv6),
mapOf("loopback_ipv4" to loopbackIpv4, "loopback_ipv6" to loopbackIpv6!!),
"644",
sudo = true
)
} else {
}
cmd("netplan apply", sudo = true)
} else {
ProvResult(true)

View file

@ -40,7 +40,7 @@ internal class CliWorkplaceKtTest {
every { getConfig("testconfig.yaml") } returns testConfig
mockkStatic(Prov::provisionWorkplace)
every { any<Prov>().provisionWorkplace(any(), any(), any(), any(), any()) } returns ProvResult(
every { any<Prov>().provisionWorkplace(any(), any(), any(), any(), any(), cmd) } returns ProvResult(
true,
cmd = "mocked command"
)
@ -72,7 +72,8 @@ internal class CliWorkplaceKtTest {
null,
null,
testConfig.gitUserName,
testConfig.gitEmail
testConfig.gitEmail,
cmd
)
}
}
@ -91,7 +92,8 @@ internal class CliWorkplaceKtTest {
null,
null,
testConfig.gitUserName,
testConfig.gitEmail
testConfig.gitEmail,
cmd
)
}
}
@ -119,7 +121,7 @@ internal class CliWorkplaceKtTest {
val expectedOutput = "Error: File\u001B[31m ConfigFileName(fileName=idontexist.yaml) \u001B[0m was not found.Pls copy file \u001B[31m WorkplaceConfigExample.yaml \u001B[0m to file \u001B[31m ConfigFileName(fileName=idontexist.yaml) \u001B[0m and change the content according to your needs."
assertEquals(expectedOutput, outContent.toString().replace("\r", "").replace("\n", ""))
verify(exactly = 0) { any<Prov>().provisionWorkplace(any()) }
verify(exactly = 0) { any<Prov>().provisionWorkplace(any(), cmd = cmd) }
}
@Test
@ -145,6 +147,6 @@ internal class CliWorkplaceKtTest {
val expectedOutput = "Error: File \"ConfigFileName(fileName=src/test/resources/InvalidWorkplaceConfig.yaml)\" has an invalid format and or invalid data."
assertEquals(expectedOutput, outContent.toString().replace("\r", "").replace("\n", ""))
verify(exactly = 0) { any<Prov>().provisionWorkplace(any()) }
verify(exactly = 0) { any<Prov>().provisionWorkplace(any(), cmd = cmd) }
}
}

View file

@ -21,7 +21,8 @@ internal class ProvisionWorkplaceKtTest {
val res = a.provisionWorkplace(
WorkplaceType.MINIMAL,
gitUserName = "testuser",
gitEmail = "testuser@test.org"
gitEmail = "testuser@test.org",
cmd = cmd
)
// then
@ -44,6 +45,7 @@ internal class ProvisionWorkplaceKtTest {
config.gpg?.keyPair(),
config.gitUserName,
config.gitEmail,
cmd,
)
// then