implement domain config store

This commit is contained in:
Brian Picciano 2023-05-07 18:07:31 +02:00
parent 7b60814681
commit 563f072e09
5 changed files with 139 additions and 8 deletions

View File

@ -7,6 +7,7 @@ edition = "2021"
[dev-dependencies]
clippy = "0.0.302"
tempdir = "0.3.7"
[dependencies]
sha2 = "0.10.6"
@ -15,7 +16,6 @@ gix = { version = "0.44.1", features = [
"blocking-network-client",
"blocking-http-transport-reqwest-rust-tls",
]}
tempdir = "0.3.7"
serde = { version = "1.0.162", features = [ "derive" ]}
serde_json = "1.0.96"
trust-dns-client = "0.22.0"

View File

@ -1 +1,2 @@
pub mod checker;
pub mod config;

View File

@ -1,12 +1,11 @@
use std::error::Error;
use std::str::FromStr;
use mockall::automock;
use trust_dns_client::client::{Client, SyncClient};
use trust_dns_client::rr::{DNSClass, Name, RData, RecordType};
use trust_dns_client::udp::UdpClientConnection;
use mockall::automock;
#[derive(Debug)]
pub enum NewDNSCheckerError {
InvalidResolverAddress,

127
src/domain/config.rs Normal file
View File

@ -0,0 +1,127 @@
use std::error::Error;
use std::path::{Path, PathBuf};
use std::{fs, io};
use crate::origin::Descr;
use mockall::automock;
use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
/// Values which the owner of a domain can configure when they install a domain.
pub struct Config {
pub origin_descr: Descr,
}
#[derive(Debug)]
pub enum GetError {
NotFound,
Unexpected(Box<dyn Error>),
}
impl<E: Error + 'static> From<E> for GetError {
fn from(e: E) -> GetError {
GetError::Unexpected(Box::from(e))
}
}
#[derive(Debug)]
pub enum SetError {
NotFound,
Unexpected(Box<dyn Error>),
}
impl<E: Error + 'static> From<E> for SetError {
fn from(e: E) -> SetError {
SetError::Unexpected(Box::from(e))
}
}
#[automock]
pub trait Store {
fn get(&self, domain: &str) -> Result<Config, GetError>;
fn set(&self, domain: &str, config: &Config) -> Result<(), SetError>;
}
pub struct FSStore {
dir_path: PathBuf,
}
impl FSStore {
pub fn new(dir_path: &Path) -> io::Result<FSStore> {
fs::create_dir_all(dir_path)?;
Ok(FSStore {
dir_path: dir_path.into(),
})
}
fn config_dir_path(&self, domain: &str) -> PathBuf {
self.dir_path.join(domain)
}
fn config_file_path(&self, domain: &str) -> PathBuf {
self.config_dir_path(domain).join("config.json")
}
}
impl Store for FSStore {
fn get(&self, domain: &str) -> Result<Config, GetError> {
let config_file =
fs::File::open(self.config_file_path(domain)).map_err(|e| match e.kind() {
io::ErrorKind::NotFound => GetError::NotFound,
_ => e.into(),
})?;
Ok(serde_json::from_reader(config_file)?)
}
fn set(&self, domain: &str, config: &Config) -> Result<(), SetError> {
fs::create_dir_all(self.config_dir_path(domain))?;
let config_file = fs::File::create(self.config_file_path(domain))?;
serde_json::to_writer(config_file, config)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::origin::Descr;
use tempdir::TempDir;
#[test]
fn basic() {
let tmp_dir = TempDir::new("domain_config_store").unwrap();
let store = FSStore::new(tmp_dir.path()).expect("store created");
let domain = "foo";
let config = Config {
origin_descr: Descr::Git {
url: "bar".to_string(),
branch_name: "baz".to_string(),
},
};
assert!(matches!(
store.get(domain),
Err::<Config, GetError>(GetError::NotFound)
));
store.set(domain, &config).expect("config set");
assert_eq!(config, store.get(domain).expect("config retrieved"));
let new_config = Config {
origin_descr: Descr::Git {
url: "BAR".to_string(),
branch_name: "BAZ".to_string(),
},
};
store.set(domain, &new_config).expect("config set");
assert_eq!(new_config, store.get(domain).expect("config retrieved"));
}
}

View File

@ -1,5 +1,4 @@
use super::Descr;
use serde_json;
use std::error::Error;
#[derive(Clone, Copy)]
@ -44,7 +43,12 @@ impl<E: Error + 'static> From<E> for AllDescrsError {
type AllDescrsResult<T> = Result<T, AllDescrsError>;
pub trait Store {
fn write_file<W>(&self, descr: &Descr, path: &str, into: &mut W) -> Result<(), WriteFileError>
fn read_file_into<W>(
&self,
descr: &Descr,
path: &str,
into: &mut W,
) -> Result<(), WriteFileError>
where
W: std::io::Write + ?Sized;
@ -140,7 +144,7 @@ pub mod git {
Ok(())
}
fn write_file<W>(
fn read_file_into<W>(
&self,
descr: &Descr,
path: &str,
@ -235,7 +239,7 @@ pub mod git {
let assert_write = |path: &str| {
let mut into: Vec<u8> = vec![];
store
.write_file(&descr, path, &mut into)
.read_file_into(&descr, path, &mut into)
.expect("write should succeed");
assert!(into.len() > 0);
};
@ -246,7 +250,7 @@ pub mod git {
// File doesn't exist
let mut into: Vec<u8> = vec![];
assert!(matches!(
store.write_file(&descr, "DNE", &mut into),
store.read_file_into(&descr, "DNE", &mut into),
Err::<(), super::WriteFileError>(super::WriteFileError::FileNotFound),
));
assert_eq!(into.len(), 0);