use super::models::{JokowayConfig, RootConfig, ServerConf, Service, TlsSettings, Upstream};
use serde_yaml;
use std::fs::File;
use std::io::BufReader;
use std::path::Path;
pub struct ConfigBuilder {
config: JokowayConfig,
server_conf: Option<ServerConf>,
}
impl Default for ConfigBuilder {
fn default() -> Self {
Self::new()
}
}
impl ConfigBuilder {
pub fn new() -> Self {
ConfigBuilder {
config: JokowayConfig::default(),
server_conf: Some(ServerConf::default()),
}
}
pub fn from_file<P: AsRef<Path>>(
mut self,
path: P,
) -> Result<Self, Box<dyn std::error::Error>> {
let path_ref = path.as_ref();
if !path_ref.exists() {
return Err(format!("Configuration file not found: {}", path_ref.display()).into());
}
let file = File::open(path_ref)?;
let reader = BufReader::new(file);
let root: RootConfig = serde_yaml::from_reader(reader).map_err(|e| {
format!(
"Failed to parse YAML config from {}: {}",
path_ref.display(),
e
)
})?;
self.config = root.jokoway;
if root.pingora.is_some() {
self.server_conf = root.pingora;
}
Ok(self)
}
pub fn with_tls(mut self, tls: TlsSettings) -> Self {
self.config.tls = Some(tls);
self
}
pub fn add_upstream(mut self, upstream: Upstream) -> Self {
self.config.upstreams.push(upstream);
self
}
pub fn add_service(mut self, service: Service) -> Self {
self.config.services.push(std::sync::Arc::new(service));
self
}
pub fn configure<F>(mut self, func: F) -> Self
where
F: FnOnce(&mut JokowayConfig, &mut ServerConf),
{
if let Some(ref mut sc) = self.server_conf {
func(&mut self.config, sc);
}
self
}
pub fn build(self) -> (JokowayConfig, Option<ServerConf>) {
(self.config, self.server_conf)
}
}