Skip to content

Commit 435c22b

Browse files
committed
Adds new dynamism metadata for Providers
New logic only allows no default variable before runtime if Provider it is of a Dynamic type Signed-off-by: Aminu Oluwaseun Joshua <[email protected]> rename: VariablesPreparationExecutorHook Signed-off-by: Aminu Oluwaseun Joshua <[email protected]>
1 parent 31bbe50 commit 435c22b

File tree

13 files changed

+78
-20
lines changed

13 files changed

+78
-20
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/expressions/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ edition = { workspace = true }
88
anyhow = { workspace = true }
99
async-trait = { workspace = true }
1010
futures = { workspace = true }
11-
spin-common = { path = "../common" }
11+
serde = { workspace = true }
1212
spin-locked-app = { path = "../locked-app" }
1313
thiserror = { workspace = true }
1414

crates/expressions/src/lib.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ mod template;
33

44
use std::{borrow::Cow, collections::HashMap, fmt::Debug};
55

6-
use spin_common::ui::quoted_path;
76
use spin_locked_app::Variable;
87

98
pub use async_trait;
@@ -12,6 +11,8 @@ pub use provider::Provider;
1211
use template::Part;
1312
pub use template::Template;
1413

14+
use crate::provider::ProviderVariableKind;
15+
1516
/// A [`ProviderResolver`] that can be shared.
1617
pub type SharedPreparedResolver =
1718
std::sync::Arc<std::sync::OnceLock<std::sync::Arc<PreparedResolver>>>;
@@ -91,15 +92,27 @@ impl ProviderResolver {
9192
Ok(PreparedResolver { variables })
9293
}
9394

95+
/// Prepares the resolver by attempting to resolve all variables, printing warnings for any
96+
/// that cannot be resolved.
9497
pub async fn pre_runtime_prepare(&self) -> Result<()> {
9598
for name in self.internal.variables.keys() {
96-
if self.resolve_variable(name).await.is_err() {
97-
eprintln!(
98-
"Default value not found for variable: {}",
99-
quoted_path(name)
100-
);
99+
self.check_variable_existence(name).await?;
100+
}
101+
Ok(())
102+
}
103+
104+
async fn check_variable_existence(&self, key: &str) -> Result<()> {
105+
for provider in &self.providers {
106+
if provider.kind() == &ProviderVariableKind::Dynamic {
107+
continue;
108+
}
109+
110+
match provider.get(&Key(key)).await {
111+
Ok(Some(_)) => return Ok(()),
112+
Err(_) | Ok(None) => return self.internal.resolve_variable(key).map(|_| ()),
101113
}
102114
}
115+
103116
Ok(())
104117
}
105118

@@ -322,6 +335,8 @@ pub enum Error {
322335
mod tests {
323336
use async_trait::async_trait;
324337

338+
use crate::provider::ProviderVariableKind;
339+
325340
use super::*;
326341

327342
#[derive(Debug)]
@@ -336,6 +351,10 @@ mod tests {
336351
_ => Ok(None),
337352
}
338353
}
354+
355+
fn kind(&self) -> &ProviderVariableKind {
356+
&ProviderVariableKind::Static
357+
}
339358
}
340359

341360
async fn test_resolve(template: &str) -> Result<String> {

crates/expressions/src/provider.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::fmt::Debug;
22

33
use async_trait::async_trait;
4+
use serde::Deserialize;
45

56
use crate::Key;
67

@@ -9,4 +10,15 @@ use crate::Key;
910
pub trait Provider: Debug + Send + Sync {
1011
/// Returns the value at the given config path, if it exists.
1112
async fn get(&self, key: &Key) -> anyhow::Result<Option<String>>;
13+
fn kind(&self) -> &ProviderVariableKind;
14+
}
15+
16+
/// The dynamism of a Provider.
17+
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
18+
pub enum ProviderVariableKind {
19+
/// Variable must be declared on start
20+
#[default]
21+
Static,
22+
/// Variable can be made available at runtime
23+
Dynamic,
1224
}

crates/factor-variables/tests/factor_test.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use spin_expressions::{Key, Provider};
1+
use spin_expressions::{provider::ProviderVariableKind, Key, Provider};
22
use spin_factor_variables::{runtime_config::RuntimeConfig, VariablesFactor};
33
use spin_factors::{anyhow, RuntimeFactors};
44
use spin_factors_test::{toml, TestEnvironment};
@@ -46,4 +46,8 @@ impl Provider for MockProvider {
4646
_ => Ok(None),
4747
}
4848
}
49+
50+
fn kind(&self) -> &ProviderVariableKind {
51+
&ProviderVariableKind::Static
52+
}
4953
}

crates/runtime-factors/src/build.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use spin_runtime_config::ResolvedRuntimeConfig;
88
use spin_trigger::cli::{
99
FactorsConfig, InitialKvSetterHook, KeyValueDefaultStoreSummaryHook, MaxInstanceMemoryHook,
1010
RuntimeFactorsBuilder, SqlStatementExecutorHook, SqliteDefaultStoreSummaryHook,
11-
StdioLoggingExecutorHooks, VariablesPreparationExecutorHooks,
11+
StdioLoggingExecutorHooks, VariablesPreparationExecutorHook,
1212
};
1313
use spin_variables_static::StaticVariablesProvider;
1414

