Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ services:
APP_ENV: development
LOG: debug
TZ: "Europe/Paris"
EDGE_KEY: "eyJzZXJ2ZXJVcmwiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODciLCJhZ2VudElkIjoiMGZiNDYyMmUtMTMxNS00MzMxLTlkMTMtZWMzMjAyZjZiNTIwIiwibWFzdGVyS2V5QjY0IjoiMUh0djdtWCtYVkJxL0IzUEV2WDlZZjlQeUdVZW5oRHlXemo5THRqNW90WT0ifQ=="
EDGE_KEY: "eyJzZXJ2ZXJVcmwiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODciLCJhZ2VudElkIjoiNmNiMmQwODMtZDQ4MS00MWY3LTk5NjItZjNhMzU2ZTJiMzllIiwibWFzdGVyS2V5QjY0IjoiMUh0djdtWCtYVkJxL0IzUEV2WDlZZjlQeUdVZW5oRHlXemo5THRqNW90WT0ifQ=="
Comment thread
RambokDev marked this conversation as resolved.
#CHUNK_SIZE_MB: "1"
#POOLING: 1
#DATABASES_CONFIG_FILE: "config.toml"
Expand Down
24 changes: 13 additions & 11 deletions src/domain/postgres/backup.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use anyhow::Result;
use std::collections::HashMap;
use std::path::PathBuf;
use std::process::Command;
use std::sync::Arc;
Expand All @@ -13,6 +14,7 @@ pub async fn run(
cfg: DatabaseConfig,
format: PostgresDumpFormat,
backup_dir: PathBuf,
env: HashMap<String, String>,
logger: Arc<JobLogger>,
) -> Result<PathBuf> {
tokio::task::spawn_blocking(move || -> Result<PathBuf> {
Expand All @@ -37,18 +39,18 @@ pub async fn run(
logger.log("info", format!("Running FC backup for {}", cfg.name));

let file_path = backup_dir.join(format!("{}.dump", cfg.generated_id));
let url = format!(
"postgresql://{}:{}@{}:{}/{}",
cfg.username, cfg.password, cfg.host, cfg.port, cfg.database
);

let start = Instant::now();
let output = Command::new(&pg_dump)
.arg("--dbname").arg(&url)
.arg("--host").arg(&cfg.host)
.arg("--port").arg(cfg.port.to_string())
.arg("--username").arg(&cfg.username)
.arg("--dbname").arg(&cfg.database)
.arg("-Fc")
.arg("-f").arg(&file_path)
.arg("-v")
.arg("--compress=3")
.envs(env)
.output();
let duration_ms = start.elapsed().as_millis() as f64;

Expand Down Expand Up @@ -87,19 +89,19 @@ pub async fn run(
return Err(e.into());
}

let url = format!(
"postgresql://{}:{}@{}:{}/{}",
cfg.username, cfg.password, cfg.host, cfg.port, cfg.database
);
let cmd_label = format!("pg_dump -Fd {}", url);
let cmd_label = format!("pg_dump -Fd {}@{}:{}/{}", cfg.username, cfg.host, cfg.port, cfg.database);

let start = Instant::now();
let output = Command::new(&pg_dump)
.arg("--dbname").arg(&url)
.arg("--host").arg(&cfg.host)
.arg("--port").arg(cfg.port.to_string())
.arg("--username").arg(&cfg.username)
.arg("--dbname").arg(&cfg.database)
.arg("-Fd")
.arg("-j").arg("4")
.arg("-f").arg(&dump_dir)
.arg("-v")
.envs(env)
.output();
let duration_ms = start.elapsed().as_millis() as f64;

Expand Down
16 changes: 10 additions & 6 deletions src/domain/postgres/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@ use crate::domain::postgres::format::PostgresDumpFormat;
use crate::services::config::DatabaseConfig;
use anyhow::Result;
use std::path::Path;
use tokio_postgres::{Client, NoTls};
use tokio_postgres::{Client, Config, NoTls};
use tracing::{error, info};

pub async fn connect(cfg: &DatabaseConfig) -> Result<Client> {
info!("Connecting to postgres database {}:{}", cfg.host, cfg.port);
let dsn = format!(
"host={} port={} user={} password={} dbname={}",
cfg.host, cfg.port, cfg.username, cfg.password, cfg.database
);

let (client, connection) = tokio_postgres::connect(&dsn, NoTls).await?;
let mut config = Config::new();
config
.host(&cfg.host)
.port(cfg.port)
.user(&cfg.username)
.password(&cfg.password)
.dbname(&cfg.database);

let (client, connection) = config.connect(NoTls).await?;
tokio::spawn(async move {
if let Err(e) = connection.await {
error!("Postgres connection error: {}", e);
Expand Down
28 changes: 25 additions & 3 deletions src/domain/postgres/database.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use anyhow::Result;
use async_trait::async_trait;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::Arc;

use tracing::info;
use super::{backup, format::PostgresDumpFormat, ping, restore};
use crate::domain::factory::Database;
use crate::services::backup::logger::JobLogger;
Expand All @@ -18,6 +19,13 @@ impl PostgresDatabase {
pub fn new(cfg: DatabaseConfig, format: PostgresDumpFormat) -> Self {
Self { cfg, format }
}

fn build_env(&self) -> HashMap<String, String> {
let mut envs = std::env::vars().collect::<HashMap<_, _>>();
envs.insert("PGPASSWORD".to_string(), self.cfg.password.to_string());
info!("envs: {:?}", envs);
envs
}
Comment thread
RambokDev marked this conversation as resolved.
}

#[async_trait]
Expand All @@ -35,14 +43,28 @@ impl Database for PostgresDatabase {

async fn backup(&self, dir: &Path, logger: Arc<JobLogger>) -> Result<PathBuf> {
FileLock::acquire(&self.cfg.generated_id, DbOpLock::Backup.as_str()).await?;
let res = backup::run(self.cfg.clone(), self.format, dir.to_path_buf(), logger).await;
let res = backup::run(
self.cfg.clone(),
self.format,
dir.to_path_buf(),
self.build_env(),
logger,
)
.await;
FileLock::release(&self.cfg.generated_id).await?;
res
}

async fn restore(&self, file: &Path, logger: Arc<JobLogger>) -> Result<()> {
FileLock::acquire(&self.cfg.generated_id, DbOpLock::Restore.as_str()).await?;
let res = restore::run(self.cfg.clone(), self.format, file.to_path_buf(), logger).await;
let res = restore::run(
self.cfg.clone(),
self.format,
file.to_path_buf(),
self.build_env(),
logger,
)
.await;
FileLock::release(&self.cfg.generated_id).await?;
res
}
Expand Down
23 changes: 12 additions & 11 deletions src/domain/postgres/restore.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use anyhow::Result;
use std::collections::HashMap;
use std::path::PathBuf;
use std::process::Command;
use std::sync::Arc;
Expand All @@ -13,6 +14,7 @@ pub async fn run(
cfg: DatabaseConfig,
format: PostgresDumpFormat,
restore_file: PathBuf,
env: HashMap<String, String>,
logger: Arc<JobLogger>,
) -> Result<()> {
tokio::task::spawn_blocking(move || -> Result<()> {
Expand All @@ -39,11 +41,6 @@ pub async fn run(
}
logger.log("info", format!("Connections terminated for database {}", cfg.name));

let url = format!(
"postgresql://{}:{}@{}:{}/{}",
cfg.username, cfg.password, cfg.host, cfg.port, cfg.database
);

match format {
PostgresDumpFormat::Fc => {
logger.log("info", format!("Running FC restore for {}", cfg.name));
Expand All @@ -54,11 +51,13 @@ pub async fn run(
.arg("--clean")
.arg("--if-exists")
// .arg("--create")
.arg("--dbname")
.arg(&url)
.arg("--host").arg(&cfg.host)
.arg("--port").arg(cfg.port.to_string())
.arg("--username").arg(&cfg.username)
.arg("--dbname").arg(&cfg.database)
.arg("-v")
.arg(&restore_file)
.env("PGPASSWORD", &cfg.password)
.envs(env)
.output();

let duration_ms = start.elapsed().as_millis() as f64;
Expand Down Expand Up @@ -154,13 +153,15 @@ pub async fn run(
.arg("--clean")
.arg("--if-exists")
// .arg("--create")
.arg("--dbname")
.arg(&url)
.arg("--host").arg(&cfg.host)
.arg("--port").arg(cfg.port.to_string())
.arg("--username").arg(&cfg.username)
.arg("--dbname").arg(&cfg.database)
.arg("-v")
.arg("-j")
.arg("4")
.arg(dump_dir)
.env("PGPASSWORD", &cfg.password)
.envs(env)
.output();

let duration_ms = start.elapsed().as_millis() as f64;
Expand Down
40 changes: 40 additions & 0 deletions src/tests/domain/postgres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,43 @@ async fn postgres_backup_restore_test() {
}
}
}

#[tokio::test]
async fn postgres_password_with_slash_test() {
init_tracing_for_test();

let special_password = "ch/ange:me@1";

let container = Postgres::default()
.with_env_var("POSTGRES_DB", "testdb")
.with_env_var("POSTGRES_USER", "testuser")
.with_env_var("POSTGRES_PASSWORD", special_password)
.with_tag("17")
.start()
.await
.unwrap();

let host = container
.get_host()
.await
.unwrap_or(Host::parse("127.0.0.1").unwrap());

let port = container.get_host_port_ipv4(5432).await.unwrap_or(5432);

let config = DatabaseConfig {
name: "My test Postgres Database with slash password".to_string(),
database: "testdb".to_string(),
db_type: DbType::Postgresql,
username: "testuser".to_string(),
password: special_password.to_string(),
port,
host: host.to_string(),
generated_id: "5a1f0e3c-9b8a-4a8e-9b1b-0a1c2d3e4f5a".to_string(),
path: "".to_string(),
};

let db = DatabaseFactory::create_for_backup(config.clone()).await;
let reachable = db.ping().await.unwrap_or(false);

assert_eq!(reachable, true);
}
Loading