// Package config handles loading and validating configuration // for the KAOS supervisor from environment variables. package config import ( "bufio" "fmt" "os" "strings" "time" ) // Config holds the supervisor configuration values. type Config struct { // Timeout is the maximum duration for supervisor operations. Timeout time.Duration // ProjectPath is the root path of the project being supervised. ProjectPath string // TasksDir is the path to the TASKS directory. TasksDir string // Port is the HTTP server port. Port string } // Load reads configuration from environment variables. // It first attempts to load a .env file from the current directory. // Required variables: KAOS_TIMEOUT, KAOS_PROJECT_PATH. func Load() (*Config, error) { loadEnvFile(".env") timeoutStr := os.Getenv("KAOS_TIMEOUT") if timeoutStr == "" { return nil, fmt.Errorf("KAOS_TIMEOUT environment variable is required") } timeout, err := time.ParseDuration(timeoutStr) if err != nil { return nil, fmt.Errorf("invalid KAOS_TIMEOUT value %q: %w", timeoutStr, err) } projectPath := os.Getenv("KAOS_PROJECT_PATH") if projectPath == "" { return nil, fmt.Errorf("KAOS_PROJECT_PATH environment variable is required") } tasksDir := os.Getenv("KAOS_TASKS_DIR") if tasksDir == "" { return nil, fmt.Errorf("KAOS_TASKS_DIR environment variable is required") } port := os.Getenv("KAOS_PORT") if port == "" { port = "8080" } return &Config{ Timeout: timeout, ProjectPath: projectPath, TasksDir: tasksDir, Port: port, }, nil } // loadEnvFile reads a .env file and sets environment variables // that are not already set. Lines starting with # are ignored. func loadEnvFile(path string) { f, err := os.Open(path) if err != nil { return } defer f.Close() scanner := bufio.NewScanner(f) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) if line == "" || strings.HasPrefix(line, "#") { continue } key, value, ok := strings.Cut(line, "=") if !ok { continue } key = strings.TrimSpace(key) value = strings.TrimSpace(value) // Don't override existing environment variables if _, exists := os.LookupEnv(key); !exists { os.Setenv(key, value) } } }