@@ -72,7 +72,7 @@ impl RuntimeFactorsBuilder for FactorsBuilder {
7272
executor.add_hooks(InitialKvSetterHook::new(args.key_values.clone()));
7373
executor.add_hooks(SqliteDefaultStoreSummaryHook);
7474
executor.add_hooks(KeyValueDefaultStoreSummaryHook);
75-
executor.add_hooks(VariablesPreparationExecutorHooks);
75+
executor.add_hooks(VariablesPreparationExecutorHook);
7676

7777
let max_instance_memory = args
7878
.max_instance_memory

crates/trigger/src/cli.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub use sqlite_statements::SqlStatementExecutorHook;
2626
use stdio::FollowComponents;
2727
pub use stdio::StdioLoggingExecutorHooks;
2828
pub use summary::{KeyValueDefaultStoreSummaryHook, SqliteDefaultStoreSummaryHook};
29-
pub use variable::VariablesPreparationExecutorHooks;
29+
pub use variable::VariablesPreparationExecutorHook;
3030

3131
pub const APP_LOG_DIR: &str = "APP_LOG_DIR";
3232
pub const SPIN_TRUNCATE_LOGS: &str = "SPIN_TRUNCATE_LOGS";

crates/trigger/src/cli/variable.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ use spin_factor_variables::VariablesFactor;
22
use spin_factors::RuntimeFactors;
33
use spin_factors_executor::ExecutorHooks;
44

5-
pub struct VariablesPreparationExecutorHooks;
5+
/// An executor hook that prepares the variables factor before runtime execution.
6+
pub struct VariablesPreparationExecutorHook;
67

78
#[spin_core::async_trait]
8-
impl<F: RuntimeFactors, U> ExecutorHooks<F, U> for VariablesPreparationExecutorHooks {
9+
impl<F: RuntimeFactors, U> ExecutorHooks<F, U> for VariablesPreparationExecutorHook {
910
async fn configure_app(
1011
&self,
1112
configured_app: &spin_factors::ConfiguredApp<F>,

crates/variables-azure/src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use anyhow::Context as _;
44
use azure_core::{auth::TokenCredential, Url};
55
use azure_security_keyvault::SecretClient;
66
use serde::Deserialize;
7-
use spin_expressions::{Key, Provider};
7+
use spin_expressions::{provider::ProviderVariableKind, Key, Provider};
88
use spin_factors::anyhow;
99
use spin_world::async_trait;
1010
use tracing::{instrument, Level};
@@ -107,6 +107,7 @@ pub enum AzureKeyVaultAuthOptions {
107107
#[derive(Debug)]
108108
pub struct AzureKeyVaultProvider {
109109
secret_client: SecretClient,
110+
kind: ProviderVariableKind,
110111
}
111112

112113
impl AzureKeyVaultProvider {
@@ -136,6 +137,7 @@ impl AzureKeyVaultProvider {
136137

137138
Ok(Self {
138139
secret_client: SecretClient::new(&vault_url.into(), token_credential)?,
140+
kind: ProviderVariableKind::Dynamic,
139141
})
140142
}
141143
}
@@ -151,6 +153,10 @@ impl Provider for AzureKeyVaultProvider {
151153
.context("Failed to read variable from Azure Key Vault")?;
152154
Ok(Some(secret.value))
153155
}
156+
157+
fn kind(&self) -> &ProviderVariableKind {
158+
&self.kind
159+
}
154160
}
155161

156162
impl From<AzureAuthorityHost> for Url {

crates/variables-env/src/lib.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::{
66
};
77

88
use serde::Deserialize;
9-
use spin_expressions::{Key, Provider};
9+
use spin_expressions::{provider::ProviderVariableKind, Key, Provider};
1010
use spin_factors::anyhow::{self, Context as _};
1111
use spin_world::async_trait;
1212
use tracing::{instrument, Level};
@@ -35,6 +35,7 @@ pub struct EnvVariablesProvider {
3535
env_fetcher: EnvFetcherFn,
3636
dotenv_path: Option<PathBuf>,
3737
dotenv_cache: OnceLock<HashMap<String, String>>,
38+
kind: ProviderVariableKind,
3839
}
3940

4041
impl Default for EnvVariablesProvider {
@@ -44,6 +45,7 @@ impl Default for EnvVariablesProvider {
4445
env_fetcher: Box::new(|s| std::env::var(s)),
4546
dotenv_path: Some(".env".into()),
4647
dotenv_cache: Default::default(),
48+
kind: Default::default(),
4749
}
4850
}
4951
}
@@ -66,6 +68,7 @@ impl EnvVariablesProvider {
6668
dotenv_path,
6769
env_fetcher: Box::new(env_fetcher),
6870
dotenv_cache: Default::default(),
71+
kind: ProviderVariableKind::Static,
6972
}
7073
}
7174

@@ -132,6 +135,10 @@ impl Provider for EnvVariablesProvider {
132135
async fn get(&self, key: &Key) -> anyhow::Result<Option<String>> {
133136
tokio::task::block_in_place(|| self.get_sync(key))
134137
}
138+
139+
fn kind(&self) -> &ProviderVariableKind {
140+
&self.kind
141+
}
135142
}
136143

137144
#[cfg(test)]

0 commit comments

Comments
 (0)