85 lines
3.0 KiB
Rust
85 lines
3.0 KiB
Rust
impl App {
|
|
pub async fn reload_certificates(self: &Arc<Self>) -> Result<u64, ApiError> {
|
|
self.reload_certificate_snapshot(None).await
|
|
}
|
|
|
|
pub async fn reload_certificate(
|
|
self: &Arc<Self>,
|
|
certificate_id: &str,
|
|
) -> Result<u64, ApiError> {
|
|
if !crate::config::valid_id(certificate_id) {
|
|
return Err(ApiError(
|
|
StatusCode::NOT_FOUND,
|
|
"certificate not found".into(),
|
|
));
|
|
}
|
|
self.reload_certificate_snapshot(Some(certificate_id)).await
|
|
}
|
|
|
|
async fn reload_certificate_snapshot(
|
|
self: &Arc<Self>,
|
|
certificate_id: Option<&str>,
|
|
) -> Result<u64, ApiError> {
|
|
let _lock = self.update_lock.lock().await;
|
|
let previous = self.config.load_full();
|
|
let desired = previous.envelope.config.clone();
|
|
if let Some(certificate_id) = certificate_id {
|
|
let certificate = desired
|
|
.tls
|
|
.certificates
|
|
.iter()
|
|
.find(|certificate| certificate.id == certificate_id)
|
|
.ok_or_else(|| ApiError(StatusCode::NOT_FOUND, "certificate not found".into()))?;
|
|
if certificate.issuer.is_some() {
|
|
return Err(ApiError(
|
|
StatusCode::CONFLICT,
|
|
"managed certificates are reloaded by the renewal pipeline".into(),
|
|
));
|
|
}
|
|
}
|
|
let desired_vhost_count = desired.vhosts.len();
|
|
let observed = self.docker.snapshot().await;
|
|
let policy = self.policy.clone();
|
|
let defaults = self.startup_listeners;
|
|
let active_listeners = self.active_listeners.clone();
|
|
let revision = previous.envelope.revision;
|
|
let prepared = tokio::task::spawn_blocking(move || {
|
|
let effective = crate::docker::effective_config(desired, &observed)?;
|
|
let mut prepared = config::compile_with_active(
|
|
effective,
|
|
revision,
|
|
&policy,
|
|
defaults,
|
|
Some(&previous),
|
|
&active_listeners,
|
|
)?;
|
|
prepared
|
|
.envelope
|
|
.config
|
|
.vhosts
|
|
.truncate(desired_vhost_count);
|
|
Ok::<_, anyhow::Error>(prepared)
|
|
})
|
|
.await
|
|
.map_err(|_| {
|
|
ApiError(
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
"certificate reload task failed".into(),
|
|
)
|
|
})?
|
|
.map_err(|error| ApiError(StatusCode::UNPROCESSABLE_ENTITY, format!("{error:#}")))?;
|
|
self.config.store(Arc::new(prepared));
|
|
crate::acl::dynamic::config_changed();
|
|
if let Some(certificate_id) = certificate_id {
|
|
tracing::info!(
|
|
revision,
|
|
certificate_id,
|
|
"configured certificate reloaded from disk"
|
|
);
|
|
} else {
|
|
tracing::info!(revision, "configured certificates reloaded from disk");
|
|
}
|
|
Ok(revision)
|
|
}
|
|
}
|