200 lines
5.8 KiB
Rust
200 lines
5.8 KiB
Rust
|
use crate::domain::{checker, config};
|
||
|
use crate::origin;
|
||
|
use std::error::Error;
|
||
|
|
||
|
#[derive(thiserror::Error, Debug)]
|
||
|
pub enum GetConfigError {
|
||
|
#[error("not found")]
|
||
|
NotFound,
|
||
|
|
||
|
#[error(transparent)]
|
||
|
Unexpected(Box<dyn Error>),
|
||
|
}
|
||
|
|
||
|
impl From<config::GetError> for GetConfigError {
|
||
|
fn from(e: config::GetError) -> GetConfigError {
|
||
|
match e {
|
||
|
config::GetError::NotFound => GetConfigError::NotFound,
|
||
|
config::GetError::Unexpected(e) => GetConfigError::Unexpected(e),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[derive(thiserror::Error, Debug)]
|
||
|
pub enum GetOriginError {
|
||
|
#[error("not found")]
|
||
|
NotFound,
|
||
|
|
||
|
#[error(transparent)]
|
||
|
Unexpected(Box<dyn Error>),
|
||
|
}
|
||
|
|
||
|
impl From<config::GetError> for GetOriginError {
|
||
|
fn from(e: config::GetError) -> GetOriginError {
|
||
|
match e {
|
||
|
config::GetError::NotFound => GetOriginError::NotFound,
|
||
|
config::GetError::Unexpected(e) => GetOriginError::Unexpected(e),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[derive(thiserror::Error, Debug)]
|
||
|
pub enum SyncError {
|
||
|
#[error("not found")]
|
||
|
NotFound,
|
||
|
|
||
|
#[error(transparent)]
|
||
|
Unexpected(Box<dyn Error>),
|
||
|
}
|
||
|
|
||
|
impl From<config::GetError> for SyncError {
|
||
|
fn from(e: config::GetError) -> SyncError {
|
||
|
match e {
|
||
|
config::GetError::NotFound => SyncError::NotFound,
|
||
|
config::GetError::Unexpected(e) => SyncError::Unexpected(e),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[derive(thiserror::Error, Debug)]
|
||
|
pub enum SyncWithConfigError {
|
||
|
#[error("invalid url")]
|
||
|
InvalidURL,
|
||
|
|
||
|
#[error("invalid branch name")]
|
||
|
InvalidBranchName,
|
||
|
|
||
|
#[error("invalid domain name")]
|
||
|
InvalidDomainName,
|
||
|
|
||
|
#[error("target CNAME not set")]
|
||
|
TargetCNAMENotSet,
|
||
|
|
||
|
#[error("challenge token not set")]
|
||
|
ChallengeTokenNotSet,
|
||
|
|
||
|
#[error(transparent)]
|
||
|
Unexpected(Box<dyn Error>),
|
||
|
}
|
||
|
|
||
|
impl From<origin::store::SyncError> for SyncWithConfigError {
|
||
|
fn from(e: origin::store::SyncError) -> SyncWithConfigError {
|
||
|
match e {
|
||
|
origin::store::SyncError::InvalidURL => SyncWithConfigError::InvalidURL,
|
||
|
origin::store::SyncError::InvalidBranchName => SyncWithConfigError::InvalidBranchName,
|
||
|
origin::store::SyncError::Unexpected(e) => SyncWithConfigError::Unexpected(e),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl From<checker::CheckDomainError> for SyncWithConfigError {
|
||
|
fn from(e: checker::CheckDomainError) -> SyncWithConfigError {
|
||
|
match e {
|
||
|
checker::CheckDomainError::InvalidDomainName => SyncWithConfigError::InvalidDomainName,
|
||
|
checker::CheckDomainError::TargetCNAMENotSet => SyncWithConfigError::TargetCNAMENotSet,
|
||
|
checker::CheckDomainError::ChallengeTokenNotSet => {
|
||
|
SyncWithConfigError::ChallengeTokenNotSet
|
||
|
}
|
||
|
checker::CheckDomainError::Unexpected(e) => SyncWithConfigError::Unexpected(e),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl From<config::SetError> for SyncWithConfigError {
|
||
|
fn from(e: config::SetError) -> SyncWithConfigError {
|
||
|
match e {
|
||
|
config::SetError::Unexpected(e) => SyncWithConfigError::Unexpected(e),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[mockall::automock]
|
||
|
pub trait Manager {
|
||
|
fn get_config(&self, domain: &str) -> Result<config::Config, GetConfigError>;
|
||
|
fn get_origin(&self, domain: &str) -> Result<Box<dyn origin::Origin>, GetOriginError>;
|
||
|
fn sync(&self, domain: &str) -> Result<(), SyncError>;
|
||
|
fn sync_with_config(
|
||
|
&self,
|
||
|
domain: &str,
|
||
|
config: &config::Config,
|
||
|
) -> Result<(), SyncWithConfigError>;
|
||
|
}
|
||
|
|
||
|
pub fn new_manager<OriginStore, DomainConfigStore, DomainChecker>(
|
||
|
origin_store: OriginStore,
|
||
|
domain_config_store: DomainConfigStore,
|
||
|
domain_checker: DomainChecker,
|
||
|
) -> impl Manager
|
||
|
where
|
||
|
OriginStore: for<'a> origin::store::Store<'a>,
|
||
|
DomainConfigStore: config::Store,
|
||
|
DomainChecker: checker::Checker,
|
||
|
{
|
||
|
ManagerImpl {
|
||
|
origin_store,
|
||
|
domain_config_store,
|
||
|
domain_checker,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
struct ManagerImpl<OriginStore, DomainConfigStore, DomainChecker>
|
||
|
where
|
||
|
OriginStore: for<'a> origin::store::Store<'a>,
|
||
|
DomainConfigStore: config::Store,
|
||
|
DomainChecker: checker::Checker,
|
||
|
{
|
||
|
origin_store: OriginStore,
|
||
|
domain_config_store: DomainConfigStore,
|
||
|
domain_checker: DomainChecker,
|
||
|
}
|
||
|
|
||
|
impl<OriginStore, DomainConfigStore, DomainChecker> Manager
|
||
|
for ManagerImpl<OriginStore, DomainConfigStore, DomainChecker>
|
||
|
where
|
||
|
OriginStore: for<'a> origin::store::Store<'a>,
|
||
|
DomainConfigStore: config::Store,
|
||
|
DomainChecker: checker::Checker,
|
||
|
{
|
||
|
fn get_config(&self, domain: &str) -> Result<config::Config, GetConfigError> {
|
||
|
Ok(self.domain_config_store.get(domain)?)
|
||
|
}
|
||
|
|
||
|
fn get_origin(&self, domain: &str) -> Result<Box<dyn origin::Origin>, GetOriginError> {
|
||
|
let config = self.domain_config_store.get(domain)?;
|
||
|
let origin = self
|
||
|
.origin_store
|
||
|
.get(config.origin_descr)
|
||
|
// if there's a config there should be an origin, any error here is unexpected
|
||
|
.map_err(|e| GetOriginError::Unexpected(Box::from(e)))?;
|
||
|
Ok(origin)
|
||
|
}
|
||
|
|
||
|
fn sync(&self, domain: &str) -> Result<(), SyncError> {
|
||
|
let config = self.domain_config_store.get(domain)?;
|
||
|
self.origin_store
|
||
|
.sync(&config.origin_descr, origin::store::Limits {})
|
||
|
// if there's a config there should be an origin, any error here is unexpected
|
||
|
.map_err(|e| SyncError::Unexpected(Box::from(e)))?;
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
fn sync_with_config(
|
||
|
&self,
|
||
|
domain: &str,
|
||
|
config: &config::Config,
|
||
|
) -> Result<(), SyncWithConfigError> {
|
||
|
let config_hash = config
|
||
|
.hash()
|
||
|
.map_err(|e| SyncWithConfigError::Unexpected(Box::from(e)))?;
|
||
|
|
||
|
self.domain_checker.check_domain(domain, &config_hash)?;
|
||
|
|
||
|
self.origin_store
|
||
|
.sync(&config.origin_descr, origin::store::Limits {})?;
|
||
|
|
||
|
self.domain_config_store.set(domain, config)?;
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
}
|