added logic for folders and testlogic
This commit is contained in:
parent
9f4d40ae6a
commit
ecbcac81f8
4 changed files with 65 additions and 11 deletions
|
@ -3,9 +3,10 @@ package org.domaindrivenarchitecture.provs.syspec.domain
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class SpecConfig(
|
data class SyspecConfig(
|
||||||
val command: List<CommandSpec>? = null,
|
val command: List<CommandSpec>? = null,
|
||||||
val file: List<FileSpec>? = null,
|
val file: List<FileSpec>? = null,
|
||||||
|
val folder: List<FolderSpec>? = null,
|
||||||
val host: List<HostSpec>? = null,
|
val host: List<HostSpec>? = null,
|
||||||
val `package`: List<PackageSpec>? = null,
|
val `package`: List<PackageSpec>? = null,
|
||||||
val netcat: List<NetcatSpec>? = null,
|
val netcat: List<NetcatSpec>? = null,
|
||||||
|
@ -13,7 +14,6 @@ data class SpecConfig(
|
||||||
val certificate: List<CertificateFileSpec>? = null,
|
val certificate: List<CertificateFileSpec>? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks that a command executes successfully and
|
* Checks that a command executes successfully and
|
||||||
* (if provided) the specified output is contained in the actual output
|
* (if provided) the specified output is contained in the actual output
|
||||||
|
@ -24,6 +24,9 @@ data class CommandSpec(val command: String, val out: String? = null)
|
||||||
@Serializable
|
@Serializable
|
||||||
data class FileSpec(val name: String, val exists: Boolean = true)
|
data class FileSpec(val name: String, val exists: Boolean = true)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class FolderSpec(val path: String, val exists: Boolean = true)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class HostSpec(val url: String, val expirationDays: Long? = null)
|
data class HostSpec(val url: String, val expirationDays: Long? = null)
|
||||||
|
|
|
@ -5,24 +5,24 @@ import org.domaindrivenarchitecture.provs.framework.core.readFromFile
|
||||||
import org.domaindrivenarchitecture.provs.framework.core.toYaml
|
import org.domaindrivenarchitecture.provs.framework.core.toYaml
|
||||||
import org.domaindrivenarchitecture.provs.framework.core.yamlToType
|
import org.domaindrivenarchitecture.provs.framework.core.yamlToType
|
||||||
import org.domaindrivenarchitecture.provs.syspec.domain.CommandSpec
|
import org.domaindrivenarchitecture.provs.syspec.domain.CommandSpec
|
||||||
import org.domaindrivenarchitecture.provs.syspec.domain.SpecConfig
|
import org.domaindrivenarchitecture.provs.syspec.domain.SyspecConfig
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileWriter
|
import java.io.FileWriter
|
||||||
|
|
||||||
private const val DEFAULT_CONFIG_FILE = "syspec-config.yaml"
|
private const val DEFAULT_CONFIG_FILE = "syspec-config.yaml"
|
||||||
|
|
||||||
// --------------------------------- read ----------------------------------
|
// --------------------------------- read ----------------------------------
|
||||||
internal fun findSpecConfigFromFile(file: ConfigFileName? = null): Result<SpecConfig> = runCatching {
|
internal fun findSpecConfigFromFile(file: ConfigFileName? = null): Result<SyspecConfig> = runCatching {
|
||||||
val filePath = file?.fileName ?: DEFAULT_CONFIG_FILE
|
val filePath = file?.fileName ?: DEFAULT_CONFIG_FILE
|
||||||
if ((filePath == DEFAULT_CONFIG_FILE) && !File(filePath).exists()) {
|
if ((filePath == DEFAULT_CONFIG_FILE) && !File(filePath).exists()) {
|
||||||
// provide default config
|
// provide default config
|
||||||
writeSpecConfigToFile(filePath, SpecConfig(listOf(CommandSpec("echo just_for_demo", "just_for_demo"))))
|
writeSpecConfigToFile(filePath, SyspecConfig(listOf(CommandSpec("echo just_for_demo", "just_for_demo"))))
|
||||||
}
|
}
|
||||||
readFromFile(filePath).yamlToType<SpecConfig>()
|
readFromFile(filePath).yamlToType<SyspecConfig>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal fun findSpecConfigFromResource(resourcePath: String): Result<SpecConfig> = runCatching {
|
internal fun findSpecConfigFromResource(resourcePath: String): Result<SyspecConfig> = runCatching {
|
||||||
val resource = Thread.currentThread().contextClassLoader.getResource(resourcePath)
|
val resource = Thread.currentThread().contextClassLoader.getResource(resourcePath)
|
||||||
requireNotNull(resource) { "Resource $resourcePath not found" }
|
requireNotNull(resource) { "Resource $resourcePath not found" }
|
||||||
resource.readText().yamlToType()
|
resource.readText().yamlToType()
|
||||||
|
@ -30,5 +30,5 @@ internal fun findSpecConfigFromResource(resourcePath: String): Result<SpecConfig
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------- write ----------------------------------
|
// --------------------------------- write ----------------------------------
|
||||||
internal fun writeSpecConfigToFile(fileName: String = DEFAULT_CONFIG_FILE, config: SpecConfig) =
|
internal fun writeSpecConfigToFile(fileName: String = DEFAULT_CONFIG_FILE, config: SyspecConfig) =
|
||||||
FileWriter(fileName).use { it.write(config.toYaml()) }
|
FileWriter(fileName).use { it.write(config.toYaml()) }
|
|
@ -2,6 +2,7 @@ package org.domaindrivenarchitecture.provs.syspec.infrastructure
|
||||||
|
|
||||||
import org.domaindrivenarchitecture.provs.framework.core.Prov
|
import org.domaindrivenarchitecture.provs.framework.core.Prov
|
||||||
import org.domaindrivenarchitecture.provs.framework.core.ProvResult
|
import org.domaindrivenarchitecture.provs.framework.core.ProvResult
|
||||||
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.checkDir
|
||||||
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.checkFile
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.checkFile
|
||||||
import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.isPackageInstalled
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.isPackageInstalled
|
||||||
import org.domaindrivenarchitecture.provs.syspec.domain.*
|
import org.domaindrivenarchitecture.provs.syspec.domain.*
|
||||||
|
@ -10,12 +11,13 @@ import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
fun Prov.verifySpecConfig(conf: SpecConfig) = task {
|
fun Prov.verifySpecConfig(conf: SyspecConfig) = task {
|
||||||
// required to guarantee that at least one result can be provided
|
// required to guarantee that at least one result can be provided
|
||||||
val dummySuccess = ProvResult(true)
|
val dummySuccess = ProvResult(true)
|
||||||
|
|
||||||
conf.command?.let { task("CommandSpecs") { for (spec in conf.command) verify(spec); dummySuccess } }
|
conf.command?.let { task("CommandSpecs") { for (spec in conf.command) verify(spec); dummySuccess } }
|
||||||
conf.file?.let { task("FileSpecs") { for (spec in conf.file) verify(spec); dummySuccess } }
|
conf.file?.let { task("FileSpecs") { for (spec in conf.file) verify(spec); dummySuccess } }
|
||||||
|
conf.folder?.let { task("FolderSpecs") { for (spec in conf.folder) verify(spec); dummySuccess } }
|
||||||
conf.host?.let { task("HostSpecs") { for (spec in conf.host) verify(spec); dummySuccess } }
|
conf.host?.let { task("HostSpecs") { for (spec in conf.host) verify(spec); dummySuccess } }
|
||||||
conf.`package`?.let { task("PackageSpecs") { for (spec in conf.`package`) verify(spec); dummySuccess } }
|
conf.`package`?.let { task("PackageSpecs") { for (spec in conf.`package`) verify(spec); dummySuccess } }
|
||||||
conf.netcat?.let { task("NetcatSpecs") { for (spec in conf.netcat) verify(spec); dummySuccess } }
|
conf.netcat?.let { task("NetcatSpecs") { for (spec in conf.netcat) verify(spec); dummySuccess } }
|
||||||
|
@ -49,6 +51,11 @@ fun Prov.verify(file: FileSpec) {
|
||||||
verify(actualExists == file.exists, "File [${file.name}] does ${actualExists.falseToNot()}exist.")
|
verify(actualExists == file.exists, "File [${file.name}] does ${actualExists.falseToNot()}exist.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Prov.verify(folder: FolderSpec) {
|
||||||
|
val actualExists = checkDir(folder.path)
|
||||||
|
verify(actualExists == folder.exists, "Folder [${folder.path}] does ${actualExists.falseToNot()}exist.")
|
||||||
|
}
|
||||||
|
|
||||||
fun Prov.verify(hostspec: HostSpec) {
|
fun Prov.verify(hostspec: HostSpec) {
|
||||||
// see https://serverfault.com/questions/661978/displaying-a-remote-ssl-certificate-details-using-cli-tools
|
// see https://serverfault.com/questions/661978/displaying-a-remote-ssl-certificate-details-using-cli-tools
|
||||||
val res =
|
val res =
|
||||||
|
|
|
@ -1,15 +1,59 @@
|
||||||
package org.domaindrivenarchitecture.provs.syspec.infrastructure
|
package org.domaindrivenarchitecture.provs.syspec.infrastructure
|
||||||
|
|
||||||
|
import org.domaindrivenarchitecture.provs.framework.core.ProvResult
|
||||||
|
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.createDir
|
||||||
|
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.fileContainsText
|
||||||
|
import org.domaindrivenarchitecture.provs.syspec.domain.FolderSpec
|
||||||
import org.domaindrivenarchitecture.provs.syspec.domain.SocketSpec
|
import org.domaindrivenarchitecture.provs.syspec.domain.SocketSpec
|
||||||
import org.domaindrivenarchitecture.provs.syspec.domain.SpecConfig
|
import org.domaindrivenarchitecture.provs.syspec.domain.SyspecConfig
|
||||||
|
import org.domaindrivenarchitecture.provs.test.defaultTestContainer
|
||||||
|
import org.domaindrivenarchitecture.provs.test.tags.ContainerTest
|
||||||
import org.domaindrivenarchitecture.provs.test.testLocal
|
import org.domaindrivenarchitecture.provs.test.testLocal
|
||||||
|
import org.junit.jupiter.api.Assertions
|
||||||
|
import org.junit.jupiter.api.Assertions.assertFalse
|
||||||
|
import org.junit.jupiter.api.Assertions.assertTrue
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
internal class VerificationKtTest {
|
internal class VerificationKtTest {
|
||||||
|
|
||||||
|
@ContainerTest
|
||||||
|
fun test_verify_folder_existing() {
|
||||||
|
// given
|
||||||
|
val dir = "/home/testuser/testdir"
|
||||||
|
val prov = defaultTestContainer()
|
||||||
|
prov.createDirs(dir)
|
||||||
|
|
||||||
|
// when
|
||||||
|
val res = defaultTestContainer().task {
|
||||||
|
verify(FolderSpec(dir))
|
||||||
|
ProvResult(true) // dummy
|
||||||
|
}
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertTrue(res.success)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ContainerTest
|
||||||
|
fun test_verify_folder_nonexisting() {
|
||||||
|
// given
|
||||||
|
val dir = "/home/testuser/testdir2"
|
||||||
|
val prov = defaultTestContainer()
|
||||||
|
|
||||||
|
// when
|
||||||
|
val res = defaultTestContainer().task {
|
||||||
|
verify(FolderSpec(dir))
|
||||||
|
ProvResult(true) // dummy
|
||||||
|
}
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertFalse(res.success)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_verify_empty_SpecConfig() {
|
fun test_verify_empty_SpecConfig() {
|
||||||
assert(testLocal().verifySpecConfig(SpecConfig()).success)
|
assert(testLocal().verifySpecConfig(SyspecConfig()).success)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in a new issue