rolling_deployer/
config.rs

1use crate::cli::CLI;
2use std::collections::HashMap;
3
4#[derive(Debug, Clone)]
5pub struct Config {
6    pub repo_url: String,
7    pub clone_path: String,
8    pub compose_file: String,
9    pub mount_path: String,
10    pub name: String,
11    pub socket_path: String,
12}
13
14impl Config {
15    pub fn from_env_and_cli(cli: &CLI) -> Result<Self, Box<dyn std::error::Error>> {
16        // Parse env file into a HashMap (don't crash if it doesn't exist)
17        let mut env_vars = HashMap::new();
18        let env_path = &cli.env_file;
19        if std::path::Path::new(env_path).exists() {
20            if let Ok(env_content) = std::fs::read_to_string(env_path) {
21                for line in env_content.lines() {
22                    let line = line.trim();
23                    // Skip empty lines and comments
24                    if line.is_empty() || line.starts_with('#') {
25                        continue;
26                    }
27                    if let Some((key, value)) = line.split_once('=') {
28                        env_vars.insert(key.trim().to_string(), value.trim().to_string());
29                    }
30                }
31            }
32        }
33
34        // Priority: CLI args > .env file > error/default
35        let repo_url = cli
36            .repo_url
37            .clone()
38            .or_else(|| env_vars.get("REPO_URL").cloned())
39            .ok_or("REPO_URL not provided. Use --repo-url flag or set REPO_URL in .env file")?;
40
41        let clone_path = cli
42            .clone_path
43            .clone()
44            .or_else(|| env_vars.get("CLONE_PATH").cloned())
45            .ok_or(
46                "CLONE_PATH not provided. Use --clone-path flag or set CLONE_PATH in .env file",
47            )?;
48
49        let mount_path = cli
50            .mount_path
51            .clone()
52            .or_else(|| env_vars.get("MOUNT_PATH").cloned())
53            .ok_or(
54                "MOUNT_PATH not provided. Use --mount-path flag or set MOUNT_PATH in .env file",
55            )?;
56
57        // New: allow compose_file, name, and socket_path from .env
58        let compose_file = if cli.compose_file != "docker-compose.yml" {
59            cli.compose_file.clone()
60        } else {
61            env_vars
62                .get("COMPOSE_FILE")
63                .cloned()
64                .unwrap_or_else(|| cli.compose_file.clone())
65        };
66
67        let name = cli
68            .name
69            .clone()
70            .or_else(|| env_vars.get("NAME").cloned())
71            .ok_or("NAME not provided. Use --name flag or set NAME in .env file")?;
72        let socket_path = if cli.socket_path != "/var/run/docker.sock" {
73            cli.socket_path.clone()
74        } else {
75            env_vars
76                .get("SOCKET_PATH")
77                .cloned()
78                .unwrap_or_else(|| cli.socket_path.clone())
79        };
80
81        Ok(Config {
82            repo_url,
83            clone_path,
84            compose_file,
85            mount_path,
86            name,
87            socket_path,
88        })
89    }
90
91    pub fn show_configuration_help() {
92        println!("Configuration options:");
93        println!("  1. Command line flags:");
94        println!(
95            "     ./app v1.2.3 --name my-project --repo-url https://github.com/org/repo.git --mount-path /opt/configs --clone-path /opt/traefik-configs --compose-file ./docker-compose.yml --socket-path /var/run/docker.sock --env-file .env"
96        );
97        println!();
98        println!("  2. Create a .env file (or use --env-file to specify a different file):");
99        println!("     REPO_URL=https://github.com/your-org/traefik-config.git");
100        println!("     CLONE_PATH=/opt/traefik-configs");
101        println!("     MOUNT_PATH=/etc/traefik/dynamic");
102        println!("     COMPOSE_FILE=./docker-compose.yml");
103        println!("     NAME=my-project");
104        println!("     SOCKET_PATH=/var/run/docker.sock");
105        println!();
106        println!("Command line flags take precedence over .env file values.");
107    }
108}