Compare commits

..

8 commits

7 changed files with 162 additions and 39 deletions

View file

@ -144,3 +144,11 @@ Or to get help for subcommands e.g.
provs-desktop.jar ide -h provs-desktop.jar ide -h
provs-server.jar k3s -h provs-server.jar k3s -h
``` ```
## Development & mirrors
Development happens at: https://repo.prod.meissa.de/meissa/provs
Mirrors are:
* https://gitlab.com/domaindrivenarchitecture/provs (CI issues and PR)
* https://github.com/DomainDrivenArchitecture/provs
For more details about our repository model see: https://repo.prod.meissa.de/meissa/federate-your-repos

View file

@ -0,0 +1,68 @@
## Initialization
```mermaid
sequenceDiagram
actor user
participant app as Application
participant ds as DesktopService
participant gtr as GitTrustFactory
participant pa as CliArgumentsParser
participant cr as DesktopConfigRepository
participant ut as CliUtils
participant su as ProvsWithSudo
user ->> app: main
activate app
app ->> pa: parseCommands
app ->> cr: getConfig(configFileName)
app ->> ut: createProvInstance(cmd.target)
app ->> su: ensureSudoWithoutPassword(cmd.target.remoteTarget()?.password)
app ->> ds: provisionDesktopCommand(cmd, config)
activate ds
ds ->> gtr : get("github", "gitlab")
gtr -->> ds: GitTrust
deactivate ds
deactivate app
```
## Domain
```mermaid
classDiagram
namespace configuration {
class TargetCliCommand {
val target: String,
val passwordInteractive: Boolean = false
}
class ConfigFileName {
fileName: String
}
}
namespace desktop {
class DesktopCliCommand {
}
class DesktopConfig {
val ssh: SshKeyPairSource? = null,
val gpg: KeyPairSource? = null,
val gitUserName: String? = null,
val gitEmail: String? = null,
}
class DesktopType {
val name: String
}
class DesktopOnlyModule {
<<enum>>
FIREFOX, VERIFY
}
}
DesktopCliCommand "1" *-- "1" DesktopType: type
DesktopCliCommand "1" *-- "1" TargetCliCommand: target
DesktopCliCommand "1" *-- "1" ConfigFileName: configFile
DesktopCliCommand "1" *-- "..n" DesktopOnlyModule: onlyModules
```

View file

@ -86,7 +86,7 @@ fun Prov.provisionIdeDesktop(onlyModules: List<String>? = null) {
} else if (onlyModules.contains(DesktopOnlyModule.VERIFY.name.lowercase())) { } else if (onlyModules.contains(DesktopOnlyModule.VERIFY.name.lowercase())) {
verifyIdeSetup() verifyIdeSetup()
} else if (onlyModules.contains(DesktopOnlyModule.FIREFOX.name.lowercase())) { } else if (onlyModules.contains(DesktopOnlyModule.FIREFOX.name.lowercase())) {
installFirefox() installPpaFirefox()
} }
} }
@ -109,7 +109,7 @@ fun Prov.provisionOfficeDesktop(onlyModules: List<String>? = null) {
} else if (onlyModules.contains(DesktopOnlyModule.VERIFY.name.lowercase())) { } else if (onlyModules.contains(DesktopOnlyModule.VERIFY.name.lowercase())) {
verifyOfficeSetup() verifyOfficeSetup()
} else if (onlyModules.contains(DesktopOnlyModule.FIREFOX.name.lowercase())) { } else if (onlyModules.contains(DesktopOnlyModule.FIREFOX.name.lowercase())) {
installFirefox() installPpaFirefox()
} }
} }
@ -140,7 +140,7 @@ fun Prov.provisionBasicDesktop(
provisionKeys(gpg, ssh) provisionKeys(gpg, ssh)
provisionGit(gitUserName ?: whoami(), gitEmail, gpg?.let { gpgFingerprint(it.publicKey.plain()) }) provisionGit(gitUserName ?: whoami(), gitEmail, gpg?.let { gpgFingerprint(it.publicKey.plain()) })
installFirefox() installPpaFirefox()
installGopass() installGopass()
configureGopass(publicGpgKey = gpg?.publicKey) configureGopass(publicGpgKey = gpg?.publicKey)
installGopassJsonApi() installGopassJsonApi()
@ -153,6 +153,6 @@ fun Prov.provisionBasicDesktop(
configureBash() configureBash()
installVirtualBoxGuestAdditions() installVirtualBoxGuestAdditions()
} else if (onlyModules.contains(DesktopOnlyModule.FIREFOX.name.lowercase())) { } else if (onlyModules.contains(DesktopOnlyModule.FIREFOX.name.lowercase())) {
installFirefox() installPpaFirefox()
} }
} }

