spin_factor_variables/
host.rs

1use spin_factors::anyhow;
2use spin_world::{v1, v2::variables, wasi::config as wasi_config};
3use tracing::{instrument, Level};
4
5use crate::InstanceState;
6
7impl variables::Host for InstanceState {
8    #[instrument(name = "spin_variables.get", skip(self), err(level = Level::INFO), fields(otel.kind = "client"))]
9    async fn get(&mut self, key: String) -> Result<String, variables::Error> {
10        let key = spin_expressions::Key::new(&key).map_err(expressions_to_variables_err)?;
11        self.expression_resolver
12            .resolve(&self.component_id, key)
13            .await
14            .map_err(expressions_to_variables_err)
15    }
16
17    fn convert_error(&mut self, error: variables::Error) -> anyhow::Result<variables::Error> {
18        Ok(error)
19    }
20}
21
22impl v1::config::Host for InstanceState {
23    async fn get_config(&mut self, key: String) -> Result<String, v1::config::Error> {
24        <Self as variables::Host>::get(self, key)
25            .await
26            .map_err(|err| match err {
27                variables::Error::InvalidName(msg) => v1::config::Error::InvalidKey(msg),
28                variables::Error::Undefined(msg) => v1::config::Error::Provider(msg),
29                other => v1::config::Error::Other(format!("{other}")),
30            })
31    }
32
33    fn convert_error(&mut self, err: v1::config::Error) -> anyhow::Result<v1::config::Error> {
34        Ok(err)
35    }
36}
37
38impl wasi_config::store::Host for InstanceState {
39    async fn get(&mut self, key: String) -> Result<Option<String>, wasi_config::store::Error> {
40        match <Self as variables::Host>::get(self, key).await {
41            Ok(value) => Ok(Some(value)),
42            Err(variables::Error::Undefined(_)) => Ok(None),
43            Err(variables::Error::InvalidName(_)) => Ok(None), // this is the guidance from https://github.com/WebAssembly/wasi-runtime-config/pull/19)
44            Err(variables::Error::Provider(msg)) => Err(wasi_config::store::Error::Upstream(msg)),
45            Err(variables::Error::Other(msg)) => Err(wasi_config::store::Error::Io(msg)),
46        }
47    }
48
49    async fn get_all(&mut self) -> Result<Vec<(String, String)>, wasi_config::store::Error> {
50        let all = self
51            .expression_resolver
52            .resolve_all(&self.component_id)
53            .await;
54        all.map_err(|e| {
55            match expressions_to_variables_err(e) {
56                variables::Error::Undefined(msg) => wasi_config::store::Error::Io(msg), // this shouldn't happen but just in case
57                variables::Error::InvalidName(msg) => wasi_config::store::Error::Io(msg), // this shouldn't happen but just in case
58                variables::Error::Provider(msg) => wasi_config::store::Error::Upstream(msg),
59                variables::Error::Other(msg) => wasi_config::store::Error::Io(msg),
60            }
61        })
62    }
63
64    fn convert_error(
65        &mut self,
66        err: wasi_config::store::Error,
67    ) -> anyhow::Result<wasi_config::store::Error> {
68        Ok(err)
69    }
70}
71
72fn expressions_to_variables_err(err: spin_expressions::Error) -> variables::Error {
73    use spin_expressions::Error;
74    match err {
75        Error::InvalidName(msg) => variables::Error::InvalidName(msg),
76        Error::Undefined(msg) => variables::Error::Undefined(msg),
77        Error::Provider(err) => variables::Error::Provider(err.to_string()),
78        other => variables::Error::Other(format!("{other}")),
79    }
80}