113 lines
3.0 KiB
Rust
113 lines
3.0 KiB
Rust
use std::io::ErrorKind;
|
|
use std::path::{Path, PathBuf};
|
|
|
|
use serde::Deserialize;
|
|
use tracing::{debug, info};
|
|
use url::Url;
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
pub enum Error {
|
|
#[error("Unable to read configuration file: {0}")]
|
|
Io(#[from] std::io::Error),
|
|
#[error("Failed to parse configuration file: {0}")]
|
|
Toml(#[from] toml::de::Error),
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct EtcdConfig {
|
|
#[serde(default = "default_etcd_hosts")]
|
|
pub hosts: Vec<Url>,
|
|
|
|
pub client_cert: Option<PathBuf>,
|
|
pub client_key: Option<PathBuf>,
|
|
pub ca_cert: Option<PathBuf>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct Configuration {
|
|
#[serde(default = "default_namespace")]
|
|
pub namespace: String,
|
|
#[serde(default)]
|
|
pub path_prefix: PathBuf,
|
|
pub etcd: EtcdConfig,
|
|
}
|
|
|
|
impl Default for EtcdConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
hosts: default_etcd_hosts(),
|
|
|
|
client_cert: None,
|
|
client_key: None,
|
|
ca_cert: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for Configuration {
|
|
fn default() -> Self {
|
|
Self {
|
|
namespace: default_namespace(),
|
|
path_prefix: Default::default(),
|
|
etcd: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Configuration {
|
|
pub fn load(path: Option<impl AsRef<Path>>) -> Result<Self, Error> {
|
|
let path = path
|
|
.map(|p| p.as_ref().into())
|
|
.unwrap_or_else(Self::default_path);
|
|
debug!("Loading configuration from {}", path.display());
|
|
let config = match std::fs::read_to_string(&path) {
|
|
Ok(d) => toml::from_str(&d)?,
|
|
Err(e) if e.kind() == ErrorKind::NotFound => {
|
|
debug!("{}: {}", path.display(), e);
|
|
Default::default()
|
|
}
|
|
Err(e) => return Err(e.into()),
|
|
};
|
|
match std::env::var("DUMP_CONFIG") {
|
|
Ok(s) if s == "1" => info!("{:?}", config),
|
|
Ok(_) | Err(_) => (),
|
|
};
|
|
Ok(config)
|
|
}
|
|
|
|
pub fn default_path() -> PathBuf {
|
|
match std::env::var_os(format!(
|
|
"{}_CONFIG",
|
|
env!("CARGO_PKG_NAME").to_uppercase()
|
|
)) {
|
|
Some(v) => PathBuf::from(v),
|
|
None => match std::env::var_os("XDG_CONFIG_HOME") {
|
|
Some(v) => {
|
|
let mut p = PathBuf::from(v);
|
|
p.push(env!("CARGO_PKG_NAME"));
|
|
p.push("config.toml");
|
|
p
|
|
}
|
|
None => match std::env::var_os("HOME") {
|
|
Some(v) => {
|
|
let mut p = PathBuf::from(v);
|
|
p.push(".config");
|
|
p.push(env!("CARGO_PKG_NAME"));
|
|
p.push("config.toml");
|
|
p
|
|
}
|
|
None => PathBuf::from("config.toml"),
|
|
},
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
fn default_namespace() -> String {
|
|
env!("CARGO_PKG_NAME").into()
|
|
}
|
|
|
|
fn default_etcd_hosts() -> Vec<Url> {
|
|
vec![Url::parse("http://localhost:2379").unwrap()]
|
|
}
|