View file

@ -1,42 +1,61 @@
package org.domaindrivenarchitecture.provs.desktop.infrastructure package org.domaindrivenarchitecture.provs.desktop.infrastructure
import org.domaindrivenarchitecture.provs.framework.core.Prov import org.domaindrivenarchitecture.provs.framework.core.Prov
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.addTextToFile import org.domaindrivenarchitecture.provs.framework.core.ProvResult
import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.aptInstall import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.checkFile
import java.io.File import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.createFile
import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.aptInstallFromPpa
/** /**
* Installs non-snap firefox, removing a firefox snap-installation if existing * Installs ppa firefox (i.e. non-snap), removing snap-firefox if existing.
*/ */
fun Prov.installFirefox() = task { fun Prov.installPpaFirefox() = taskWithResult {
// inspired by: https://www.omgubuntu.co.uk/2022/04/how-to-install-firefox-deb-apt-ubuntu-22-04 // inspired by: https://wiki.ubuntuusers.de/Firefox/Installation/PPA/
task("remove snap firefox") { val unattendeUpgradesForPpaFirefox = "/etc/apt/apt.conf.d/51unattended-upgrades-firefox"
if (chk("snap list | grep firefox")) {
cmd("snap remove firefox", sudo = true) val preCondition = checkFile(unattendeUpgradesForPpaFirefox)
} if (preCondition) {
return@taskWithResult ProvResult(true, out = "Firefox already installed with ppa")
} }
aptInstall("software-properties-common") cmd("sudo apt-get -qy remove firefox", sudo = true)
cmd("add-apt-repository -y ppa:mozillateam/ppa", sudo = true) optional {
cmd("snap remove firefox", sudo = true)
}
// set prio in order to use ppa-firefox above snap createFile("/etc/apt/preferences.d/mozillateam", mozillaTeamFileContent, sudo = true)
addTextToFile(
"\nPackage: *\n" + aptInstallFromPpa("mozillateam", "ppa", "firefox")
"Pin: release o=LP-PPA-mozillateam\n" +
"Pin-Priority: 1001\n", createFile(
File("/etc/apt/preferences.d/mozilla-firefox"), unattendeUpgradesForPpaFirefox,
"Unattended-Upgrade::Allowed-Origins:: \"LP-PPA-mozillateam:\${distro_codename}\";\n",
sudo = true sudo = true
) )
addTextToFile(
"""Unattended-Upgrade::Allowed-Origins:: "LP-PPA-mozillateam:${'$'}{distro_codename}";""",
File("/etc/apt/preferences.d/mozilla-firefox"),
sudo = true
)
aptInstall("firefox")
cmd("apt-get upgrade -y --allow-downgrades firefox", sudo = true)
} }
private val mozillaTeamFileContent = """
Package: *
Pin: release o=LP-PPA-mozillateam
Pin-Priority: 100
Package: firefox*
Pin: release o=LP-PPA-mozillateam
Pin-Priority: 1001
Package: firefox*
Pin: release o=Ubuntu
Pin-Priority: -1
Package: thunderbird*
Pin: release o=LP-PPA-mozillateam
Pin-Priority: 1001
Package: thunderbird*
Pin: release o=Ubuntu
Pin-Priority: -1
""".trimIndent()

