gandi-live-dns-rust/src/config.rs

83 lines
2.4 KiB
Rust
Raw Normal View History

2022-01-23 15:12:27 -06:00
use crate::opts;
use anyhow;
2021-12-12 03:32:05 -06:00
use directories::ProjectDirs;
use serde::Deserialize;
use std::fs;
use std::path::PathBuf;
2021-12-24 19:20:31 -06:00
#[derive(Deserialize, Debug)]
pub struct Entry {
pub name: String,
types: Option<Vec<String>>,
fqdn: Option<String>,
ttl: Option<u32>,
2021-12-24 19:20:31 -06:00
}
fn default_ttl() -> u32 { return 300; }
2021-12-12 03:32:05 -06:00
#[derive(Deserialize, Debug)]
pub struct Config {
2021-12-24 19:20:31 -06:00
fqdn: String,
2021-12-14 21:30:36 -06:00
pub api_key: String,
2021-12-24 19:20:31 -06:00
pub entry: Vec<Entry>,
#[serde(default = "default_ttl")]
pub ttl: u32,
2021-12-24 19:20:31 -06:00
}
2022-01-23 15:12:27 -06:00
const DEFAULT_TYPES: &'static [&'static str] = &["A"];
2021-12-24 19:20:31 -06:00
impl Config {
pub fn fqdn<'c>(entry: &'c Entry, config: &'c Config) -> &'c str {
entry.fqdn.as_ref().unwrap_or(&config.fqdn).as_str()
}
pub fn ttl(entry: &Entry, config: &Config) -> u32 {
entry.ttl.unwrap_or(config.ttl)
2021-12-24 19:20:31 -06:00
}
pub fn types<'e>(entry: &'e Entry) -> Vec<&'e str> {
entry
2022-01-23 15:12:27 -06:00
.types
.as_ref()
.and_then(|ts| Some(ts.iter().map(|t| t.as_str()).collect()))
.unwrap_or_else(|| DEFAULT_TYPES.to_vec())
2021-12-24 19:20:31 -06:00
}
2021-12-12 03:32:05 -06:00
}
2022-01-23 15:12:27 -06:00
fn load_config_from<P: std::convert::AsRef<std::path::Path>>(path: P) -> anyhow::Result<Config> {
let contents = fs::read_to_string(path)?;
Ok(toml::from_str(&contents)?)
}
2021-12-12 03:32:05 -06:00
2022-01-23 15:12:27 -06:00
pub fn load_config(opts: &opts::Opts) -> anyhow::Result<Config> {
match &opts.config {
Some(config_path) => load_config_from(&config_path),
None => {
let confpath = ProjectDirs::from("me", "kaangenc", "gandi-dynamic-dns")
2022-01-23 21:26:57 -06:00
.and_then(|dir| Some(PathBuf::from(dir.config_dir()).join("config.toml")))
.ok_or(anyhow::anyhow!("Can't find config directory"));
confpath
2022-01-23 15:12:27 -06:00
.and_then(|path| {
2022-01-23 21:26:57 -06:00
println!("Checking for config: {}", path.to_string_lossy());
2022-01-23 15:12:27 -06:00
load_config_from(path)
})
.or_else(|_| {
2022-01-23 21:26:57 -06:00
let path = PathBuf::from(".").join("gandi.toml");
println!("Checking for config: {}", path.to_string_lossy());
load_config_from(path)
2022-01-23 15:12:27 -06:00
})
}
}
2021-12-12 03:32:05 -06:00
}
2022-01-23 15:12:27 -06:00
pub fn validate_config(config: &Config) -> anyhow::Result<()> {
2021-12-24 19:20:31 -06:00
for entry in &config.entry {
for entry_type in Config::types(&entry) {
2022-01-23 21:26:57 -06:00
if entry_type != "A" && entry_type != "AAAA" {
2022-01-23 15:12:27 -06:00
anyhow::bail!("Entry {} has invalid type {}", entry.name, entry_type);
2021-12-24 19:20:31 -06:00
}
}
}
return Ok(());
}