diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ConfigMapPropertiesPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ConfigMapPropertiesPatcher.kt new file mode 100644 index 0000000000000000000000000000000000000000..b1c168987d894bd33b848de10c67476628fde3e0 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ConfigMapPropertiesPatcher.kt @@ -0,0 +1,37 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.ConfigMap +import io.fabric8.kubernetes.api.model.HasMetadata +import java.io.StringReader +import java.io.StringWriter +import java.util.Properties + +/** + * The ConfigMapYamlPatcher allows to add/modify a key-value pair in a .properties file of a ConfigMap + * + * @property fileName of the .properties file in the ConfigMap that should be modified. + * @property variableName Name of the environment variable to be patched. + */ +class ConfigMapPropertiesPatcher( + private val fileName: String, + private val variableName: String, +) : AbstractStringPatcher() { + + override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata { + if (resource is ConfigMap) { + val propertiesFile = resource.data[fileName] + + // Read properties string + val properties = Properties().also { it.load(StringReader(propertiesFile)) } + + // Change value + properties.setProperty(this.variableName, value) + + // Convert back to String and set in Kubernetes resource + val writer = StringWriter() + properties.store(writer, null) + resource.data[fileName] = writer.toString() + } + return resource + } +} diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt index 4b75999e70197f775e7fa610eeb6700545bf6869..f469eaee39e5e2eb9e5aa0ae2bd8346eabf3006d 100644 --- a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt @@ -78,6 +78,15 @@ class PatcherFactory { suffix = patcher.properties["suffix"], factor = patcher.properties["factor"]?.toInt(), ) + "ConfigMapPropertiesPatcher" -> DecoratingPatcher( + ConfigMapPropertiesPatcher( + fileName = patcher.properties["fileName"] ?: throwInvalid(patcher), + variableName = patcher.properties["variableName"] ?: throwInvalid(patcher) + ), + prefix = patcher.properties["prefix"], + suffix = patcher.properties["suffix"], + factor = patcher.properties["factor"]?.toInt(), + ) "NamePatcher" -> NamePatcher() "ServiceSelectorPatcher" -> ServiceSelectorPatcher( variableName = patcher.properties["label"] ?: throwInvalid(patcher) diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ConfigMapPropertiesPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ConfigMapPropertiesPatcherTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..493343baf77350c09fb7c16ca93bb1215660d3db --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ConfigMapPropertiesPatcherTest.kt @@ -0,0 +1,50 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.ConfigMap +import io.fabric8.kubernetes.api.model.ConfigMapBuilder +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource + +internal class ConfigMapPropertiesPatcherTest { + + private lateinit var configMap: ConfigMap + + private val patcher = ConfigMapPropertiesPatcher("some-file.properties", "second.prop.value") + + @BeforeEach + fun setUp() { + val data = mapOf( + "some-file.properties" to """ + first.properties.value = some-test + second.prop.value = 1 + third = 1234 + """.trimIndent() + ) + + this.configMap = ConfigMapBuilder() + .withNewMetadata() + .withName("example") + .endMetadata() + .addToData(data) + .build() + } + + @ParameterizedTest + @ValueSource(strings = ["some-string", "42", "42.42", "true"]) + fun setSettingString(inputValue: String) { + val patched = patcher.patchSingleResource(this.configMap, inputValue) + assertTrue(patched is ConfigMap) + //patched.let { it as ConfigMap }.data + patched as ConfigMap + val properties = patched.data["some-file.properties"] + assertTrue(properties != null) + val matchLines = properties!!.lines().filter { it.startsWith("second.prop.value") } + assertEquals(1, matchLines.size) + val value = matchLines[0].split("=").getOrNull(1) + assertEquals(inputValue, value) + } + + +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ConfigMapYamlPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ConfigMapYamlPatcherTest.kt index 474080b5cea34a621d387e6f0a805a9cb5e1820c..38e807dc4fd06c1974c0ef3b2f9d10dc7f6bbab1 100644 --- a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ConfigMapYamlPatcherTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ConfigMapYamlPatcherTest.kt @@ -20,6 +20,7 @@ internal class ConfigMapYamlPatcherTest { val data = mapOf( "some-file.yaml" to """ first: some-test + # some comment: with colon second: 1 third: 1234 """.trimIndent()