Split domain manager "sync all domains" task into separate ones
Each new task corresponds to syncing a particular kind of thing for each domain, e.g. origins, https certs, etc...
This commit is contained in:
parent
70c78b823a
commit
c95f4b9b39
@ -182,12 +182,58 @@ impl ManagerImpl {
|
||||
config,
|
||||
});
|
||||
|
||||
const SYNC_PERIOD_SECS: u64 = 20 * 60; // 20 minutes
|
||||
|
||||
task_stack.push_spawn_periodically(
|
||||
manager.clone(),
|
||||
20 * 60,
|
||||
|_canceller, manager| async move { manager.sync_all_domains().await },
|
||||
SYNC_PERIOD_SECS,
|
||||
|_canceller, manager| async move {
|
||||
manager
|
||||
.sync_origins()
|
||||
.await
|
||||
.or_unexpected_while("syncing origins")
|
||||
},
|
||||
);
|
||||
|
||||
if manager.can_sync_gemini_cert() {
|
||||
task_stack.push_spawn_periodically(
|
||||
manager.clone(),
|
||||
SYNC_PERIOD_SECS,
|
||||
|_canceller, manager| async move {
|
||||
manager
|
||||
.sync_gemini_certs()
|
||||
.await
|
||||
.or_unexpected_while("syncing gemini certs")
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if manager.can_sync_https_cert() {
|
||||
task_stack.push_spawn_periodically(
|
||||
manager.clone(),
|
||||
SYNC_PERIOD_SECS,
|
||||
|_canceller, manager| async move {
|
||||
manager
|
||||
.sync_https_certs()
|
||||
.await
|
||||
.or_unexpected_while("syncing https certs")
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if manager.can_sync_external_cert() {
|
||||
task_stack.push_spawn_periodically(
|
||||
manager.clone(),
|
||||
SYNC_PERIOD_SECS,
|
||||
|_canceller, manager| async move {
|
||||
manager
|
||||
.sync_external_certs()
|
||||
.await
|
||||
.or_unexpected_while("syncing external certs")
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
manager
|
||||
}
|
||||
|
||||
@ -200,99 +246,155 @@ impl ManagerImpl {
|
||||
self.origin_store.sync(origin_descr)
|
||||
}
|
||||
|
||||
fn sync_domain_gemini_cert(&self, domain: &domain::Name) -> unexpected::Result<()> {
|
||||
if let Some(ref gemini_store) = self.gemini_store {
|
||||
log::info!("Syncing gemini certificate for domain {domain}");
|
||||
if gemini_store
|
||||
.get_certificate(domain)
|
||||
.or_unexpected()?
|
||||
.is_some()
|
||||
async fn sync_origins(&self) -> unexpected::Result<()> {
|
||||
let domains = self
|
||||
.all_domains()
|
||||
.or_unexpected_while("fetching all domains")?
|
||||
.into_iter();
|
||||
|
||||
for ManagedDomain { domain, .. } in domains {
|
||||
let settings = match self
|
||||
.get_settings(&domain)
|
||||
.map_unexpected_while(|| format!("fetching settings for {domain}"))?
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
GetSettingsResult::Stored(settings) => settings,
|
||||
GetSettingsResult::Builtin(config) => config.settings,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
// no cert/key stored for the domain, generate and store it
|
||||
let pkey = tls::PrivateKey::new();
|
||||
let cert = tls::Certificate::new_self_signed(&pkey, domain)
|
||||
.or_unexpected_while("creating self-signed cert")?;
|
||||
|
||||
gemini_store.set_certificate(domain, pkey, cert)?;
|
||||
self.sync_domain_origin(&domain, &settings.origin_descr)
|
||||
.map_unexpected_while(|| {
|
||||
format!(
|
||||
"syncing origin {:?} for domain {domain}",
|
||||
&settings.origin_descr,
|
||||
)
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn sync_domain_https_cert(&self, domain: &domain::Name) -> unexpected::Result<()> {
|
||||
if let Some(ref acme_manager) = self.acme_manager {
|
||||
log::info!("Syncing HTTPS certificate for domain {domain}");
|
||||
acme_manager.sync_domain(domain.clone(), None).await?;
|
||||
fn can_sync_gemini_cert(&self) -> bool {
|
||||
self.gemini_store.is_some()
|
||||
}
|
||||
|
||||
fn sync_domain_gemini_cert(&self, domain: &domain::Name) -> unexpected::Result<()> {
|
||||
let gemini_store = self.gemini_store.as_ref().unwrap();
|
||||
|
||||
log::info!("Syncing gemini certificate for domain {domain}");
|
||||
if gemini_store
|
||||
.get_certificate(domain)
|
||||
.or_unexpected_while("checking if cert is already stored")?
|
||||
.is_some()
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// no cert/key stored for the domain, generate and store it
|
||||
let pkey = tls::PrivateKey::new();
|
||||
let cert = tls::Certificate::new_self_signed(&pkey, domain)
|
||||
.or_unexpected_while("creating self-signed cert")?;
|
||||
|
||||
gemini_store.set_certificate(domain, pkey, cert)
|
||||
}
|
||||
|
||||
async fn sync_gemini_certs(&self) -> unexpected::Result<()> {
|
||||
let domains = self
|
||||
.all_domains()
|
||||
.or_unexpected_while("fetching all domains")?
|
||||
.into_iter();
|
||||
|
||||
for ManagedDomain { domain, .. } in domains {
|
||||
match self
|
||||
.get_settings(&domain)
|
||||
.map_unexpected_while(|| format!("fetching settings for {domain}"))?
|
||||
{
|
||||
GetSettingsResult::Stored(_) => (),
|
||||
GetSettingsResult::Builtin(_) => (),
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
self.sync_domain_gemini_cert(&domain)
|
||||
.map_unexpected_while(|| format!("syncing domain {domain}"))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn can_sync_https_cert(&self) -> bool {
|
||||
self.acme_manager.is_some()
|
||||
}
|
||||
|
||||
async fn sync_domain_https_cert(&self, domain: &domain::Name) -> unexpected::Result<()> {
|
||||
log::info!("Syncing HTTPS certificate for domain {domain}");
|
||||
self.acme_manager
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.sync_domain(domain.clone(), None)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn sync_https_certs(&self) -> unexpected::Result<()> {
|
||||
let domains = self
|
||||
.all_domains()
|
||||
.or_unexpected_while("fetching all domains")?
|
||||
.into_iter();
|
||||
|
||||
for ManagedDomain { domain, .. } in domains {
|
||||
match self
|
||||
.get_settings(&domain)
|
||||
.map_unexpected_while(|| format!("fetching settings for {domain}"))?
|
||||
{
|
||||
GetSettingsResult::Stored(_) => (),
|
||||
GetSettingsResult::Builtin(_) => (),
|
||||
GetSettingsResult::Proxied(config) => {
|
||||
if config.https_disabled {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
GetSettingsResult::Interface => (),
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
self.sync_domain_https_cert(&domain)
|
||||
.await
|
||||
.map_unexpected_while(|| format!("syncing domain {domain}",))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn can_sync_external_cert(&self) -> bool {
|
||||
self.acme_manager.is_some()
|
||||
}
|
||||
|
||||
async fn sync_external_domain(
|
||||
&self,
|
||||
domain: &domain::Name,
|
||||
config: &domain::ConfigExternalDomain,
|
||||
) -> unexpected::Result<()> {
|
||||
if let Some(ref acme_manager) = self.acme_manager {
|
||||
log::info!("Syncing HTTPS certificate for external domain {domain}");
|
||||
acme_manager
|
||||
.sync_domain(domain.clone(), Some(config.clone()))
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
log::info!("Syncing HTTPS certificate for external domain {domain}");
|
||||
self.acme_manager
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.sync_domain(domain.clone(), Some(config.clone()))
|
||||
.await
|
||||
}
|
||||
|
||||
async fn sync_all_domains(&self) -> unexpected::Result<()> {
|
||||
async fn sync_external_certs(&self) -> unexpected::Result<()> {
|
||||
let domains = self
|
||||
.all_domains()
|
||||
.or_unexpected_while("fetching all domains")?
|
||||
.into_iter();
|
||||
|
||||
for ManagedDomain { domain, .. } in domains {
|
||||
let (settings, https_cert, gemini_cert) = match self
|
||||
if let GetSettingsResult::External(config) = self
|
||||
.get_settings(&domain)
|
||||
.map_unexpected_while(|| format!("fetching settings for {domain}"))?
|
||||
{
|
||||
GetSettingsResult::Stored(settings) => (Some(settings), true, true),
|
||||
GetSettingsResult::Builtin(config) => (Some(config.settings), true, true),
|
||||
|
||||
// A proxied domain never needs gemini certs, since gemini requests will be
|
||||
// transparently proxied to the backing server anyway.
|
||||
GetSettingsResult::Proxied(config) => (None, !config.https_disabled, false),
|
||||
|
||||
GetSettingsResult::Interface => (None, true, false),
|
||||
|
||||
// External domains do their own thing, separate from the rest of this flow.
|
||||
GetSettingsResult::External(config) => {
|
||||
self.sync_external_domain(&domain, &config)
|
||||
.await
|
||||
.map_unexpected_while(|| format!("syncing external domain {domain}"))?;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(settings) = settings {
|
||||
self.sync_domain_origin(&domain, &settings.origin_descr)
|
||||
.map_unexpected_while(|| {
|
||||
format!(
|
||||
"syncing origin {:?} for domain {domain}",
|
||||
&settings.origin_descr,
|
||||
)
|
||||
})?;
|
||||
}
|
||||
|
||||
if gemini_cert {
|
||||
self.sync_domain_gemini_cert(&domain)
|
||||
.map_unexpected_while(|| format!("syncing gemini cert for domain {domain}"))?;
|
||||
}
|
||||
|
||||
if https_cert {
|
||||
self.sync_domain_https_cert(&domain)
|
||||
self.sync_external_domain(&domain, &config)
|
||||
.await
|
||||
.map_unexpected_while(|| format!("syncing https cert for domain {domain}",))?;
|
||||
.map_unexpected_while(|| format!("syncing external {domain}"))?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,12 +478,16 @@ impl Manager for ManagerImpl {
|
||||
|
||||
self.sync_domain_origin(&domain, &settings.origin_descr)?;
|
||||
|
||||
self.sync_domain_gemini_cert(&domain)
|
||||
.or_unexpected_while("syncing domain gemini cert")?;
|
||||
if self.can_sync_gemini_cert() {
|
||||
self.sync_domain_gemini_cert(&domain)
|
||||
.or_unexpected_while("syncing domain gemini cert")?;
|
||||
}
|
||||
|
||||
self.sync_domain_https_cert(&domain)
|
||||
.await
|
||||
.or_unexpected_while("syncing domain https cert")?;
|
||||
if self.can_sync_https_cert() {
|
||||
self.sync_domain_https_cert(&domain)
|
||||
.await
|
||||
.or_unexpected_while("syncing domain https cert")?;
|
||||
}
|
||||
|
||||
self.domain_store.set(&domain, &settings)?;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user