add possibility for monthly reboot of host system of k3s server
This commit is contained in:
parent
1118bc7d07
commit
e6db481ac9
5 changed files with 76 additions and 25 deletions
|
@ -0,0 +1,40 @@
|
||||||
|
package org.domaindrivenarchitecture.provs.framework.ubuntu.cron.infrastructure
|
||||||
|
|
||||||
|
import org.domaindrivenarchitecture.provs.framework.core.Prov
|
||||||
|
import org.domaindrivenarchitecture.provs.framework.core.ProvResult
|
||||||
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.checkFile
|
||||||
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.createDirs
|
||||||
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.createFile
|
||||||
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.user.base.whoami
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a cron job.
|
||||||
|
* @param cronFilename e.g. "90_my_cron"; file is created in folder /etc/cron.d/
|
||||||
|
* @param schedule in the usual cron-format, examples: "0 * * * *" for each hour, "0 3 1-7 * 1" for the first Monday each month at 3:00, etc
|
||||||
|
* @param command the executed command
|
||||||
|
* @param user the user with whom the command will be executed, if null the current user is used
|
||||||
|
*/
|
||||||
|
fun Prov.createCronJob(cronFilename: String, schedule: String, command: String, user: String? = null) = task {
|
||||||
|
val cronUser = user ?: whoami()
|
||||||
|
val cronLine = "$schedule $cronUser $command\n"
|
||||||
|
|
||||||
|
createDirs("/etc/cron.d/", sudo = true)
|
||||||
|
createFile("/etc/cron.d/$cronFilename", cronLine, "644", sudo = true, overwriteIfExisting = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a cronJob for a monthly reboot of the (Linux) system.
|
||||||
|
* ATTENTION: Use with care!!
|
||||||
|
*/
|
||||||
|
fun Prov.scheduleMonthlyReboot() = task {
|
||||||
|
val shutdown = "/sbin/shutdown"
|
||||||
|
if (checkFile(shutdown, sudo = true)) {
|
||||||
|
// reboot each first Tuesday in a month at 3:00
|
||||||
|
// use controlled "shutdown" instead of direct "reboot"
|
||||||
|
createCronJob("50_monthly_reboot", "0 3 1-7 * 2", "shutdown -r now", "root")
|
||||||
|
} else {
|
||||||
|
addResultToEval(ProvResult(false, err = "$shutdown not found."))
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,22 +0,0 @@
|
||||||
package org.domaindrivenarchitecture.provs.framework.ubuntu.cron.infrstructure
|
|
||||||
|
|
||||||
import org.domaindrivenarchitecture.provs.framework.core.Prov
|
|
||||||
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.createDirs
|
|
||||||
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.createFile
|
|
||||||
import org.domaindrivenarchitecture.provs.framework.ubuntu.user.base.whoami
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a cron job.
|
|
||||||
* @param cronFilename e.g. "90_my_cron", file is created in folder /etc/cron.d/
|
|
||||||
* @param schedule in the usual cron-format, examples: "0 * * * *" for each hour, "0 3 1-7 * 1" for the first Monday each month at 3:00, etc
|
|
||||||
* @param cronCommand the executed command
|
|
||||||
* @param cronUser the user with whom the command will be executed, if null the current user is used
|
|
||||||
*/
|
|
||||||
fun Prov.createCronJob(cronFilename: String, schedule: String, cronCommand: String, cronUser: String? = null) = task {
|
|
||||||
val user = cronUser ?: whoami()
|
|
||||||
val cronLine = "$schedule $user $cronCommand\n"
|
|
||||||
|
|
||||||
createDirs("/etc/cron.d/", sudo = true)
|
|
||||||
createFile("/etc/cron.d/$cronFilename", cronLine, "644", sudo = true, overwriteIfExisting = true)
|
|
||||||
}
|
|
|
@ -10,7 +10,8 @@ data class K3sConfig(
|
||||||
val loopback: Loopback = Loopback(ipv4 = "192.168.5.1", ipv6 = "fc00::5:1"),
|
val loopback: Loopback = Loopback(ipv4 = "192.168.5.1", ipv6 = "fc00::5:1"),
|
||||||
val certmanager: Certmanager? = null,
|
val certmanager: Certmanager? = null,
|
||||||
val echo: Echo? = null,
|
val echo: Echo? = null,
|
||||||
val reprovision: Reprovision = false
|
val reprovision: Reprovision = false,
|
||||||
|
val monthlyReboot: Boolean = false,
|
||||||
) {
|
) {
|
||||||
fun isDualStack(): Boolean {
|
fun isDualStack(): Boolean {
|
||||||
return node.ipv6 != null && loopback.ipv6 != null
|
return node.ipv6 != null && loopback.ipv6 != null
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.domaindrivenarchitecture.provs.server.domain.k3s
|
||||||
|
|
||||||
import org.domaindrivenarchitecture.provs.configuration.infrastructure.DefaultConfigFileRepository
|
import org.domaindrivenarchitecture.provs.configuration.infrastructure.DefaultConfigFileRepository
|
||||||
import org.domaindrivenarchitecture.provs.framework.core.Prov
|
import org.domaindrivenarchitecture.provs.framework.core.Prov
|
||||||
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.cron.infrastructure.scheduleMonthlyReboot
|
||||||
import org.domaindrivenarchitecture.provs.server.domain.hetzner_csi.HetznerCSIConfigResolved
|
import org.domaindrivenarchitecture.provs.server.domain.hetzner_csi.HetznerCSIConfigResolved
|
||||||
import org.domaindrivenarchitecture.provs.server.domain.hetzner_csi.provisionHetznerCSI
|
import org.domaindrivenarchitecture.provs.server.domain.hetzner_csi.provisionHetznerCSI
|
||||||
import org.domaindrivenarchitecture.provs.server.domain.k8s_grafana_agent.GrafanaAgentConfigResolved
|
import org.domaindrivenarchitecture.provs.server.domain.k8s_grafana_agent.GrafanaAgentConfigResolved
|
||||||
|
@ -70,6 +71,10 @@ fun Prov.provisionK3s(
|
||||||
provisionServerCliConvenience()
|
provisionServerCliConvenience()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (k3sConfig.monthlyReboot) {
|
||||||
|
scheduleMonthlyReboot()
|
||||||
|
}
|
||||||
|
|
||||||
installK9s()
|
installK9s()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
package org.domaindrivenarchitecture.provs.framework.ubuntu.cron.infrstructure
|
package org.domaindrivenarchitecture.provs.framework.ubuntu.cron.infrastructure
|
||||||
|
|
||||||
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.checkFile
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.checkFile
|
||||||
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.createDirs
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.createDirs
|
||||||
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.createFile
|
||||||
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.fileContent
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.fileContent
|
||||||
import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.aptInstall
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.aptInstall
|
||||||
import org.domaindrivenarchitecture.provs.framework.ubuntu.user.base.whoami
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.user.base.whoami
|
||||||
|
@ -10,7 +11,8 @@ import org.junit.jupiter.api.Assertions.*
|
||||||
import org.junit.jupiter.api.Disabled
|
import org.junit.jupiter.api.Disabled
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
class CronJobKtTest {
|
class CronJobsKtTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun createCronJob_creates_cron_file() {
|
fun createCronJob_creates_cron_file() {
|
||||||
// given
|
// given
|
||||||
|
@ -29,6 +31,7 @@ class CronJobKtTest {
|
||||||
assertEquals("0 * * * * $expectedUser echo hello > /dev/null 2>&1\n", actualFileContent)
|
assertEquals("0 * * * * $expectedUser echo hello > /dev/null 2>&1\n", actualFileContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled // only for manual execution and manual check for the created files
|
@Disabled // only for manual execution and manual check for the created files
|
||||||
// Test if cron-job is actually running, but needs manual checks
|
// Test if cron-job is actually running, but needs manual checks
|
||||||
|
@ -65,4 +68,28 @@ class CronJobKtTest {
|
||||||
// after a minute check manually if files exist, e.g. with: sudo docker exec provs_test /bin/bash -c "ls -l tmp"
|
// after a minute check manually if files exist, e.g. with: sudo docker exec provs_test /bin/bash -c "ls -l tmp"
|
||||||
// each minute a new file should be created with the timestamp
|
// each minute a new file should be created with the timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun scheduleMonthlyReboot() {
|
||||||
|
// given
|
||||||
|
val prov = defaultTestContainer()
|
||||||
|
// create dummy shutdown in test container if missing (containers do usually not have shutdown installed)
|
||||||
|
prov.createFile(
|
||||||
|
"/sbin/shutdown",
|
||||||
|
"dummy file for test of scheduleMonthlyReboot",
|
||||||
|
sudo = true,
|
||||||
|
overwriteIfExisting = false
|
||||||
|
)
|
||||||
|
|
||||||
|
// when
|
||||||
|
val result = prov.scheduleMonthlyReboot()
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertTrue(result.success)
|
||||||
|
val fqFilename = "/etc/cron.d/50_monthly_reboot"
|
||||||
|
assertTrue(prov.checkFile(fqFilename), "")
|
||||||
|
val actualFileContent = prov.fileContent(fqFilename, sudo = true)
|
||||||
|
assertEquals("0 3 1-7 * 2 root shutdown -r now\n", actualFileContent)
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue