1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use std::fs::File;
use std::path::Path;
use std::process::{Command, Stdio};
use std::thread;

pub struct DockerCompose {
    file: String,
    logs_dir: String,
}

impl DockerCompose {
    pub fn new(file: &str, logs_dir: &str) -> DockerCompose {
        DockerCompose {
            file: file.to_string(),
            logs_dir: logs_dir.to_string(), 
        }
    }

    pub fn up(&self) {
        let output = Command::new("docker-compose")
            .arg("-f")
            .arg(self.file.clone())
            .arg("up")
            .arg("-d")
            .output()
            .expect("Failed to execute command");
        println!("Output: {}", String::from_utf8_lossy(&output.stdout));
        println!("Errors: {}", String::from_utf8_lossy(&output.stderr));
        println!("Starting Test");

        let dir = &self.logs_dir;
        if Path::new(dir).exists() {
            std::fs::remove_dir_all(dir).unwrap();
        }
        std::fs::create_dir_all(dir).unwrap();

        let output = Command::new("docker")
            .arg("ps")
            .arg("--format")
            .arg("{{.Names}}")
            .output()
            .unwrap();

        let stdout = String::from_utf8(output.stdout).unwrap();
        let containers: Vec<String> = stdout.lines().map(String::from).collect();

        let _handles: Vec<_> = containers
            .into_iter()
            .map(|container| {
                let file_name = format!("{}/{}.log", dir, container);
                let file_path = std::path::PathBuf::from(file_name);
                let docker_compose_file = self.file.clone();
                thread::spawn(move || DockerCompose::follow_container_log(docker_compose_file, container, file_path))
            })
            .collect();
    }

    pub fn down(&self) {
        let _output = Command::new("docker-compose")
            .arg("-f")
            .arg(self.file.clone())
            .arg("down")
            .output()
            .expect("Failed to execute command");

        println!("Gracefully shutting down...");
    }

    fn follow_container_log(docker_compose_file: String, container: String, file_path: std::path::PathBuf) {
        let file = File::create(file_path).unwrap();
        let _ = Command::new("docker-compose")
            .arg("-f")
            .arg(docker_compose_file)
            .arg("logs")
            .arg("--follow")
            .arg("--no-log-prefix")
            .arg(&container)
            .stdout(Stdio::from(file))
            .spawn()
            .unwrap();
    }
}