config-rs: Cannot get config-rs to read env variables
Getting the following error when trying to get an environmental variable from config-rs:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: configuration property "DEV_SERVER_ADDRESS" not found', src/app/config.rs:14:27 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
use config::Config;
use lazy_static;
lazy_static! {
#[derive(Debug)]
pub static ref CONFIG: Config = Config::builder()
.add_source(config::Environment::with_prefix("APP_NAME").separator("_"))
.add_source(config::File::with_name("AppName"))
.build()
.unwrap();
}
pub fn get<'a, T: serde::Deserialize<'a>>(key: &str) -> T {
CONFIG.get::<T>(&key).unwrap()
}
ENV variable:
export APP_NAME_DEV_SERVER_ADDRESS="testtt dev addr"
Trying to get the variable in main:
#[actix_web::main]
async fn main() -> result::Result<(), io::Error> {
let dev_server_address: String = app::config::get("DEV_SERVER_ADDRESS");
println!("DEV_SERVER_ADDRESS: {}", dev_server_address);
...
What am I doing wrong?
About this issue
- Original URL
- State: open
- Created 2 years ago
- Reactions: 3
- Comments: 16
It will work as expected if used like this:
then
APP__BRAINTREE__MERCHANT_ID
will be correctly parsed toBraintree.merchant_id
with snake_case setting name. Probably an example could be added to cover this case.FWIW, I also cannot get this working with 0.13.2 and nested structs in my config.
When I use
.add_source(config::Environment::with_prefix("TEST"))
then I can successfully use environment variables likeTEST_MYSTRUCT.MYFIELD
However, when I use
.add_source(config::Environment::with_prefix("TEST").separator("_"))
, no environment variables seem to work at all:TEST_MYSTRUCT.MYFIELD
– no longer works, which is expected since the separator should be_
TEST_MYSTRUCT_MYFIELD
– does not work, which is NOT expectedSomething about
separator(...)
does not seem to behave as I would expectIt would be good to surface this in the docs, leaving a comment here so I remember to come back later and do this.
I just spent half an hour running a debugger getting to the bottom of this, only to realize that fundamentally
_
as the separator while having_
in the variable names will never work, based on the approach in the code. I assumed that it was doing something like ‘for each variable in the config schema, check for an env-var’, which would be predictable and scale with the size of the schema. But instead it’s doing “check each envvar and if it matches the rules, try to insert it to the global config map”, without any schema-enriched info, which doesn’t work because_
s get translated to.
s. The approach taken also doesn’t seem to surface a warning anywhere when a close-but-not-quite envvar was set but is having no impact.It may also be good to default the separator to
__
, since_
will be so common in struct field names.What if for
person.first_name
you use a a dunderscore__
as theseparator
? Then you could writePERSON__FIRST_NAME
and thereplace
would change it toPERSON.FIRST_NAME
?meh.
All this is really inconvenient. I hope I can make this better in the future with the rewrite I am planning.