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

No support for having no prefix? #41

Closed
golx opened this issue Oct 22, 2019 · 7 comments
Closed

No support for having no prefix? #41

golx opened this issue Oct 22, 2019 · 7 comments

Comments

@golx
Copy link

golx commented Oct 22, 2019

Hello,

Say I have the following set of existing environment variables within my infrastructure:

DATABASE=foo.example.com
DATABASE_USER=john
DATABASE_PASS=doe

I want to, without modifying them, be able to resolve these variables from both YAML file and environment variables, with latter having precedence.

It seems that such naming is discouraged by konf.

I tried the following:

object Root : ConfigSpec("") {
    val DATABASE by required<String>()
    val DATABASE_USER by required<String>()
    val DATABASE_PASS by required<String>()
}

Config {
    addSpec(Root)
}
        .from.yaml.resource("server.yml")
        .from.env()
        .from.systemProperties()

With YAML file having similar structure to the above:

DATABASE: foo.example.com
DATABASE_USER: john
DATABASE_PASS: doe

Sadly, the moment DATABASE_PASS or similar variable appears in the env, I get the following exception:

Exception in thread "main" com.uchuhimo.konf.source.LoadException: fail to load DATABASE
	at com.uchuhimo.konf.source.SourceKt.loadItem(Source.kt:519)
	at com.uchuhimo.konf.source.SourceKt$load$1.invoke(Source.kt:532)
	at com.uchuhimo.konf.source.SourceKt$load$1.invoke(Source.kt)
	at com.uchuhimo.konf.BaseConfig.lock(BaseConfig.kt:65)
	at com.uchuhimo.konf.source.SourceKt.load(Source.kt:530)
	at com.uchuhimo.konf.BaseConfig.withSource(BaseConfig.kt:585)
	at com.uchuhimo.konf.source.DefaultLoaders.env(DefaultLoaders.kt:118)
	at example.server.ServerSpecKt.getApplicationConfig(ServerSpec.kt:41)
	at example.StarterAppKt.initializeApplicationContext(StarterApp.kt:43)
	at example.StarterAppKt.main(StarterApp.kt:68)
	at example.StarterAppKt.main(StarterApp.kt)
Caused by: com.uchuhimo.konf.source.ObjectMappingException: unable to map source com.uchuhimo.konf.ContainerNode@33c2bd in [type: system-environment] to value of type String
	at com.uchuhimo.konf.source.SourceKt.toValue(Source.kt:820)
	at com.uchuhimo.konf.source.SourceKt.loadItem(Source.kt:512)
	... 10 more
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token
 at [Source: UNKNOWN; line: -1, column: -1]
	at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
	at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1343)
	at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1139)
	at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1093)
	at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:63)
	at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:10)
	at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:3985)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2343)
	at com.uchuhimo.konf.source.SourceKt.toValue(Source.kt:815)
	... 11 more

Is there a mode to rely on simple naming without inferred nesting?

@uchuhimo
Copy link
Owner

uchuhimo commented Oct 23, 2019

@golx There is no mode to disable inferred nesting, you can define a new source as a workaround. Here is an example:

fun envSource(): Source {
    return FlatSource(
        System.getenv().filter { (key, _) ->
            !(key.startsWith('.') || key.endsWith('.'))
        }.toSortedMap(),
        type = "system-environment",
        allowConflict = true
    )
}

Config {
    addSpec(Root)
}
        .from.yaml.resource("server.yml")
        .withSource(envSource())
        .from.systemProperties()

@golx
Copy link
Author

golx commented Oct 23, 2019

@uchuhimo thanks! your workaround worked for me.
Any plans to add such functionality in the future? This could help those like me who would want to introduce konf with minimal impact to their existing infrastructure.

In any case, this ticket can now be closed.

@DanySK
Copy link
Contributor

DanySK commented Oct 24, 2019

I hit the same issue as well. In my case, it's a TOML configuration of the kind:

[ arbitraryname1 ]
description = "..."

[ arbitraryname1.configuration ]
...

[ arbitraryname1.expectations ]
...

there are several entries with arbitrary prefixes

@uchuhimo
Copy link
Owner

@DanySK Would you like to provide a minimal code snippet of your ConfigSpec and Config for me to debug?

@uchuhimo
Copy link
Owner

@golx I would like to add this feature to the next release. Thank you for your proposal!

@uchuhimo
Copy link
Owner

@golx I have added this feature in v0.22.0. You can use the following code to achieve the same purpose:

Config {
    addSpec(Root)
}.from.env(nested=false)

@golx
Copy link
Author

golx commented Dec 24, 2019

Thanks! We'll give it a try.

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

No branches or pull requests

3 participants