spin_variables/
lib.rs

1//! The runtime configuration for the variables factor used in the Spin CLI.
2
3mod azure_key_vault;
4mod env;
5mod statik;
6mod vault;
7
8pub use azure_key_vault::*;
9pub use env::*;
10pub use statik::*;
11pub use vault::*;
12
13use serde::Deserialize;
14use spin_expressions::Provider;
15use spin_factors::{anyhow, runtime_config::toml::GetTomlValue};
16
17use spin_factor_variables::runtime_config::RuntimeConfig;
18
19/// Resolves a runtime configuration for the variables factor from a TOML table.
20pub fn runtime_config_from_toml(table: &impl GetTomlValue) -> anyhow::Result<RuntimeConfig> {
21    // Always include the environment variable provider.
22    let var_provider = vec![Box::<EnvVariablesProvider>::default() as _];
23    let value = table
24        .get("variables_provider")
25        .or_else(|| table.get("config_provider"));
26    let Some(array) = value else {
27        return Ok(RuntimeConfig {
28            providers: var_provider,
29        });
30    };
31
32    let provider_configs: Vec<VariableProviderConfiguration> = array.clone().try_into()?;
33    let mut providers = provider_configs
34        .into_iter()
35        .map(VariableProviderConfiguration::into_provider)
36        .collect::<anyhow::Result<Vec<_>>>()?;
37    providers.extend(var_provider);
38    Ok(RuntimeConfig { providers })
39}
40
41/// A runtime configuration used in the Spin CLI for one type of variable provider.
42#[derive(Debug, Deserialize)]
43#[serde(rename_all = "snake_case", tag = "type")]
44pub enum VariableProviderConfiguration {
45    /// A provider that uses Azure Key Vault.
46    AzureKeyVault(AzureKeyVaultVariablesConfig),
47    /// A static provider of variables.
48    Static(StaticVariablesProvider),
49    /// A provider that uses HashiCorp Vault.
50    Vault(VaultVariablesProvider),
51    /// An environment variable provider.
52    Env(EnvVariablesConfig),
53}
54
55impl VariableProviderConfiguration {
56    /// Returns the provider for the configuration.
57    pub fn into_provider(self) -> anyhow::Result<Box<dyn Provider>> {
58        let provider: Box<dyn Provider> = match self {
59            VariableProviderConfiguration::Static(provider) => Box::new(provider),
60            VariableProviderConfiguration::Env(config) => Box::new(env::EnvVariablesProvider::new(
61                config.prefix,
62                |s| std::env::var(s),
63                config.dotenv_path,
64            )),
65            VariableProviderConfiguration::Vault(provider) => Box::new(provider),
66            VariableProviderConfiguration::AzureKeyVault(config) => Box::new(
67                AzureKeyVaultProvider::create(config.vault_url.clone(), config.try_into()?)?,
68            ),
69        };
70        Ok(provider)
71    }
72}