use crate::{error::BindError, source::SourceRegistry};
pub trait Bindable {
fn bind_secrets(&mut self, registry: &SourceRegistry) -> Result<(), Vec<BindError>>;
}
pub fn bind_all<T: Bindable>(
target: &mut T,
registry: &SourceRegistry,
) -> Result<(), Vec<BindError>> {
target.bind_secrets(registry)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{Secret, SourceRegistry};
struct Config {
key_a: Secret<String>,
key_b: Secret<String>,
}
impl Bindable for Config {
fn bind_secrets(&mut self, registry: &SourceRegistry) -> Result<(), Vec<BindError>> {
let mut errors = Vec::new();
if let Err(e) = self.key_a.bind(registry) {
errors.push(e);
}
if let Err(e) = self.key_b.bind(registry) {
errors.push(e);
}
if errors.is_empty() {
Ok(())
} else {
Err(errors)
}
}
}
#[test]
fn bind_all_populates_both_secrets() {
unsafe {
std::env::set_var("BINDABLE_TEST_A", "alpha");
std::env::set_var("BINDABLE_TEST_B", "beta");
}
let mut config = Config {
key_a: Secret::new("urn:secrets-rs:env:BINDABLE_TEST_A").unwrap(),
key_b: Secret::new("urn:secrets-rs:env:BINDABLE_TEST_B").unwrap(),
};
let registry = SourceRegistry::new();
bind_all(&mut config, ®istry).unwrap();
assert_eq!(config.key_a.value().unwrap(), "alpha");
assert_eq!(config.key_b.value().unwrap(), "beta");
unsafe {
std::env::remove_var("BINDABLE_TEST_A");
std::env::remove_var("BINDABLE_TEST_B");
}
}
#[test]
fn bind_all_collects_all_errors() {
unsafe {
std::env::remove_var("BINDABLE_MISSING_A");
std::env::remove_var("BINDABLE_MISSING_B");
}
let mut config = Config {
key_a: Secret::new("urn:secrets-rs:env:BINDABLE_MISSING_A").unwrap(),
key_b: Secret::new("urn:secrets-rs:env:BINDABLE_MISSING_B").unwrap(),
};
let registry = SourceRegistry::new();
let errors = bind_all(&mut config, ®istry).unwrap_err();
assert_eq!(errors.len(), 2);
}
}