From a625d5f43cfbba48936aa8add7d44aaa13df4105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Jane=C5=BEi=C4=8D?= Date: Tue, 23 May 2023 23:40:29 +0200 Subject: [PATCH] feat: finish postgres cli Implemented basic wanted functionality for postgres subcommands. We currently assume that postgres is running in docker-compose project in a service named "postgresdb". This could be looked at and changed at some point in the future. --- src/scripts/mod.rs | 8 ++++- src/scripts/postgres.rs | 77 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 76 insertions(+), 9 deletions(-) diff --git a/src/scripts/mod.rs b/src/scripts/mod.rs index 48f2808..151e9b9 100644 --- a/src/scripts/mod.rs +++ b/src/scripts/mod.rs @@ -7,7 +7,7 @@ use std::{ ffi::OsStr, fs::{File, OpenOptions}, path::PathBuf, - process::Command, + process::{Command, Stdio}, }; use anyhow::{Context, Result}; @@ -47,6 +47,12 @@ impl DockerCommand { self.command.spawn()?.wait()?; Ok(()) } + + fn write_stdout(mut self, stdio: Stdio) -> Result<()> { + self.command.stdout(stdio); + self.spawn_wait()?; + Ok(()) + } } fn safe_create_file(path: PathBuf) -> Result { diff --git a/src/scripts/postgres.rs b/src/scripts/postgres.rs index ff59148..36443b9 100644 --- a/src/scripts/postgres.rs +++ b/src/scripts/postgres.rs @@ -1,12 +1,73 @@ -use anyhow::Result; -use std::path::PathBuf; +use super::{docker_compose, DockerCommand}; -pub fn import(path: &PathBuf) -> Result<()> { - println!("{path:?}"); - todo!() +use anyhow::{Context, Result}; +use std::{ + fs::File, + path::{Path, PathBuf}, + process::Stdio, +}; + +fn get_containers() -> Result<[String; 2]> { + // get db container + // FIX: we assume we are running db in service named "postgresbd" + let db_container = DockerCommand::docker_compose() + .args("ps -q postgresdb") + .stdout()? + .trim() + .to_string(); + + // get all containers and filter out db container + let app_containers = DockerCommand::docker_compose() + .args("ps -q") + .stdout()? + .split_whitespace() + .filter(|x| x != &db_container) + .collect::>() + .join(" "); + + Ok([db_container, app_containers]) } -pub fn dump(path: &PathBuf) -> Result<()> { - println!("{path:?}"); - todo!() +pub fn import(file: &Path) -> Result<()> { + let [db_container, app_containers] = get_containers()?; + let dump_file = file.to_string_lossy(); + + println!("stopping all containers"); + docker_compose::stop()?; + + println!("starting db container"); + docker_compose::start(Some(&db_container))?; + + println!("restoring database"); + let commands = [ + format!("cp {dump_file} {db_container}:/tmp/dbdump"), + format!("exec {db_container} dropdb -U db db"), + format!("exec {db_container} createdb -U db -E utf8 -T template0 db"), + format!("exec {db_container} pg_restore -U db --dbname=db /tmp/dbdump"), + ]; + for command in commands { + DockerCommand::docker().args(&command).spawn_wait()?; + } + + println!("restarting containers"); + docker_compose::stop()?; + docker_compose::up()?; + + Ok(()) +} + +pub fn dump(file: &PathBuf) -> Result<()> { + let [db_container, _] = get_containers()?; + + println!("dumping to local file {}", file.to_string_lossy()); + + let file = File::create(file)?; + let stdout = Stdio::from(file); + + let command = format!("exec {db_container} pg_dump -U db --format=c db"); + DockerCommand::docker() + .args(&command) + .write_stdout(stdout)?; + + Ok(()) }