Compare commits

..

1 Commits

Author SHA1 Message Date
Brian Picciano
1a1e1e4c5a WIP 2023-06-25 17:51:14 +02:00
8 changed files with 127 additions and 148 deletions

View File

@ -24,16 +24,15 @@ pub trait Manager: Sync + Send {
) -> Result<(PrivateKey, Vec<Certificate>), GetCertificateError>; ) -> Result<(PrivateKey, Vec<Certificate>), GetCertificateError>;
} }
pub struct ManagerImpl { struct ManagerImpl {
store: Box<dyn acme::store::Store>, store: Box<dyn acme::store::Store>,
account: sync::Arc<acme2::Account>, account: sync::Arc<acme2::Account>,
} }
impl ManagerImpl { pub async fn new(
pub async fn new<Store: acme::store::Store + 'static>( store: Box<dyn acme::store::Store>,
store: Store,
contact_email: &str, contact_email: &str,
) -> Result<Self, unexpected::Error> { ) -> Result<Box<dyn Manager>, unexpected::Error> {
let dir = acme2::DirectoryBuilder::new(LETS_ENCRYPT_URL.to_string()) let dir = acme2::DirectoryBuilder::new(LETS_ENCRYPT_URL.to_string())
.build() .build()
.await .await
@ -55,9 +54,7 @@ impl ManagerImpl {
); );
} }
Err(acme::store::GetAccountKeyError::NotFound) => (), Err(acme::store::GetAccountKeyError::NotFound) => (),
Err(acme::store::GetAccountKeyError::Unexpected(err)) => { Err(acme::store::GetAccountKeyError::Unexpected(err)) => return Err(err.into_unexpected()),
return Err(err.into_unexpected())
}
} }
let account = builder let account = builder
@ -75,11 +72,7 @@ impl ManagerImpl {
.set_account_key(&account_key) .set_account_key(&account_key)
.or_unexpected_while("storing account key")?; .or_unexpected_while("storing account key")?;
Ok(Self { Ok(Box::new(ManagerImpl { store, account }))
store: Box::from(store),
account,
})
}
} }
impl Manager for ManagerImpl { impl Manager for ManagerImpl {

View File

@ -66,12 +66,11 @@ struct StoredPKeyCert {
cert: Vec<Certificate>, cert: Vec<Certificate>,
} }
pub struct FSStore { struct FSStore {
dir_path: path::PathBuf, dir_path: path::PathBuf,
} }
impl FSStore { pub fn new(dir_path: &path::Path) -> Result<Box<dyn Store>, unexpected::Error> {
pub fn new(dir_path: &path::Path) -> Result<Self, unexpected::Error> {
vec![ vec![
dir_path, dir_path,
dir_path.join("http01_challenge_keys").as_ref(), dir_path.join("http01_challenge_keys").as_ref(),
@ -79,16 +78,16 @@ impl FSStore {
] ]
.iter() .iter()
.map(|dir| { .map(|dir| {
fs::create_dir_all(dir) fs::create_dir_all(dir).map_unexpected_while(|| format!("creating dir {}", dir.display()))
.map_unexpected_while(|| format!("creating dir {}", dir.display()))
}) })
.try_collect()?; .try_collect()?;
Ok(Self { Ok(Box::new(FSStore {
dir_path: dir_path.into(), dir_path: dir_path.into(),
}) }))
} }
impl FSStore {
fn account_key_path(&self) -> path::PathBuf { fn account_key_path(&self) -> path::PathBuf {
self.dir_path.join("account.key") self.dir_path.join("account.key")
} }

View File

@ -36,11 +36,10 @@ pub struct DNSChecker {
client: tokio::sync::Mutex<AsyncClient>, client: tokio::sync::Mutex<AsyncClient>,
} }
impl DNSChecker {
pub async fn new( pub async fn new(
target_a: net::Ipv4Addr, target_a: net::Ipv4Addr,
resolver_addr: &str, resolver_addr: &str,
) -> Result<Self, NewDNSCheckerError> { ) -> Result<DNSChecker, NewDNSCheckerError> {
let resolver_addr = resolver_addr let resolver_addr = resolver_addr
.parse() .parse()
.map_err(|_| NewDNSCheckerError::InvalidResolverAddress)?; .map_err(|_| NewDNSCheckerError::InvalidResolverAddress)?;
@ -51,12 +50,13 @@ impl DNSChecker {
tokio::spawn(bg); tokio::spawn(bg);
Ok(Self { Ok(DNSChecker {
target_a, target_a,
client: tokio::sync::Mutex::new(client), client: tokio::sync::Mutex::new(client),
}) })
} }
impl DNSChecker {
pub async fn check_domain( pub async fn check_domain(
&self, &self,
domain: &domain::Name, domain: &domain::Name,

View File

@ -45,18 +45,18 @@ pub trait Store: Sync + Send {
fn all_domains(&self) -> Result<Vec<domain::Name>, unexpected::Error>; fn all_domains(&self) -> Result<Vec<domain::Name>, unexpected::Error>;
} }
pub struct FSStore { struct FSStore {
dir_path: PathBuf, dir_path: PathBuf,
} }
impl FSStore { pub fn new(dir_path: &Path) -> io::Result<Box<dyn Store>> {
pub fn new(dir_path: &Path) -> io::Result<Self> {
fs::create_dir_all(dir_path)?; fs::create_dir_all(dir_path)?;
Ok(Self { Ok(Box::new(FSStore {
dir_path: dir_path.into(), dir_path: dir_path.into(),
}) }))
} }
impl FSStore {
fn config_dir_path(&self, domain: &domain::Name) -> PathBuf { fn config_dir_path(&self, domain: &domain::Name) -> PathBuf {
self.dir_path.join(domain.as_str()) self.dir_path.join(domain.as_str())
} }

View File

@ -176,22 +176,18 @@ async fn sync_origins(origin_store: &dyn origin::store::Store, canceller: Cancel
} }
} }
pub fn new< pub fn new(
OriginStore: origin::store::Store + 'static,
DomainConfigStore: config::Store + 'static,
AcmeManager: acme::manager::Manager + 'static,
>(
task_stack: &mut util::TaskStack<unexpected::Error>, task_stack: &mut util::TaskStack<unexpected::Error>,
origin_store: OriginStore, origin_store: Box<dyn origin::store::Store>,
domain_config_store: DomainConfigStore, domain_config_store: Box<dyn config::Store>,
domain_checker: checker::DNSChecker, domain_checker: checker::DNSChecker,
acme_manager: Option<AcmeManager>, acme_manager: Option<Box<dyn acme::manager::Manager>>,
) -> sync::Arc<dyn Manager> { ) -> sync::Arc<dyn Manager> {
let manager = sync::Arc::new(ManagerImpl { let manager = sync::Arc::new(ManagerImpl {
origin_store: Box::from(origin_store), origin_store,
domain_config_store: Box::from(domain_config_store), domain_config_store,
domain_checker: domain_checker, domain_checker,
acme_manager: acme_manager.map(|m| Box::new(m) as Box<dyn acme::manager::Manager>), acme_manager,
}); });
task_stack.push_spawn(|canceller| { task_stack.push_spawn(|canceller| {

View File

@ -73,25 +73,23 @@ async fn main() {
) )
.init(); .init();
let origin_store = domani::origin::store::git::FSStore::new(config.origin_store_git_dir_path) let origin_store = domani::origin::store::git::new(config.origin_store_git_dir_path)
.expect("git origin store initialization failed"); .expect("git origin store initialization failed");
let domain_checker = domani::domain::checker::DNSChecker::new( let domain_checker = domani::domain::checker::new(
config.domain_checker_target_a, config.domain_checker_target_a,
&config.domain_checker_resolver_addr, &config.domain_checker_resolver_addr,
) )
.await .await
.expect("domain checker initialization failed"); .expect("domain checker initialization failed");
let domain_config_store = let domain_config_store = domani::domain::config::new(&config.domain_config_store_dir_path)
domani::domain::config::FSStore::new(&config.domain_config_store_dir_path)
.expect("domain config store initialization failed"); .expect("domain config store initialization failed");
let domain_acme_manager = if config.https_listen_addr.is_some() { let domain_acme_manager = if config.https_listen_addr.is_some() {
let domain_acme_store_dir_path = config.domain_acme_store_dir_path.unwrap(); let domain_acme_store_dir_path = config.domain_acme_store_dir_path.unwrap();
let domain_acme_store = let domain_acme_store = domani::domain::acme::store::new(&domain_acme_store_dir_path)
domani::domain::acme::store::FSStore::new(&domain_acme_store_dir_path)
.expect("domain acme store initialization failed"); .expect("domain acme store initialization failed");
// if https_listen_addr is set then domain_acme_contact_email is required, see the Cli/clap // if https_listen_addr is set then domain_acme_contact_email is required, see the Cli/clap
@ -99,10 +97,7 @@ async fn main() {
let domain_acme_contact_email = config.domain_acme_contact_email.unwrap(); let domain_acme_contact_email = config.domain_acme_contact_email.unwrap();
Some( Some(
domani::domain::acme::manager::ManagerImpl::new( domani::domain::acme::manager::new(domain_acme_store, &domain_acme_contact_email)
domain_acme_store,
&domain_acme_contact_email,
)
.await .await
.expect("domain acme manager initialization failed"), .expect("domain acme manager initialization failed"),
) )

View File

@ -59,9 +59,9 @@ enum GetOriginError {
Unexpected(#[from] unexpected::Error), Unexpected(#[from] unexpected::Error),
} }
/// Implements the Store trait for any Descr::Git based Origins, storing the git repos on disk. If /// git::Store implements the Store trait for any Descr::Git based Origins. If any non-git
/// any non-git Descrs are used then this implementation will panic. /// Descrs are used then this implementation will panic.
pub struct FSStore { struct Store {
dir_path: PathBuf, dir_path: PathBuf,
// to prevent against syncing the same origin more than once at a time, but still allowing // to prevent against syncing the same origin more than once at a time, but still allowing
@ -71,16 +71,16 @@ pub struct FSStore {
origins: sync::RwLock<collections::HashMap<origin::Descr, sync::Arc<Origin>>>, origins: sync::RwLock<collections::HashMap<origin::Descr, sync::Arc<Origin>>>,
} }
impl FSStore { pub fn new(dir_path: PathBuf) -> io::Result<Box<dyn super::Store>> {
pub fn new(dir_path: PathBuf) -> io::Result<Self> {
fs::create_dir_all(&dir_path)?; fs::create_dir_all(&dir_path)?;
Ok(Self { Ok(Box::new(Store {
dir_path, dir_path,
sync_guard: sync::Mutex::new(collections::HashMap::new()), sync_guard: sync::Mutex::new(collections::HashMap::new()),
origins: sync::RwLock::new(collections::HashMap::new()), origins: sync::RwLock::new(collections::HashMap::new()),
}) }))
} }
impl Store {
fn repo_path(&self, descr: &origin::Descr) -> PathBuf { fn repo_path(&self, descr: &origin::Descr) -> PathBuf {
self.dir_path.join(descr.id()) self.dir_path.join(descr.id())
} }
@ -208,7 +208,7 @@ impl FSStore {
} }
} }
impl super::Store for FSStore { impl super::Store for Store {
fn sync(&self, descr: origin::Descr, limits: store::Limits) -> Result<(), store::SyncError> { fn sync(&self, descr: origin::Descr, limits: store::Limits) -> Result<(), store::SyncError> {
// attempt to lock this descr for syncing, doing so within a new scope so the mutex // attempt to lock this descr for syncing, doing so within a new scope so the mutex
// isn't actually being held for the whole method duration. // isn't actually being held for the whole method duration.
@ -344,7 +344,7 @@ mod tests {
let limits = store::Limits {}; let limits = store::Limits {};
let store = super::FSStore::new(tmp_dir.path().to_path_buf()).expect("store created"); let store = super::new(tmp_dir.path().to_path_buf()).expect("store created");
store store
.sync(descr.clone(), limits) .sync(descr.clone(), limits)

View File

@ -2,28 +2,26 @@ use crate::error::unexpected::Mappable;
use crate::origin::{self, store}; use crate::origin::{self, store};
use std::sync; use std::sync;
pub struct Store<F, S> struct Store<F, S>
where where
S: store::Store + 'static, S: store::Store,
F: Fn(&origin::Descr) -> Option<S> + Sync + Send, F: Fn(&origin::Descr) -> Option<S> + Sync + Send,
{ {
mapping_fn: F, mapping_fn: F,
stores: Vec<S>, //stores: Vec<S>,
} }
impl<F, S> Store<F, S> pub fn new<F, S>(mapping_fn: F) -> Box<dyn store::Store>
where where
S: store::Store + 'static, S: store::Store + 'static,
F: Fn(&origin::Descr) -> Option<S> + Sync + Send, F: Fn(&origin::Descr) -> Option<S> + Sync + Send + 'static,
{ {
pub fn new(mapping_fn: F, stores: Vec<S>) -> Store<F, S> { Box::new(Store { mapping_fn })
Store { mapping_fn, stores }
}
} }
impl<F, S> store::Store for Store<F, S> impl<F, S> store::Store for Store<F, S>
where where
S: store::Store + 'static, S: store::Store,
F: Fn(&origin::Descr) -> Option<S> + Sync + Send, F: Fn(&origin::Descr) -> Option<S> + Sync + Send,
{ {
fn sync(&self, descr: origin::Descr, limits: store::Limits) -> Result<(), store::SyncError> { fn sync(&self, descr: origin::Descr, limits: store::Limits) -> Result<(), store::SyncError> {
@ -41,15 +39,14 @@ where
fn all_descrs(&self) -> Result<Vec<origin::Descr>, store::AllDescrsError> { fn all_descrs(&self) -> Result<Vec<origin::Descr>, store::AllDescrsError> {
let mut res = Vec::<origin::Descr>::new(); let mut res = Vec::<origin::Descr>::new();
for store in self.stores.iter() { //for store in self.stores.iter() {
store.all_descrs()?.into_iter().collect_into(&mut res); // store.all_descrs()?.into_iter().collect_into(&mut res);
} //}
Ok(res) Ok(res)
} }
} }
/*
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::origin::{self, store}; use crate::origin::{self, store};
@ -95,4 +92,3 @@ mod tests {
assert_eq!(Ok(()), s.sync(descrA, store::Limits {})) assert_eq!(Ok(()), s.sync(descrA, store::Limits {}))
} }
} }
*/