greentic_setup/platform_setup/
persistence.rs1use std::path::{Path, PathBuf};
4
5use anyhow::{Context, Result};
6use serde::Deserialize;
7
8use crate::platform_setup::types::StaticRoutesPolicy;
9
10pub fn static_routes_artifact_path(bundle_root: &Path) -> PathBuf {
12 bundle_root
13 .join("state")
14 .join("config")
15 .join("platform")
16 .join("static-routes.json")
17}
18
19pub fn load_static_routes_artifact(bundle_root: &Path) -> Result<Option<StaticRoutesPolicy>> {
21 let path = static_routes_artifact_path(bundle_root);
22 if !path.exists() {
23 return Ok(None);
24 }
25 let raw = std::fs::read_to_string(&path)
26 .with_context(|| format!("failed to read {}", path.display()))?;
27 let policy = serde_json::from_str(&raw)
28 .or_else(|_| serde_yaml_bw::from_str(&raw))
29 .with_context(|| format!("failed to parse {}", path.display()))?;
30 Ok(Some(policy))
31}
32
33#[derive(Debug, Deserialize)]
34struct RuntimeEndpoints {
35 #[allow(dead_code)]
36 tenant: Option<String>,
37 #[allow(dead_code)]
38 team: Option<String>,
39 public_base_url: Option<String>,
40}
41
42pub fn load_runtime_public_base_url(
44 bundle_root: &Path,
45 tenant: &str,
46 team: Option<&str>,
47) -> Result<Option<String>> {
48 let team = team.unwrap_or("default");
49 let path = bundle_root
50 .join("state")
51 .join("runtime")
52 .join(format!("{tenant}.{team}"))
53 .join("endpoints.json");
54 if !path.exists() {
55 return Ok(None);
56 }
57 let raw = std::fs::read_to_string(&path)
58 .with_context(|| format!("failed to read {}", path.display()))?;
59 let endpoints: RuntimeEndpoints = serde_json::from_str(&raw)
60 .with_context(|| format!("failed to parse {}", path.display()))?;
61 Ok(endpoints
62 .public_base_url
63 .as_deref()
64 .map(str::trim)
65 .filter(|value| !value.is_empty())
66 .map(ToString::to_string))
67}
68
69pub fn load_effective_static_routes_defaults(
71 bundle_root: &Path,
72 tenant: &str,
73 team: Option<&str>,
74) -> Result<Option<StaticRoutesPolicy>> {
75 let mut policy = load_static_routes_artifact(bundle_root)?.unwrap_or_default();
76 if policy.public_base_url.is_none()
77 && let Some(runtime_url) = load_runtime_public_base_url(bundle_root, tenant, team)?
78 {
79 policy.public_base_url = Some(runtime_url);
80 }
81 if policy == StaticRoutesPolicy::disabled() {
82 return Ok(None);
83 }
84 Ok(Some(policy))
85}
86
87pub fn persist_static_routes_artifact(
89 bundle_root: &Path,
90 policy: &StaticRoutesPolicy,
91) -> Result<PathBuf> {
92 let path = static_routes_artifact_path(bundle_root);
93 if let Some(parent) = path.parent() {
94 std::fs::create_dir_all(parent)?;
95 }
96 let payload = serde_json::to_string_pretty(policy).context("serialize static routes policy")?;
97 std::fs::write(&path, payload)
98 .with_context(|| format!("failed to write {}", path.display()))?;
99 Ok(path)
100}