diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/configuration/infrastructure/DefaultConfigFileRepository.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/configuration/infrastructure/DefaultConfigFileRepository.kt index 7ce2000..e683e95 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/configuration/infrastructure/DefaultConfigFileRepository.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/configuration/infrastructure/DefaultConfigFileRepository.kt @@ -7,7 +7,7 @@ import org.domaindrivenarchitecture.provs.configuration.domain.ConfigFileReposit class DefaultConfigFileRepository : ConfigFileRepository { override fun assertExists(configFileName: ConfigFileName?) { if (configFileName != null && !checkLocalFile(configFileName.fullqualified())) { - throw RuntimeException("Config file ${configFileName.fileName} not found. Please check if path is correct.") + throw RuntimeException("Config file not found. Please check if path is correct.") } } } diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/application/CliArgumentsParser.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/application/CliArgumentsParser.kt index bae346a..77a866d 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/application/CliArgumentsParser.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/application/CliArgumentsParser.kt @@ -7,9 +7,11 @@ import org.domaindrivenarchitecture.provs.configuration.domain.ConfigFileName import org.domaindrivenarchitecture.provs.configuration.domain.TargetCliCommand import org.domaindrivenarchitecture.provs.server.domain.ServerCliCommand 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.K3sCliCommand import org.domaindrivenarchitecture.provs.server.domain.k3s.ServerOnlyModule +import org.domaindrivenarchitecture.provs.server.infrastructure.DefaultApplicationFileRepository class CliArgumentsParser(name: String) : CliTargetParser(name) { diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/ApplicationFile.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/ApplicationFile.kt new file mode 100644 index 0000000..419d573 --- /dev/null +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/ApplicationFile.kt @@ -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 { + val output = ArrayList() + 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() + } +} diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/ApplicationFileName.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/ApplicationFileName.kt index 2b89348..368a8c9 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/ApplicationFileName.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/ApplicationFileName.kt @@ -2,8 +2,8 @@ package org.domaindrivenarchitecture.provs.server.domain.k3s import java.io.File -data class ApplicationFileName(val fileName: String) { - fun fullqualified() : String { +class ApplicationFileName(val fileName: String) { + fun fullyQualifiedName() : String { return File(fileName).absoluteFile.absolutePath } -} +} \ No newline at end of file diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/ApplicationFileRepository.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/ApplicationFileRepository.kt index 9bce73e..37fc361 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/ApplicationFileRepository.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/domain/k3s/ApplicationFileRepository.kt @@ -1,5 +1,6 @@ package org.domaindrivenarchitecture.provs.server.domain.k3s interface ApplicationFileRepository { - fun assertExists(applicationFileName: ApplicationFileName?) + fun getFile() : ApplicationFile + } \ No newline at end of file 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 b569410..d75dc41 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 @@ -14,11 +14,11 @@ fun Prov.provisionK3sCommand(cli: K3sCliCommand) = task { if (cli.onlyModules == null ) { val k3sConfig: K3sConfig = getK3sConfig(cli.configFileName) - DefaultApplicationFileRepository().assertExists(cli.applicationFileName) DefaultConfigFileRepository().assertExists(cli.configFileName) - 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 { provisionGrafana(cli.onlyModules, grafanaConfigResolved) } @@ -30,7 +30,7 @@ fun Prov.provisionK3sCommand(cli: K3sCliCommand) = task { fun Prov.provisionK3s( k3sConfig: K3sConfig, grafanaConfigResolved: GrafanaAgentConfigResolved? = null, - applicationFileName: ApplicationFileName? = null) = task { + applicationFile: ApplicationFile? = null) = task { if (k3sConfig.reprovision) { deprovisionK3sInfra() @@ -52,10 +52,11 @@ fun Prov.provisionK3s( provisionGrafanaAgent(grafanaConfigResolved) } - if (applicationFileName != null) { - provisionK3sApplication(applicationFileName) + if (applicationFile != null) { + provisionK3sApplication(applicationFile) } + if (!k3sConfig.reprovision) { provisionServerCliConvenience() } diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/DefaultApplicationFileRepository.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/DefaultApplicationFileRepository.kt index 806356d..4a33d16 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/DefaultApplicationFileRepository.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/DefaultApplicationFileRepository.kt @@ -1,14 +1,26 @@ 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.server.domain.k3s.ApplicationFile import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileName import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileRepository +import java.io.File -class DefaultApplicationFileRepository : ApplicationFileRepository { +class DefaultApplicationFileRepository(val applicationFileName: ApplicationFileName?) : ApplicationFileRepository { - override fun assertExists(applicationFileName: ApplicationFileName?) { - if (applicationFileName != null && !checkLocalFile(applicationFileName.fullqualified())) { - throw RuntimeException("Application file ${applicationFileName.fileName} not found. Please check if path is correct.") + private fun assertExists(applicationFileName: String?) { + if (applicationFileName != null && !checkLocalFile(applicationFileName)) { + throw RuntimeException("Application file not found. Please check if path is correct.") } } + override fun getFile() : ApplicationFile { + assertExists(applicationFileName!!.fullyQualifiedName()) + + val applicationFileContents = getLocalFileContent(applicationFileName.fullyQualifiedName()) + val applicationFile = ApplicationFile(applicationFileName, applicationFileContents) + + return if (applicationFile.isValid()) { applicationFile } + else { throw RuntimeException("Application file was invalid.") } + } } 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 4d57a7b..7d48276 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/K3s.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/K3s.kt @@ -5,10 +5,7 @@ import org.domaindrivenarchitecture.provs.framework.core.ProvResult import org.domaindrivenarchitecture.provs.framework.core.repeatTaskUntilSuccess import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.* import org.domaindrivenarchitecture.provs.server.domain.CertmanagerEndpoint -import org.domaindrivenarchitecture.provs.server.domain.k3s.ApplicationFileName -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 org.domaindrivenarchitecture.provs.server.domain.k3s.* import java.io.File // ----------------------------------- versions -------------------------------- @@ -154,9 +151,9 @@ fun Prov.provisionK3sEcho(fqdn: String, endpoint: CertmanagerEndpoint? = null) = applyK3sFileFromResourceTemplate(k3sEcho, mapOf("fqdn" to fqdn, "issuer_name" to issuer)) } -fun Prov.provisionK3sApplication(applicationFileName: ApplicationFileName) = task { +fun Prov.provisionK3sApplication(applicationFile: ApplicationFile) = task { copyFileFromLocal( - fullyQualifiedLocalFilename = applicationFileName.fullqualified(), + fullyQualifiedLocalFilename = applicationFile.id.fullyQualifiedName(), fullyQualifiedFilename = k3sManualManifestsDir + "application.yaml", posixFilePermission = "644", sudo = true diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/configuration/infrastructure/DefaultConfigFileRepositoryKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/configuration/infrastructure/DefaultConfigFileRepositoryKtTest.kt index 6319fdb..16a7a8b 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/configuration/infrastructure/DefaultConfigFileRepositoryKtTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/configuration/infrastructure/DefaultConfigFileRepositoryKtTest.kt @@ -1,6 +1,8 @@ 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.infrastructure.DefaultApplicationFileRepository import org.junit.jupiter.api.Test @@ -12,8 +14,8 @@ internal class DefaultConfigFileRepositoryKtTest { @Test fun assertExistsThrowsRuntimeException() { // when - val invalidFileName = ApplicationFileName("iDontExist") - val repo: ApplicationFileRepository = DefaultApplicationFileRepository() + val invalidFileName = ConfigFileName("iDontExist") + val repo: ConfigFileRepository = DefaultConfigFileRepository() // then val exception = assertThrows( @@ -21,18 +23,18 @@ internal class DefaultConfigFileRepositoryKtTest { ) { repo.assertExists(invalidFileName) } assertEquals( - "Application file iDontExist not found. Please check if path is correct.", + "Config file not found. Please check if path is correct.", exception.message) } @Test fun assertExistsPasses() { // given - val validFileName = "src/test/resources/existing_file" + val validFileName = "src/test/resources/existing-file" // when - val validFile = ApplicationFileName(File(validFileName).path) - val repo: ApplicationFileRepository = DefaultApplicationFileRepository() + val validFile = ConfigFileName(File(validFileName).path) + val repo: ConfigFileRepository = DefaultConfigFileRepository() repo.assertExists(validFile) // then diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/server/application/CliArgumentParserTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/server/application/CliArgumentParserTest.kt index f72a20f..af00369 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/server/application/CliArgumentParserTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/server/application/CliArgumentParserTest.kt @@ -1,6 +1,7 @@ package org.domaindrivenarchitecture.provs.server.application 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.K3sCliCommand import org.junit.jupiter.api.Assertions.assertEquals @@ -45,7 +46,7 @@ internal class CliArgumentParserTest { // then assertTrue(result.isValidTarget()) - assertEquals(ApplicationFileName("app.yaml"), result.applicationFileName) + assertEquals(ApplicationFileName("app.yaml").fullyQualifiedName(), result.applicationFileName!!.fullyQualifiedName()) assertEquals(TargetCliCommand("user@host.com"), result.target) } } \ No newline at end of file diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/server/domain/ApplicationFileKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/server/domain/ApplicationFileKtTest.kt new file mode 100644 index 0000000..68e29c9 --- /dev/null +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/server/domain/ApplicationFileKtTest.kt @@ -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) + } +} \ No newline at end of file diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/DefaultApplicationFileRepositoryKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/DefaultApplicationFileRepositoryKtTest.kt index eb57bd6..b1d7bdc 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/DefaultApplicationFileRepositoryKtTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/server/infrastructure/DefaultApplicationFileRepositoryKtTest.kt @@ -2,6 +2,8 @@ package org.domaindrivenarchitecture.provs.server.infrastructure import org.domaindrivenarchitecture.provs.configuration.domain.ConfigFileName 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.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows @@ -12,30 +14,32 @@ internal class DefaultApplicationFileRepositoryKtTest { @Test fun assertExistsThrowsRuntimeException() { // when - val invalidFileName = ConfigFileName("iDontExist") - val repo = DefaultConfigFileRepository() + val invalidFileName = ApplicationFileName("iDontExist") + val repo = DefaultApplicationFileRepository(invalidFileName) // then val exception = assertThrows( "Should not find the file." - ) { repo.assertExists(invalidFileName) } + ) { repo.getFile() } assertEquals( - "Config file iDontExist not found. Please check if path is correct.", + "Application file not found. Please check if path is correct.", exception.message) } @Test - fun assertExistsPasses() { - // given - val validFileName = "src/test/resources/existing_file" - + fun assertGetFileThrowsRuntimeException() { // when - val validFile = ConfigFileName(File(validFileName).path) - val repo = DefaultConfigFileRepository() - repo.assertExists(validFile) + val invalidFileName = ApplicationFileName("src/test/resources/java-exception.yaml") + val repo = DefaultApplicationFileRepository(invalidFileName) // then - // no exception is thrown + val exception = assertThrows( + "Should not find the file." + ) { repo.getFile() } + + assertEquals( + "Application file was invalid.", + exception.message) } } \ No newline at end of file diff --git a/src/test/resources/existing_file b/src/test/resources/existing-file similarity index 100% rename from src/test/resources/existing_file rename to src/test/resources/existing-file diff --git a/src/test/resources/failed-spec.yaml b/src/test/resources/failed-spec.yaml new file mode 100644 index 0000000..028b008 --- /dev/null +++ b/src/test/resources/failed-spec.yaml @@ -0,0 +1,13 @@ + -- Spec failed -------------------- + + {:jvb-auth-password 1234, + ^^^^ + :jicofo-auth-password ..., + :jicofo-component-secret ...} + + should satisfy + + bash-env-string? + + ------------------------- + Detected 1 error \ No newline at end of file diff --git a/src/test/resources/java-exception.yaml b/src/test/resources/java-exception.yaml new file mode 100644 index 0000000..d8c5ac7 --- /dev/null +++ b/src/test/resources/java-exception.yaml @@ -0,0 +1,34 @@ +Exception in thread "main" java.lang.IllegalArgumentException: Cannot open as a Reader. + at clojure.java.io$fn__11641.invokeStatic(io.clj:288) + at clojure.java.io$fn__11641.invoke(io.clj:288) + at clojure.java.io$fn__11530$G__11519__11537.invoke(io.clj:69) + at clojure.java.io$reader.invokeStatic(io.clj:102) + at clojure.java.io$reader.doInvoke(io.clj:86) + at clojure.lang.RestFn.invoke(RestFn.java:410) + at clojure.lang.AFn.applyToHelper(AFn.java:154) + at clojure.lang.RestFn.applyTo(RestFn.java:132) + at clojure.core$apply.invokeStatic(core.clj:669) + at clojure.core$slurp.invokeStatic(core.clj:7009) + at clojure.core$slurp.doInvoke(core.clj:7009) + at clojure.lang.RestFn.invoke(RestFn.java:410) + at dda.c4k_common.yaml$fn__577.invokeStatic(yaml.clj:39) + at dda.c4k_common.yaml$fn__577.invoke(yaml.clj:38) + at clojure.lang.MultiFn.invoke(MultiFn.java:229) + at dda.c4k_common.yaml$load_as_edn.invokeStatic(yaml.clj:42) + at dda.c4k_common.yaml$load_as_edn.invoke(yaml.clj:41) + at dda.c4k_website.website$replace_common_data.invokeStatic(website.cljc:122) + at dda.c4k_website.website$replace_common_data.invoke(website.cljc:117) + at dda.c4k_website.website$generate_hashfile_volume.invokeStatic(website.cljc:198) + at dda.c4k_website.website$generate_hashfile_volume.invoke(website.cljc:196) + at dda.c4k_website.core$generate_configs.invokeStatic(core.cljc:60) + at dda.c4k_website.core$generate_configs.invoke(core.cljc:45) + at dda.c4k_website.core$k8s_objects.invokeStatic(core.cljc:74) + at dda.c4k_website.core$k8s_objects.invoke(core.cljc:66) + at dda.c4k_common.common$generate_common.invokeStatic(common.cljc:68) + at dda.c4k_common.common$generate_common.invoke(common.cljc:60) + at dda.c4k_common.uberjar$main_common.invokeStatic(uberjar.clj:50) + at dda.c4k_common.uberjar$main_common.invoke(uberjar.clj:31) + at dda.c4k_website.uberjar$_main.invokeStatic(uberjar.clj:9) + at dda.c4k_website.uberjar$_main.doInvoke(uberjar.clj:8) + at clojure.lang.RestFn.applyTo(RestFn.java:137) + at dda.c4k_website.uberjar.main(Unknown Source) \ No newline at end of file diff --git a/src/test/resources/valid.yaml b/src/test/resources/valid.yaml new file mode 100644 index 0000000..6f1afbf --- /dev/null +++ b/src/test/resources/valid.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: config +type: Opaque +data: + JVB_AUTH_PASSWORD: BLA + JICOFO_AUTH_PASSWORD: BLA + JICOFO_COMPONENT_SECRET: BLA \ No newline at end of file