Skip to content

Commit

Permalink
feat(rust): fix the initialization of databases when using postgres
Browse files Browse the repository at this point in the history
  • Loading branch information
etorreborre committed Jun 26, 2024
1 parent 7e5da6a commit 45c08ef
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 99 deletions.
26 changes: 17 additions & 9 deletions implementations/rust/ockam/ockam_api/src/cli_state/cli_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ impl CliState {
pub fn is_database_path(&self, path: &Path) -> bool {
let database_configuration = self.database_configuration().ok();
match database_configuration {
Some(c) => c.path() == Some(path),
Some(c) => c.path() == Some(path.to_path_buf()),
None => false,
}
}
Expand Down Expand Up @@ -125,17 +125,24 @@ impl CliState {
self.delete_all_named_identities().await?;
self.delete_all_nodes(true).await?;
self.delete_all_named_vaults().await?;
self.delete()
self.delete().await
}

/// Removes all the directories storing state without loading the current state
/// The database data is only removed if the database is a SQLite one
pub fn hard_reset() -> Result<()> {
let dir = Self::default_dir()?;
Self::delete_at(&dir)
}

/// Delete the local database and log files
pub fn delete(&self) -> Result<()> {
pub async fn delete(&self) -> Result<()> {
self.database.drop_tables().await?;
Ok(Self::delete_at(&self.dir)?)
}

/// Delete the local data on disk: sqlite database file and log files
pub fn delete_local_data(&self) -> Result<()> {
Self::delete_at(&self.dir)
}

Expand All @@ -146,7 +153,8 @@ impl CliState {
}

/// Backup and reset is used to save aside
/// some corrupted local state for later inspection and then reset the state
/// some corrupted local state for later inspection and then reset the state.
/// The database is backed-up only if it is a SQLite database.
pub fn backup_and_reset() -> Result<()> {
let dir = Self::default_dir()?;

Expand Down Expand Up @@ -239,8 +247,8 @@ impl CliState {
pub(super) fn make_database_configuration(root_path: &Path) -> Result<DatabaseConfiguration> {
match DatabaseConfiguration::postgres()? {
Some(configuration) => Ok(configuration),
None => Ok(DatabaseConfiguration::Sqlite(
root_path.join("database.sqlite3"),
None => Ok(DatabaseConfiguration::sqlite(
root_path.join("database.sqlite3").as_path(),
)),
}
}
Expand All @@ -251,8 +259,8 @@ impl CliState {
) -> Result<DatabaseConfiguration> {
match DatabaseConfiguration::postgres()? {
Some(configuration) => Ok(configuration),
None => Ok(DatabaseConfiguration::Sqlite(
root_path.join("application_database.sqlite3"),
None => Ok(DatabaseConfiguration::sqlite(
root_path.join("application_database.sqlite3").as_path(),
)),
}
}
Expand All @@ -272,7 +280,7 @@ impl CliState {
// Delete the nodes database, keep the application database
let _ = match Self::make_database_configuration(root_path)? {
DatabaseConfiguration::Sqlite(path) => std::fs::remove_file(path)?,
_ => (),
DatabaseConfiguration::Postgres { .. } => (),
};
Ok(())
}
Expand Down
4 changes: 3 additions & 1 deletion implementations/rust/ockam/ockam_api/src/test_utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ pub struct NodeManagerHandle {

impl Drop for NodeManagerHandle {
fn drop(&mut self) {
self.cli_state.delete().expect("cannot delete cli state");
self.cli_state
.delete_local_data()
.expect("cannot delete cli state");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub async fn default_configuration() -> Result<Configuration> {
let mut configuration = authority_node::Configuration {
identifier: "I4dba4b2e53b2ed95967b3bab350b6c9ad9c624e5a1b2c3d4e5f6a6b5c4d3e2f1"
.try_into()?,
database_configuration: DatabaseConfiguration::Sqlite(database_path),
database_configuration: DatabaseConfiguration::sqlite(database_path.as_path()),
project_identifier: "123456".to_string(),
tcp_listener_address: InternetAddress::new(&format!("127.0.0.1:{}", port)).unwrap(),
secure_channel_listener_name: None,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use ockam_core::compat::rand::random_string;
use ockam_core::env::get_env;
use ockam_core::errcode::{Kind, Origin};
use ockam_core::{Error, Result};
Expand All @@ -20,7 +21,7 @@ pub const OCKAM_POSTGRES_PASSWORD: &str = "OCKAM_POSTGRES_PASSWORD";
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum DatabaseConfiguration {
/// Configuration for a SQLite database
Sqlite(PathBuf),
Sqlite(String),
/// Configuration for a Postgres database
Postgres {
/// Database host name
Expand Down Expand Up @@ -102,7 +103,12 @@ impl DatabaseConfiguration {

/// Create a local sqlite configuration
pub fn sqlite(path: &Path) -> DatabaseConfiguration {
DatabaseConfiguration::Sqlite(path.to_path_buf())
DatabaseConfiguration::Sqlite(Self::create_sqlite_on_disk_connection_string(path))
}

/// Create an in-memory sqlite configuration
pub fn sqlite_in_memory() -> DatabaseConfiguration {
DatabaseConfiguration::Sqlite(Self::create_sqlite_in_memory_connection_string())
}

/// Return the type of database that has been configured
Expand All @@ -113,10 +119,28 @@ impl DatabaseConfiguration {
}
}

/// Return the type of database that has been configured
pub fn connection_string(&self) -> String {
match self {
DatabaseConfiguration::Sqlite(path) => path.clone(),
DatabaseConfiguration::Postgres {
host,
port,
database_name,
user,
} => Self::create_postgres_connection_string(
host.clone(),
*port,
database_name.clone(),
user.clone(),
),
}
}

/// Create a directory for the SQLite database file if necessary
pub fn create_directory_if_necessary(&self) -> Result<()> {
match self {
DatabaseConfiguration::Sqlite(path) => match path.parent() {
DatabaseConfiguration::Sqlite(path) => match PathBuf::from(path).parent() {
Some(parent) => {
if !parent.exists() {
create_dir_all(parent)
Expand All @@ -132,17 +156,37 @@ impl DatabaseConfiguration {

/// Return true if the path for a SQLite database exists
pub fn exists(&self) -> bool {
match self {
DatabaseConfiguration::Sqlite(path) => path.exists(),
_ => false,
}
self.path().map(|p| p.exists()).unwrap_or(false)
}

/// Return the database path if the database is a SQLite file.
pub fn path(&self) -> Option<&Path> {
pub fn path(&self) -> Option<PathBuf> {
match self {
DatabaseConfiguration::Sqlite(path) => Some(path.as_path()),
DatabaseConfiguration::Sqlite(path) => Some(PathBuf::from(path)),
_ => None,
}
}

fn create_sqlite_in_memory_connection_string() -> String {
let file_name = random_string();
format!("sqlite:file:{file_name}?mode=memory&cache=shared")
}

fn create_sqlite_on_disk_connection_string(path: &Path) -> String {
let url_string = &path.to_string_lossy().to_string();
format!("sqlite:file://{url_string}?mode=rwc")
}

fn create_postgres_connection_string(
host: String,
port: u16,
database_name: String,
user: Option<DatabaseUser>,
) -> String {
let user_password = match user {
Some(user) => format!("{}:{}@", user.user_name(), user.password()),
None => "".to_string(),
};
format!("postgres://{user_password}{host}:{port}/{database_name}")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,8 @@ mod tests {
async fn test() -> Result<()> {
let db_file = NamedTempFile::new().unwrap();

let db = SqlxDatabase::create_no_migration(DatabaseConfiguration::Sqlite(
db_file.path().to_path_buf(),
))
.await?;
let db = SqlxDatabase::create_no_migration(DatabaseConfiguration::sqlite(db_file.path()))
.await?;

ApplicationMigrationSet::new(DatabaseType::Sqlite)
.create_migrator()?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,8 @@ impl NextMigration<'_> {
Origin::Node,
Kind::Conflict,
format!(
"Checksum mismatch for sql migration for version {}",
migration.version
"Checksum mismatch for sql migration '{}' for version {}",
migration.description, migration.version,
),
));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,8 @@ mod tests {
async fn test() -> Result<()> {
let db_file = NamedTempFile::new().unwrap();

let db = SqlxDatabase::create_no_migration(DatabaseConfiguration::Sqlite(
db_file.path().to_path_buf(),
))
.await?;
let db = SqlxDatabase::create_no_migration(DatabaseConfiguration::sqlite(db_file.path()))
.await?;

NodeMigrationSet::new(DatabaseType::Sqlite)
.create_migrator()?
Expand Down
Loading

0 comments on commit 45c08ef

Please sign in to comment.