diff --git a/Cargo.toml b/Cargo.toml index dd27db5..06bfd34 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,7 @@ uuid = { version = "1.4.1", features = ["v4", "serde"] } rand = "0.8.5" semver = { version = "1.0.18", features = ["serde"] } toml = "0.7.6" -tokio = { version = "1.32.0", features = ["sync", "time"] } +tokio = { version = "1.32.0", features = ["sync", "time", "process"] } clap = { version = "4.4.6", features = ["derive"] } actix-rt = "2.7.0" tera = { version = "1.19.1", default-features = false } diff --git a/src/ctx.rs b/src/ctx.rs index 6442589..d13d6c7 100644 --- a/src/ctx.rs +++ b/src/ctx.rs @@ -10,7 +10,7 @@ use tokio::sync::mpsc::Sender; use crate::db::*; use crate::docker::Docker; -use crate::docker::DockerLike; +//use crate::docker::DockerLike; use crate::settings::Settings; use super::complaince::result::Result as CResult; @@ -21,7 +21,7 @@ pub type ArcMinCtx = Arc; pub trait FullAppContext: std::marker::Send + std::marker::Sync + CloneFullAppCtx { fn settings(&self) -> &Settings; fn db(&self) -> &Database; - fn docker(&self) -> Arc; + fn docker(&self) -> Arc; fn results(&self) -> &ResultStore; fn port(&self) -> u32; } @@ -46,13 +46,13 @@ impl Clone for Box { } pub trait MinAppContext: std::marker::Send + std::marker::Sync { - fn docker_(&self) -> Arc; + fn docker_(&self) -> Arc; fn results_(&self) -> &ResultStore; fn port_(&self) -> u32; } impl MinAppContext for Arc { - fn docker_(&self) -> Arc { + fn docker_(&self) -> Arc { self.docker() } fn results_(&self) -> &ResultStore { @@ -68,7 +68,7 @@ pub struct DaemonCtx { settings: Settings, db: Database, results: ResultStore, - docker: Arc, + docker: Arc, } impl FullAppContext for DaemonCtx { @@ -78,7 +78,7 @@ impl FullAppContext for DaemonCtx { fn db(&self) -> &Database { &self.db } - fn docker(&self) -> Arc { + fn docker(&self) -> Arc { self.docker.clone() } fn results(&self) -> &ResultStore { @@ -90,7 +90,7 @@ impl FullAppContext for DaemonCtx { } impl MinAppContext for DaemonCtx { - fn docker_(&self) -> Arc { + fn docker_(&self) -> Arc { self.docker() } fn results_(&self) -> &ResultStore { @@ -120,11 +120,11 @@ impl DaemonCtx { #[derive(Clone)] pub struct CliCtx { results: ResultStore, - docker: Arc, + docker: Arc, } impl MinAppContext for CliCtx { - fn docker_(&self) -> Arc { + fn docker_(&self) -> Arc { self.docker.clone() } fn results_(&self) -> &ResultStore { diff --git a/src/docker.rs b/src/docker.rs index bb6f609..ce3f095 100644 --- a/src/docker.rs +++ b/src/docker.rs @@ -14,24 +14,8 @@ impl Docker { } } -pub trait DockerLike: std::marker::Send + std::marker::Sync + CloneDockerLike { - fn version(&self) -> String; - fn run_container( - &self, - name: &str, - img: &str, - detached: bool, - env: &HashMap, - network: Option, - pull: bool, - ); - fn get_exit_status(&self, name: &str) -> isize; - fn get_logs(&self, name: &str) -> String; - fn rm_container(&self, name: &str, force: bool); -} - -impl DockerLike for Docker { - fn version(&self) -> String { +impl Docker { + pub fn version(&self) -> String { let version = Command::new("docker") .arg("--version") .output() @@ -41,7 +25,7 @@ impl DockerLike for Docker { x.get(1).unwrap().trim().to_string() } - fn run_container( + pub fn run_container( &self, name: &str, img: &str, @@ -81,7 +65,7 @@ impl DockerLike for Docker { child.wait().unwrap(); } - fn get_exit_status(&self, name: &str) -> isize { + pub fn get_exit_status(&self, name: &str) -> isize { let output = Command::new("docker") .args(["inspect", name, "--format={{.State.ExitCode}}"]) .output() @@ -90,7 +74,7 @@ impl DockerLike for Docker { let out = out.trim(); out.parse::().unwrap() } - fn get_logs(&self, name: &str) -> String { + pub fn get_logs(&self, name: &str) -> String { let output = Command::new("docker") .args(["logs", name]) .output() @@ -98,7 +82,29 @@ impl DockerLike for Docker { String::from_utf8(output.stdout).unwrap() } - fn rm_container(&self, name: &str, force: bool) { + pub async fn block_till_container_exists(&self, name: &str, mut timeout: usize) -> bool { + let args = ["container", "inspect", name, "--format={{.State.Status}}"]; + loop { + let out = tokio::process::Command::new("docker") + .args(args) + .output() + .await + .unwrap_or_else(|_| panic!("unable to run docker command on container {name}")); + let out = String::from_utf8(out.stdout).unwrap(); + let out = out.trim(); + if out == "exited" { + return true; + } + + if timeout == 0 { + return false; + } + tokio::time::sleep(std::time::Duration::new(1, 0)).await; + timeout -= 1; + } + } + + pub fn rm_container(&self, name: &str, force: bool) { let args = if force { vec!["rm", "--force", name] } else { @@ -111,34 +117,14 @@ impl DockerLike for Docker { } } -pub trait CloneDockerLike { - /// clone DB - fn clone_docker_like(&self) -> Box; -} - -impl CloneDockerLike for T -where - T: DockerLike + Clone + 'static, -{ - fn clone_docker_like(&self) -> Box { - Box::new(self.clone()) - } -} - -impl Clone for Box { - fn clone(&self) -> Self { - (**self).clone_docker_like() - } -} - #[cfg(test)] mod tests { use crate::utils::get_random; use super::*; - #[test] - fn test_docker_util() { + #[actix_rt::test] + async fn test_docker_util() { let d = Docker::new(); d.version(); let name = format!("test_sleep__{}", get_random(4)); @@ -159,7 +145,13 @@ mod tests { .unwrap(); let out = String::from_utf8(out.stdout).unwrap(); assert!(out.contains("true")); - std::thread::sleep(std::time::Duration::new(10, 0)); + + loop { + if d.block_till_container_exists(&name, 13).await { + break; + } + } + let logs = d.get_logs(&name); println!("{logs}"); assert!(logs.contains("running")); diff --git a/src/docker_compose.rs b/src/docker_compose.rs index 67a460f..d9d53f1 100644 --- a/src/docker_compose.rs +++ b/src/docker_compose.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use serde::{Deserialize, Serialize}; use serde_json::Value as JValue; -use crate::docker::DockerLike; +use crate::docker::Docker; #[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)] pub struct Container { @@ -20,11 +20,11 @@ pub struct Container { pub struct DockerCompose { base_dir: PathBuf, - docker: Arc, + docker: Arc, } impl DockerCompose { - pub fn new(base_dir: PathBuf, docker: Arc) -> Self { + pub fn new(base_dir: PathBuf, docker: Arc) -> Self { Self { base_dir, docker } } pub fn version() -> String {