diff --git a/server/src/storage_provider/postgres/qs.rs b/server/src/storage_provider/postgres/qs.rs index a9bec2b4..1868fc5d 100644 --- a/server/src/storage_provider/postgres/qs.rs +++ b/server/src/storage_provider/postgres/qs.rs @@ -60,8 +60,8 @@ impl PostgresQsStorage { // TODO: All the functions below use two queries. This can probably be optimized. async fn generate_fresh_signing_key(&self) -> Result<(), GenerateKeyError> { - // Delete the existing key. - sqlx::query!( "DELETE FROM qs_signing_key") + // Delete the existing key. + sqlx::query!("DELETE FROM qs_signing_key") .execute(&self.pool) .await?; diff --git a/server/tests/database_initialization.rs b/server/tests/database_initialization.rs new file mode 100644 index 00000000..f70e8160 --- /dev/null +++ b/server/tests/database_initialization.rs @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: 2023 Phoenix R&D GmbH +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use phnxserver_test_harness::docker::run_server_restart_test; + +#[actix_rt::test] +#[ignore] +#[tracing::instrument(name = "Server restart test", skip_all)] +async fn skip_db_creation() { + run_server_restart_test().await +} diff --git a/test_harness/src/docker.rs b/test_harness/src/docker.rs index 50443949..65197f55 100644 --- a/test_harness/src/docker.rs +++ b/test_harness/src/docker.rs @@ -5,12 +5,15 @@ use std::{ collections::{HashMap, HashSet}, process::{Child, Command, Stdio}, + thread::sleep, + time::Duration, }; +use once_cell::sync::Lazy; use phnxapiclient::ApiClient; use phnxtypes::{identifiers::Fqdn, DEFAULT_PORT_HTTP}; -use crate::test_scenarios::FederationTestScenario; +use crate::{test_scenarios::FederationTestScenario, TRACING}; pub(crate) struct DockerTestBed { // (server, db) @@ -307,3 +310,125 @@ fn assert_docker_is_running() { panic!("Docker is not running. Please start docker and try again."); } } + +pub async fn run_server_restart_test() { + Lazy::force(&TRACING); + + // Make sure that Docker is actually running + assert_docker_is_running(); + + let server_domain = "example.com"; + let network_name = "server_restart_network"; + // Create docker network + create_network(network_name); + + // Start server and db container + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + std::env::set_current_dir(manifest_dir.to_owned() + "/..").unwrap(); + + let db_image_name = "postgres"; + let db_container_name = format!("{server_domain}_db_container"); + let db_domain = format!("db.{server_domain}"); + let db_user = "postgres"; + let db_password = "password"; + let db_name = "phnx_server_db"; + let db_port = "5432"; + + let db_domain_env_variable = format!("PHNX_DB_DOMAIN={db_domain}"); + let db_user_env_variable = format!("POSTGRES_USER={db_user}"); + let db_password_env_variable = format!("POSTGRES_PASSWORD={db_password}"); + let db_name_env_variable = format!("POSTGRES_DB={db_name}"); + + let _db = run_docker_container( + &db_image_name, + &db_container_name, + &[ + db_domain_env_variable, + db_user_env_variable, + db_password_env_variable, + db_name_env_variable, + ], + Some(&db_domain), + Some(network_name), + Some(db_port), + &["-N".to_string(), "1000".to_string(), "-i".to_string()], + false, + ); + + let server_image_name = "phnxserver_image"; + let server_container_name = format!("{server_domain}_server_container"); + + build_docker_image("server/Dockerfile", &server_image_name); + + let server_domain_env_variable = format!("PHNX_APPLICATION_DOMAIN={}", server_domain); + let server_db_user_env_variable = format!("PHNX_DATABASE_USERNAME={}", db_user); + let server_db_password_env_variable = format!("PHNX_DATABASE_PASSWORD={}", db_password); + let server_db_port_env_variable = format!("PHNX_DATABASE_PORT={}", db_port); + let server_host_env_variable = format!("PHNX_DATABASE_HOST={}", db_domain); + let server_db_name_env_variable = format!("PHNX_DATABASE_DATABASE_NAME={}", db_name); + let server_sqlx_offline_env_variable = format!("SQLX_OFFLINE=true"); + + tracing::info!("Starting phnx server"); + let _server = run_docker_container( + &server_image_name, + &server_container_name, + &[ + server_domain_env_variable.clone(), + server_host_env_variable.clone(), + server_db_name_env_variable.clone(), + server_db_user_env_variable.clone(), + server_db_password_env_variable.clone(), + server_db_port_env_variable.clone(), + server_sqlx_offline_env_variable.clone(), + ], + Some(&server_domain.to_string()), + Some(network_name), + None, + &[], + false, + ); + + //let server_domain_fqdn = Fqdn::from(server_domain); + //let server_domains = vec![server_domain_fqdn.clone()] + // .into_iter() + // .collect::>(); + //wait_until_servers_are_up(server_domains).await; + + sleep(Duration::from_secs(3)); + + tracing::info!("All servers are up, stopping server."); + + // Stop server container + stop_docker_container(&server_container_name); + + sleep(Duration::from_secs(3)); + + tracing::info!("Waited three seconds, starting server again."); + + // Start server container again + let _server = run_docker_container( + &server_image_name, + &server_container_name, + &[ + server_domain_env_variable, + server_host_env_variable, + server_db_name_env_variable, + server_db_user_env_variable, + server_db_password_env_variable, + server_db_port_env_variable, + server_sqlx_offline_env_variable, + ], + Some(&server_domain.to_string()), + Some(network_name), + None, + &[], + false, + ); + + sleep(Duration::from_secs(3)); + + stop_docker_container(&server_container_name); + stop_docker_container(&db_container_name); + + tracing::info!("Done running server restart test"); +}