From c837899d82895bbd3007ad4d55c0ca54c54df2a5 Mon Sep 17 00:00:00 2001 From: Taylan Date: Mon, 21 Apr 2025 11:29:56 +0200 Subject: [PATCH 1/6] Relaxed health check for crowdsec and dependance to traefik --- install/config/crowdsec/docker-compose.yml | 3 +++ install/config/docker-compose.yml | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/install/config/crowdsec/docker-compose.yml b/install/config/crowdsec/docker-compose.yml index 20c6938..28470d1 100644 --- a/install/config/crowdsec/docker-compose.yml +++ b/install/config/crowdsec/docker-compose.yml @@ -9,6 +9,9 @@ services: PARSERS: crowdsecurity/whitelists ENROLL_TAGS: docker healthcheck: + interval: 10s + retries: 15 + timeout: 10s test: ["CMD", "cscli", "capi", "status"] labels: - "traefik.enable=false" # Disable traefik for crowdsec diff --git a/install/config/docker-compose.yml b/install/config/docker-compose.yml index 496b013..1cccffa 100644 --- a/install/config/docker-compose.yml +++ b/install/config/docker-compose.yml @@ -48,6 +48,10 @@ services: depends_on: pangolin: condition: service_healthy +{{if .DoCrowdsecInstall}} + crowdsec: + condition: service_healthy +{{end}} command: - --configFile=/etc/traefik/traefik_config.yml volumes: From 181071e4f63b28d8e1ac3ecd198f87af4387a53f Mon Sep 17 00:00:00 2001 From: Taylan Date: Wed, 23 Apr 2025 18:35:15 +0200 Subject: [PATCH 2/6] refactoring multiple used code parts, cleared some warnings and added more error checking --- install/main.go | 194 +++++++++++++++--------------------------------- 1 file changed, 58 insertions(+), 136 deletions(-) diff --git a/install/main.go b/install/main.go index 47c846c..8decf14 100644 --- a/install/main.go +++ b/install/main.go @@ -87,7 +87,15 @@ func main() { if isDockerInstalled() { if readBool(reader, "Would you like to install and start the containers?", true) { - pullAndStartContainers() + if err := pullContainers(); err != nil { + fmt.Println("Error: ", err) + return + } + + if err := startContainers(); err != nil { + fmt.Println("Error: ", err) + return + } } } } else { @@ -427,24 +435,24 @@ func installDocker() error { apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin `, dockerArch)) case strings.Contains(osRelease, "ID=fedora"): - installCmd = exec.Command("bash", "-c", fmt.Sprintf(` + installCmd = exec.Command("bash", "-c", ` dnf -y install dnf-plugins-core && dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo && dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin - `)) + `) case strings.Contains(osRelease, "ID=opensuse") || strings.Contains(osRelease, "ID=\"opensuse-"): installCmd = exec.Command("bash", "-c", ` zypper install -y docker docker-compose && systemctl enable docker `) case strings.Contains(osRelease, "ID=rhel") || strings.Contains(osRelease, "ID=\"rhel"): - installCmd = exec.Command("bash", "-c", fmt.Sprintf(` + installCmd = exec.Command("bash", "-c", ` dnf remove -y runc && dnf -y install yum-utils && dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo && dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin && systemctl enable docker - `)) + `) case strings.Contains(osRelease, "ID=amzn"): installCmd = exec.Command("bash", "-c", ` yum update -y && @@ -468,165 +476,79 @@ func isDockerInstalled() bool { return true } -func getCommandString(useNewStyle bool) string { - if useNewStyle { - return "'docker compose'" - } - return "'docker-compose'" -} - -func pullAndStartContainers() error { - fmt.Println("Starting containers...") - - // Check which docker compose command is available +// executeDockerComposeCommandWithArgs executes the appropriate docker command with arguments supplied +func executeDockerComposeCommandWithArgs(args ...string) error { + var cmd *exec.Cmd var useNewStyle bool + + if !isDockerInstalled() { + return fmt.Errorf("docker is not installed") + } + checkCmd := exec.Command("docker", "compose", "version") if err := checkCmd.Run(); err == nil { useNewStyle = true } else { - // Check if docker-compose (old style) is available checkCmd = exec.Command("docker-compose", "version") - if err := checkCmd.Run(); err != nil { - return fmt.Errorf("neither 'docker compose' nor 'docker-compose' command is available: %v", err) - } - } - - // Helper function to execute docker compose commands - executeCommand := func(args ...string) error { - var cmd *exec.Cmd - if useNewStyle { - cmd = exec.Command("docker", append([]string{"compose"}, args...)...) + if err := checkCmd.Run(); err == nil { + useNewStyle = false } else { - cmd = exec.Command("docker-compose", args...) + return fmt.Errorf("neither 'docker compose' nor 'docker-compose' command is available") } - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - return cmd.Run() + } + + if useNewStyle { + cmd = exec.Command("docker", append([]string{"compose"}, args...)...) + } else { + cmd = exec.Command("docker-compose", args...) } - // Pull containers - fmt.Printf("Using %s command to pull containers...\n", getCommandString(useNewStyle)) - if err := executeCommand("-f", "docker-compose.yml", "pull"); err != nil { - return fmt.Errorf("failed to pull containers: %v", err) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} + +// pullContainers pulls the containers using the appropriate command. +func pullContainers() error { + fmt.Println("Pulling the container images...") + + if err := executeDockerComposeCommandWithArgs("-f", "docker-compose.yml", "pull", "--policy", "always"); err != nil { + return fmt.Errorf("failed to pull the containers: %v", err) } - // Start containers - fmt.Printf("Using %s command to start containers...\n", getCommandString(useNewStyle)) - if err := executeCommand("-f", "docker-compose.yml", "up", "-d"); err != nil { + return nil +} + +// startContainers starts the containers using the appropriate command. +func startContainers() error { + fmt.Println("Starting containers...") + if err := executeDockerComposeCommandWithArgs("-f", "docker-compose.yml", "up", "-d", "--force-recreate"); err != nil { return fmt.Errorf("failed to start containers: %v", err) } return nil } -// bring containers down +// stopContainers stops the containers using the appropriate command. func stopContainers() error { fmt.Println("Stopping containers...") - - // Check which docker compose command is available - var useNewStyle bool - checkCmd := exec.Command("docker", "compose", "version") - if err := checkCmd.Run(); err == nil { - useNewStyle = true - } else { - // Check if docker-compose (old style) is available - checkCmd = exec.Command("docker-compose", "version") - if err := checkCmd.Run(); err != nil { - return fmt.Errorf("neither 'docker compose' nor 'docker-compose' command is available: %v", err) - } - } - - // Helper function to execute docker compose commands - executeCommand := func(args ...string) error { - var cmd *exec.Cmd - if useNewStyle { - cmd = exec.Command("docker", append([]string{"compose"}, args...)...) - } else { - cmd = exec.Command("docker-compose", args...) - } - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - return cmd.Run() - } - - if err := executeCommand("-f", "docker-compose.yml", "down"); err != nil { + + if err := executeDockerComposeCommandWithArgs("-f", "docker-compose.yml", "down"); err != nil { return fmt.Errorf("failed to stop containers: %v", err) } return nil } -// just start containers -func startContainers() error { - fmt.Println("Starting containers...") - - // Check which docker compose command is available - var useNewStyle bool - checkCmd := exec.Command("docker", "compose", "version") - if err := checkCmd.Run(); err == nil { - useNewStyle = true - } else { - // Check if docker-compose (old style) is available - checkCmd = exec.Command("docker-compose", "version") - if err := checkCmd.Run(); err != nil { - return fmt.Errorf("neither 'docker compose' nor 'docker-compose' command is available: %v", err) - } - } - - // Helper function to execute docker compose commands - executeCommand := func(args ...string) error { - var cmd *exec.Cmd - if useNewStyle { - cmd = exec.Command("docker", append([]string{"compose"}, args...)...) - } else { - cmd = exec.Command("docker-compose", args...) - } - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - return cmd.Run() - } - - if err := executeCommand("-f", "docker-compose.yml", "up", "-d"); err != nil { - return fmt.Errorf("failed to start containers: %v", err) - } - - return nil -} - +// restartContainer restarts a specific container using the appropriate command. func restartContainer(container string) error { - fmt.Printf("Restarting %s container...\n", container) + fmt.Println("Restarting containers...") + + if err := executeDockerComposeCommandWithArgs("-f", "docker-compose.yml", "restart", container); err != nil { + return fmt.Errorf("failed to stop the container \"%s\": %v", container, err) + } - // Check which docker compose command is available - var useNewStyle bool - checkCmd := exec.Command("docker", "compose", "version") - if err := checkCmd.Run(); err == nil { - useNewStyle = true - } else { - // Check if docker-compose (old style) is available - checkCmd = exec.Command("docker-compose", "version") - if err := checkCmd.Run(); err != nil { - return fmt.Errorf("neither 'docker compose' nor 'docker-compose' command is available: %v", err) - } - } - - // Helper function to execute docker compose commands - executeCommand := func(args ...string) error { - var cmd *exec.Cmd - if useNewStyle { - cmd = exec.Command("docker", append([]string{"compose"}, args...)...) - } else { - cmd = exec.Command("docker-compose", args...) - } - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - return cmd.Run() - } - - if err := executeCommand("-f", "docker-compose.yml", "restart", container); err != nil { - return fmt.Errorf("failed to restart %s container: %v", container, err) - } - - return nil + return nil } func copyFile(src, dst string) error { From 87915f29f6e7095baa3e1ceb0857b2cc17d17c8f Mon Sep 17 00:00:00 2001 From: Taylan Date: Wed, 23 Apr 2025 18:37:36 +0200 Subject: [PATCH 3/6] correct formated the file --- install/main.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/install/main.go b/install/main.go index 8decf14..157a3ab 100644 --- a/install/main.go +++ b/install/main.go @@ -544,11 +544,11 @@ func stopContainers() error { func restartContainer(container string) error { fmt.Println("Restarting containers...") - if err := executeDockerComposeCommandWithArgs("-f", "docker-compose.yml", "restart", container); err != nil { - return fmt.Errorf("failed to stop the container \"%s\": %v", container, err) - } + if err := executeDockerComposeCommandWithArgs("-f", "docker-compose.yml", "restart", container); err != nil { + return fmt.Errorf("failed to stop the container \"%s\": %v", container, err) + } - return nil + return nil } func copyFile(src, dst string) error { From 6fd1dbc638a83e4a0a20459217f908c9f21e1bf3 Mon Sep 17 00:00:00 2001 From: Taylan Date: Wed, 23 Apr 2025 18:39:48 +0200 Subject: [PATCH 4/6] some more warning about indirect requirements --- install/go.mod | 7 ++++--- install/go.sum | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/install/go.mod b/install/go.mod index 536ac2d..1d12aa1 100644 --- a/install/go.mod +++ b/install/go.mod @@ -3,7 +3,8 @@ module installer go 1.23.0 require ( - golang.org/x/sys v0.29.0 // indirect - golang.org/x/term v0.28.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + golang.org/x/term v0.28.0 + gopkg.in/yaml.v3 v3.0.1 ) + +require golang.org/x/sys v0.29.0 // indirect diff --git a/install/go.sum b/install/go.sum index 3316e03..169165e 100644 --- a/install/go.sum +++ b/install/go.sum @@ -2,6 +2,7 @@ golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 419bacf55ff6cd61ff29c4f8e61ac4c5549f8386 Mon Sep 17 00:00:00 2001 From: Taylan Date: Wed, 23 Apr 2025 20:36:16 +0200 Subject: [PATCH 5/6] check and add the service dependency of crowdsec to traefik --- install/config/docker-compose.yml | 4 -- install/crowdsec.go | 64 +++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/install/config/docker-compose.yml b/install/config/docker-compose.yml index 1cccffa..496b013 100644 --- a/install/config/docker-compose.yml +++ b/install/config/docker-compose.yml @@ -48,10 +48,6 @@ services: depends_on: pangolin: condition: service_healthy -{{if .DoCrowdsecInstall}} - crowdsec: - condition: service_healthy -{{end}} command: - --configFile=/etc/traefik/traefik_config.yml volumes: diff --git a/install/crowdsec.go b/install/crowdsec.go index 9fadadc..c17bf54 100644 --- a/install/crowdsec.go +++ b/install/crowdsec.go @@ -3,9 +3,12 @@ package main import ( "bytes" "fmt" + "log" "os" "os/exec" "strings" + + "gopkg.in/yaml.v3" ) func installCrowdsec(config Config) error { @@ -63,6 +66,12 @@ func installCrowdsec(config Config) error { os.Exit(1) } + // check and add the service dependency of crowdsec to traefik + if err := CheckAndAddCrowdsecDependency("docker-compose.yml"); err != nil { + fmt.Printf("Error adding crowdsec dependency to traefik: %v\n", err) + os.Exit(1) + } + if err := startContainers(); err != nil { return fmt.Errorf("failed to start containers: %v", err) } @@ -135,3 +144,58 @@ func checkIfTextInFile(file, text string) bool { // Check for text return bytes.Contains(content, []byte(text)) } + +func CheckAndAddCrowdsecDependency(composePath string) error { + // Read the docker-compose.yml file + data, err := os.ReadFile(composePath) + if err != nil { + return fmt.Errorf("error reading compose file: %w", err) + } + + // Parse YAML into a generic map + var compose map[string]interface{} + if err := yaml.Unmarshal(data, &compose); err != nil { + return fmt.Errorf("error parsing compose file: %w", err) + } + + // Get services section + services, ok := compose["services"].(map[string]interface{}) + if !ok { + return fmt.Errorf("services section not found or invalid") + } + + // Get traefik service + traefik, ok := services["traefik"].(map[string]interface{}) + if !ok { + return fmt.Errorf("traefik service not found or invalid") + } + + // Get dependencies + dependsOn, ok := traefik["depends_on"].(map[string]interface{}) + if ok { + // Append the new block for crowdsec + dependsOn["crowdsec"] = map[string]interface{}{ + "condition": "service_healthy", + } + } else { + // No dependencies exist, create it + traefik["depends_on"] = map[string]interface{}{ + "crowdsec": map[string]interface{}{ + "condition": "service_healthy", + }, + } + } + + // Marshal the modified data back to YAML with indentation + modifiedData, err := MarshalYAMLWithIndent(compose, 2) // Set indentation to 2 spaces + if err != nil { + log.Fatalf("error marshaling YAML: %v", err) + } + + if err := os.WriteFile(composePath, modifiedData, 0644); err != nil { + return fmt.Errorf("error writing updated compose file: %w", err) + } + + fmt.Println("Added dependency of crowdsec to traefik") + return nil +} From 5d6e15b0d66b2fe70e82be1e1034591e5e516407 Mon Sep 17 00:00:00 2001 From: Taylan Date: Wed, 23 Apr 2025 20:54:03 +0200 Subject: [PATCH 6/6] indentation fix --- install/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/main.go b/install/main.go index 157a3ab..8411e30 100644 --- a/install/main.go +++ b/install/main.go @@ -545,7 +545,7 @@ func restartContainer(container string) error { fmt.Println("Restarting containers...") if err := executeDockerComposeCommandWithArgs("-f", "docker-compose.yml", "restart", container); err != nil { - return fmt.Errorf("failed to stop the container \"%s\": %v", container, err) + return fmt.Errorf("failed to stop the container \"%s\": %v", container, err) } return nil