From b4b7605e1f947ef0c58d94354c10fd74fd010a53 Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Thu, 23 Jan 2020 14:04:42 +0100 Subject: Use envy to parse environment variables for Config This patch uses the envy crate to parse the environment. A variable NITROCLI_KEY can be used to overwrite the configuration for *key*. This has the side effect that the NITROCLI_NO_CACHE variable is evaluated as a boolean variable (instead of only checking whether it is set). We also accept two new variables, NITROCLI_MODEL and NITROCLI_VERBOSITY. --- CHANGELOG.md | 7 +++++++ Cargo.lock | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 6 ++++++ src/config.rs | 20 ++++++++++++++++++-- src/main.rs | 7 +------ 5 files changed, 80 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c22351..17c176c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ Unreleased - Added support for configuration files - Added `toml` dependency in version `0.5.6` - Added `serde` dependency in version `1.0.114` + - Added `envy` dependency in version `0.4.1` + - Added `merge` dependency in version `0.1.0` 0.3.4 @@ -10,6 +12,11 @@ Unreleased - Changed default OTP format from `hex` to `base32` - Improved error reporting format and fidelity - Added `anyhow` dependency in version `1.0.32` +- Reworked environment variables: + - Added the `NITROCLI_MODEL` and `NITROCLI_VERBOSITY` variables that + set the defaults for the `--model` and `--verbose` options + - Changed the handling of the `NITROCLI_NO_CACHE` variable to check + the value of the variable instead of only the presence - Updated minimum required Rust version to `1.42.0` - Bumped `nitrokey` dependency to `0.7.1` - Bumped `proc-macro2` dependency to `1.0.19` diff --git a/Cargo.lock b/Cargo.lock index 6893b95..3eff078 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,6 +15,12 @@ version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b" +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + [[package]] name = "base32" version = "0.4.0" @@ -50,6 +56,15 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "envy" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f938a4abd5b75fe3737902dbc2e79ca142cc1526827a9e40b829a086758531a9" +dependencies = [ + "serde", +] + [[package]] name = "getrandom" version = "0.1.14" @@ -88,13 +103,37 @@ version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" +[[package]] +name = "merge" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10bbef93abb1da61525bbc45eeaff6473a41907d19f8f9aa5168d214e10693e9" +dependencies = [ + "merge_derive", + "num-traits", +] + +[[package]] +name = "merge_derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "209d075476da2e63b4b29e72a2ef627b840589588e71400a25e3565c4f849d07" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "nitrocli" version = "0.3.4" dependencies = [ "anyhow", "base32", + "envy", "libc", + "merge", "nitrokey", "nitrokey-test", "nitrokey-test-state", @@ -142,6 +181,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a59b732ed6d5212424ed31ec9649f05652bcbc38f45f2292b27a6044e7098803" +[[package]] +name = "num-traits" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" +dependencies = [ + "autocfg", +] + [[package]] name = "proc-macro-error" version = "1.0.2" diff --git a/Cargo.toml b/Cargo.toml index 23602ec..2e2e47f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,9 +52,15 @@ version = "1.0" [dependencies.base32] version = "0.4.0" +[dependencies.envy] +version = "0.4.1" + [dependencies.libc] version = "0.2" +[dependencies.merge] +version = "0.1" + [dependencies.nitrokey] version = "0.7.1" diff --git a/src/config.rs b/src/config.rs index 850d217..2e8f3ba 100644 --- a/src/config.rs +++ b/src/config.rs @@ -26,21 +26,31 @@ use anyhow::Context as _; /// The configuration for nitrocli, usually read from configuration /// files and environment variables. -#[derive(Clone, Copy, Debug, Default, PartialEq, serde::Deserialize)] +#[derive(Clone, Copy, Debug, Default, PartialEq, merge::Merge, serde::Deserialize)] pub struct Config { /// The model to connect to. pub model: Option, /// Whether to bypass the cache for all secrets or not. + #[merge(strategy = merge::bool::overwrite_false)] #[serde(default)] pub no_cache: bool, /// The log level. + #[merge(strategy = merge::num::overwrite_zero)] #[serde(default)] pub verbosity: u8, } impl Config { pub fn load() -> anyhow::Result { - load_user_config().map(|o| o.unwrap_or_default()) + use merge::Merge as _; + + let mut config = Config::default(); + if let Some(user_config) = load_user_config()? { + config.merge(user_config); + } + config.merge(load_env_config()?); + + Ok(config) } pub fn update(&mut self, args: &args::Args) { @@ -62,6 +72,12 @@ fn load_user_config() -> anyhow::Result> { } } +fn load_env_config() -> anyhow::Result { + envy::prefixed("NITROCLI_") + .from_env() + .context("Failed to parse environment variables") +} + pub fn read_config_file(path: &path::Path) -> anyhow::Result { let s = fs::read_to_string(path) .with_context(|| format!("Failed to read configuration file '{}'", path.display()))?; diff --git a/src/main.rs b/src/main.rs index 3535a91..b53358e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -84,7 +84,6 @@ const NITROCLI_USER_PIN: &str = "NITROCLI_USER_PIN"; const NITROCLI_NEW_ADMIN_PIN: &str = "NITROCLI_NEW_ADMIN_PIN"; const NITROCLI_NEW_USER_PIN: &str = "NITROCLI_NEW_USER_PIN"; const NITROCLI_PASSWORD: &str = "NITROCLI_PASSWORD"; -const NITROCLI_NO_CACHE: &str = "NITROCLI_NO_CACHE"; trait Stdio { fn stdio(&mut self) -> (&mut dyn io::Write, &mut dyn io::Write); @@ -206,11 +205,7 @@ fn main() { let mut stderr = io::stderr(); let rc = match config::Config::load() { - Ok(mut config) => { - if env::var_os(NITROCLI_NO_CACHE).is_some() { - config.no_cache = true; - } - + Ok(config) => { let args = env::args().collect::>(); let ctx = &mut RunCtx { stdout: &mut stdout, -- cgit v1.2.1