mehcode / config-rs

⚙️ Layered configuration system for Rust applications (with strong support for 12-factor applications).
Apache License 2.0
2.57k stars 213 forks source link

Can't override nested settings #333

Closed sedrik closed 2 years ago

sedrik commented 2 years ago

Given a Config structure like

#[derive(serde::Deserialize, Debug)]
pub struct Settings {
    pub authentication_url: String,
    pub database: DatabaseSettings,
}

#[derive(serde::Deserialize, Debug)]
pub struct DatabaseSettings {
    pub host: String,
}

And the following config setup

    let config = Config::builder()
        .add_source(config::File::from(
            configuration_directory.join("base.yaml"),
        ))
        .add_source(config::Environment::with_prefix("APP"));

I am able to use APP_AUTHENTICATION_URL to override settings.authentication_url but when I try APP_DATABASE_HOST my customization is not detected. Is there something special I need to do to allow env overrides for nested configs?

Using the following entry in Cargo.toml

config = "0.13.0"
szarykott commented 2 years ago

It is more of an educated guess and quick look at env.rs, but did you try something like APP_DATABASE.HOST?

kjaleshire commented 2 years ago

It's non-obvious but you must explicitly set the separator, otherwise the environment source won't attempt to break up the key into nested components:


std::env::set_var("APP_DATABASE_HOST", "postgres://foo.url");

let config = Config::builder()
    .add_source(config::File::from(
        configuration_directory.join("base.yaml"),
    ))
    .add_source(config::Environment::with_prefix("APP").separator("_"))
    .try_deserialize()
    .unwrap();

println!("{}", config.database.host);
// # postgres://foo.url
kjaleshire commented 2 years ago

@szarykott or @mehcode , is there a reason nesting is impossible using env vars by default?

matthiasbeyer commented 2 years ago

It seems to me that the env-var stuff makes more problems than it solves. :cry:

sedrik commented 2 years ago

Ah, setting the separator did indeed solve it.

While the env overwrite logic complicates things it is really nice for running the same docker in different envs.

Thanks for the support, it's a great library to use :heart: