Skip to main content

s2_lite/
init.rs

1//! Declarative basin/stream initialization from a JSON spec file.
2//!
3//! Loaded at startup when `--init-file` / `S2LITE_INIT_FILE` is set.
4
5use std::path::Path;
6
7use s2_common::{
8    config::{BasinConfig, OptionalStreamConfig},
9    resources::ProvisionMode,
10};
11use tracing::info;
12
13use crate::backend::Backend;
14
15pub fn load(path: &Path) -> eyre::Result<s2_resource_spec::Resources> {
16    let contents = std::fs::read_to_string(path)
17        .map_err(|e| eyre::eyre!("failed to read init file {:?}: {}", path, e))?;
18    let spec: s2_resource_spec::Resources = serde_json::from_str(&contents)
19        .map_err(|e| eyre::eyre!("failed to parse init file {:?}: {}", path, e))?;
20    Ok(spec)
21}
22
23pub async fn apply(backend: &Backend, spec: s2_resource_spec::Resources) -> eyre::Result<()> {
24    s2_resource_spec::validate(&spec).map_err(|e| eyre::eyre!(e))?;
25
26    for basin_spec in spec.basins {
27        let config = basin_spec.config.map(BasinConfig::from).unwrap_or_default();
28
29        backend
30            .provision_basin(basin_spec.name.clone(), config, ProvisionMode::Ensure)
31            .await
32            .map_err(|e| {
33                eyre::eyre!(
34                    "failed to apply basin {:?}: {}",
35                    basin_spec.name.as_ref(),
36                    e
37                )
38            })?;
39
40        info!(basin = basin_spec.name.as_ref(), "basin applied");
41
42        for stream_spec in basin_spec.streams {
43            let config = stream_spec
44                .config
45                .map(OptionalStreamConfig::from)
46                .unwrap_or_default();
47
48            backend
49                .provision_stream(
50                    basin_spec.name.clone(),
51                    stream_spec.name.clone(),
52                    config,
53                    ProvisionMode::Ensure,
54                )
55                .await
56                .map_err(|e| {
57                    eyre::eyre!(
58                        "failed to apply stream {:?}/{:?}: {}",
59                        basin_spec.name.as_ref(),
60                        stream_spec.name.as_ref(),
61                        e
62                    )
63                })?;
64
65            info!(
66                basin = basin_spec.name.as_ref(),
67                stream = stream_spec.name.as_ref(),
68                "stream applied"
69            );
70        }
71    }
72    Ok(())
73}