doido_controller/
config.rs1use crate::environment::Environment;
8use serde::Deserialize;
9
10pub use doido_core::logger::LoggerConfig;
13
14#[derive(Debug, Clone, Deserialize)]
17pub struct ServerConfig {
18 pub bind: String,
19 pub port: u16,
20}
21
22impl Default for ServerConfig {
23 fn default() -> Self {
24 Self {
25 bind: "0.0.0.0".to_string(),
26 port: 3000,
27 }
28 }
29}
30
31pub trait Config: Send + Sync {
34 fn server(&self) -> &ServerConfig;
36 fn logger(&self) -> &LoggerConfig;
38}
39
40#[derive(Debug, Clone, Default, Deserialize)]
42pub struct YamlConfig {
43 #[serde(default)]
44 pub server: ServerConfig,
45 #[serde(default)]
46 pub logger: LoggerConfig,
47}
48
49impl Config for YamlConfig {
50 fn server(&self) -> &ServerConfig {
51 &self.server
52 }
53
54 fn logger(&self) -> &LoggerConfig {
55 &self.logger
56 }
57}
58
59impl YamlConfig {
60 pub fn load() -> std::io::Result<Self> {
62 Self::load_env(Environment::get_env())
63 }
64
65 pub fn load_env(env: Environment) -> std::io::Result<Self> {
67 let path = format!("config/{}.yml", env.as_str());
68 let contents = std::fs::read_to_string(&path)?;
69 Self::from_yaml(&contents)
70 }
71
72 pub fn from_yaml(yaml: &str) -> std::io::Result<Self> {
74 serde_norway::from_str(yaml)
75 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
76 }
77}
78
79pub fn load() -> Box<dyn Config> {
82 Box::new(YamlConfig::load().unwrap_or_default())
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn parses_logger_level() {
91 let config = YamlConfig::from_yaml("logger:\n level: debug\n").unwrap();
92 assert_eq!(config.logger().level, "debug");
93 assert_eq!(
94 config.logger().directives(),
95 doido_core::logger::directives_for_level("debug")
96 );
97 }
98
99 #[test]
100 fn explicit_directives_override_level() {
101 let yaml = "logger:\n level: info\n directives: warn,my_app=debug\n";
102 let config = YamlConfig::from_yaml(yaml).unwrap();
103 assert_eq!(config.logger().directives(), "warn,my_app=debug");
104 }
105
106 #[test]
107 fn defaults_to_info_when_logger_section_absent() {
108 let config = YamlConfig::from_yaml("server:\n bind: 0.0.0.0\n port: 3000\n").unwrap();
109 assert_eq!(config.logger().level, "info");
110 assert!(config.logger().sql);
111 assert!(config.logger().file.is_none());
112 assert_eq!(
113 config.logger().directives(),
114 doido_core::logger::DEFAULT_DIRECTIVES
115 );
116 }
117}