spin_factor_variables/
lib.rs1mod host;
2pub mod runtime_config;
3
4use std::sync::Arc;
5
6use runtime_config::RuntimeConfig;
7use spin_expressions::{ProviderResolver as ExpressionResolver, Template};
8use spin_factor_otel::OtelFactorState;
9use spin_factors::{
10 ConfigureAppContext, Factor, FactorData, InitContext, PrepareContext, RuntimeFactors,
11 SelfInstanceBuilder, anyhow,
12};
13use spin_world::spin::variables::variables as v3;
14
15#[derive(Default)]
17pub struct VariablesFactor {
18 _priv: (),
19}
20
21impl VariablesFactor {
22 pub fn new() -> Self {
24 Default::default()
25 }
26}
27
28impl Factor for VariablesFactor {
29 type RuntimeConfig = RuntimeConfig;
30 type AppState = AppState;
31 type InstanceBuilder = InstanceState;
32
33 fn init(&mut self, ctx: &mut impl InitContext<Self>) -> anyhow::Result<()> {
34 ctx.link_bindings(spin_world::v1::config::add_to_linker::<_, FactorData<Self>>)?;
35 ctx.link_bindings(spin_world::v2::variables::add_to_linker::<_, FactorData<Self>>)?;
36 ctx.link_bindings(spin_world::wasi::config::store::add_to_linker::<_, FactorData<Self>>)?;
37 ctx.link_bindings(v3::add_to_linker::<_, VariablesFactorData>)?;
38 Ok(())
39 }
40
41 fn configure_app<T: RuntimeFactors>(
42 &self,
43 mut ctx: ConfigureAppContext<T, Self>,
44 ) -> anyhow::Result<Self::AppState> {
45 let app = ctx.app();
46 let mut expression_resolver =
47 ExpressionResolver::new(app.variables().map(|(key, val)| (key.clone(), val.clone())))?;
48
49 for component in app.components() {
50 expression_resolver.add_component_variables(
51 component.id(),
52 component.config().map(|(k, v)| (k.into(), v.into())),
53 )?;
54 }
55
56 let providers = ctx.take_runtime_config().unwrap_or_default();
57 for provider in providers {
58 expression_resolver.add_provider(provider);
59 }
60
61 Ok(AppState {
62 expression_resolver: Arc::new(expression_resolver),
63 })
64 }
65
66 fn prepare<T: RuntimeFactors>(
67 &self,
68 mut ctx: PrepareContext<T, Self>,
69 ) -> anyhow::Result<InstanceState> {
70 let component_id = ctx.app_component().id().to_string();
71 let expression_resolver = ctx.app_state().expression_resolver.clone();
72 let otel = OtelFactorState::from_prepare_context(&mut ctx)?;
73 Ok(InstanceState {
74 component_id,
75 expression_resolver,
76 otel,
77 })
78 }
79}
80
81pub struct AppState {
82 expression_resolver: Arc<ExpressionResolver>,
83}
84
85impl AppState {
86 pub async fn resolve_expression(
87 &self,
88 expr: impl Into<Box<str>>,
89 ) -> spin_expressions::Result<String> {
90 let template = Template::new(expr)?;
91 self.expression_resolver.resolve_template(&template).await
92 }
93
94 pub fn expression_resolver(&self) -> &Arc<ExpressionResolver> {
95 &self.expression_resolver
96 }
97}
98
99pub struct InstanceState {
100 component_id: String,
101 expression_resolver: Arc<ExpressionResolver>,
102 otel: OtelFactorState,
103}
104
105impl InstanceState {
106 pub fn expression_resolver(&self) -> &Arc<ExpressionResolver> {
107 &self.expression_resolver
108 }
109}
110
111impl SelfInstanceBuilder for InstanceState {}
112
113pub struct VariablesFactorData(VariablesFactor);
114
115impl spin_core::wasmtime::component::HasData for VariablesFactorData {
116 type Data<'a> = &'a mut InstanceState;
117}