uchuhimo / konf

A type-safe cascading configuration library for Kotlin/Java/Android, supporting most configuration formats
Apache License 2.0
309 stars 28 forks source link

Load configuration values from optional files or resources #33

Closed aneveux closed 5 years ago

aneveux commented 5 years ago

Hello!

Thanks a lot for all the good work you put in that library, it looks really nice! I tested it on simple use cases and everything is going really fine for me, but I have one use case I'd like to use it for, and I can't manage to find a solution yet.

I had a look at the documentation, the source code, and all past issues, but couldn't manage to find an answer, which is why I created this issue.

My concern is pretty simple, right now I'm writting this:

val configuration = Config { addSpec(ServerSpec) }
    .from.yaml.resource("production.yml")
    .from.yaml.resource("local.yml")
    .from.yaml.watchFile("./debug.yml")
    .from.env()
    .from.systemProperties()

Because what I'd like to have is:

Right now my issue is that if something isn't present, I have exceptions such as: java.io.FileNotFoundException: config.yml (No such file or directory). Which is normal since the file doesn't exist, but I'd like the framework just to ignore that source silently.

From my point of view, I could either write something like:

val configuration = Config { addSpec(ServerSpec) }
    .disable(Feature.FAIL_ON_UNFOUND_SOURCE)
    .from.yaml.resource("production.yml")
    .from.yaml.resource("local.yml")
    .from.yaml.watchFile("./debug.yml")
    .from.env()
    .from.systemProperties()

or something like:

val configuration = Config { addSpec(ServerSpec) }
    .from.optional.yaml.resource("production.yml")
    .from.optional.yaml.resource("local.yml")
    .from.optional.yaml.watchFile("./debug.yml")
    .from.env()
    .from.systemProperties()

Of course if there are any other solutions (existing or not) you have in mind, do not hesitate to let me know.

What do you think about this use case? If I can be of any help regarding the resolution of that issue, do not hesitate to tell me.

Thanks a lot for your attention and your help! Have a great day!

aneveux commented 5 years ago

Just for information, I tested the #34 pull request over my actual example, and it does the job :)

Don't hesitate to let me know how you'd like (if you'd like) to solve such issue :)

Have a great day!

lfmunoz commented 5 years ago

I have the same exact issue I want to load a file only if it exists, if it doesn't exist don't do anything.

lfmunoz commented 5 years ago

Workaround

  val configDefault = Config { addSpec(ServerSpec) }
    .from.yaml.resource("default.yml")

  val configLoad =
   try {
     Config { addSpec(ServerSpec) }
       .from.yaml.file("config.yml")
       .from.env() // SERVER_HOST=0.0.0.0
       .from.systemProperties()  // -Dserver.host=0.0.0.0 -Dserver.port=8080
   } catch (e : FileNotFoundException) {
      Config{ addSpec(ServerSpec) }
   }

  val finalConfig =  configDefault + configLoad 
uchuhimo commented 5 years ago

@aneveux @lfmunoz I release a new version v0.14.0 that contains the required feature. Now file/URL/resource/Git sources have a new argument optional to indicate whether they are optional or not. optional is false by default, but you can use config.enable(Feature.OPTIONAL_SOURCE_BY_DEFAULT) to make optional=true by default for all default loaders. You can give them a try.

aneveux commented 5 years ago

Thank you very much @uchuhimo! I'll give it a try tomorrow :)

Thanks for your time and your attention! Have a great day!