use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use tracing::{debug, error};
use version_compare::{Cmp, compare};
use crate::{DbError, error::DbResult};
pub(crate) const KMS_VERSION_BEFORE_MIGRATION_SUPPORT: &str = "4.12.0";
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub(crate) enum DbState {
Ready,
Upgrading,
}
#[async_trait(?Send)]
pub(crate) trait Migrate<DB> {
async fn migrate(&self) -> DbResult<()> {
fn lower(version: &str, target: &str) -> DbResult<bool> {
let cmp = compare(version, target).map_err(|()| {
DbError::DatabaseError(format!(
"Error comparing versions. The current DB version: {version}, cannot be \
parsed."
))
})?;
Ok(matches!(cmp, Cmp::Lt))
}
let db_state = self.get_db_state().await?.unwrap_or(DbState::Ready);
if db_state != DbState::Ready {
let error_string = "Database is not in a ready state; it is either upgrading or a \
previous upgrading failed. Bailing out. Please wait for the \
migration to complete or restore a previous version of the \
database.";
error!(error_string,);
return Err(DbError::DatabaseError("error_string".to_owned()));
}
let current_db_version = self
.get_current_db_version()
.await?
.unwrap_or_else(|| KMS_VERSION_BEFORE_MIGRATION_SUPPORT.to_owned());
let kms_version = env!("CARGO_PKG_VERSION");
debug!("Database version: {current_db_version}, Current KMS version: {kms_version}");
if lower(¤t_db_version, "5.0.0")? {
let msg = format!(
"Database version {current_db_version} cannot be upgraded to version \
5.0.0.\nPlease export all keys using standard formats such as PKCS#8 or Raw and \
reimport them in this KMS version."
);
error!("{}", msg);
return Err(DbError::DatabaseError(msg));
}
debug!(" ==> database is up to date.");
Ok(())
}
async fn get_db_state(&self) -> DbResult<Option<DbState>>;
async fn set_db_state(&self, state: DbState) -> DbResult<()>;
async fn get_current_db_version(&self) -> DbResult<Option<String>>;
async fn set_current_db_version(&self, version: &str) -> DbResult<()>;
#[allow(dead_code)]
async fn migrate_from_4_12_0_to_4_13_0(&self) -> DbResult<()>;
#[allow(dead_code)]
async fn migrate_to_4_22_2(&self) -> DbResult<()>;
}