1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
use crate::auth::AuthConfig; use crate::errors::*; use serde::Deserialize; use std::collections::HashMap; use std::fs; use std::path::{Path, PathBuf}; pub const IDLE_DELAY: u64 = 180; pub const PING_DEADLINE: i64 = IDLE_DELAY as i64 + 20; pub const PING_INTERVAL: u64 = 60; pub const WORKER_DELAY: u64 = 3; pub const API_ERROR_DELAY: u64 = 30; pub fn load<P: AsRef<Path>>(path: Option<P>) -> Result<ConfigFile> { let mut config = ConfigFile::default(); if let Some(c) = load_from("/etc/rebuilderd.conf")? { config.update(c); } if let Ok(path) = config_path() { if let Some(c) = load_from(path)? { config.update(c); } } if let Some(path) = path { let c = load_from(path)? .ok_or_else(|| format_err!("Failed to read config file"))?; config.update(c); } Ok(config) } fn config_path() -> Result<PathBuf> { let config_dir = dirs::config_dir() .ok_or_else(|| format_err!("Failed to find config dir"))?; Ok(config_dir.join("rebuilderd.conf")) } fn load_from<P: AsRef<Path>>(path: P) -> Result<Option<ConfigFile>> { if let Ok(buf) = fs::read(path.as_ref()) { debug!("loading config file {:?}", path.as_ref()); let config = toml::from_slice(&buf) .context("Failed to load config")?; Ok(Some(config)) } else { Ok(None) } } #[derive(Debug, Default, Deserialize)] pub struct ConfigFile { #[serde(default)] pub http: HttpConfig, #[serde(default)] pub auth: AuthConfig, #[serde(default)] pub endpoints: HashMap<String, EndpointConfig>, #[serde(default)] pub worker: WorkerConfig, } impl ConfigFile { pub fn update(&mut self, c: ConfigFile) { self.http.update(c.http); self.auth.update(c.auth); for (k, v) in c.endpoints { if let Some(o) = self.endpoints.get_mut(&k) { o.update(v); } else { self.endpoints.insert(k, v); } } self.worker.update(c.worker); } } #[derive(Debug, Default, Deserialize)] pub struct HttpConfig { pub bind_addr: Option<String>, pub endpoint: Option<String>, } impl HttpConfig { pub fn update(&mut self, c: HttpConfig) { if c.bind_addr.is_some() { self.bind_addr = c.bind_addr; } if c.endpoint.is_some() { self.endpoint = c.endpoint; } } } #[derive(Debug, Default, Clone, Deserialize)] pub struct EndpointConfig { pub cookie: String, } impl EndpointConfig { pub fn update(&mut self, c: EndpointConfig) { self.cookie = c.cookie; } } #[derive(Debug, Default, Clone, Deserialize)] pub struct WorkerConfig { #[serde(default)] pub authorized_workers: Vec<String>, pub signup_secret: Option<String>, } impl WorkerConfig { pub fn update(&mut self, c: WorkerConfig) { if !c.authorized_workers.is_empty() { self.authorized_workers = c.authorized_workers; } if c.signup_secret.is_some() { self.signup_secret = c.signup_secret; } } }