spin_runtime_config/
variables.rs

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