add prov installation for desktop
This commit is contained in:
parent
89c0fba39e
commit
83d590f1c9
12 changed files with 150 additions and 80 deletions
11
.run/provs-desktop.run.xml
Normal file
11
.run/provs-desktop.run.xml
Normal 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>
|
|
@ -2,7 +2,7 @@
|
||||||
<configuration default="false" name="provs-server statistics.prod" type="JetRunConfigurationType">
|
<configuration default="false" name="provs-server statistics.prod" type="JetRunConfigurationType">
|
||||||
<option name="MAIN_CLASS_NAME" value="org.domaindrivenarchitecture.provs.server.application.ApplicationKt" />
|
<option name="MAIN_CLASS_NAME" value="org.domaindrivenarchitecture.provs.server.application.ApplicationKt" />
|
||||||
<module name="provs.main" />
|
<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" />
|
<shortenClasspath name="NONE" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Make" enabled="true" />
|
<option name="Make" enabled="true" />
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
package org.domaindrivenarchitecture.provs.desktop.application
|
package org.domaindrivenarchitecture.provs.desktop.application
|
||||||
|
|
||||||
import kotlinx.cli.ArgType
|
import kotlinx.cli.ArgType
|
||||||
|
import kotlinx.cli.default
|
||||||
|
import kotlinx.cli.multiple
|
||||||
import org.domaindrivenarchitecture.provs.configuration.application.CliTargetParser
|
import org.domaindrivenarchitecture.provs.configuration.application.CliTargetParser
|
||||||
import org.domaindrivenarchitecture.provs.configuration.domain.ConfigFileName
|
import org.domaindrivenarchitecture.provs.configuration.domain.ConfigFileName
|
||||||
import org.domaindrivenarchitecture.provs.configuration.domain.TargetCliCommand
|
import org.domaindrivenarchitecture.provs.configuration.domain.TargetCliCommand
|
||||||
|
import org.domaindrivenarchitecture.provs.desktop.domain.Scope
|
||||||
|
|
||||||
|
|
||||||
open class CliArgumentsParser(name: String) : CliTargetParser(name) {
|
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"
|
"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 {
|
fun parseWorkplaceArguments(args: Array<String>): DesktopCliCommand {
|
||||||
super.parse(args)
|
super.parse(args)
|
||||||
|
|
||||||
return DesktopCliCommand(
|
return DesktopCliCommand(
|
||||||
ConfigFileName(configFileName),
|
ConfigFileName(configFileName),
|
||||||
|
scopes,
|
||||||
TargetCliCommand(
|
TargetCliCommand(
|
||||||
localHost,
|
localHost,
|
||||||
remoteHost,
|
remoteHost,
|
||||||
|
|
|
@ -2,12 +2,20 @@ package org.domaindrivenarchitecture.provs.desktop.application
|
||||||
|
|
||||||
import org.domaindrivenarchitecture.provs.configuration.domain.ConfigFileName
|
import org.domaindrivenarchitecture.provs.configuration.domain.ConfigFileName
|
||||||
import org.domaindrivenarchitecture.provs.configuration.domain.TargetCliCommand
|
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 {
|
fun isValid(): Boolean {
|
||||||
return configFile.fileName.isNotEmpty() && target.isValid()
|
return configFile.fileName.isNotEmpty() && target.isValid()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun haScope(): Boolean {
|
||||||
|
return scopes.isNotEmpty()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.keys.provisionKeys
|
||||||
import org.domaindrivenarchitecture.provs.framework.ubuntu.user.base.currentUserCanSudo
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.user.base.currentUserCanSudo
|
||||||
import org.domaindrivenarchitecture.provs.framework.ubuntu.user.base.whoami
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.user.base.whoami
|
||||||
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.web.base.downloadFromURL
|
||||||
|
|
||||||
fun provisionDesktop(prov: Prov, cmd: DesktopCliCommand) {
|
fun provisionDesktop(prov: Prov, cmd: DesktopCliCommand) {
|
||||||
// retrieve config
|
// retrieve config
|
||||||
val conf = getConfig(cmd.configFile.fileName)
|
val conf = getConfig(cmd.configFile.fileName)
|
||||||
with(conf) {
|
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,
|
ssh: KeyPair? = null,
|
||||||
gpg: KeyPair? = null,
|
gpg: KeyPair? = null,
|
||||||
gitUserName: String? = null,
|
gitUserName: String? = null,
|
||||||
gitEmail: String? = null
|
gitEmail: String? = null,
|
||||||
|
cmd: DesktopCliCommand
|
||||||
) = requireAll {
|
) = requireAll {
|
||||||
|
|
||||||
if (!currentUserCanSudo()) {
|
if (!currentUserCanSudo()) {
|
||||||
throw Exception("Current user ${whoami()} cannot execute sudo without entering a password! This is necessary to execute provisionWorkplace")
|
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(KEY_MANAGEMENT)
|
||||||
aptInstall(VERSION_MANAGEMENT)
|
aptInstall(VERSION_MANAGEMENT)
|
||||||
aptInstall(NETWORK_TOOLS)
|
aptInstall(NETWORK_TOOLS)
|
||||||
|
@ -108,6 +131,6 @@ fun Prov.provisionWorkplace(
|
||||||
|
|
||||||
installPython()
|
installPython()
|
||||||
}
|
}
|
||||||
|
ProvResult(true)
|
||||||
ProvResult(true) // dummy
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package org.domaindrivenarchitecture.provs.desktop.domain
|
||||||
|
|
||||||
|
enum class Scope {
|
||||||
|
PROVS
|
||||||
|
}
|
|
@ -13,12 +13,15 @@ import org.domaindrivenarchitecture.provs.server.infrastructure.k3s.getK3sConfig
|
||||||
fun Prov.provisionK3s(configFileName: ConfigFileName?) = task {
|
fun Prov.provisionK3s(configFileName: ConfigFileName?) = task {
|
||||||
val k3sConfig: K3sConfig = getK3sConfig(configFileName!!)
|
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()) {
|
if (k3sConfig.reprovision && testConfigExists()) {
|
||||||
deprovisionK3sInfra()
|
deprovisionK3sInfra()
|
||||||
}
|
}
|
||||||
provisionK3sInfra(tlsName = k3sConfig.fqdn, nodeIpv4 = k3sConfig.node.ipv4, nodeIpv6 = k3sConfig.node.ipv6,
|
provisionK3sInfra(
|
||||||
loopbackIpv4 = k3sConfig.loopback.ipv4, loopbackIpv6 = k3sConfig.loopback.ipv6)
|
tlsName = k3sConfig.fqdn, nodeIpv4 = k3sConfig.node.ipv4, nodeIpv6 = k3sConfig.node.ipv6,
|
||||||
|
loopbackIpv4 = k3sConfig.loopback.ipv4, loopbackIpv6 = k3sConfig.loopback.ipv6
|
||||||
|
)
|
||||||
|
|
||||||
provisionK3sCertManager(k3sConfig.letsencryptEndpoint)
|
provisionK3sCertManager(k3sConfig.letsencryptEndpoint)
|
||||||
provisionK3sApple(k3sConfig.fqdn, k3sConfig.letsencryptEndpoint)
|
provisionK3sApple(k3sConfig.fqdn, k3sConfig.letsencryptEndpoint)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 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.
|
* 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 {
|
nodeIpv6: String? = null) = task {
|
||||||
val isDualStack = nodeIpv6?.isNotEmpty() ?: false
|
val isDualStack = nodeIpv6 != null && loopbackIpv6 != null
|
||||||
if (!testConfigExists()) {
|
if (!testConfigExists()) {
|
||||||
createDirs(k3sAutomatedManifestsDir, sudo = true)
|
createDirs(k3sAutomatedManifestsDir, sudo = true)
|
||||||
createDirs(k3sManualManifestsDir, sudo = true)
|
createDirs(k3sManualManifestsDir, sudo = true)
|
||||||
var k3sConfigFileName = "config"
|
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)
|
"node_ipv4" to nodeIpv4, "tls_name" to tlsName)
|
||||||
if (isDualStack) {
|
if (isDualStack) {
|
||||||
k3sConfigFileName += ".dual.template.yaml"
|
k3sConfigFileName += ".dual.template.yaml"
|
||||||
k3sConfigMap = k3sConfigMap.plus("node_ipv6" to nodeIpv6!!)
|
k3sConfigMap = k3sConfigMap.plus("node_ipv6" to nodeIpv6!!)
|
||||||
|
.plus("loopback_ipv6" to loopbackIpv6!!)
|
||||||
} else {
|
} else {
|
||||||
k3sConfigFileName += ".ipv4.template.yaml"
|
k3sConfigFileName += ".ipv4.template.yaml"
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,16 +12,21 @@ fun Prov.testNetworkExists(): Boolean {
|
||||||
return fileExists(loopbackFile)
|
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(!testNetworkExists()) {
|
||||||
|
if(isDualStack) {
|
||||||
createFileFromResourceTemplate(
|
createFileFromResourceTemplate(
|
||||||
loopbackFile,
|
loopbackFile,
|
||||||
"99-loopback.yaml.template",
|
"99-loopback.yaml.template",
|
||||||
resourcePath,
|
resourcePath,
|
||||||
mapOf("loopback_ipv4" to loopbackIpv4, "loopback_ipv6" to loopbackIpv6),
|
mapOf("loopback_ipv4" to loopbackIpv4, "loopback_ipv6" to loopbackIpv6!!),
|
||||||
"644",
|
"644",
|
||||||
sudo = true
|
sudo = true
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
cmd("netplan apply", sudo = true)
|
cmd("netplan apply", sudo = true)
|
||||||
} else {
|
} else {
|
||||||
ProvResult(true)
|
ProvResult(true)
|
||||||
|
|
|
@ -40,7 +40,7 @@ internal class CliWorkplaceKtTest {
|
||||||
every { getConfig("testconfig.yaml") } returns testConfig
|
every { getConfig("testconfig.yaml") } returns testConfig
|
||||||
|
|
||||||
mockkStatic(Prov::provisionWorkplace)
|
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,
|
true,
|
||||||
cmd = "mocked command"
|
cmd = "mocked command"
|
||||||
)
|
)
|
||||||
|
@ -72,7 +72,8 @@ internal class CliWorkplaceKtTest {
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
testConfig.gitUserName,
|
testConfig.gitUserName,
|
||||||
testConfig.gitEmail
|
testConfig.gitEmail,
|
||||||
|
cmd
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +92,8 @@ internal class CliWorkplaceKtTest {
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
testConfig.gitUserName,
|
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."
|
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", ""))
|
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
|
@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."
|
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", ""))
|
assertEquals(expectedOutput, outContent.toString().replace("\r", "").replace("\n", ""))
|
||||||
|
|
||||||
verify(exactly = 0) { any<Prov>().provisionWorkplace(any()) }
|
verify(exactly = 0) { any<Prov>().provisionWorkplace(any(), cmd = cmd) }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,7 +21,8 @@ internal class ProvisionWorkplaceKtTest {
|
||||||
val res = a.provisionWorkplace(
|
val res = a.provisionWorkplace(
|
||||||
WorkplaceType.MINIMAL,
|
WorkplaceType.MINIMAL,
|
||||||
gitUserName = "testuser",
|
gitUserName = "testuser",
|
||||||
gitEmail = "testuser@test.org"
|
gitEmail = "testuser@test.org",
|
||||||
|
cmd = cmd
|
||||||
)
|
)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
|
@ -44,6 +45,7 @@ internal class ProvisionWorkplaceKtTest {
|
||||||
config.gpg?.keyPair(),
|
config.gpg?.keyPair(),
|
||||||
config.gitUserName,
|
config.gitUserName,
|
||||||
config.gitEmail,
|
config.gitEmail,
|
||||||
|
cmd,
|
||||||
)
|
)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
|
|
Loading…
Reference in a new issue