mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-27 07:16:40 +00:00
fix(install): add error handling and minor code cleanups
Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>
This commit is contained in:
@@ -192,8 +192,7 @@ func MarshalYAMLWithIndent(data interface{}, indent int) ([]byte, error) {
|
|||||||
encoder := yaml.NewEncoder(buffer)
|
encoder := yaml.NewEncoder(buffer)
|
||||||
encoder.SetIndent(indent)
|
encoder.SetIndent(indent)
|
||||||
|
|
||||||
err := encoder.Encode(data)
|
if err := encoder.Encode(data); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +208,7 @@ func replaceInFile(filepath, oldStr, newStr string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Replace the string
|
// Replace the string
|
||||||
newContent := strings.Replace(string(content), oldStr, newStr, -1)
|
newContent := strings.ReplaceAll(string(content), oldStr, newStr)
|
||||||
|
|
||||||
// Write the modified content back to the file
|
// Write the modified content back to the file
|
||||||
err = os.WriteFile(filepath, []byte(newContent), 0644)
|
err = os.WriteFile(filepath, []byte(newContent), 0644)
|
||||||
|
|||||||
@@ -144,12 +144,13 @@ func installDocker() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func startDockerService() error {
|
func startDockerService() error {
|
||||||
if runtime.GOOS == "linux" {
|
switch runtime.GOOS {
|
||||||
|
case "linux":
|
||||||
cmd := exec.Command("systemctl", "enable", "--now", "docker")
|
cmd := exec.Command("systemctl", "enable", "--now", "docker")
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
return cmd.Run()
|
return cmd.Run()
|
||||||
} else if runtime.GOOS == "darwin" {
|
case "darwin":
|
||||||
// On macOS, Docker is usually started via the Docker Desktop application
|
// On macOS, Docker is usually started via the Docker Desktop application
|
||||||
fmt.Println("Please start Docker Desktop manually on macOS.")
|
fmt.Println("Please start Docker Desktop manually on macOS.")
|
||||||
return nil
|
return nil
|
||||||
@@ -302,7 +303,7 @@ func pullContainers(containerType SupportedContainer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("Unsupported container type: %s", containerType)
|
return fmt.Errorf("unsupported container type: %s", containerType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// startContainers starts the containers using the appropriate command.
|
// startContainers starts the containers using the appropriate command.
|
||||||
@@ -325,7 +326,7 @@ func startContainers(containerType SupportedContainer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("Unsupported container type: %s", containerType)
|
return fmt.Errorf("unsupported container type: %s", containerType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// stopContainers stops the containers using the appropriate command.
|
// stopContainers stops the containers using the appropriate command.
|
||||||
@@ -347,7 +348,7 @@ func stopContainers(containerType SupportedContainer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("Unsupported container type: %s", containerType)
|
return fmt.Errorf("unsupported container type: %s", containerType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// restartContainer restarts a specific container using the appropriate command.
|
// restartContainer restarts a specific container using the appropriate command.
|
||||||
@@ -369,5 +370,5 @@ func restartContainer(container string, containerType SupportedContainer) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("Unsupported container type: %s", containerType)
|
return fmt.Errorf("unsupported container type: %s", containerType)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,9 +27,18 @@ func installCrowdsec(config Config) error {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
os.MkdirAll("config/crowdsec/db", 0755)
|
if err := os.MkdirAll("config/crowdsec/db", 0755); err != nil {
|
||||||
os.MkdirAll("config/crowdsec/acquis.d", 0755)
|
fmt.Printf("Error creating config files: %v\n", err)
|
||||||
os.MkdirAll("config/traefik/logs", 0755)
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll("config/crowdsec/acquis.d", 0755); err != nil {
|
||||||
|
fmt.Printf("Error creating config files: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll("config/traefik/logs", 0755); err != nil {
|
||||||
|
fmt.Printf("Error creating config files: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
if err := copyDockerService("config/crowdsec/docker-compose.yml", "docker-compose.yml", "crowdsec"); err != nil {
|
if err := copyDockerService("config/crowdsec/docker-compose.yml", "docker-compose.yml", "crowdsec"); err != nil {
|
||||||
fmt.Printf("Error copying docker service: %v\n", err)
|
fmt.Printf("Error copying docker service: %v\n", err)
|
||||||
|
|||||||
@@ -57,11 +57,12 @@ func readBool(reader *bufio.Reader, prompt string, defaultValue bool) bool {
|
|||||||
for {
|
for {
|
||||||
input := readString(reader, prompt+" (yes/no)", defaultStr)
|
input := readString(reader, prompt+" (yes/no)", defaultStr)
|
||||||
lower := strings.ToLower(input)
|
lower := strings.ToLower(input)
|
||||||
if lower == "yes" {
|
switch lower {
|
||||||
|
case "yes":
|
||||||
return true
|
return true
|
||||||
} else if lower == "no" {
|
case "no":
|
||||||
return false
|
return false
|
||||||
} else {
|
default:
|
||||||
fmt.Println("Please enter 'yes' or 'no'.")
|
fmt.Println("Please enter 'yes' or 'no'.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,11 +72,12 @@ func readBoolNoDefault(reader *bufio.Reader, prompt string) bool {
|
|||||||
for {
|
for {
|
||||||
input := readStringNoDefault(reader, prompt+" (yes/no)")
|
input := readStringNoDefault(reader, prompt+" (yes/no)")
|
||||||
lower := strings.ToLower(input)
|
lower := strings.ToLower(input)
|
||||||
if lower == "yes" {
|
switch lower {
|
||||||
|
case "yes":
|
||||||
return true
|
return true
|
||||||
} else if lower == "no" {
|
case "no":
|
||||||
return false
|
return false
|
||||||
} else {
|
default:
|
||||||
fmt.Println("Please enter 'yes' or 'no'.")
|
fmt.Println("Please enter 'yes' or 'no'.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"crypto/rand"
|
||||||
"embed"
|
"embed"
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"crypto/rand"
|
|
||||||
"encoding/base64"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -102,7 +102,10 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
moveFile("config/docker-compose.yml", "docker-compose.yml")
|
if err := moveFile("config/docker-compose.yml", "docker-compose.yml"); err != nil {
|
||||||
|
fmt.Printf("Error moving docker-compose.yml: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println("\nConfiguration files created successfully!")
|
fmt.Println("\nConfiguration files created successfully!")
|
||||||
|
|
||||||
@@ -123,7 +126,11 @@ func main() {
|
|||||||
|
|
||||||
if !isDockerInstalled() && runtime.GOOS == "linux" && config.InstallationContainerType == Docker {
|
if !isDockerInstalled() && runtime.GOOS == "linux" && config.InstallationContainerType == Docker {
|
||||||
if readBool(reader, "Docker is not installed. Would you like to install it?", true) {
|
if readBool(reader, "Docker is not installed. Would you like to install it?", true) {
|
||||||
installDocker()
|
if err := installDocker(); err != nil {
|
||||||
|
fmt.Printf("Error installing Docker: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// try to start docker service but ignore errors
|
// try to start docker service but ignore errors
|
||||||
if err := startDockerService(); err != nil {
|
if err := startDockerService(); err != nil {
|
||||||
fmt.Println("Error starting Docker service:", err)
|
fmt.Println("Error starting Docker service:", err)
|
||||||
@@ -132,7 +139,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
// wait 10 seconds for docker to start checking if docker is running every 2 seconds
|
// wait 10 seconds for docker to start checking if docker is running every 2 seconds
|
||||||
fmt.Println("Waiting for Docker to start...")
|
fmt.Println("Waiting for Docker to start...")
|
||||||
for i := 0; i < 5; i++ {
|
for range 5 {
|
||||||
if isDockerRunning() {
|
if isDockerRunning() {
|
||||||
fmt.Println("Docker is running!")
|
fmt.Println("Docker is running!")
|
||||||
break
|
break
|
||||||
@@ -290,7 +297,8 @@ func podmanOrDocker(reader *bufio.Reader) SupportedContainer {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if chosenContainer == Podman {
|
switch chosenContainer {
|
||||||
|
case Podman:
|
||||||
if !isPodmanInstalled() {
|
if !isPodmanInstalled() {
|
||||||
fmt.Println("Podman or podman-compose is not installed. Please install both manually. Automated installation will be available in a later release.")
|
fmt.Println("Podman or podman-compose is not installed. Please install both manually. Automated installation will be available in a later release.")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@@ -311,7 +319,7 @@ func podmanOrDocker(reader *bufio.Reader) SupportedContainer {
|
|||||||
// Linux only.
|
// Linux only.
|
||||||
|
|
||||||
if err := run("bash", "-c", "echo 'net.ipv4.ip_unprivileged_port_start=80' > /etc/sysctl.d/99-podman.conf && sysctl --system"); err != nil {
|
if err := run("bash", "-c", "echo 'net.ipv4.ip_unprivileged_port_start=80' > /etc/sysctl.d/99-podman.conf && sysctl --system"); err != nil {
|
||||||
fmt.Printf("Error configuring unprivileged ports: %v\n", err)
|
fmt.Printf("Error configuring unprivileged ports: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -321,7 +329,7 @@ func podmanOrDocker(reader *bufio.Reader) SupportedContainer {
|
|||||||
fmt.Println("Unprivileged ports have been configured.")
|
fmt.Println("Unprivileged ports have been configured.")
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if chosenContainer == Docker {
|
case Docker:
|
||||||
// check if docker is not installed and the user is root
|
// check if docker is not installed and the user is root
|
||||||
if !isDockerInstalled() {
|
if !isDockerInstalled() {
|
||||||
if os.Geteuid() != 0 {
|
if os.Geteuid() != 0 {
|
||||||
@@ -336,7 +344,7 @@ func podmanOrDocker(reader *bufio.Reader) SupportedContainer {
|
|||||||
fmt.Println("The installer will not be able to run docker commands without running it as root.")
|
fmt.Println("The installer will not be able to run docker commands without running it as root.")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
} else {
|
default:
|
||||||
// This shouldn't happen unless there's a third container runtime.
|
// This shouldn't happen unless there's a third container runtime.
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
@@ -405,10 +413,18 @@ func collectUserInput(reader *bufio.Reader) Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createConfigFiles(config Config) error {
|
func createConfigFiles(config Config) error {
|
||||||
os.MkdirAll("config", 0755)
|
if err := os.MkdirAll("config", 0755); err != nil {
|
||||||
os.MkdirAll("config/letsencrypt", 0755)
|
return fmt.Errorf("failed to create config directory: %v", err)
|
||||||
os.MkdirAll("config/db", 0755)
|
}
|
||||||
os.MkdirAll("config/logs", 0755)
|
if err := os.MkdirAll("config/letsencrypt", 0755); err != nil {
|
||||||
|
return fmt.Errorf("failed to create letsencrypt directory: %v", err)
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll("config/db", 0755); err != nil {
|
||||||
|
return fmt.Errorf("failed to create db directory: %v", err)
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll("config/logs", 0755); err != nil {
|
||||||
|
return fmt.Errorf("failed to create logs directory: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Walk through all embedded files
|
// Walk through all embedded files
|
||||||
err := fs.WalkDir(configFiles, "config", func(path string, d fs.DirEntry, err error) error {
|
err := fs.WalkDir(configFiles, "config", func(path string, d fs.DirEntry, err error) error {
|
||||||
@@ -562,22 +578,24 @@ func showSetupTokenInstructions(containerType SupportedContainer, dashboardDomai
|
|||||||
fmt.Println("To get your setup token, you need to:")
|
fmt.Println("To get your setup token, you need to:")
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
fmt.Println("1. Start the containers")
|
fmt.Println("1. Start the containers")
|
||||||
if containerType == Docker {
|
switch containerType {
|
||||||
|
case Docker:
|
||||||
fmt.Println(" docker compose up -d")
|
fmt.Println(" docker compose up -d")
|
||||||
} else if containerType == Podman {
|
case Podman:
|
||||||
fmt.Println(" podman-compose up -d")
|
fmt.Println(" podman-compose up -d")
|
||||||
} else {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
fmt.Println("2. Wait for the Pangolin container to start and generate the token")
|
fmt.Println("2. Wait for the Pangolin container to start and generate the token")
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
fmt.Println("3. Check the container logs for the setup token")
|
fmt.Println("3. Check the container logs for the setup token")
|
||||||
if containerType == Docker {
|
switch containerType {
|
||||||
|
case Docker:
|
||||||
fmt.Println(" docker logs pangolin | grep -A 2 -B 2 'SETUP TOKEN'")
|
fmt.Println(" docker logs pangolin | grep -A 2 -B 2 'SETUP TOKEN'")
|
||||||
} else if containerType == Podman {
|
case Podman:
|
||||||
fmt.Println(" podman logs pangolin | grep -A 2 -B 2 'SETUP TOKEN'")
|
fmt.Println(" podman logs pangolin | grep -A 2 -B 2 'SETUP TOKEN'")
|
||||||
} else {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
fmt.Println("4. Look for output like")
|
fmt.Println("4. Look for output like")
|
||||||
fmt.Println(" === SETUP TOKEN GENERATED ===")
|
fmt.Println(" === SETUP TOKEN GENERATED ===")
|
||||||
@@ -639,10 +657,7 @@ func checkPortsAvailable(port int) error {
|
|||||||
addr := fmt.Sprintf(":%d", port)
|
addr := fmt.Sprintf(":%d", port)
|
||||||
ln, err := net.Listen("tcp", addr)
|
ln, err := net.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf("ERROR: port %d is occupied or cannot be bound: %w", port, err)
|
||||||
"ERROR: port %d is occupied or cannot be bound: %w\n\n",
|
|
||||||
port, err,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if closeErr := ln.Close(); closeErr != nil {
|
if closeErr := ln.Close(); closeErr != nil {
|
||||||
fmt.Fprintf(os.Stderr,
|
fmt.Fprintf(os.Stderr,
|
||||||
|
|||||||
Reference in New Issue
Block a user