I'm using the standard Kotlin application.conf behavior to use environment variables to override config values. So my HOCON file looks like this (simplified):
Then I implemented a configuration class which is (very simplified) like this:
enum class Stage {
DEV,
PROD
}
// this interface is needed to be able to process the configuration
sealed interface Configuration
data class StageConfig(
val host: String,
) : Configuration
object HostConfiguration {
data class HostConfig(
val stages: Map<Stage, StageConfig>,
val anotherProperty: String,
)
private val hostConfig: HostConfig
init {
// by the way: how can i avoid this and read the nested configuration direct into HostConfig???
data class InternalHostConfig(
val prod: Configuration,
val dev: Configuration,
val anotherProperty: String,
)
val config = ConfigLoaderBuilder.default()
.addPropertySource(PropertySource.resource("/host.conf"))
.build()
.loadConfigOrThrow<InternalHostConfig>()
hostConfig = HostConfig(
mapOf(
Stage.PROD to (config.prod as StageConfig),
Stage.DEV to (config.dev as StageConfig)
),
config.anoherProperty,
)
}
fun stageConfig(stage: Stage): StageConfig = hostConfig.stages[stage]!!
fun anotherProperty() = hostConfig.anotherProperty
}
At least I wrote some unit tests for my configuration with the aid of Kotest. Kotest has a feature to inject environment variables into a test (which works fine). This tests runs successful when starting them from the IntelliJ editor pane but are failing when running them in a Gradle build or with the Kotest runner. In this cases config.host contains "myprodhost:myport". Here is the, again very simpolified code:
class HostConfigurationKtTest : FunSpec({
test("Environment variables should be used when present") {
withEnvironment(
mapof(
"FIXED_PREFIX_MY_PROD_HOST" to "host_url_prod",
)
) {
// This is successful
System.getenv("FIXED_PREFIX_MY_PROD_HOST") shouldBe "host_url_prod"
val prodConfig = HostConfiguration.stageConfig(Stage.PROD)
// This will fail
prodConfig.host shouldBe "broker_url_prod"
}
}
})
I've read about the EnvironmentVariablesOverridePropertySource but i can't prefix environment variables with config.override. In our production environment the environment variables are generated by a tool which follows a specific naming convention which i can't override. For example, if i declare a variable MY_HOST in the tool, a prefix FIXED_PREFIX is automatically added.
I used hopelite because my real configuration is much more complicated and the library helps me to save a lot of work in opposite to use the standard application.conf.
I'm using the standard Kotlin application.conf behavior to use environment variables to override config values. So my HOCON file looks like this (simplified):
Then I implemented a configuration class which is (very simplified) like this:
At least I wrote some unit tests for my configuration with the aid of Kotest. Kotest has a feature to inject environment variables into a test (which works fine). This tests runs successful when starting them from the IntelliJ editor pane but are failing when running them in a Gradle build or with the Kotest runner. In this cases
config.host
contains "myprodhost:myport". Here is the, again very simpolified code:I've read about the
EnvironmentVariablesOverridePropertySource
but i can't prefix environment variables withconfig.override
. In our production environment the environment variables are generated by a tool which follows a specific naming convention which i can't override. For example, if i declare a variableMY_HOST
in the tool, a prefixFIXED_PREFIX
is automatically added.Interesting, when I change my code like you do in the EnvironmentVariablesOverridePropertySourceTest the test fails always.
I used hopelite because my real configuration is much more complicated and the library helps me to save a lot of work in opposite to use the standard application.conf.
Before I forget, my environment is:
IntelliJ IDEA Ultimate 2023.3 Kotlin 1.9.21 targeting Java 21 Kotest 5.8.0 hopelite 2.7.5