olai_stack_runtime/
source.rs1use std::collections::BTreeMap;
4use std::fmt;
5use std::time::SystemTime;
6
7use async_trait::async_trait;
8use olai_stack_state::{InstanceId, VarSet};
9
10use crate::secrets::SecretValue;
11
12#[derive(Clone, Default)]
14pub struct Overlay {
15 pub vars: BTreeMap<String, String>,
17 pub endpoints: BTreeMap<String, String>,
19 pub credentials: BTreeMap<String, SecretValue>,
22 pub expires_at: Option<SystemTime>,
24}
25
26impl fmt::Debug for Overlay {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 f.debug_struct("Overlay")
29 .field("vars", &self.vars)
30 .field("endpoints", &self.endpoints)
31 .field("credentials", &self.credentials.keys().collect::<Vec<_>>())
32 .field("expires_at", &self.expires_at)
33 .finish()
34 }
35}
36
37impl Overlay {
38 pub fn is_expired(&self, now: SystemTime) -> bool {
40 self.expires_at.is_some_and(|t| t <= now)
41 }
42}
43
44#[derive(Clone, Debug)]
46pub struct SourceCtx {
47 pub instance: InstanceId,
49 pub workspace: String,
51 pub environment: String,
53 pub revision: u32,
55}
56
57#[derive(Debug, thiserror::Error)]
59#[error("source `{source_name}`: {reason}")]
60pub struct SourceError {
61 pub source_name: String,
63 pub reason: String,
65}
66
67#[async_trait]
72pub trait Source: Send + Sync {
73 fn name(&self) -> &str;
75
76 async fn overlay(&self, ctx: &SourceCtx) -> Result<Overlay, SourceError>;
78
79 async fn refresh(&self, ctx: &SourceCtx, current: &Overlay) -> Result<Overlay, SourceError> {
81 let _ = current;
82 self.overlay(ctx).await
83 }
84}
85
86#[derive(Clone, Debug, Default)]
89pub struct UserVars {
90 vars: BTreeMap<String, String>,
91}
92
93impl UserVars {
94 pub fn new(vars: BTreeMap<String, String>) -> Self {
96 UserVars { vars }
97 }
98
99 pub fn from_var_set(set: &VarSet) -> Self {
101 UserVars::new(
102 set.0
103 .iter()
104 .filter_map(|(k, v)| match v {
105 olai_stack_state::VarValue::Literal(l) => Some((k.clone(), l.clone())),
106 olai_stack_state::VarValue::Secret(_) => None,
107 })
108 .collect(),
109 )
110 }
111}
112
113#[async_trait]
114impl Source for UserVars {
115 fn name(&self) -> &str {
116 "user"
117 }
118
119 async fn overlay(&self, _ctx: &SourceCtx) -> Result<Overlay, SourceError> {
120 Ok(Overlay {
121 vars: self.vars.clone(),
122 ..Overlay::default()
123 })
124 }
125}