Add brokerd's configuration
Implemented crates/brokerd/src/config.rs: typed Paths, Sockets, Approvals and Config with serde(deny_unknown_fields, default) on every struct, hand-written ConfigError (Read/Parse) with Display and std::error::Error, and the parse/load/ broker_socket/admin_socket/audit_dir/state_dir methods. Added serde, serde_json and toml to crates/brokerd/Cargo.toml, registered pub mod config; in lib.rs, added brokerd to the serde and serde_json Used-by cells in docs/dependencies.md, and copied the given test and six fixtures byte-identical. 7 config tests pass; make gate prints gate: ok. Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
//! `brokerd` configuration: read `brokerd.toml` into a typed `Config`.
|
||||
//!
|
||||
//! This is our own format, so unknown keys are errors in every table: a
|
||||
//! misspelt key that silently fell back to its default would be a setting the
|
||||
//! owner believes is set and is not.
|
||||
|
||||
use serde::Deserialize;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct Paths {
|
||||
pub home: PathBuf,
|
||||
pub grants: PathBuf,
|
||||
}
|
||||
|
||||
impl Default for Paths {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
home: std::env::var_os("BOXMAKER_HOME")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|| PathBuf::from("/var/lib/boxmaker")),
|
||||
grants: PathBuf::from("/etc/boxmaker/grants"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An empty path means "the default under `home`".
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Default)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct Sockets {
|
||||
pub broker: PathBuf,
|
||||
pub admin: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct Approvals {
|
||||
pub ttl_ms: u64,
|
||||
}
|
||||
|
||||
impl Default for Approvals {
|
||||
fn default() -> Self {
|
||||
Self { ttl_ms: 900_000 }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Config {
|
||||
#[serde(default)]
|
||||
pub paths: Paths,
|
||||
#[serde(default)]
|
||||
pub sockets: Sockets,
|
||||
#[serde(default)]
|
||||
pub approvals: Approvals,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ConfigError {
|
||||
Read(PathBuf, std::io::Error),
|
||||
Parse(PathBuf, toml::de::Error),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ConfigError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
ConfigError::Read(path, err) => write!(f, "{}: {err}", path.display()),
|
||||
ConfigError::Parse(path, err) => write!(f, "{}: {err}", path.display()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for ConfigError {}
|
||||
|
||||
impl Config {
|
||||
pub fn parse(text: &str) -> Result<Config, toml::de::Error> {
|
||||
toml::from_str(text)
|
||||
}
|
||||
pub fn load(path: &Path) -> Result<Config, ConfigError> {
|
||||
let text =
|
||||
std::fs::read_to_string(path).map_err(|e| ConfigError::Read(path.to_path_buf(), e))?;
|
||||
let config: Config =
|
||||
toml::from_str(&text).map_err(|e| ConfigError::Parse(path.to_path_buf(), e))?;
|
||||
Ok(config)
|
||||
}
|
||||
pub fn broker_socket(&self) -> PathBuf {
|
||||
if self.sockets.broker.as_os_str().is_empty() {
|
||||
self.paths.home.join("run/loop-broker/broker.sock")
|
||||
} else {
|
||||
self.sockets.broker.clone()
|
||||
}
|
||||
}
|
||||
pub fn admin_socket(&self) -> PathBuf {
|
||||
if self.sockets.admin.as_os_str().is_empty() {
|
||||
self.paths.home.join("run/owner-broker/admin.sock")
|
||||
} else {
|
||||
self.sockets.admin.clone()
|
||||
}
|
||||
}
|
||||
pub fn audit_dir(&self) -> PathBuf {
|
||||
self.paths.home.join("audit")
|
||||
}
|
||||
pub fn state_dir(&self) -> PathBuf {
|
||||
self.paths.home.join("broker/sessions")
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
//! The broker: the only role that holds authority.
|
||||
|
||||
pub mod config;
|
||||
pub mod policy;
|
||||
pub mod runner;
|
||||
|
||||
Reference in New Issue
Block a user