diff --git a/.run/provs-desktop.run.xml b/.run/provs-desktop.run.xml
new file mode 100644
index 0000000..824afd5
--- /dev/null
+++ b/.run/provs-desktop.run.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/provs-server statistics.prod.run.xml b/.run/provs-server statistics.prod.run.xml
index 4c49865..5dacf84 100644
--- a/.run/provs-server statistics.prod.run.xml
+++ b/.run/provs-server statistics.prod.run.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/Types.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/configuration/domain/Types.kt
similarity index 100%
rename from src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/Types.kt
rename to src/main/kotlin/org/domaindrivenarchitecture/provs/configuration/domain/Types.kt
diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/application/CliArgumentsParser.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/application/CliArgumentsParser.kt
index 9f04326..86e2800 100644
--- a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/application/CliArgumentsParser.kt
+++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/application/CliArgumentsParser.kt
@@ -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(),
+ shortName = "s",
+ fullName = "scope",
+ description = "only provision component in scope."
+ ).multiple()
fun parseWorkplaceArguments(args: Array): DesktopCliCommand {
super.parse(args)
return DesktopCliCommand(
ConfigFileName(configFileName),
+ scopes,
TargetCliCommand(
localHost,
remoteHost,
diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/CliWorkplaceCommand.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/CliWorkplaceCommand.kt
index f3d706f..b9fa504 100644
--- a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/CliWorkplaceCommand.kt
+++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/CliWorkplaceCommand.kt
@@ -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,
+ val target: TargetCliCommand, ) {
fun isValid(): Boolean {
return configFile.fileName.isNotEmpty() && target.isValid()
}
+
+ fun haScope(): Boolean {
+ return scopes.isNotEmpty()
+ }
}
diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopService.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopService.kt
index d408f26..4e9fc8a 100644
--- a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopService.kt
+++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopService.kt
@@ -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)
+ with(conf) {
+ prov.provisionWorkplace(type, ssh?.keyPair(), gpg?.keyPair(), gitUserName, gitEmail, cmd)
}
}
@@ -36,78 +37,100 @@ 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")
}
- aptInstall(KEY_MANAGEMENT)
- aptInstall(VERSION_MANAGEMENT)
- aptInstall(NETWORK_TOOLS)
+ 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)
- provisionKeys(gpg, ssh)
- provisionGit(gitUserName ?: whoami(), gitEmail, gpg?.let { gpgFingerprint(it.publicKey.plain()) })
+ provisionKeys(gpg, ssh)
+ provisionGit(gitUserName ?: whoami(), gitEmail, gpg?.let { gpgFingerprint(it.publicKey.plain()) })
- installVirtualBoxGuestAdditions()
+ installVirtualBoxGuestAdditions()
- aptPurge(
- "remove-power-management xfce4-power-manager " +
- "xfce4-power-manager-plugins xfce4-power-manager-data"
- )
- aptPurge("abiword gnumeric")
- aptPurge("popularity-contest")
+ aptPurge(
+ "remove-power-management xfce4-power-manager " +
+ "xfce4-power-manager-plugins xfce4-power-manager-data"
+ )
+ aptPurge("abiword gnumeric")
+ aptPurge("popularity-contest")
- configureNoSwappiness()
+ configureNoSwappiness()
- configureBash()
+ configureBash()
- if (workplaceType == WorkplaceType.OFFICE || workplaceType == WorkplaceType.IDE) {
- aptInstall(KEY_MANAGEMENT_GUI)
- aptInstall(BASH_UTILS)
- aptInstall(OS_ANALYSIS)
- aptInstall(ZIP_UTILS)
- aptInstall(PASSWORD_TOOLS)
+ if (workplaceType == WorkplaceType.OFFICE || workplaceType == WorkplaceType.IDE) {
+ aptInstall(KEY_MANAGEMENT_GUI)
+ aptInstall(BASH_UTILS)
+ aptInstall(OS_ANALYSIS)
+ aptInstall(ZIP_UTILS)
+ aptInstall(PASSWORD_TOOLS)
- aptInstall(BROWSER)
- aptInstall(EMAIL_CLIENT)
- aptInstall(OFFICE_SUITE)
- aptInstall(CLIP_TOOLS)
+ aptInstall(BROWSER)
+ aptInstall(EMAIL_CLIENT)
+ aptInstall(OFFICE_SUITE)
+ aptInstall(CLIP_TOOLS)
- installZimWiki()
- installGopass()
- aptInstallFromPpa("nextcloud-devs", "client", "nextcloud-client")
+ installZimWiki()
+ installGopass()
+ aptInstallFromPpa("nextcloud-devs", "client", "nextcloud-client")
- optional {
- aptInstall(DRAWING_TOOLS)
- }
+ optional {
+ aptInstall(DRAWING_TOOLS)
+ }
- aptInstall(SPELLCHECKING_DE)
+ aptInstall(SPELLCHECKING_DE)
- installRedshift()
- configureRedshift()
- }
+ installRedshift()
+ configureRedshift()
+ }
- if (workplaceType == WorkplaceType.IDE) {
+ if (workplaceType == WorkplaceType.IDE) {
- aptInstall(JAVA_JDK)
+ aptInstall(JAVA_JDK)
- aptInstall(OPEN_VPM)
- aptInstall(OPENCONNECT)
- aptInstall(VPNC)
+ aptInstall(OPEN_VPM)
+ aptInstall(OPENCONNECT)
+ aptInstall(VPNC)
- installDocker()
+ installDocker()
- // IDEs
- installVSC("python", "clojure")
- aptInstall(CLOJURE_TOOLS)
- installIntelliJ()
+ // IDEs
+ installVSC("python", "clojure")
+ aptInstall(CLOJURE_TOOLS)
+ installIntelliJ()
- installDevOps()
+ installDevOps()
- installPython()
+ installPython()
+ }
+ ProvResult(true)
}
-
- ProvResult(true) // dummy
}
diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/Scope.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/Scope.kt
new file mode 100644
index 0000000..2f1535f
--- /dev/null
+++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/Scope.kt
@@ -0,0 +1,5 @@
+package org.domaindrivenarchitecture.provs.desktop.domain
+
+enum class Scope {
+ PROVS
+}
diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/K3sService.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/K3sService.kt
index f9de730..89c582e 100644
--- a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/K3sService.kt
+++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/K3sService.kt
@@ -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)
}
diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/K3s.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/K3s.kt
index 03a1317..828171d 100644
--- a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/K3s.kt
+++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/K3s.kt
@@ -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 = mapOf("loopback_ipv4" to loopbackIpv4, "loopback_ipv6" to loopbackIpv6,
+ var k3sConfigMap: Map = 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"
}
diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/network.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/network.kt
index e685dc3..1d3ecc6 100644
--- a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/network.kt
+++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/network.kt
@@ -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()) {
- createFileFromResourceTemplate(
- loopbackFile,
- "99-loopback.yaml.template",
- resourcePath,
- mapOf("loopback_ipv4" to loopbackIpv4, "loopback_ipv6" to loopbackIpv6),
- "644",
- sudo = true
- )
+ if(isDualStack) {
+ createFileFromResourceTemplate(
+ loopbackFile,
+ "99-loopback.yaml.template",
+ resourcePath,
+ mapOf("loopback_ipv4" to loopbackIpv4, "loopback_ipv6" to loopbackIpv6!!),
+ "644",
+ sudo = true
+ )
+ } else {
+
+ }
cmd("netplan apply", sudo = true)
} else {
ProvResult(true)
diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/application/CliWorkplaceKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/application/CliWorkplaceKtTest.kt
index 536e8b3..cc7e623 100644
--- a/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/application/CliWorkplaceKtTest.kt
+++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/application/CliWorkplaceKtTest.kt
@@ -40,7 +40,7 @@ internal class CliWorkplaceKtTest {
every { getConfig("testconfig.yaml") } returns testConfig
mockkStatic(Prov::provisionWorkplace)
- every { any().provisionWorkplace(any(), any(), any(), any(), any()) } returns ProvResult(
+ every { any().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().provisionWorkplace(any()) }
+ verify(exactly = 0) { any().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().provisionWorkplace(any()) }
+ verify(exactly = 0) { any().provisionWorkplace(any(), cmd = cmd) }
}
}
\ No newline at end of file
diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/extensions/workplace/ProvisionWorkplaceKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/extensions/workplace/ProvisionWorkplaceKtTest.kt
index a00187d..3bce6d0 100644
--- a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/extensions/workplace/ProvisionWorkplaceKtTest.kt
+++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/extensions/workplace/ProvisionWorkplaceKtTest.kt
@@ -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