feat: config types and loader
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
08b7f94e4c
commit
8ab3bb2d12
@@ -0,0 +1,141 @@
|
||||
use anyhow::{Context, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum NodeRole { Primary, Secondary }
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct NodeConfig {
|
||||
pub name: String,
|
||||
pub role: NodeRole,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct HotConfig {
|
||||
pub path: PathBuf,
|
||||
pub max_gb: u64,
|
||||
pub stale_hours: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct WarmConfig {
|
||||
pub projects_path: PathBuf,
|
||||
pub zfs_dataset: String,
|
||||
pub snapshot_retain_hours: u64,
|
||||
pub snapshot_retain_days: u64,
|
||||
pub snapshot_retain_weeks: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct ColdConfig {
|
||||
pub archive_path: PathBuf,
|
||||
pub zfs_dataset: String,
|
||||
pub retain_weeks: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct ReplicationConfig {
|
||||
pub receive_from_peer: Option<bool>,
|
||||
pub peer_user: Option<String>,
|
||||
pub send_to_host: Option<String>,
|
||||
pub send_to_user: Option<String>,
|
||||
pub cold_dataset_on_peer: Option<String>,
|
||||
pub nightly_at: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct Config {
|
||||
pub node: NodeConfig,
|
||||
pub hot: HotConfig,
|
||||
pub warm: WarmConfig,
|
||||
pub cold: Option<ColdConfig>,
|
||||
pub replication: Option<ReplicationConfig>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn load(path: &Path) -> Result<Self> {
|
||||
let content = std::fs::read_to_string(path)
|
||||
.with_context(|| format!("reading config at {}", path.display()))?;
|
||||
toml::from_str(&content)
|
||||
.with_context(|| format!("parsing config at {}", path.display()))
|
||||
}
|
||||
|
||||
pub fn default_path() -> PathBuf {
|
||||
PathBuf::from("/etc/claw-store/config.toml")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_load_primary_config() {
|
||||
let toml = r#"
|
||||
[node]
|
||||
name = "architect"
|
||||
role = "primary"
|
||||
|
||||
[hot]
|
||||
path = "/hot/targets"
|
||||
max_gb = 200
|
||||
stale_hours = 48
|
||||
|
||||
[warm]
|
||||
projects_path = "/slab/projects"
|
||||
zfs_dataset = "slab/projects"
|
||||
snapshot_retain_hours = 24
|
||||
snapshot_retain_days = 7
|
||||
snapshot_retain_weeks = 4
|
||||
|
||||
[cold]
|
||||
archive_path = "/data/archive"
|
||||
zfs_dataset = "data/archive"
|
||||
retain_weeks = 12
|
||||
|
||||
[replication]
|
||||
receive_from_peer = true
|
||||
peer_user = "osobh"
|
||||
"#;
|
||||
let cfg: Config = toml::from_str(toml).unwrap();
|
||||
assert_eq!(cfg.node.name, "architect");
|
||||
assert_eq!(cfg.node.role, NodeRole::Primary);
|
||||
assert_eq!(cfg.hot.max_gb, 200);
|
||||
assert!(cfg.cold.is_some());
|
||||
assert_eq!(cfg.cold.unwrap().retain_weeks, 12);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_load_secondary_config() {
|
||||
let toml = r#"
|
||||
[node]
|
||||
name = "tank"
|
||||
role = "secondary"
|
||||
|
||||
[hot]
|
||||
path = "/hot/targets"
|
||||
max_gb = 300
|
||||
stale_hours = 48
|
||||
|
||||
[warm]
|
||||
projects_path = "/slab/projects"
|
||||
zfs_dataset = "slab/projects"
|
||||
snapshot_retain_hours = 24
|
||||
snapshot_retain_days = 7
|
||||
snapshot_retain_weeks = 4
|
||||
|
||||
[replication]
|
||||
send_to_host = "10.10.0.9"
|
||||
send_to_user = "osobh"
|
||||
cold_dataset_on_peer = "data/archive/tank-projects"
|
||||
nightly_at = "03:30"
|
||||
"#;
|
||||
let cfg: Config = toml::from_str(toml).unwrap();
|
||||
assert_eq!(cfg.node.role, NodeRole::Secondary);
|
||||
assert!(cfg.cold.is_none());
|
||||
let rep = cfg.replication.unwrap();
|
||||
assert_eq!(rep.send_to_host.unwrap(), "10.10.0.9");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user