Files
ahab/src/scripts/postgres.rs

96 lines
2.6 KiB
Rust

use anyhow::{anyhow, Context, Result};
use std::{
fs::File,
path::{Path, PathBuf},
process::Stdio,
thread,
time::Duration,
};
use super::docker_compose;
use crate::{command_builder::CommandBuilder, debug_eprintln};
fn get_containers(container: &str) -> Result<[String; 2]> {
// get db container
let db_container = CommandBuilder::docker_compose()
.args("ps -q")
.args(container)
.exec_get_stdout()?
.trim()
.to_string();
let no_result = db_container.is_empty();
if no_result {
return Err(anyhow!("no container"));
}
// get all containers and filter out db container
let app_containers = CommandBuilder::docker_compose()
.args("ps -q")
.exec_get_stdout()?
.split_whitespace()
.filter(|x| x != &db_container)
.collect::<Vec<&str>>()
.join(" ");
Ok([db_container, app_containers])
}
pub fn import(container: &str, file: &Path) -> Result<()> {
let [db_container, app_containers] = get_containers(container)?;
let dump_file = file.to_string_lossy();
eprintln!("stopping all containers");
docker_compose::stop()?;
eprintln!("starting db container");
docker_compose::start(Some(container))?;
eprintln!("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 {
debug_eprintln!("waiting until pg_isready");
while !CommandBuilder::docker()
.args(&format!(
"exec {db_container} pg_isready -h {container} -p 5432 -U db",
))
.build()?
.stdout(Stdio::null())
.spawn()?
.wait()?
.success()
{
thread::sleep(Duration::from_secs(1));
}
CommandBuilder::docker().args(&command).exec()?;
}
eprintln!("restarting containers");
docker_compose::stop()?;
docker_compose::up()?;
Ok(())
}
pub fn dump(container: &str, file: &PathBuf) -> Result<()> {
let [db_container, _] = get_containers(container)?;
eprintln!("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");
CommandBuilder::docker()
.args(&command)
.exec_redirect_stdout(stdout)?;
Ok(())
}