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
83
84
85
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!("Docker Compose started");

        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-compose")
            .arg("-f")
            .arg(self.file.clone())
            .arg("ps")
            .arg("--services")
            .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 || {
                    let follow_container_log = |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();
                    };
                
                    follow_container_log(container, file_path);
                });
            })
            .collect();
    }

    pub fn down(&self) {
        println!("Gracefully shutting down...");

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