feat: rm DockerLike and add block method to wait for container to exit
This commit is contained in:
parent
bca4c795b2
commit
36c64878e0
4 changed files with 50 additions and 58 deletions
|
@ -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 }
|
||||
|
|
18
src/ctx.rs
18
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<dyn MinAppContext>;
|
|||
pub trait FullAppContext: std::marker::Send + std::marker::Sync + CloneFullAppCtx {
|
||||
fn settings(&self) -> &Settings;
|
||||
fn db(&self) -> &Database;
|
||||
fn docker(&self) -> Arc<dyn DockerLike>;
|
||||
fn docker(&self) -> Arc<Docker>;
|
||||
fn results(&self) -> &ResultStore;
|
||||
fn port(&self) -> u32;
|
||||
}
|
||||
|
@ -46,13 +46,13 @@ impl Clone for Box<dyn FullAppContext> {
|
|||
}
|
||||
|
||||
pub trait MinAppContext: std::marker::Send + std::marker::Sync {
|
||||
fn docker_(&self) -> Arc<dyn DockerLike>;
|
||||
fn docker_(&self) -> Arc<Docker>;
|
||||
fn results_(&self) -> &ResultStore;
|
||||
fn port_(&self) -> u32;
|
||||
}
|
||||
|
||||
impl MinAppContext for Arc<dyn FullAppContext> {
|
||||
fn docker_(&self) -> Arc<dyn DockerLike> {
|
||||
fn docker_(&self) -> Arc<Docker> {
|
||||
self.docker()
|
||||
}
|
||||
fn results_(&self) -> &ResultStore {
|
||||
|
@ -68,7 +68,7 @@ pub struct DaemonCtx {
|
|||
settings: Settings,
|
||||
db: Database,
|
||||
results: ResultStore,
|
||||
docker: Arc<dyn DockerLike>,
|
||||
docker: Arc<Docker>,
|
||||
}
|
||||
|
||||
impl FullAppContext for DaemonCtx {
|
||||
|
@ -78,7 +78,7 @@ impl FullAppContext for DaemonCtx {
|
|||
fn db(&self) -> &Database {
|
||||
&self.db
|
||||
}
|
||||
fn docker(&self) -> Arc<dyn DockerLike> {
|
||||
fn docker(&self) -> Arc<Docker> {
|
||||
self.docker.clone()
|
||||
}
|
||||
fn results(&self) -> &ResultStore {
|
||||
|
@ -90,7 +90,7 @@ impl FullAppContext for DaemonCtx {
|
|||
}
|
||||
|
||||
impl MinAppContext for DaemonCtx {
|
||||
fn docker_(&self) -> Arc<dyn DockerLike> {
|
||||
fn docker_(&self) -> Arc<Docker> {
|
||||
self.docker()
|
||||
}
|
||||
fn results_(&self) -> &ResultStore {
|
||||
|
@ -120,11 +120,11 @@ impl DaemonCtx {
|
|||
#[derive(Clone)]
|
||||
pub struct CliCtx {
|
||||
results: ResultStore,
|
||||
docker: Arc<dyn DockerLike>,
|
||||
docker: Arc<Docker>,
|
||||
}
|
||||
|
||||
impl MinAppContext for CliCtx {
|
||||
fn docker_(&self) -> Arc<dyn DockerLike> {
|
||||
fn docker_(&self) -> Arc<Docker> {
|
||||
self.docker.clone()
|
||||
}
|
||||
fn results_(&self) -> &ResultStore {
|
||||
|
|
|
@ -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<String, String>,
|
||||
network: Option<String>,
|
||||
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::<isize>().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<dyn DockerLike>;
|
||||
}
|
||||
|
||||
impl<T> CloneDockerLike for T
|
||||
where
|
||||
T: DockerLike + Clone + 'static,
|
||||
{
|
||||
fn clone_docker_like(&self) -> Box<dyn DockerLike> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Box<dyn DockerLike> {
|
||||
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"));
|
||||
|
|
|
@ -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<dyn DockerLike>,
|
||||
docker: Arc<Docker>,
|
||||
}
|
||||
|
||||
impl DockerCompose {
|
||||
pub fn new(base_dir: PathBuf, docker: Arc<dyn DockerLike>) -> Self {
|
||||
pub fn new(base_dir: PathBuf, docker: Arc<Docker>) -> Self {
|
||||
Self { base_dir, docker }
|
||||
}
|
||||
pub fn version() -> String {
|
||||
|
|
Loading…
Reference in a new issue