Merge branch 'refactoring-application-validierung' into 'master'

Validate Application File

See merge request domaindrivenarchitecture/provs!5
This commit is contained in:
Pat Dyn 2023-02-10 08:47:52 +00:00
commit 31bea54d3b
11 changed files with 120 additions and 126 deletions

View file

@ -7,9 +7,11 @@ 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.server.domain.ServerCliCommand import org.domaindrivenarchitecture.provs.server.domain.ServerCliCommand
import org.domaindrivenarchitecture.provs.server.domain.ServerType import org.domaindrivenarchitecture.provs.server.domain.ServerType
import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFile
import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileName import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileName
import org.domaindrivenarchitecture.provs.server.domain.k3s.K3sCliCommand import org.domaindrivenarchitecture.provs.server.domain.k3s.K3sCliCommand
import org.domaindrivenarchitecture.provs.server.domain.k3s.ServerOnlyModule import org.domaindrivenarchitecture.provs.server.domain.k3s.ServerOnlyModule
import org.domaindrivenarchitecture.provs.server.infrastructure.DefaultApplicationFileRepository
class CliArgumentsParser(name: String) : CliTargetParser(name) { class CliArgumentsParser(name: String) : CliTargetParser(name) {

View file

@ -0,0 +1,28 @@
package org.domaindrivenarchitecture.provs.server.domain.k3s
import org.domaindrivenarchitecture.provs.framework.core.getLocalFileContent
import java.io.File
data class ApplicationFile(val id: ApplicationFileName, val fileContent: String) {
fun validate() : List<String> {
val output = ArrayList<String>()
val specRegex = "Spec.failed".toRegex()
val javaRegex = "Exception.in.thread".toRegex()
if(fileContent.isEmpty()) {
output.add("fileContent is empty.")
}
if (fileContent.contains(specRegex)) {
output.add(specRegex.find(fileContent)!!.value)
}
if (fileContent.contains(javaRegex)) {
output.add(javaRegex.find(fileContent)!!.value)
}
return output
}
fun isValid() : Boolean {
return validate().isEmpty()
}
}

View file

@ -2,8 +2,8 @@ package org.domaindrivenarchitecture.provs.server.domain.k3s
import java.io.File import java.io.File
data class ApplicationFileName(val fileName: String) { class ApplicationFileName(val fileName: String) {
fun fullqualified() : String { fun fullyQualifiedName() : String {
return File(fileName).absoluteFile.absolutePath return File(fileName).absoluteFile.absolutePath
} }
} }

View file

@ -1,7 +1,6 @@
package org.domaindrivenarchitecture.provs.server.domain.k3s package org.domaindrivenarchitecture.provs.server.domain.k3s
interface ApplicationFileRepository { interface ApplicationFileRepository {
fun assertExists(applicationFileName: ApplicationFileName?) fun getFile() : ApplicationFile
fun assertC4kSpecError(applicationFileName: ApplicationFileName?)
fun assertC4kJavaException(applicationFileName: ApplicationFileName?)
} }

View file

@ -14,13 +14,11 @@ fun Prov.provisionK3sCommand(cli: K3sCliCommand) = task {
if (cli.onlyModules == null ) { if (cli.onlyModules == null ) {
val k3sConfig: K3sConfig = getK3sConfig(cli.configFileName) val k3sConfig: K3sConfig = getK3sConfig(cli.configFileName)
DefaultApplicationFileRepository().assertExists(cli.applicationFileName)
DefaultApplicationFileRepository().assertC4kSpecError(cli.applicationFileName)
DefaultApplicationFileRepository().assertC4kJavaException(cli.applicationFileName)
DefaultConfigFileRepository().assertExists(cli.configFileName) DefaultConfigFileRepository().assertExists(cli.configFileName)
val k3sConfigReprovision = k3sConfig.copy(reprovision = cli.reprovision || k3sConfig.reprovision) val k3sConfigReprovision = k3sConfig.copy(reprovision = cli.reprovision || k3sConfig.reprovision)
provisionK3s(k3sConfigReprovision, grafanaConfigResolved, cli.applicationFileName)
val applicationFile = DefaultApplicationFileRepository(cli.applicationFileName).getFile()
provisionK3s(k3sConfigReprovision, grafanaConfigResolved, applicationFile)
} else { } else {
provisionGrafana(cli.onlyModules, grafanaConfigResolved) provisionGrafana(cli.onlyModules, grafanaConfigResolved)
} }
@ -32,7 +30,7 @@ fun Prov.provisionK3sCommand(cli: K3sCliCommand) = task {
fun Prov.provisionK3s( fun Prov.provisionK3s(
k3sConfig: K3sConfig, k3sConfig: K3sConfig,
grafanaConfigResolved: GrafanaAgentConfigResolved? = null, grafanaConfigResolved: GrafanaAgentConfigResolved? = null,
applicationFileName: ApplicationFileName? = null) = task { applicationFile: ApplicationFile? = null) = task {
if (k3sConfig.reprovision) { if (k3sConfig.reprovision) {
deprovisionK3sInfra() deprovisionK3sInfra()
@ -54,10 +52,11 @@ fun Prov.provisionK3s(
provisionGrafanaAgent(grafanaConfigResolved) provisionGrafanaAgent(grafanaConfigResolved)
} }
if (applicationFileName != null) { if (applicationFile != null) {
provisionK3sApplication(applicationFileName) provisionK3sApplication(applicationFile)
} }
if (!k3sConfig.reprovision) { if (!k3sConfig.reprovision) {
provisionServerCliConvenience() provisionServerCliConvenience()
} }

View file

@ -1,41 +1,26 @@
package org.domaindrivenarchitecture.provs.server.infrastructure package org.domaindrivenarchitecture.provs.server.infrastructure
import org.domaindrivenarchitecture.provs.framework.core.getLocalFileContent
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.checkLocalFile import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.checkLocalFile
import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFile
import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileName import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileName
import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileRepository import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileRepository
import java.io.File import java.io.File
class DefaultApplicationFileRepository : ApplicationFileRepository { class DefaultApplicationFileRepository(val applicationFileName: ApplicationFileName?) : ApplicationFileRepository {
override fun assertExists(applicationFileName: ApplicationFileName?) { private fun assertExists(applicationFileName: String?) {
if (applicationFileName != null && !checkLocalFile(applicationFileName.fullqualified())) { if (applicationFileName != null && !checkLocalFile(applicationFileName)) {
throw RuntimeException("Application file ${applicationFileName.fileName} not found. Please check if path is correct.") throw RuntimeException("Application file not found. Please check if path is correct.")
} }
} }
override fun getFile() : ApplicationFile {
assertExists(applicationFileName!!.fullyQualifiedName())
override fun assertC4kSpecError(applicationFileName: ApplicationFileName?) { val applicationFileContents = getLocalFileContent(applicationFileName.fullyQualifiedName())
if (applicationFileName != null) { val applicationFile = ApplicationFile(applicationFileName, applicationFileContents)
val fileContent = File(applicationFileName.fullqualified()).readText()
return if (applicationFile.isValid()) { applicationFile }
if (fileContent.contains("Spec.failed".toRegex()) && fileContent.contains("Detected.*[0-9].*error+".toRegex())) { else { throw RuntimeException("Application file was invalid.") }
throw RuntimeException("Application file ${applicationFileName.fileName} contains spec errors. Please check your configuration file.")
} }
}
}
override fun assertC4kJavaException(applicationFileName: ApplicationFileName?) {
if (applicationFileName != null) {
val fileContent = File(applicationFileName.fullqualified()).readText()
if (fileContent.contains("Exception.in.thread".toRegex())) {
throw RuntimeException("Application file ${applicationFileName.fileName} contains java exception. Please check the c4k code for errors.")
}
}
}
} }

View file

@ -5,10 +5,7 @@ import org.domaindrivenarchitecture.provs.framework.core.ProvResult
import org.domaindrivenarchitecture.provs.framework.core.repeatTaskUntilSuccess import org.domaindrivenarchitecture.provs.framework.core.repeatTaskUntilSuccess
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.* import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.*
import org.domaindrivenarchitecture.provs.server.domain.CertmanagerEndpoint import org.domaindrivenarchitecture.provs.server.domain.CertmanagerEndpoint
import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileName import org.domaindrivenarchitecture.provs.server.domain.k3s.*
import org.domaindrivenarchitecture.provs.server.domain.k3s.Certmanager
import org.domaindrivenarchitecture.provs.server.domain.k3s.FileMode
import org.domaindrivenarchitecture.provs.server.domain.k3s.K3sConfig
import java.io.File import java.io.File
// ----------------------------------- versions -------------------------------- // ----------------------------------- versions --------------------------------
@ -154,9 +151,9 @@ fun Prov.provisionK3sEcho(fqdn: String, endpoint: CertmanagerEndpoint? = null) =
applyK3sFileFromResourceTemplate(k3sEcho, mapOf("fqdn" to fqdn, "issuer_name" to issuer)) applyK3sFileFromResourceTemplate(k3sEcho, mapOf("fqdn" to fqdn, "issuer_name" to issuer))
} }
fun Prov.provisionK3sApplication(applicationFileName: ApplicationFileName) = task { fun Prov.provisionK3sApplication(applicationFile: ApplicationFile) = task {
copyFileFromLocal( copyFileFromLocal(
fullyQualifiedLocalFilename = applicationFileName.fullqualified(), fullyQualifiedLocalFilename = applicationFile.id.fullyQualifiedName(),
fullyQualifiedFilename = k3sManualManifestsDir + "application.yaml", fullyQualifiedFilename = k3sManualManifestsDir + "application.yaml",
posixFilePermission = "644", posixFilePermission = "644",
sudo = true sudo = true

View file

@ -1,6 +1,8 @@
package org.domaindrivenarchitecture.provs.configuration.infrastructure package org.domaindrivenarchitecture.provs.configuration.infrastructure
import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileName import org.domaindrivenarchitecture.provs.configuration.domain.ConfigFileName
import org.domaindrivenarchitecture.provs.configuration.domain.ConfigFileRepository
import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFile
import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileRepository import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileRepository
import org.domaindrivenarchitecture.provs.server.infrastructure.DefaultApplicationFileRepository import org.domaindrivenarchitecture.provs.server.infrastructure.DefaultApplicationFileRepository
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@ -12,8 +14,8 @@ internal class DefaultConfigFileRepositoryKtTest {
@Test @Test
fun assertExistsThrowsRuntimeException() { fun assertExistsThrowsRuntimeException() {
// when // when
val invalidFileName = ApplicationFileName("iDontExist") val invalidFileName = ConfigFileName("iDontExist")
val repo: ApplicationFileRepository = DefaultApplicationFileRepository() val repo: ConfigFileRepository = DefaultConfigFileRepository()
// then // then
val exception = assertThrows<RuntimeException>( val exception = assertThrows<RuntimeException>(
@ -31,8 +33,8 @@ internal class DefaultConfigFileRepositoryKtTest {
val validFileName = "src/test/resources/existing-file" val validFileName = "src/test/resources/existing-file"
// when // when
val validFile = ApplicationFileName(File(validFileName).path) val validFile = ConfigFileName(File(validFileName).path)
val repo: ApplicationFileRepository = DefaultApplicationFileRepository() val repo: ConfigFileRepository = DefaultConfigFileRepository()
repo.assertExists(validFile) repo.assertExists(validFile)
// then // then

View file

@ -1,6 +1,7 @@
package org.domaindrivenarchitecture.provs.server.application package org.domaindrivenarchitecture.provs.server.application
import org.domaindrivenarchitecture.provs.configuration.domain.TargetCliCommand import org.domaindrivenarchitecture.provs.configuration.domain.TargetCliCommand
import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFile
import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileName import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileName
import org.domaindrivenarchitecture.provs.server.domain.k3s.K3sCliCommand import org.domaindrivenarchitecture.provs.server.domain.k3s.K3sCliCommand
import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertEquals

View file

@ -0,0 +1,44 @@
package org.domaindrivenarchitecture.provs.server.domain
import org.domaindrivenarchitecture.provs.configuration.domain.ConfigFileName
import org.domaindrivenarchitecture.provs.configuration.infrastructure.DefaultConfigFileRepository
import org.domaindrivenarchitecture.provs.framework.core.getLocalFileContent
import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFile
import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileName
import org.domaindrivenarchitecture.provs.server.infrastructure.DefaultApplicationFileRepository
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import java.io.File
internal class ApplicationFileKtTest {
@Test
fun assertValidateReturnsSpecErrors() {
// given
val applicationFileName = ApplicationFileName("src/test/resources/failed-spec.yaml")
// when
val file = ApplicationFile(applicationFileName, getLocalFileContent(applicationFileName.fullyQualifiedName()))
// then
val result = file.validate()
assertEquals(arrayListOf("Spec failed"), result)
}
@Test
fun assertValidateReturnsJavaErrors() {
// given
val applicationFileName = ApplicationFileName("src/test/resources/java-exception.yaml")
// when
val file = ApplicationFile(applicationFileName, getLocalFileContent(applicationFileName.fullyQualifiedName()))
// then
val result = file.validate()
assertEquals(arrayListOf("Exception in thread"), result)
}
}

View file

@ -2,6 +2,7 @@ package org.domaindrivenarchitecture.provs.server.infrastructure
import org.domaindrivenarchitecture.provs.configuration.domain.ConfigFileName import org.domaindrivenarchitecture.provs.configuration.domain.ConfigFileName
import org.domaindrivenarchitecture.provs.configuration.infrastructure.DefaultConfigFileRepository import org.domaindrivenarchitecture.provs.configuration.infrastructure.DefaultConfigFileRepository
import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFile
import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileName import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileName
import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@ -13,96 +14,32 @@ internal class DefaultApplicationFileRepositoryKtTest {
@Test @Test
fun assertExistsThrowsRuntimeException() { fun assertExistsThrowsRuntimeException() {
// when // when
val invalidFileName = ConfigFileName("iDontExist") val invalidFileName = ApplicationFileName("iDontExist")
val repo = DefaultConfigFileRepository() val repo = DefaultApplicationFileRepository(invalidFileName)
// then // then
val exception = assertThrows<RuntimeException>( val exception = assertThrows<RuntimeException>(
"Should not find the file." "Should not find the file."
) { repo.assertExists(invalidFileName) } ) { repo.getFile() }
assertEquals( assertEquals(
"Config file iDontExist not found. Please check if path is correct.", "Application file not found. Please check if path is correct.",
exception.message) exception.message)
} }
@Test @Test
fun assertExistsPasses() { fun assertGetFileThrowsRuntimeException() {
// given
val validFileName = "src/test/resources/existing-file"
// when // when
val validFile = ConfigFileName(File(validFileName).path) val invalidFileName = ApplicationFileName("src/test/resources/java-exception.yaml")
val repo = DefaultConfigFileRepository() val repo = DefaultApplicationFileRepository(invalidFileName)
repo.assertExists(validFile)
// then
// no exception is thrown
}
@Test
fun assertC4kSpecErrorThrows() {
// given
val applicationFileName = "src/test/resources/failed-spec.yaml"
// when
val failedFile = ApplicationFileName(File(applicationFileName).path)
val repo = DefaultApplicationFileRepository()
// then // then
val exception = assertThrows<RuntimeException>( val exception = assertThrows<RuntimeException>(
"Should throw because of bad spec." "Should not find the file."
) { repo.assertC4kSpecError(failedFile) } ) { repo.getFile() }
assertEquals( assertEquals(
"Application file src/test/resources/failed-spec.yaml contains spec errors. Please check your configuration file.", "Application file was invalid.",
exception.message) exception.message)
} }
@Test
fun assertC4kSpecErrorPasses() {
// given
val validFileName = "src/test/resources/valid.yaml"
// when
val validFile = ApplicationFileName(File(validFileName).path)
val repo = DefaultApplicationFileRepository()
repo.assertC4kSpecError(validFile)
// then
// no exception is thrown
}
@Test
fun assertC4kJavaExceptionThrows() {
// given
val applicationFileName = "src/test/resources/java-exception.yaml"
// when
val failedFile = ApplicationFileName(File(applicationFileName).path)
val repo = DefaultApplicationFileRepository()
// then
val exception = assertThrows<RuntimeException>(
"Should throw because of java exception."
) { repo.assertC4kJavaException(failedFile) }
assertEquals(
"Application file src/test/resources/java-exception.yaml contains java exception. Please check the c4k code for errors.",
exception.message)
}
@Test
fun assertC4kJavaExceptionPasses() {
// given
val validFileName = "src/test/resources/valid.yaml"
// when
val validFile = ApplicationFileName(File(validFileName).path)
val repo = DefaultApplicationFileRepository()
repo.assertC4kJavaException(validFile)
// then
// no exception is thrown
}
} }