use anyhow::Result;
use super::Db;
fn is_infra_key(key: &str) -> bool {
matches!(
key,
KEY_ACME_EMAIL | KEY_REGISTRY_DOMAIN | KEY_DOCKER_CLEANUP_CONFIG
)
}
pub async fn get(db: &Db, key: &str) -> Result<Option<String>> {
if is_infra_key(key) {
let st = db.infra().snapshot();
return Ok(match key {
KEY_ACME_EMAIL => st.settings.acme_email.clone(),
KEY_REGISTRY_DOMAIN => st.settings.registry_domain.clone(),
_ => st.settings.docker_cleanup_config.as_ref().map(|v| match v {
serde_json::Value::String(s) => s.clone(),
other => other.to_string(),
}),
});
}
sql_get(db, key).await
}
pub async fn set(db: &Db, key: &str, value: &str) -> Result<()> {
if is_infra_key(key) {
let value = value.to_string();
return db.infra().update(|st| {
match key {
KEY_ACME_EMAIL => st.settings.acme_email = Some(value),
KEY_REGISTRY_DOMAIN => st.settings.registry_domain = Some(value),
_ => {
st.settings.docker_cleanup_config = Some(
serde_json::from_str(&value)
.unwrap_or(serde_json::Value::String(value.clone())),
)
}
}
Ok(())
});
}
sqlx::query(
"INSERT INTO daemon_settings (key, value) VALUES (?, ?)
ON CONFLICT(key) DO UPDATE SET value = excluded.value",
)
.bind(key)
.bind(value)
.execute(db.pool())
.await?;
Ok(())
}
pub async fn delete(db: &Db, key: &str) -> Result<()> {
if is_infra_key(key) {
return db.infra().update(|st| {
match key {
KEY_ACME_EMAIL => st.settings.acme_email = None,
KEY_REGISTRY_DOMAIN => st.settings.registry_domain = None,
_ => st.settings.docker_cleanup_config = None,
}
Ok(())
});
}
sqlx::query("DELETE FROM daemon_settings WHERE key = ?")
.bind(key)
.execute(db.pool())
.await?;
Ok(())
}
pub async fn sql_get(db: &Db, key: &str) -> Result<Option<String>> {
let row = sqlx::query_scalar::<_, String>("SELECT value FROM daemon_settings WHERE key = ?")
.bind(key)
.fetch_optional(db.pool())
.await?;
Ok(row)
}
#[allow(dead_code)]
pub const KEY_WEBHOOK_BASE_URL: &str = "webhook_base_url";
pub const KEY_ACME_EMAIL: &str = "acme_email";
pub const KEY_REGISTRY_DOMAIN: &str = "registry_domain";
pub const KEY_DOCKER_CLEANUP_CONFIG: &str = "docker_cleanup_config";
pub const KEY_DOCKER_CLEANUP_LAST_RUN: &str = "docker_cleanup_last_run";
pub const KEY_BUILD_CACHE_LAST_PRUNE: &str = "build_cache_last_prune";
pub const KEY_JOB_WARM_PREFIX: &str = "job_warm:";
pub const KEY_SERVICE_WARM_PREFIX: &str = "service_warm:";
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn chaves_de_config_vao_ao_yaml_e_as_de_runtime_ficam_no_sql() {
let db = Db::memory_for_test().await;
set(&db, KEY_ACME_EMAIL, "a@b.c").await.unwrap();
set(&db, KEY_DOCKER_CLEANUP_CONFIG, r#"{"enabled":true}"#)
.await
.unwrap();
set(&db, KEY_DOCKER_CLEANUP_LAST_RUN, "{}").await.unwrap();
assert_eq!(
get(&db, KEY_ACME_EMAIL).await.unwrap().as_deref(),
Some("a@b.c")
);
assert_eq!(
get(&db, KEY_DOCKER_CLEANUP_CONFIG)
.await
.unwrap()
.as_deref(),
Some(r#"{"enabled":true}"#)
);
assert!(sql_get(&db, KEY_ACME_EMAIL).await.unwrap().is_none());
assert!(
sql_get(&db, KEY_DOCKER_CLEANUP_LAST_RUN)
.await
.unwrap()
.is_some()
);
let yaml =
String::from_utf8(db.infra().tree().read("settings.yml").unwrap().unwrap()).unwrap();
assert!(yaml.contains("a@b.c") && !yaml.contains("last_run"));
delete(&db, KEY_ACME_EMAIL).await.unwrap();
assert!(get(&db, KEY_ACME_EMAIL).await.unwrap().is_none());
}
}