Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

layer and yaml don't work together as expected #55

Closed
benjishults opened this issue Apr 24, 2020 · 3 comments
Closed

layer and yaml don't work together as expected #55

benjishults opened this issue Apr 24, 2020 · 3 comments
Labels

Comments

@benjishults
Copy link

benjishults commented Apr 24, 2020

I'm finding that toValue fails with a layered configs.

Test code:

package st.legevent

import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import com.uchuhimo.konf.BaseConfig
import com.uchuhimo.konf.Config
import com.uchuhimo.konf.source.LoadException
import com.uchuhimo.konf.source.yaml
import com.uchuhimo.konf.toValue
import org.junit.Test

class TestConfigTestReport {

    @Test
    fun succeed1() {
        val config = Config()
            .from.yaml.resource("testKonf.yml")

        loadAndPrint(config)
    }

    @Test
    fun succeed2() {
        val config = BaseConfig(
            mapper = ObjectMapper(/*YAMLFactory()*/)
                .registerKotlinModule()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        )
            .from.yaml.resource("testKonf.yml")

        loadAndPrint(config)
    }

    @Test(expected = LoadException::class)
    fun fail1() {
        val config = Config()
            .from.yaml.resource("testKonf.yml")
            .from.yaml.file(
                System.getenv("SERVICE_CONFIG") ?: "/opt/legacy-event-service/conf/legacy-event-service.yml",
                true
            )

        loadAndPrint(config)
    }

    @Test(expected = LoadException::class)
    fun fail2() {
        val config = BaseConfig(
            mapper = ObjectMapper(/*YAMLFactory()*/)
                .registerKotlinModule()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        )
            .from.yaml.resource("testKonf.yml")
            .from.yaml.file(
                System.getenv("SERVICE_CONFIG") ?: "/opt/legacy-event-service/conf/legacy-event-service.yml",
                true
            )

        loadAndPrint(config)
    }

    @Test(expected = LoadException::class)
    fun fail3() {
        val config = BaseConfig(
            mapper = ObjectMapper(/*YAMLFactory()*/)
                .registerKotlinModule()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        )
            .from.yaml.resource("testKonf.yml")
            .from.env()

        loadAndPrint(config)
    }

    @Test(expected = LoadException::class)
    fun fail4() {
        val config = Config()
            .from.yaml.resource("testKonf.yml")
            .from.env()

        loadAndPrint(config)
    }

    @Test(expected = LoadException::class)
    fun fail5() {
        val config = BaseConfig(
            mapper = ObjectMapper(/*YAMLFactory()*/)
                .registerKotlinModule()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        )
            .from.yaml.resource("testKonf.yml")
            .from.systemProperties()

        loadAndPrint(config)
    }

    @Test(expected = LoadException::class)
    fun fail6() {
        val config = Config()
            .from.yaml.resource("testKonf.yml")
            .from.systemProperties()

        loadAndPrint(config)
    }

}

private fun loadAndPrint(config: Config) {
    val db = config.toValue<ConfigTestReport>()

    println(db)
}

data class ConfigTestReport(val db: Map<String, *>)

Contents of src/test/resources/testKonf.yml:

db:
  driverClassName: org.h2.Driver
  url: 'jdbc:h2:mem:db;DB_CLOSE_DELAY=-1'
@benjishults
Copy link
Author

I figured out how to get it to work the way I wanted. Feel free to add something like this to your docs:

import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import com.uchuhimo.konf.BaseConfig
import com.uchuhimo.konf.ConfigSpec
import com.uchuhimo.konf.source.Source
import com.uchuhimo.konf.source.yaml
import com.uchuhimo.konf.toValue
import kotlin.test.assertEquals
import org.junit.Test

class TestConfigTest {

    @Test
    fun succeed() {
        System.setProperty("db.url", "url from sys props")
        System.setProperty("db.driverClassName", "class from sys props")
        val configPreferringSystemProperties = BaseConfig(
            specsInLayer = mutableListOf(ConfigSpec("")),
            mapper = ObjectMapper()
                .registerKotlinModule()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        )
            .withSource(
                Source.from.yaml.resource("testKonf.yml") +
                    Source.from.yaml.file(
                        System.getenv("SERVICE_CONFIG") ?: "/opt/non-existent-file.yml",
                        true
                    ) +
                    Source.from.systemProperties()
            )
        val configPreferringYamlFile = BaseConfig(
            specsInLayer = mutableListOf(ConfigSpec("")),
            mapper = ObjectMapper()
                .registerKotlinModule()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        )
            .withSource(
                Source.from.systemProperties() +
                    Source.from.yaml.file(
                        System.getenv("SERVICE_CONFIG") ?: "/opt/non-existent-file.yml",
                        true
                    ) +
                    Source.from.yaml.resource("testKonf.yml")
            )

        val configYaml = configPreferringYamlFile.toValue<ConfigTest>()
        val configSystem = configPreferringSystemProperties.toValue<ConfigTest>()
        val configDbYaml = configPreferringYamlFile.toValue<ConfigTest2>()
        val configDbSystem = configPreferringSystemProperties.toValue<ConfigTest2>()
        val dbYaml = configPreferringYamlFile.at("db").toValue<DB>()
        val dbSystem = configPreferringSystemProperties.at("db").toValue<DB>()

        assertEquals("url from sys props", configSystem.db["url"])
        assertEquals("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1", configYaml.db["url"])

        assertEquals("url from sys props", configDbSystem.db.url)
        assertEquals("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1", configDbYaml.db.url)

        assertEquals("url from sys props", dbSystem.url)
        assertEquals("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1", dbYaml.url)
    }

}

data class ConfigTest(val db: Map<String, String> /*= emptyMap<String, Any>()*/)
data class ConfigTest2(val db: DB /*= emptyMap<String, Any>()*/)
data class DB(val driverClassName: String, val url: String)

testKonf.yml:

db:
  driverClassName: org.h2.Driver
  url: 'jdbc:h2:mem:db;DB_CLOSE_DELAY=-1'

other:
  thing: hi

@stale
Copy link

stale bot commented Jul 27, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 30 days if no further activity occurs, but feel free to re-open a closed issue if needed.

@stale stale bot added the stale label Jul 27, 2020
@uchuhimo uchuhimo added 0.23.0 and removed stale labels Oct 10, 2020
@uchuhimo
Copy link
Owner

@benjishults I have released a new version v0.23.0 that can pass all your tests except fail4, which should fail on unknown properties from the environment variables. You can try it now. Any further feedback is welcome.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants