Skip to content

Commit c9abacf

Browse files
committed
variables: Refactor Provider::kind into ::may_resolve
Signed-off-by: Lann Martin <[email protected]>
1 parent 1525f7b commit c9abacf

File tree

8 files changed

+42
-78
lines changed

8 files changed

+42
-78
lines changed

crates/expressions/src/lib.rs

Lines changed: 20 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ pub use provider::Provider;
1111
use template::Part;
1212
pub use template::Template;
1313

14-
use crate::provider::ProviderVariableKind;
15-
1614
/// A [`ProviderResolver`] that can be shared.
1715
pub type SharedPreparedResolver =
1816
std::sync::Arc<std::sync::OnceLock<std::sync::Arc<PreparedResolver>>>;
@@ -92,50 +90,25 @@ impl ProviderResolver {
9290
Ok(PreparedResolver { variables })
9391
}
9492

95-
/// Ensures that all required variables are resolvable at startup
93+
/// Ensures that all required variables are not unresolvable
9694
pub async fn ensure_required_variables_resolvable(&self) -> Result<()> {
97-
// If a dynamic provider is available, skip validation.
98-
if self
99-
.providers
100-
.iter()
101-
.any(|p| p.kind() == ProviderVariableKind::Dynamic)
102-
{
103-
return Ok(());
104-
}
105-
106-
let mut unvalidated_keys = vec![];
107-
for key in self.internal.variables.keys() {
108-
// If default value is provided, skip validation.
109-
if let Some(value) = self.internal.variables.get(key) {
110-
if value.default.is_some() {
111-
continue;
112-
}
113-
}
114-
115-
let mut resolved = false;
116-
117-
for provider in &self.providers {
118-
if provider
119-
.get(&Key(key))
120-
.await
121-
.map_err(Error::Provider)?
122-
.is_some()
123-
{
124-
resolved = true;
125-
break;
126-
}
127-
}
128-
129-
if !resolved {
130-
unvalidated_keys.push(key);
95+
let mut unresolvable_keys = vec![];
96+
for key in self.internal.required_variables() {
97+
let key = Key::new(key)?;
98+
let resolvable = self
99+
.providers
100+
.iter()
101+
.any(|provider| provider.may_resolve(&key));
102+
if !resolvable {
103+
unresolvable_keys.push(key);
131104
}
132105
}
133106

134-
if unvalidated_keys.is_empty() {
107+
if unresolvable_keys.is_empty() {
135108
Ok(())
136109
} else {
137110
Err(Error::Provider(anyhow::anyhow!(
138-
"no provider resolved required variable(s): {unvalidated_keys:?}",
111+
"no provider resolved required variable(s): {unresolvable_keys:?}",
139112
)))
140113
}
141114
}
@@ -248,6 +221,12 @@ impl Resolver {
248221
})?;
249222
Ok(template)
250223
}
224+
225+
fn required_variables(&self) -> impl Iterator<Item = &str> {
226+
self.variables
227+
.iter()
228+
.filter_map(|(name, variable)| variable.default.is_none().then_some(name.as_str()))
229+
}
251230
}
252231

253232
/// A resolver who has resolved all variables.
@@ -360,7 +339,6 @@ mod tests {
360339
use async_trait::async_trait;
361340

362341
use super::*;
363-
use crate::provider::ProviderVariableKind;
364342

365343
#[derive(Debug)]
366344
struct TestProvider;
@@ -375,8 +353,8 @@ mod tests {
375353
}
376354
}
377355

378-
fn kind(&self) -> ProviderVariableKind {
379-
ProviderVariableKind::Static
356+
fn may_resolve(&self, key: &Key) -> bool {
357+
key.as_ref() == "required"
380358
}
381359
}
382360

crates/expressions/src/provider.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,13 @@ use crate::Key;
99
pub trait Provider: Debug + Send + Sync {
1010
/// Returns the value at the given config path, if it exists.
1111
async fn get(&self, key: &Key) -> anyhow::Result<Option<String>>;
12-
fn kind(&self) -> ProviderVariableKind;
13-
}
1412

15-
/// The dynamism of a Provider.
16-
#[derive(Clone, Debug, Default, PartialEq)]
17-
pub enum ProviderVariableKind {
18-
/// Variable must be declared on start
19-
Static,
20-
/// Variable can be made available at runtime
21-
#[default]
22-
Dynamic,
13+
/// Returns true if the given key _might_ be resolvable by this Provider.
14+
///
15+
/// Dynamic resolvers will typically return true unconditionally, which is
16+
/// the default implementation.
17+
fn may_resolve(&self, key: &Key) -> bool {
18+
let _ = key;
19+
true
20+
}
2321
}

crates/expressions/tests/validation_test.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::collections::HashMap;
22

33
use async_trait::async_trait;
4-
use spin_expressions::{provider::ProviderVariableKind, Key, Provider, ProviderResolver};
4+
use spin_expressions::{Key, Provider, ProviderResolver};
55
use spin_locked_app::Variable;
66

77
#[derive(Default)]
@@ -247,8 +247,8 @@ impl Provider for StaticProvider {
247247
Ok(self.variables.get(key.as_str()).cloned().flatten())
248248
}
249249

250-
fn kind(&self) -> ProviderVariableKind {
251-
ProviderVariableKind::Static
250+
fn may_resolve(&self, key: &Key) -> bool {
251+
self.variables.contains_key(key.as_str())
252252
}
253253
}
254254

@@ -260,8 +260,4 @@ impl Provider for DynamicProvider {
260260
async fn get(&self, _key: &Key) -> anyhow::Result<Option<String>> {
261261
panic!("validation should never call get for a dynamic provider")
262262
}
263-
264-
fn kind(&self) -> ProviderVariableKind {
265-
ProviderVariableKind::Dynamic
266-
}
267263
}

crates/factor-variables/tests/factor_test.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use spin_expressions::{provider::ProviderVariableKind, Key, Provider};
1+
use spin_expressions::{Key, Provider};
22
use spin_factor_variables::{runtime_config::RuntimeConfig, VariablesFactor};
33
use spin_factors::{anyhow, RuntimeFactors};
44
use spin_factors_test::{toml, TestEnvironment};
@@ -47,7 +47,7 @@ impl Provider for MockProvider {
4747
}
4848
}
4949

50-
fn kind(&self) -> ProviderVariableKind {
51-
ProviderVariableKind::Static
50+
fn may_resolve(&self, key: &Key) -> bool {
51+
key.as_ref() == "foo"
5252
}
5353
}

crates/variables-azure/src/lib.rs

Lines changed: 1 addition & 5 deletions
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::{provider::ProviderVariableKind, Key, Provider};
7+
use spin_expressions::{Key, Provider};
88
use spin_factors::anyhow;
99
use spin_world::async_trait;
1010
use tracing::{instrument, Level};
@@ -151,10 +151,6 @@ impl Provider for AzureKeyVaultProvider {
151151
.context("Failed to read variable from Azure Key Vault")?;
152152
Ok(Some(secret.value))
153153
}
154-
155-
fn kind(&self) -> ProviderVariableKind {
156-
ProviderVariableKind::Dynamic
157-
}
158154
}
159155

160156
impl From<AzureAuthorityHost> for Url {

crates/variables-env/src/lib.rs

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

88
use serde::Deserialize;
9-
use spin_expressions::{provider::ProviderVariableKind, Key, Provider};
9+
use spin_expressions::{Key, Provider};
1010
use spin_factors::anyhow::{self, Context as _};
1111
use spin_world::async_trait;
1212
use tracing::{instrument, Level};
@@ -133,8 +133,8 @@ impl Provider for EnvVariablesProvider {
133133
tokio::task::block_in_place(|| self.get_sync(key))
134134
}
135135

136-
fn kind(&self) -> ProviderVariableKind {
137-
ProviderVariableKind::Static
136+
fn may_resolve(&self, key: &Key) -> bool {
137+
matches!(self.get_sync(key), Ok(Some(_)))
138138
}
139139
}
140140

crates/variables-static/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::{collections::HashMap, hash::Hash, sync::Arc};
22

33
use serde::Deserialize;
4-
use spin_expressions::{async_trait::async_trait, provider::ProviderVariableKind, Key, Provider};
4+
use spin_expressions::{async_trait::async_trait, Key, Provider};
55
use spin_factors::anyhow;
66

77
pub use source::*;
@@ -19,8 +19,8 @@ impl Provider for StaticVariablesProvider {
1919
Ok(self.values.get(key.as_str()).cloned())
2020
}
2121

22-
fn kind(&self) -> ProviderVariableKind {
23-
ProviderVariableKind::Static
22+
fn may_resolve(&self, key: &Key) -> bool {
23+
self.values.contains_key(key.as_str())
2424
}
2525
}
2626

crates/variables-vault/src/lib.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use serde::{Deserialize, Serialize};
2-
use spin_expressions::{async_trait::async_trait, provider::ProviderVariableKind};
2+
use spin_expressions::async_trait::async_trait;
33
use spin_factors::anyhow::{self, Context as _};
44
use tracing::{instrument, Level};
55
use vaultrs::{
@@ -52,8 +52,4 @@ impl Provider for VaultVariablesProvider {
5252
Err(e) => Err(e).context("Failed to check Vault for config"),
5353
}
5454
}
55-
56-
fn kind(&self) -> ProviderVariableKind {
57-
ProviderVariableKind::Dynamic
58-
}
5955
}

0 commit comments

Comments
 (0)