implement domain config store
This commit is contained in:
parent
7b60814681
commit
563f072e09
@ -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"
|
||||
|
@ -1 +1,2 @@
|
||||
pub mod checker;
|
||||
pub mod config;
|
||||
|
@ -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
127
src/domain/config.rs
Normal 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"));
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user