-
Notifications
You must be signed in to change notification settings - Fork 11
Description
Having native environment variable injection is a powerful feature as it allows 12-factor type configuration, however it doesn't play well with non-string types (AFAICS; happy to be proven wrong).
e.g. If you have the following config definitions (based on a real use-case):
#[derive(Deserialize)]
pub struct Insecure {
pub port: u16,
pub redirect: bool,
}
#[derive(Deserialize)]
pub struct TlsConfig {
pub port: u16,
}
#[derive(Deserialize)]
pub struct Config {
pub insecure: Insecure,
pub tls: TlsConfig,
}And this config file:
let {
$env_INSECURE_PORT = 80
$env_INSECURE_REDIRECT = true
$env_TLS_PORT = 443
} in {
insecure = {
port = $env_INSECURE_PORT
redirect = $env_INSECURE_REDIRECT
}
tls = {
port = $env_TLS_PORT
}
}
If you deserialise with no environment variables set then it works fine. However setting any of the env-vars will result in DeserializationError("Expected integer (u16), found 'String(\"8080\")'" (or DeserializationError("Expected boolean, found 'String(\"false\")'")).
I'm not sure if there's any simple workaround for this? It looks like the only way is to make any variables that may be provided from the environment into strings an have serde parse them into the appropriate type (with serde-with or similar). However the user could potentially supply any variable, so everything would end up being a string.