View file

@ -13,7 +13,7 @@ import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
internal class CliTargetCommandKtTest { internal class TargetCliCommandKtTest {
companion object { companion object {
@BeforeAll @BeforeAll

View file

@ -1,32 +1,60 @@
package org.domaindrivenarchitecture.provs.desktop.infrastructure package org.domaindrivenarchitecture.provs.desktop.infrastructure
import org.domaindrivenarchitecture.provs.framework.core.remote import org.domaindrivenarchitecture.provs.framework.core.remote
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.deleteFile
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.fileContainsText
import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.checkPackageInstalled import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.checkPackageInstalled
import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.isPackageInstalled
import org.domaindrivenarchitecture.provs.framework.ubuntu.secret.secretSources.PromptSecretSource import org.domaindrivenarchitecture.provs.framework.ubuntu.secret.secretSources.PromptSecretSource
import org.domaindrivenarchitecture.provs.test.defaultTestContainer import org.domaindrivenarchitecture.provs.test.defaultTestContainer
import org.domaindrivenarchitecture.provs.test.tags.ExtensiveContainerTest import org.domaindrivenarchitecture.provs.test.tags.ExtensiveContainerTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
internal class FirefoxKtTest { internal class FirefoxKtTest {
// Attention: this test does not test full functionality of installFirefox, e.g. does not test // Attention: this test does not test full functionality of installPpaFirefox, e.g. does not test
// remove snap, as this test runs against a container which does not have snap-firefox installed // remove snap-firefox, as this test runs against a container, which does have neither snap nor snap-firefox installed
@ExtensiveContainerTest @ExtensiveContainerTest
fun installFirefox() { fun installFirefox() {
// given
val prov = defaultTestContainer()
// when // when
val result = defaultTestContainer().session { val result = prov.session {
installFirefox() deleteFile("/etc/apt/apt.conf.d/51unattended-upgrades-firefox", sudo = true)
checkPackageInstalled("firefox") deleteFile("/etc/apt/preferences.d/mozillateam", sudo = true)
installPpaFirefox()
} }
val result2 = prov.installPpaFirefox()
// then // then
assertTrue(result.success) assertTrue(result.success)
assertEquals("Firefox already installed with ppa", result2.out)
assertTrue(prov.isPackageInstalled("firefox"))
assertTrue(
prov.fileContainsText(
"/etc/apt/apt.conf.d/51unattended-upgrades-firefox",
"Unattended-Upgrade::Allowed-Origins:: \"LP-PPA-mozillateam:\${distro_codename}\";\n",
sudo = true
)
)
val expectedPolicyLine = Regex("1001? https?://ppa.launchpad(?:content)?.net/mozillateam/ppa/ubuntu")
val policy = prov.cmd("apt policy firefox").out
assertTrue(
policy?.contains(expectedPolicyLine) ?: false,
"$expectedPolicyLine was not found in $policy"
)
} }
/**
* Tests installing firefox on a remote machine, e.g. a virtual machine
*/
@Test @Test
@Disabled("Update connection details,then enable and run manually") @Disabled("Update connection details, then enable the test and run manually")
fun installFirefox_remotely() { fun installFirefox_remotely() {
val host = "192.168.56.123" val host = "192.168.56.123"
val user = "user" val user = "user"
@ -39,7 +67,7 @@ internal class FirefoxKtTest {
/* remove for ssh authentication */ /* remove for ssh authentication */
PromptSecretSource("Remote password for user $user").secret() PromptSecretSource("Remote password for user $user").secret()
).session { ).session {
installFirefox() installPpaFirefox()
firefoxVersion = cmd("apt list firefox --installed").out ?: "" firefoxVersion = cmd("apt list firefox --installed").out ?: ""
checkPackageInstalled("firefox") checkPackageInstalled("firefox")
} }