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