From c46c301371f0906daa49604f72513c95a64d49a2 Mon Sep 17 00:00:00 2001 From: charlesgauthereau Date: Mon, 16 Mar 2026 08:55:16 +0100 Subject: [PATCH 1/9] fix: s3 port type mismatch, add string_or_number_to_string deserializer --- Cargo.lock | 105 ++++++++++---------- docker-compose.yml | 6 +- docker/Dockerfile | 2 +- src/services/storage/providers/s3/models.rs | 3 + src/utils/deserializer.rs | 17 ++++ 5 files changed, 76 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e49eb4..dd3b6d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -82,9 +82,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anyhow" @@ -275,9 +275,9 @@ dependencies = [ [[package]] name = "aws-sdk-s3" -version = "1.125.0" +version = "1.126.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "223f5c95650d9557925a91f4c2db3def189e8f659452134a29e5cd2d37d708ed" +checksum = "7878050a2321d215eec9db8be09f8db59418b53860ae86cc7042b4094d6cb2bb" dependencies = [ "aws-credential-types", "aws-runtime", @@ -744,9 +744,9 @@ dependencies = [ [[package]] name = "bollard" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "227aa051deec8d16bd9c34605e7aaf153f240e35483dd42f6f78903847934738" +checksum = "ee04c4c84f1f811b017f2fbb7dd8815c976e7ca98593de9c1e2afad0f636bff4" dependencies = [ "async-stream", "base64 0.22.1", @@ -869,9 +869,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.56" +version = "1.2.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" dependencies = [ "find-msvc-tools", "jobserver", @@ -1199,9 +1199,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" dependencies = [ "darling_core", "darling_macro", @@ -1209,11 +1209,10 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" dependencies = [ - "fnv", "ident_case", "proc-macro2", "quote", @@ -1223,9 +1222,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core", "quote", @@ -1289,9 +1288,9 @@ dependencies = [ [[package]] name = "derive-where" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" +checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534" dependencies = [ "proc-macro2", "quote", @@ -1450,7 +1449,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -1957,9 +1956,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hybrid-array" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b229d73f5803b562cc26e4da0396c8610a4ee209f4fac8fa4f8d709166dc45" +checksum = "8655f91cd07f2b9d0c24137bd650fe69617773435ee5ec83022377777ce65ef1" dependencies = [ "typenum", ] @@ -2089,7 +2088,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.3", "system-configuration", "tokio", "tower-service", @@ -2680,7 +2679,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -2821,9 +2820,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" dependencies = [ "critical-section", "portable-atomic", @@ -2831,9 +2830,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.75" +version = "0.10.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" dependencies = [ "bitflags 2.11.0", "cfg-if", @@ -2863,9 +2862,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" -version = "0.9.111" +version = "0.9.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" dependencies = [ "cc", "libc", @@ -3256,7 +3255,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls 0.23.37", - "socket2 0.5.10", + "socket2 0.6.3", "thiserror 2.0.18", "tokio", "tracing", @@ -3265,9 +3264,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ "aws-lc-rs", "bytes", @@ -3294,7 +3293,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.3", "tracing", "windows-sys 0.60.2", ] @@ -3647,7 +3646,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -3718,7 +3717,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -3772,9 +3771,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ "windows-sys 0.61.2", ] @@ -3961,9 +3960,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.17.0" +version = "3.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "381b283ce7bc6b476d903296fb59d0d36633652b633b27f64db4fb46dcbfc3b9" +checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" dependencies = [ "base64 0.22.1", "chrono", @@ -3980,9 +3979,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.17.0" +version = "3.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6d4e30573c8cb306ed6ab1dca8423eec9a463ea0e155f45399455e0368b27e0" +checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" dependencies = [ "darling", "proc-macro2", @@ -4094,7 +4093,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -4248,15 +4247,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.26.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -4408,9 +4407,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -4720,9 +4719,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "chrono", "matchers", @@ -5171,7 +5170,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -5736,18 +5735,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.40" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" +checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.40" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" +checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" dependencies = [ "proc-macro2", "quote", diff --git a/docker-compose.yml b/docker-compose.yml index d6fbc5c..80cbcc1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,14 +11,14 @@ services: # - ./databases.toml:/config/config.toml - cargo-registry:/usr/local/cargo/registry - cargo-git:/usr/local/cargo/git - - cargo-target:/app/target +# - cargo-target:/app/target # - sqlite-data:/sqlite-data/workspace/data # - ./scripts/sqlite/test-db:/sqlite-data-2/workspace/data environment: APP_ENV: development LOG: debug TZ: "Europe/Paris" - EDGE_KEY: "eyJzZXJ2ZXJVcmwiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODciLCJhZ2VudElkIjoiOGYwMmExZTAtNDY0NC00MWFmLWIzYjctYjZkYWNjNzQ4OWVhIiwibWFzdGVyS2V5QjY0IjoiQlhWM1hvbEM2NTZTVjdkTmdjV1BHUWxrKytycExJNmxHRGk3Q1BCNWllbz0ifQ==" + EDGE_KEY: "eyJzZXJ2ZXJVcmwiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODciLCJhZ2VudElkIjoiZWE5OWE5ZjMtNDhkYy00MjMyLTkzMTAtNTc5YWVkY2IyZjhmIiwibWFzdGVyS2V5QjY0IjoiQlhWM1hvbEM2NTZTVjdkTmdjV1BHUWxrKytycExJNmxHRGk3Q1BCNWllbz0ifQ==" #POOLING: 1 #DATABASES_CONFIG_FILE: "config.toml" extra_hosts: @@ -130,7 +130,7 @@ services: volumes: cargo-registry: cargo-git: - cargo-target: +# cargo-target: postgres-data: # mariadb-data: diff --git a/docker/Dockerfile b/docker/Dockerfile index 66e38d9..56437d5 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,7 +1,7 @@ # ========================= # Base image (shared) # ========================= -FROM rust:1.92.0 AS base +FROM rust:1.94.0 AS base RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ pkg-config \ diff --git a/src/services/storage/providers/s3/models.rs b/src/services/storage/providers/s3/models.rs index 2410fd6..ab3036c 100644 --- a/src/services/storage/providers/s3/models.rs +++ b/src/services/storage/providers/s3/models.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use crate::utils::deserializer::string_or_number_to_string; #[derive(Debug, Deserialize, Serialize)] pub struct S3ProviderConfig { @@ -8,5 +9,7 @@ pub struct S3ProviderConfig { pub end_point_url: String, pub ssl: bool, pub region: Option, + #[serde(default, deserialize_with = "string_or_number_to_string")] pub port: Option, } + diff --git a/src/utils/deserializer.rs b/src/utils/deserializer.rs index 01e77f9..e4d094a 100644 --- a/src/utils/deserializer.rs +++ b/src/utils/deserializer.rs @@ -1,5 +1,7 @@ use serde::{Deserialize, Deserializer}; use toml::Value; +use serde_json::{Value as ValueJson, }; + pub fn deserialize_snake_case<'de, D>(deserializer: D) -> Result where @@ -36,3 +38,18 @@ pub fn camel_to_snake(s: &str) -> String { } out } + + +pub fn string_or_number_to_string<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let value = Option::::deserialize(deserializer)?; + + match value { + Some(ValueJson::String(s)) => Ok(Some(s)), + Some(ValueJson::Number(n)) => Ok(Some(n.to_string())), + Some(_) => Err(serde::de::Error::custom("port must be string or number")), + None => Ok(None), + } +} From 61c7224104dddf1f663572c64ad99decf809da82 Mon Sep 17 00:00:00 2001 From: charles-gauthereau Date: Thu, 2 Apr 2026 19:28:20 +0200 Subject: [PATCH 2/9] chore: docker-compose.databases.yml --- docker-compose.databases.yml | 4 +++- docker-compose.yml | 12 ++++++------ docker/entrypoints/app-dev-entrypoint.sh | 12 ++++++++---- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/docker-compose.databases.yml b/docker-compose.databases.yml index 67abe07..92c2d6a 100644 --- a/docker-compose.databases.yml +++ b/docker-compose.databases.yml @@ -1,3 +1,5 @@ +name: databases + services: db-postgres: container_name: db-postgres @@ -95,7 +97,7 @@ services: image: redis:latest container_name: db-redis ports: - - "6379:6379" + - "6378:6379" volumes: - redis-data:/data command: [ "redis-server", "--appendonly", "yes" ] diff --git a/docker-compose.yml b/docker-compose.yml index a83ef58..ac14fb6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,15 +13,15 @@ services: #- ./databases.toml:/config/config.toml #- /var/run/docker.sock:/var/run/docker.sock #- cargo-target:/app/target - #- agent-rust_sqlite-data:/sqlite-data/workspace/data - #- ./scripts/sqlite/test-db:/sqlite-data-2/workspace/data + - databases_sqlite-data:/sqlite-data/workspace/data + - ./scripts/sqlite/test-db:/sqlite-data-2/workspace/data environment: APP_ENV: development LOG: debug TZ: "Europe/Paris" - EDGE_KEY: "eyJzZXJ2ZXJVcmwiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODciLCJhZ2VudElkIjoiOWRjZjYzNzQtZTc5ZC00MzU5LTkwMTYtNjA0OTQ2NDNhNjEwIiwibWFzdGVyS2V5QjY0IjoiQlhWM1hvbEM2NTZTVjdkTmdjV1BHUWxrKytycExJNmxHRGk3Q1BCNWllbz0ifQ==" + EDGE_KEY: "eyJzZXJ2ZXJVcmwiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODciLCJhZ2VudElkIjoiNTMwMjNkYjQtN2EzYS00ZTM0LTk0MWEtNjU2ZTNlNzE2NzlkIiwibWFzdGVyS2V5QjY0IjoiMUh0djdtWCtYVkJxL0IzUEV2WDlZZjlQeUdVZW5oRHlXemo5THRqNW90WT0ifQ==" #POOLING: 1 - DATABASES_CONFIG_FILE: "config.toml" + #DATABASES_CONFIG_FILE: "config.toml" extra_hosts: - "localhost:host-gateway" networks: @@ -31,8 +31,8 @@ volumes: cargo-registry: cargo-git: #cargo-target: -# agent-rust_sqlite-data: -# external: true + databases_sqlite-data: + external: true diff --git a/docker/entrypoints/app-dev-entrypoint.sh b/docker/entrypoints/app-dev-entrypoint.sh index d7d9a2d..57ea5dd 100755 --- a/docker/entrypoints/app-dev-entrypoint.sh +++ b/docker/entrypoints/app-dev-entrypoint.sh @@ -31,10 +31,14 @@ check_network() { fi } -#check_docker +check_docker check_network -echo "Starting docker-compose..." +echo "Stopping old database containers..." +docker compose -f ./docker-compose.databases.yml down + +echo "Starting database containers..." docker compose -f ./docker-compose.databases.yml up -d -docker compose -f ./docker-compose.yml up -echo "Docker-compose started successfully." \ No newline at end of file + +echo "Starting main services..." +docker compose -f ./docker-compose.yml up \ No newline at end of file From bfe63d7fd355fd68ad0f1f41b472a66045799d8c Mon Sep 17 00:00:00 2001 From: Charles GTE Date: Sun, 26 Apr 2026 17:42:30 +0200 Subject: [PATCH 3/9] fix: tests and refactoring, add justfile instead of makefile --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index d161be9..260eb2c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,7 +19,7 @@ services: APP_ENV: development LOG: debug TZ: "Europe/Paris" - EDGE_KEY: "eyJzZXJ2ZXJVcmwiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODciLCJhZ2VudElkIjoiNzM0NjU3Y2YtMGQzYy00Y2UwLTkyODQtZDJmOGYyMjI2MzgzIiwibWFzdGVyS2V5QjY0IjoiMUh0djdtWCtYVkJxL0IzUEV2WDlZZjlQeUdVZW5oRHlXemo5THRqNW90WT0ifQ==" + EDGE_KEY: "eyJzZXJ2ZXJVcmwiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODciLCJhZ2VudElkIjoiNjIyNWFlMzMtODQwMy00NmE3LWEyNDEtMjU4MTI2MjVlYTA4IiwibWFzdGVyS2V5QjY0IjoiQlhWM1hvbEM2NTZTVjdkTmdjV1BHUWxrKytycExJNmxHRGk3Q1BCNWllbz0ifQ==" #CHUNK_SIZE_MB: "1" #POOLING: 1 #DATABASES_CONFIG_FILE: "config.toml" From cef38e9e7774ef580d45cf609bd39d7e5624a797 Mon Sep 17 00:00:00 2001 From: Charles GTE Date: Sun, 26 Apr 2026 20:40:14 +0200 Subject: [PATCH 4/9] fix: restoration process for postgres/mysql and mariadb --- docker-compose.yml | 3 ++- src/domain/mariadb/backup.rs | 7 ++++--- src/domain/mariadb/restore.rs | 3 ++- src/domain/mysql/backup.rs | 16 +++++++--------- src/domain/postgres/restore.rs | 10 +++++----- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 260eb2c..a933aca 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,7 +9,8 @@ services: - .:/app - cargo-registry:/usr/local/cargo/registry - cargo-git:/usr/local/cargo/git - - ./databases.json:/config/config.json + - /Users/charlesgauthereau/Desktop/test-portabase/databases.json:/config/config.json +# - ./databases.json:/config/config.json #- ./databases.toml:/config/config.toml #- /var/run/docker.sock:/var/run/docker.sock #- cargo-target:/app/target diff --git a/src/domain/mariadb/backup.rs b/src/domain/mariadb/backup.rs index ff323f1..1a2bfef 100644 --- a/src/domain/mariadb/backup.rs +++ b/src/domain/mariadb/backup.rs @@ -33,6 +33,7 @@ pub async fn run( let mariadb_dump = select_mariadb_path(&version).join("mariadb-dump"); info!("Mariadb dump found: {}", mariadb_dump.display()); + let output = Command::new("mariadb-dump") .arg("--host").arg(&cfg.host) .arg("--port").arg(cfg.port.to_string()) @@ -43,18 +44,18 @@ pub async fn run( .arg("--single-transaction") .arg("--quick") .arg("--skip-lock-tables") - .arg("--add-drop-database") - .arg("--databases").arg(&cfg.database) + .arg("--no-create-db") + .arg("--skip-add-drop-table") .arg("--compress") .arg("--max-allowed-packet=512M") .arg("--net-buffer-length=16K") .arg("--default-character-set=utf8mb4") + .arg(&cfg.database) .arg("-r").arg(&file_path) .envs(env) .output() .with_context(|| format!("Failed to run mariadb-dump for {}", cfg.name))?; - if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); anyhow::bail!("Mariadb backup failed for {}: {}", cfg.name, stderr); diff --git a/src/domain/mariadb/restore.rs b/src/domain/mariadb/restore.rs index 8433277..bc881be 100644 --- a/src/domain/mariadb/restore.rs +++ b/src/domain/mariadb/restore.rs @@ -47,6 +47,7 @@ pub async fn run(cfg: DatabaseConfig, restore_file: PathBuf) -> Result<()> { .arg(cfg.port.to_string()) .arg("--user") .arg(&cfg.username) + .arg("--database") .arg(&cfg.database) .env("MYSQL_PWD", &cfg.password) .stdin(std::process::Stdio::piped()) @@ -77,4 +78,4 @@ pub async fn run(cfg: DatabaseConfig, restore_file: PathBuf) -> Result<()> { handle.await??; Ok(()) -} \ No newline at end of file +} diff --git a/src/domain/mysql/backup.rs b/src/domain/mysql/backup.rs index 85d2e2f..9cc1071 100644 --- a/src/domain/mysql/backup.rs +++ b/src/domain/mysql/backup.rs @@ -30,25 +30,23 @@ pub async fn run( let file_path = backup_dir.join(format!("{}{}", cfg.generated_id, file_extension)); - // let mysql_dump = select_mysql_path(&version).join("mysqldump"); - // info!("MySQL dump found: {}", mysql_dump.display()); - let output = Command::new("mysqldump") .arg("--host") - .arg(cfg.host) + .arg(&cfg.host) .arg("--port") .arg(cfg.port.to_string()) .arg("--user") - .arg(cfg.username) + .arg(&cfg.username) .arg("--routines") .arg("--events") .arg("--triggers") - .arg("--verbose") .arg("--single-transaction") .arg("--quick") - .arg("--add-drop-database") - .arg("--databases") - .arg(cfg.database) + .arg("--skip-lock-tables") + .arg("--skip-add-drop-table") + .arg("--no-create-db") // IMPORTANT + .arg("--default-character-set=utf8mb4") + .arg(&cfg.database) // IMPORTANT: NOT --databases .arg("-r") .arg(&file_path) .envs(env) diff --git a/src/domain/postgres/restore.rs b/src/domain/postgres/restore.rs index 98a7732..40ddd6e 100644 --- a/src/domain/postgres/restore.rs +++ b/src/domain/postgres/restore.rs @@ -37,8 +37,8 @@ pub async fn run( info!("Connections terminated for database {}", cfg.name); let url = format!( - "postgresql://{}:{}@{}:{}/postgres", - cfg.username, cfg.password, cfg.host, cfg.port + "postgresql://{}:{}@{}:{}/{}", + cfg.username, cfg.password, cfg.host, cfg.port, cfg.database ); debug!("Restore URL: {}", url); @@ -51,7 +51,7 @@ pub async fn run( .arg("--no-privileges") .arg("--clean") .arg("--if-exists") - .arg("--create") + // .arg("--create") .arg("--dbname") .arg(&url) .arg("-v") @@ -139,8 +139,8 @@ pub async fn run( .arg("--no-privileges") .arg("--clean") .arg("--if-exists") - .arg("--create") - .arg("--dbname") + // .arg("--create") + .arg("--dbname={}") .arg(&url) .arg("-v") .arg("-j") From 60c1d9a71388df0c94ca721a9088757e5cea3a5e Mon Sep 17 00:00:00 2001 From: Charles GTE Date: Sun, 26 Apr 2026 20:43:17 +0200 Subject: [PATCH 5/9] fix: restoration process for postgres/mysql and mariadb --- src/domain/mysql/restore.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/domain/mysql/restore.rs b/src/domain/mysql/restore.rs index f662a50..54c1d2b 100644 --- a/src/domain/mysql/restore.rs +++ b/src/domain/mysql/restore.rs @@ -47,6 +47,7 @@ pub async fn run(cfg: DatabaseConfig, restore_file: PathBuf) -> Result<()> { .arg(cfg.port.to_string()) .arg("--user") .arg(&cfg.username) + .arg("--database") .arg(&cfg.database) .env("MYSQL_PWD", &cfg.password) .stdin(std::process::Stdio::piped()) From 2414954717e57f68085a47c8cc8d6568fd591afa Mon Sep 17 00:00:00 2001 From: Charles GTE Date: Mon, 27 Apr 2026 20:49:56 +0200 Subject: [PATCH 6/9] fix: postgres restore --- src/domain/postgres/restore.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/postgres/restore.rs b/src/domain/postgres/restore.rs index 40ddd6e..f722556 100644 --- a/src/domain/postgres/restore.rs +++ b/src/domain/postgres/restore.rs @@ -140,7 +140,7 @@ pub async fn run( .arg("--clean") .arg("--if-exists") // .arg("--create") - .arg("--dbname={}") + .arg("--dbname") .arg(&url) .arg("-v") .arg("-j") From 14caae894047f3e2d0a77e2a6e39f3ddb9063993 Mon Sep 17 00:00:00 2001 From: Charles GTE Date: Mon, 27 Apr 2026 21:50:00 +0200 Subject: [PATCH 7/9] fix: mariadb/mysql restore, added backticks to drop command --- src/domain/mariadb/restore.rs | 4 ++-- src/domain/mysql/restore.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/domain/mariadb/restore.rs b/src/domain/mariadb/restore.rs index bc881be..5357cbf 100644 --- a/src/domain/mariadb/restore.rs +++ b/src/domain/mariadb/restore.rs @@ -15,9 +15,9 @@ pub async fn run(cfg: DatabaseConfig, restore_file: PathBuf) -> Result<()> { .with_context(|| format!("Failed to open restore file {}", restore_file.display()))?; file.read_to_string(&mut sql_content) .with_context(|| format!("Failed to read restore file {}", restore_file.display()))?; - + let drop_create_cmd = format!( - "DROP DATABASE IF EXISTS {0}; CREATE DATABASE {0};", + "DROP DATABASE IF EXISTS `{0}`; CREATE DATABASE `{0}`;", cfg.database ); diff --git a/src/domain/mysql/restore.rs b/src/domain/mysql/restore.rs index 54c1d2b..8f569aa 100644 --- a/src/domain/mysql/restore.rs +++ b/src/domain/mysql/restore.rs @@ -17,7 +17,7 @@ pub async fn run(cfg: DatabaseConfig, restore_file: PathBuf) -> Result<()> { .with_context(|| format!("Failed to read restore file {}", restore_file.display()))?; let drop_create_cmd = format!( - "DROP DATABASE IF EXISTS {0}; CREATE DATABASE {0};", + "DROP DATABASE IF EXISTS `{0}`; CREATE DATABASE `{0}`;", cfg.database ); From cc163c22fec99c573647645ec2ceffb8267a6af4 Mon Sep 17 00:00:00 2001 From: Charles GTE Date: Wed, 29 Apr 2026 21:34:10 +0200 Subject: [PATCH 8/9] fix: mongodb and migration test for firebird --- justfile | 3 ++- src/domain/mongodb/backup.rs | 1 - src/domain/mongodb/connection.rs | 15 +++++++++++++++ src/domain/mongodb/restore.rs | 29 ++++++++++++++++++++++++++--- src/services/status.rs | 1 - 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/justfile b/justfile index 135ef1d..47a04d5 100644 --- a/justfile +++ b/justfile @@ -42,7 +42,8 @@ seed-firebird: docker exec -i db-firebird isql -user alice -password fake_password /var/lib/firebird/data/mirror.fdb < ./scripts/firebird/seed.sql echo "Verifying Firebird tables..." - docker exec -i db-firebird isql -user alice -password fake_password /var/lib/firebird/data/mirror.fdb -sql "SHOW TABLES;" + echo "SELECT RDB\$RELATION_NAME FROM RDB\$RELATIONS WHERE RDB\$SYSTEM_FLAG = 0 AND RDB\$VIEW_BLR IS NULL;" \ + | docker exec -i db-firebird isql -user alice -password fake_password /var/lib/firebird/data/mirror.fdb seed-all: just seed-mongo diff --git a/src/domain/mongodb/backup.rs b/src/domain/mongodb/backup.rs index 7abb6fd..d4724b3 100644 --- a/src/domain/mongodb/backup.rs +++ b/src/domain/mongodb/backup.rs @@ -15,7 +15,6 @@ pub async fn run( let file_path = backup_dir.join(format!("{}{}", cfg.generated_id, file_extension)); let mongodump = select_mongo_path().join("mongodump"); - info!("{:?}", mongodump); let uri = get_mongo_uri(cfg.clone())?; let output = Command::new(mongodump) diff --git a/src/domain/mongodb/connection.rs b/src/domain/mongodb/connection.rs index 311895b..912f140 100644 --- a/src/domain/mongodb/connection.rs +++ b/src/domain/mongodb/connection.rs @@ -28,3 +28,18 @@ pub fn get_mongo_uri(cfg: DatabaseConfig) -> Result { )) } } + + +pub fn extract_db_name(dry_output: &str) -> Option { + let mut dbs = std::collections::HashSet::new(); + for line in dry_output.lines() { + if let Some(pos) = line.find("archive prelude ") { + let rest = &line[pos + "archive prelude ".len()..]; + if let Some(dot) = rest.find('.') { + let db = &rest[..dot]; + dbs.insert(db.to_string()); + } + } + } + dbs.into_iter().next() +} diff --git a/src/domain/mongodb/restore.rs b/src/domain/mongodb/restore.rs index 617834d..0a8012d 100644 --- a/src/domain/mongodb/restore.rs +++ b/src/domain/mongodb/restore.rs @@ -1,4 +1,4 @@ -use crate::domain::mongodb::connection::{get_mongo_uri, select_mongo_path}; +use crate::domain::mongodb::connection::{extract_db_name, get_mongo_uri, select_mongo_path}; use crate::services::config::DatabaseConfig; use anyhow::{Context, Result}; use std::path::PathBuf; @@ -12,18 +12,41 @@ pub async fn run(cfg: DatabaseConfig, restore_file: PathBuf) -> Result<()> { let mongorestore = select_mongo_path().join("mongorestore"); let uri = get_mongo_uri(cfg.clone())?; - let output = Command::new(mongorestore) + let dry_run = Command::new(&mongorestore) + .arg(format!( + "--uri={}", + format!( + "mongodb://{}:{}@{}:{}/?authSource=admin", + cfg.username, cfg.password, cfg.host, cfg.port + ) + )) + .arg(format!("--archive={}", restore_file.display())) + .arg("--gzip") + .arg("--dryRun") + .arg("--verbose") + .output()?; + + let dry_output = String::from_utf8_lossy(&dry_run.stderr); + let source_db = extract_db_name(&dry_output) + .context("Could not detect source database name from archive")?; + + info!("Detected source database in archive: {}", source_db); + + let output = Command::new(&mongorestore) .arg(format!("--uri={}", uri)) .arg(format!("--archive={}", restore_file.display())) .arg("--gzip") .arg("--drop") + .arg(format!("--nsInclude={}.*", source_db)) + .arg(format!("--nsFrom={}.*", source_db)) + .arg(format!("--nsTo={}.*", cfg.database)) .output() .with_context(|| format!("Failed to run mongorestore for {}", cfg.name))?; if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); error!("MongoDB restore failed for {}: {}", cfg.name, stderr); - anyhow::bail!("MongoDB restore failed for : {}", cfg.name); + anyhow::bail!("MongoDB restore failed for: {}", cfg.name); } info!("MongoDB restore completed for {}", cfg.name); diff --git a/src/services/status.rs b/src/services/status.rs index 3f8a018..c117d4c 100644 --- a/src/services/status.rs +++ b/src/services/status.rs @@ -33,7 +33,6 @@ impl StatusService { let db_engine = DatabaseFactory::create_for_backup(db.clone()).await; let reachable = db_engine.ping().await?; - info!("Ping {} => {:?}",db.name, reachable); Ok::(DatabasePayload { From e990e3b19a76ebdd29ed278b485deb30d2b94b2b Mon Sep 17 00:00:00 2001 From: Charles GTE Date: Wed, 29 Apr 2026 22:32:43 +0200 Subject: [PATCH 9/9] fix: docker-compose.yml --- docker-compose.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index a933aca..fcbf2ef 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,8 +9,7 @@ services: - .:/app - cargo-registry:/usr/local/cargo/registry - cargo-git:/usr/local/cargo/git - - /Users/charlesgauthereau/Desktop/test-portabase/databases.json:/config/config.json -# - ./databases.json:/config/config.json + - ./databases.json:/config/config.json #- ./databases.toml:/config/config.toml #- /var/run/docker.sock:/var/run/docker.sock #- cargo-target:/app/target @@ -20,7 +19,7 @@ services: APP_ENV: development LOG: debug TZ: "Europe/Paris" - EDGE_KEY: "eyJzZXJ2ZXJVcmwiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODciLCJhZ2VudElkIjoiNjIyNWFlMzMtODQwMy00NmE3LWEyNDEtMjU4MTI2MjVlYTA4IiwibWFzdGVyS2V5QjY0IjoiQlhWM1hvbEM2NTZTVjdkTmdjV1BHUWxrKytycExJNmxHRGk3Q1BCNWllbz0ifQ==" + EDGE_KEY: "eyJzZXJ2ZXJVcmwiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODciLCJhZ2VudElkIjoiOTFlYmY4MmYtY2I4OC00N2M3LWE5MWUtMDUyMmU2NzNjZjE4IiwibWFzdGVyS2V5QjY0IjoiQlhWM1hvbEM2NTZTVjdkTmdjV1BHUWxrKytycExJNmxHRGk3Q1BCNWllbz0ifQ==" #CHUNK_SIZE_MB: "1" #POOLING: 1 #DATABASES_CONFIG_FILE: "config.toml" @@ -36,8 +35,6 @@ volumes: databases_sqlite-data: external: true - - networks: portabase: name: portabase_network