Merge pull request #558 from TuncTaylan/main

Added dependency of crowdsec to traefik and relaxed its health check
This commit is contained in:
Owen Schwartz 2025-04-28 20:29:17 -04:00 committed by GitHub
commit eed6081ade
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 128 additions and 137 deletions

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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=

View file

@ -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,162 +476,76 @@ 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)
// 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)
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 nil