use systemprompt_manifest::profile::ExternalSecretsConfig;
use super::SecretsBootstrapError;
use super::provider::DynSecretsProvider;
pub type EnvLookup = Box<dyn Fn(&str) -> Option<String> + Send + Sync>;
pub type SharedSecretsProvider = Box<dyn DynSecretsProvider>;
pub type SecretsSourceFactory =
fn(&ExternalSecretsConfig, EnvLookup) -> Result<SharedSecretsProvider, SecretsBootstrapError>;
#[derive(Debug, Clone, Copy)]
pub struct SecretsSourceRegistration {
pub kind: &'static str,
pub factory: SecretsSourceFactory,
}
inventory::collect!(SecretsSourceRegistration);
#[must_use]
pub fn process_env_lookup() -> EnvLookup {
Box::new(systemprompt_manifest::read_env_optional)
}
pub fn build_external_provider(
cfg: &ExternalSecretsConfig,
env: EnvLookup,
) -> Result<SharedSecretsProvider, SecretsBootstrapError> {
let registration = inventory::iter::<SecretsSourceRegistration>()
.find(|registration| registration.kind == cfg.kind)
.ok_or_else(|| SecretsBootstrapError::UnknownExternalKind {
kind: cfg.kind.clone(),
known: registered_external_kinds()
.into_iter()
.map(str::to_owned)
.collect(),
})?;
(registration.factory)(cfg, env)
}
#[must_use]
pub fn registered_external_kinds() -> Vec<&'static str> {
let mut kinds: Vec<&'static str> = inventory::iter::<SecretsSourceRegistration>()
.map(|registration| registration.kind)
.collect();
kinds.sort_unstable();
kinds.dedup();
kinds
}
#[macro_export]
macro_rules! register_secrets_source {
($kind:expr, $factory:expr $(,)?) => {
$crate::__inventory::submit! {
$crate::SecretsSourceRegistration {
kind: $kind,
factory: $factory,
}
}
};
}