Implement PostgreSQL Installer Module for Rhai #6
@ -168,6 +168,20 @@ pub fn install_postgres(
|
|||||||
// Build the image name
|
// Build the image name
|
||||||
let image = format!("postgres:{}", config.version);
|
let image = format!("postgres:{}", config.version);
|
||||||
|
|
||||||
|
// Pull the PostgreSQL image to ensure we have the latest version
|
||||||
|
println!("Pulling PostgreSQL image: {}...", image);
|
||||||
|
let pull_result = Command::new("nerdctl")
|
||||||
|
.args(&["pull", &image])
|
||||||
|
.output()
|
||||||
|
.map_err(|e| PostgresInstallerError::IoError(e))?;
|
||||||
|
|
||||||
|
if !pull_result.status.success() {
|
||||||
|
return Err(PostgresInstallerError::NerdctlError(format!(
|
||||||
|
"Failed to pull PostgreSQL image: {}",
|
||||||
|
String::from_utf8_lossy(&pull_result.stderr)
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
// Create the container
|
// Create the container
|
||||||
let mut container = Container::new(&config.container_name).map_err(|e| {
|
let mut container = Container::new(&config.container_name).map_err(|e| {
|
||||||
PostgresInstallerError::NerdctlError(format!("Failed to create container: {}", e))
|
PostgresInstallerError::NerdctlError(format!("Failed to create container: {}", e))
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -134,6 +135,234 @@ mod postgres_client_tests {
|
|||||||
|
|
||||||
// Integration tests that require a real PostgreSQL server
|
// Integration tests that require a real PostgreSQL server
|
||||||
// These tests will be skipped if PostgreSQL is not available
|
// These tests will be skipped if PostgreSQL is not available
|
||||||
|
#[cfg(test)]
|
||||||
|
mod postgres_installer_tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::virt::nerdctl::Container;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_postgres_installer_config() {
|
||||||
|
// Test default configuration
|
||||||
|
let config = PostgresInstallerConfig::default();
|
||||||
|
assert_eq!(config.container_name, "postgres");
|
||||||
|
assert_eq!(config.version, "latest");
|
||||||
|
assert_eq!(config.port, 5432);
|
||||||
|
assert_eq!(config.username, "postgres");
|
||||||
|
assert_eq!(config.password, "postgres");
|
||||||
|
assert_eq!(config.data_dir, None);
|
||||||
|
assert_eq!(config.env_vars.len(), 0);
|
||||||
|
assert_eq!(config.persistent, true);
|
||||||
|
|
||||||
|
// Test builder pattern
|
||||||
|
let config = PostgresInstallerConfig::new()
|
||||||
|
.container_name("my-postgres")
|
||||||
|
.version("15")
|
||||||
|
.port(5433)
|
||||||
|
.username("testuser")
|
||||||
|
.password("testpass")
|
||||||
|
.data_dir("/tmp/pgdata")
|
||||||
|
.env_var("POSTGRES_INITDB_ARGS", "--encoding=UTF8")
|
||||||
|
.persistent(false);
|
||||||
|
|
||||||
|
assert_eq!(config.container_name, "my-postgres");
|
||||||
|
assert_eq!(config.version, "15");
|
||||||
|
assert_eq!(config.port, 5433);
|
||||||
|
assert_eq!(config.username, "testuser");
|
||||||
|
assert_eq!(config.password, "testpass");
|
||||||
|
assert_eq!(config.data_dir, Some("/tmp/pgdata".to_string()));
|
||||||
|
assert_eq!(config.env_vars.len(), 1);
|
||||||
|
assert_eq!(
|
||||||
|
config.env_vars.get("POSTGRES_INITDB_ARGS").unwrap(),
|
||||||
|
"--encoding=UTF8"
|
||||||
|
);
|
||||||
|
assert_eq!(config.persistent, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_postgres_installer_error() {
|
||||||
|
// Test IoError
|
||||||
|
let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "File not found");
|
||||||
|
let installer_error = PostgresInstallerError::IoError(io_error);
|
||||||
|
assert!(format!("{}", installer_error).contains("I/O error"));
|
||||||
|
|
||||||
|
// Test NerdctlError
|
||||||
|
let nerdctl_error = PostgresInstallerError::NerdctlError("Container not found".to_string());
|
||||||
|
assert!(format!("{}", nerdctl_error).contains("Nerdctl error"));
|
||||||
|
|
||||||
|
// Test PostgresError
|
||||||
|
let postgres_error =
|
||||||
|
PostgresInstallerError::PostgresError("Database not found".to_string());
|
||||||
|
assert!(format!("{}", postgres_error).contains("PostgreSQL error"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_postgres_with_defaults() {
|
||||||
|
// This is a unit test that doesn't actually install PostgreSQL
|
||||||
|
// It just tests the configuration and error handling
|
||||||
|
|
||||||
|
// Test with default configuration
|
||||||
|
let config = PostgresInstallerConfig::default();
|
||||||
|
|
||||||
|
// We expect this to fail because nerdctl is not available
|
||||||
|
let result = install_postgres(config);
|
||||||
|
assert!(result.is_err());
|
||||||
|
|
||||||
|
// Check that the error is a NerdctlError or IoError
|
||||||
|
match result {
|
||||||
|
Err(PostgresInstallerError::NerdctlError(_)) => {
|
||||||
|
// This is fine, we expected a NerdctlError
|
||||||
|
}
|
||||||
|
Err(PostgresInstallerError::IoError(_)) => {
|
||||||
|
// This is also fine, we expected an error
|
||||||
|
}
|
||||||
|
_ => panic!("Expected NerdctlError or IoError"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_postgres_with_custom_config() {
|
||||||
|
// Test with custom configuration
|
||||||
|
let config = PostgresInstallerConfig::new()
|
||||||
|
.container_name("test-postgres")
|
||||||
|
.version("15")
|
||||||
|
.port(5433)
|
||||||
|
.username("testuser")
|
||||||
|
.password("testpass")
|
||||||
|
.data_dir("/tmp/pgdata")
|
||||||
|
.env_var("POSTGRES_INITDB_ARGS", "--encoding=UTF8")
|
||||||
|
.persistent(true);
|
||||||
|
|
||||||
|
// We expect this to fail because nerdctl is not available
|
||||||
|
let result = install_postgres(config);
|
||||||
|
assert!(result.is_err());
|
||||||
|
|
||||||
|
// Check that the error is a NerdctlError or IoError
|
||||||
|
match result {
|
||||||
|
Err(PostgresInstallerError::NerdctlError(_)) => {
|
||||||
|
// This is fine, we expected a NerdctlError
|
||||||
|
}
|
||||||
|
Err(PostgresInstallerError::IoError(_)) => {
|
||||||
|
// This is also fine, we expected an error
|
||||||
|
}
|
||||||
|
_ => panic!("Expected NerdctlError or IoError"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_database() {
|
||||||
|
// Create a mock container
|
||||||
|
// In a real test, we would use mockall to create a mock container
|
||||||
|
// But for this test, we'll just test the error handling
|
||||||
|
|
||||||
|
// We expect this to fail because the container is not running
|
||||||
|
let result = create_database(
|
||||||
|
&Container {
|
||||||
|
name: "test-postgres".to_string(),
|
||||||
|
container_id: None,
|
||||||
|
image: Some("postgres:15".to_string()),
|
||||||
|
config: HashMap::new(),
|
||||||
|
ports: Vec::new(),
|
||||||
|
volumes: Vec::new(),
|
||||||
|
env_vars: HashMap::new(),
|
||||||
|
network: None,
|
||||||
|
network_aliases: Vec::new(),
|
||||||
|
cpu_limit: None,
|
||||||
|
memory_limit: None,
|
||||||
|
memory_swap_limit: None,
|
||||||
|
cpu_shares: None,
|
||||||
|
restart_policy: None,
|
||||||
|
health_check: None,
|
||||||
|
detach: false,
|
||||||
|
snapshotter: None,
|
||||||
|
},
|
||||||
|
"testdb",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(result.is_err());
|
||||||
|
|
||||||
|
// Check that the error is a PostgresError
|
||||||
|
match result {
|
||||||
|
Err(PostgresInstallerError::PostgresError(msg)) => {
|
||||||
|
assert!(msg.contains("Container is not running"));
|
||||||
|
}
|
||||||
|
_ => panic!("Expected PostgresError"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_execute_sql() {
|
||||||
|
// Create a mock container
|
||||||
|
// In a real test, we would use mockall to create a mock container
|
||||||
|
// But for this test, we'll just test the error handling
|
||||||
|
|
||||||
|
// We expect this to fail because the container is not running
|
||||||
|
let result = execute_sql(
|
||||||
|
&Container {
|
||||||
|
name: "test-postgres".to_string(),
|
||||||
|
container_id: None,
|
||||||
|
image: Some("postgres:15".to_string()),
|
||||||
|
config: HashMap::new(),
|
||||||
|
ports: Vec::new(),
|
||||||
|
volumes: Vec::new(),
|
||||||
|
env_vars: HashMap::new(),
|
||||||
|
network: None,
|
||||||
|
network_aliases: Vec::new(),
|
||||||
|
cpu_limit: None,
|
||||||
|
memory_limit: None,
|
||||||
|
memory_swap_limit: None,
|
||||||
|
cpu_shares: None,
|
||||||
|
restart_policy: None,
|
||||||
|
health_check: None,
|
||||||
|
detach: false,
|
||||||
|
snapshotter: None,
|
||||||
|
},
|
||||||
|
"testdb",
|
||||||
|
"SELECT 1",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(result.is_err());
|
||||||
|
|
||||||
|
// Check that the error is a PostgresError
|
||||||
|
match result {
|
||||||
|
Err(PostgresInstallerError::PostgresError(msg)) => {
|
||||||
|
assert!(msg.contains("Container is not running"));
|
||||||
|
}
|
||||||
|
_ => panic!("Expected PostgresError"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_postgres_running() {
|
||||||
|
// Create a mock container
|
||||||
|
// In a real test, we would use mockall to create a mock container
|
||||||
|
// But for this test, we'll just test the error handling
|
||||||
|
|
||||||
|
// We expect this to return false because the container is not running
|
||||||
|
let result = is_postgres_running(&Container {
|
||||||
|
name: "test-postgres".to_string(),
|
||||||
|
container_id: None,
|
||||||
|
image: Some("postgres:15".to_string()),
|
||||||
|
config: HashMap::new(),
|
||||||
|
ports: Vec::new(),
|
||||||
|
volumes: Vec::new(),
|
||||||
|
env_vars: HashMap::new(),
|
||||||
|
network: None,
|
||||||
|
network_aliases: Vec::new(),
|
||||||
|
cpu_limit: None,
|
||||||
|
memory_limit: None,
|
||||||
|
memory_swap_limit: None,
|
||||||
|
cpu_shares: None,
|
||||||
|
restart_policy: None,
|
||||||
|
health_check: None,
|
||||||
|
detach: false,
|
||||||
|
snapshotter: None,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
assert_eq!(result.unwrap(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod postgres_integration_tests {
|
mod postgres_integration_tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
Loading…
Reference in New Issue
Block a user