pub struct PostgresManager { /* private fields */ }Expand description
PostgreSQL Manager
Main entry point for managing PostgreSQL installations on remote servers.
Use PostgresManagerBuilder to construct instances.
§Example
use lmrc_postgres::{PostgresConfig, PostgresManager};
let config = PostgresConfig::builder()
.version("15")
.database_name("myapp")
.username("myuser")
.password("secure_password")
.build()?;
let manager = PostgresManager::builder()
.config(config)
.server_ip("192.168.1.100")
.ssh_user("root")
.build()?;
manager.install().await?;Implementations§
Source§impl PostgresManager
impl PostgresManager
Sourcepub fn builder() -> PostgresManagerBuilder
pub fn builder() -> PostgresManagerBuilder
Create a new builder
Sourcepub async fn is_installed(&self) -> Result<bool>
pub async fn is_installed(&self) -> Result<bool>
Check if PostgreSQL is installed
§Example
if !manager.is_installed().await? {
println!("PostgreSQL is not installed");
}Sourcepub async fn get_installed_version(&self) -> Result<Option<String>>
pub async fn get_installed_version(&self) -> Result<Option<String>>
Get installed PostgreSQL version
Returns None if PostgreSQL is not installed.
Sourcepub async fn install(&self) -> Result<()>
pub async fn install(&self) -> Result<()>
Install PostgreSQL (idempotent)
This operation is idempotent - it can be safely run multiple times. If PostgreSQL is already installed with the correct version, it will skip installation.
§Example
manager.install().await?;
println!("PostgreSQL installed successfully");Sourcepub async fn configure_database(&self) -> Result<()>
pub async fn configure_database(&self) -> Result<()>
Configure database and user (idempotent)
Creates the database and user if they don’t exist, grants permissions. This operation is idempotent.
§Example
manager.configure_database().await?;Sourcepub async fn configure_server(&self) -> Result<()>
pub async fn configure_server(&self) -> Result<()>
Configure PostgreSQL server settings
Updates server configuration (listen addresses, port, memory settings, etc.) and restarts the service.
§Example
manager.configure_server().await?;Sourcepub async fn configure(&self) -> Result<()>
pub async fn configure(&self) -> Result<()>
Configure both database and server
Convenience method that calls both configure_database() and configure_server().
§Example
manager.configure().await?;Sourcepub async fn setup(&self) -> Result<()>
pub async fn setup(&self) -> Result<()>
Complete setup (install and configure)
Installs PostgreSQL (if not already installed) and configures both database and server. All operations are idempotent.
§Example
manager.setup().await?;
println!("PostgreSQL is ready!");Sourcepub async fn diff(&self) -> Result<ConfigDiff>
pub async fn diff(&self) -> Result<ConfigDiff>
Detect configuration differences
Compares the desired configuration with the current server configuration and returns a diff of changes.
§Example
let diff = manager.diff().await?;
if diff.has_changes() {
println!("Configuration changes:");
for change in diff.changes() {
println!(" {}", change);
}
}Sourcepub async fn apply_diff(&self, diff: &ConfigDiff) -> Result<()>
pub async fn apply_diff(&self, diff: &ConfigDiff) -> Result<()>
Sourcepub async fn test_connection(&self) -> Result<()>
pub async fn test_connection(&self) -> Result<()>
Test database connection
Attempts to connect to the database and verify credentials.
§Example
manager.test_connection().await?;
println!("Connection successful!");Sourcepub fn config(&self) -> &PostgresConfig
pub fn config(&self) -> &PostgresConfig
Get the PostgreSQL configuration
Sourcepub fn private_ip(&self) -> Option<&str>
pub fn private_ip(&self) -> Option<&str>
Get the private IP (if set)
Sourcepub async fn detect_platform(&self) -> Result<Platform>
pub async fn detect_platform(&self) -> Result<Platform>
Detect the server platform
§Example
let platform = manager.detect_platform().await?;
println!("Platform: {:?}", platform);Sourcepub async fn get_system_info(&self) -> Result<SystemInfo>
pub async fn get_system_info(&self) -> Result<SystemInfo>
Get system information
§Example
let info = manager.get_system_info().await?;
println!("RAM: {}MB, Disk: {}MB, CPUs: {}",
info.total_ram_mb, info.free_disk_mb, info.cpu_cores);Sourcepub async fn check_requirements(
&self,
requirements: Option<SystemRequirements>,
) -> Result<SystemInfo>
pub async fn check_requirements( &self, requirements: Option<SystemRequirements>, ) -> Result<SystemInfo>
Check system requirements before installation
§Arguments
requirements- Optional custom requirements (uses defaults if None)
§Example
// Use default requirements
manager.check_requirements(None).await?;
// Or use custom requirements
let requirements = SystemRequirements {
min_ram_mb: 2048,
min_disk_mb: 10240,
min_cpu_cores: 2,
};
manager.check_requirements(Some(requirements)).await?;Sourcepub async fn check_version_available(&self, version: &str) -> Result<bool>
pub async fn check_version_available(&self, version: &str) -> Result<bool>
Check if a PostgreSQL version is available for installation
§Example
if manager.check_version_available("16").await? {
println!("PostgreSQL 16 is available");
}Sourcepub async fn verify_installation(&self) -> Result<()>
pub async fn verify_installation(&self) -> Result<()>
Verify installation comprehensively
Performs extensive verification including:
- Binary existence
- Version check
- Service status
- Configuration files
- Network listening
§Example
manager.verify_installation().await?;
println!("Installation verified!");Sourcepub async fn upgrade(&self, new_version: &str) -> Result<()>
pub async fn upgrade(&self, new_version: &str) -> Result<()>
Upgrade PostgreSQL to a new version
§Arguments
new_version- Target PostgreSQL version
§Example
// Upgrade from current version to version 16
manager.upgrade("16").await?;§Warning
This is a simplified upgrade. For production systems, you should:
- Backup your data first
- Review migration notes for the new version
- Test in a staging environment
- Plan for data migration with pg_upgrade
Sourcepub async fn backup_config(&self) -> Result<ConfigBackup>
pub async fn backup_config(&self) -> Result<ConfigBackup>
Create a backup of the current PostgreSQL configuration
Backs up:
- postgresql.conf
- pg_hba.conf
- pg_ident.conf (if exists)
Returns backup metadata including backup directory and timestamp.
§Example
let backup = manager.backup_config().await?;
println!("Backup created: {}", backup.backup_dir);Sourcepub async fn list_backups(&self) -> Result<Vec<ConfigBackup>>
pub async fn list_backups(&self) -> Result<Vec<ConfigBackup>>
List available configuration backups
§Example
let backups = manager.list_backups().await?;
for backup in backups {
println!("Backup: {} ({} files)", backup.timestamp, backup.files.len());
}Sourcepub async fn restore_backup(&self, backup: &ConfigBackup) -> Result<()>
pub async fn restore_backup(&self, backup: &ConfigBackup) -> Result<()>
Sourcepub async fn rollback_config(&self) -> Result<()>
pub async fn rollback_config(&self) -> Result<()>
Rollback to the most recent configuration backup
§Example
// Make some changes that you want to undo
// ...
// Rollback to previous configuration
manager.rollback_config().await?;
println!("Configuration rolled back successfully");Sourcepub async fn cleanup_old_backups(&self, keep_count: usize) -> Result<usize>
pub async fn cleanup_old_backups(&self, keep_count: usize) -> Result<usize>
Sourcepub async fn read_pg_hba(&self) -> Result<String>
pub async fn read_pg_hba(&self) -> Result<String>
Detect pg_hba.conf configuration differences
Compares the current pg_hba.conf rules with a desired state.
§Example
let current_content = manager.read_pg_hba().await?;
println!("Current pg_hba.conf:\n{}", current_content);Sourcepub async fn dry_run_configure(&self) -> Result<ConfigDiff>
pub async fn dry_run_configure(&self) -> Result<ConfigDiff>
Preview configuration changes without applying them (dry-run)
This method shows what changes would be made without actually applying them. Useful for validating changes before execution.
§Example
// Preview changes
let diff = manager.dry_run_configure().await?;
if diff.has_changes() {
println!("Would make the following changes:");
println!("{}", diff);
// If changes look good, apply them
manager.apply_diff(&diff).await?;
}Sourcepub async fn apply_diff_safe(&self, diff: &ConfigDiff) -> Result<()>
pub async fn apply_diff_safe(&self, diff: &ConfigDiff) -> Result<()>
Apply configuration changes with automatic backup
This method:
- Creates a backup of the current configuration
- Applies the changes
- Verifies the changes
- Rolls back if verification fails
§Arguments
diff- Configuration diff to apply
§Example
let diff = manager.diff().await?;
if diff.has_changes() {
// Apply with automatic backup and rollback on failure
manager.apply_diff_safe(&diff).await?;
}Sourcepub async fn list_users(&self) -> Result<Vec<UserInfo>>
pub async fn list_users(&self) -> Result<Vec<UserInfo>>
List all PostgreSQL users
§Example
let users = manager.list_users().await?;
for user in users {
println!("User: {} (superuser: {})", user.name, user.is_superuser);
}Sourcepub async fn list_databases(&self) -> Result<Vec<DatabaseInfo>>
pub async fn list_databases(&self) -> Result<Vec<DatabaseInfo>>
List all PostgreSQL databases
§Example
let databases = manager.list_databases().await?;
for db in databases {
println!("Database: {} (owner: {}, encoding: {})", db.name, db.owner, db.encoding);
}Sourcepub async fn drop_database(&self, database_name: &str) -> Result<()>
pub async fn drop_database(&self, database_name: &str) -> Result<()>
Sourcepub async fn grant_privileges(
&self,
database: &str,
username: &str,
privileges: &[Privilege],
) -> Result<()>
pub async fn grant_privileges( &self, database: &str, username: &str, privileges: &[Privilege], ) -> Result<()>
Sourcepub async fn revoke_privileges(
&self,
database: &str,
username: &str,
privileges: &[Privilege],
) -> Result<()>
pub async fn revoke_privileges( &self, database: &str, username: &str, privileges: &[Privilege], ) -> Result<()>
Sourcepub async fn create_role(
&self,
role_name: &str,
can_login: bool,
is_superuser: bool,
) -> Result<()>
pub async fn create_role( &self, role_name: &str, can_login: bool, is_superuser: bool, ) -> Result<()>
Sourcepub async fn user_exists(&self, username: &str) -> Result<bool>
pub async fn user_exists(&self, username: &str) -> Result<bool>
Sourcepub async fn database_exists(&self, database: &str) -> Result<bool>
pub async fn database_exists(&self, database: &str) -> Result<bool>
Sourcepub async fn create_database_with_options(
&self,
database_name: &str,
owner: Option<&str>,
encoding: Option<&str>,
template: Option<&str>,
) -> Result<()>
pub async fn create_database_with_options( &self, database_name: &str, owner: Option<&str>, encoding: Option<&str>, template: Option<&str>, ) -> Result<()>
Create a database with advanced options
§Arguments
database_name- Name of the database to createowner- Optional owner of the databaseencoding- Optional character encoding (e.g., “UTF8”)template- Optional template database
§Example
manager.create_database_with_options(
"analytics_db",
Some("analytics_user"),
Some("UTF8"),
Some("template0")
).await?;Sourcepub async fn create_user_with_options(
&self,
username: &str,
password: &str,
is_superuser: bool,
can_create_db: bool,
can_create_role: bool,
connection_limit: Option<i32>,
) -> Result<()>
pub async fn create_user_with_options( &self, username: &str, password: &str, is_superuser: bool, can_create_db: bool, can_create_role: bool, connection_limit: Option<i32>, ) -> Result<()>
Create a user with advanced options
§Arguments
username- Name of the user to createpassword- Password for the useris_superuser- Whether the user should be a superusercan_create_db- Whether the user can create databasescan_create_role- Whether the user can create rolesconnection_limit- Optional connection limit (-1 for unlimited)
§Example
manager.create_user_with_options(
"limited_user",
"secure_password",
false,
false,
false,
Some(10)
).await?;