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