- Introduced new methods for writing environment files in YAML and DotEnv formats. - Updated EnvFile struct to include a buffer for storing key-value pairs. - Modified write_env_files function to create and write to environment files based on configuration. - Added tests for environment file writing functionality.
116 lines
3.8 KiB
Rust
116 lines
3.8 KiB
Rust
use path_clean::PathClean;
|
|
use std::path::{Path, PathBuf};
|
|
use tokio::signal::unix::{SignalKind, signal};
|
|
|
|
use crate::{
|
|
API_CONFIG_PATH, DB_CONFIG_PATH,
|
|
db::DBConfigInfoType,
|
|
env::{self, EnvFile},
|
|
types::{ConfigInfoType, WithContainer, WithoutContainer},
|
|
};
|
|
|
|
// relative to the current working directory
|
|
pub fn to_absolute_path(path: &str) -> PathBuf {
|
|
if Path::new(path).is_absolute() {
|
|
return PathBuf::from(path);
|
|
}
|
|
std::env::current_dir()
|
|
.map(|cwd| cwd.join(path))
|
|
.unwrap_or_else(|_| PathBuf::from(path))
|
|
.clean()
|
|
}
|
|
|
|
pub fn write_env_files(db_config: &DBConfigInfoType) {
|
|
let api_config_path_absolute = to_absolute_path(API_CONFIG_PATH);
|
|
let db_config_path_absolute = to_absolute_path(DB_CONFIG_PATH);
|
|
|
|
let (db_type, db_url) = match db_config {
|
|
DBConfigInfoType::Containerized(config) => (config.db_type.clone(), config.url.clone()),
|
|
DBConfigInfoType::PreExisting(config) => (config.db_type.clone(), config.url.clone()),
|
|
};
|
|
|
|
let mut api_env = EnvFile::new(env::EnvFileType::Yaml, db_type, db_url);
|
|
let mut db_env = api_env.clone();
|
|
db_env.file_type = env::EnvFileType::DotEnv;
|
|
|
|
let mut api_file =
|
|
std::fs::File::create(&api_config_path_absolute).expect("Failed to create API config file");
|
|
|
|
let mut db_file =
|
|
std::fs::File::create(&db_config_path_absolute).expect("Failed to create DB config file");
|
|
|
|
api_env.write(&mut api_file, true);
|
|
db_env.write(&mut db_file, false);
|
|
}
|
|
|
|
pub async fn stop_container(
|
|
config: &ConfigInfoType<impl WithContainer, impl WithoutContainer>,
|
|
config_name: String,
|
|
) {
|
|
match config {
|
|
ConfigInfoType::Containerized(container_info) => {
|
|
let container = container_info.container();
|
|
if let Err(e) = container.stop().await {
|
|
eprintln!(
|
|
"Failed to stop container: {}. With error: {}",
|
|
config_name, e
|
|
);
|
|
} else {
|
|
println!("Container {} stopped successfully.", config_name);
|
|
}
|
|
}
|
|
ConfigInfoType::PreExisting(pre_existing_info) => {
|
|
pre_existing_info.on_delete();
|
|
println!(
|
|
"Pre-existing resource for {} cleaned up successfully.",
|
|
config_name
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn remove_file_if_exists(path: &str) {
|
|
let path = std::path::Path::new(path);
|
|
if path.exists() {
|
|
if let Err(e) = std::fs::remove_file(path) {
|
|
eprintln!("Failed to remove file {}: {}", path.display(), e);
|
|
} else {
|
|
println!("Removed existing file: {}", path.display());
|
|
}
|
|
}
|
|
}
|
|
|
|
pub async fn await_termination_signal() {
|
|
tokio::select! {
|
|
_ = tokio::signal::ctrl_c() => {
|
|
println!("\nReceived Ctrl+C, stopping container...");
|
|
}
|
|
_ = async {
|
|
#[cfg(unix)]
|
|
{
|
|
let mut sigterm = signal(SignalKind::terminate()).expect("Failed to register SIGTERM handler");
|
|
sigterm.recv().await;
|
|
println!("\nReceived SIGTERM, stopping container...");
|
|
}
|
|
#[cfg(not(unix))]
|
|
{
|
|
// On non-Unix systems, just wait indefinitely
|
|
std::future::pending::<()>().await;
|
|
}
|
|
} => {}
|
|
_ = async {
|
|
#[cfg(unix)]
|
|
{
|
|
let mut sigquit = signal(SignalKind::quit()).expect("Failed to register SIGQUIT handler");
|
|
sigquit.recv().await;
|
|
println!("\nReceived SIGQUIT, stopping container...");
|
|
}
|
|
#[cfg(not(unix))]
|
|
{
|
|
// On non-Unix systems, just wait indefinitely
|
|
std::future::pending::<()>().await;
|
|
}
|
|
} => {}
|
|
}
|
|
}
|