diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f037083 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +.git +qlub +nginx.conf \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3502e90 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +FROM golang:1.23.2-alpine AS builder + +WORKDIR /app + +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . + +RUN CGO_ENABLED=0 GOOS=linux go build -o qlub . + +FROM alpine:latest + +WORKDIR /app + +COPY --from=builder /app/qlub /usr/local/bin/qlub + +COPY subdomains.json . + +CMD ["/usr/local/bin/qlub", "--config", "/app/subdomains.json", "--watch"] diff --git a/README.md b/README.md index 251c1b3..3cd027e 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,18 @@ El archivo de configuración JSON debe contener una lista de subdominios. Cada s ] ``` +## Docker Compose +Puedes descargar la imagen lista para trabajar `docker pull njavilas/qlub:1.0` + +```yml +services: + qlub: + image: njavilas/qlub:1.0 + volumes: + - ./subdomains.json:/app/subdomains.json + - ./nginx.conf:/app/nginx.conf +``` + ## Build go build -o qlub diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..2f6e822 --- /dev/null +++ b/build.sh @@ -0,0 +1 @@ +docker build -t njavilas/qlub:1.0 . \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..284debe --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,6 @@ +services: + qlub: + image: njavilas/qlub:1.0 + volumes: + - ./subdomains.json:/app/subdomains.json + - ./nginx.conf:/app/nginx.conf \ No newline at end of file diff --git a/go.mod b/go.mod index c0605e7..9038332 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,8 @@ module github.com/njavilas2015/qlub go 1.23.2 + +require ( + github.com/fsnotify/fsnotify v1.8.0 // indirect + golang.org/x/sys v0.13.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..b6b937f --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/internal/config/config.go b/internal/config/config.go index ac4ab99..941c9f9 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -4,7 +4,10 @@ import ( "encoding/json" "flag" "fmt" + "log" "os" + + "github.com/fsnotify/fsnotify" ) type Subdomain struct { @@ -26,16 +29,20 @@ func LoadConfig(filename *string) ([]Subdomain, error) { var subdomains []Subdomain - if err := json.Unmarshal(data, &subdomains); err != nil { - return nil, err + if len(data) > 0 { + + if err := json.Unmarshal(data, &subdomains); err != nil { + return nil, err + } } return subdomains, nil } -func ParseFlags() (*bool, *string) { +func ParseFlags() (*bool, *string, *bool) { showVersion := flag.Bool("version", false, "Show qlub version") configPath := flag.String("config", "", "Path to JSON configuration file") + watcher := flag.Bool("watch", false, "Update configuration realtime") flag.Parse() @@ -44,10 +51,52 @@ func ParseFlags() (*bool, *string) { os.Exit(1) } - return showVersion, configPath + return showVersion, configPath, watcher } func CheckFileExistence(filename string) bool { _, err := os.Stat(filename) return !os.IsNotExist(err) } + +func Watcher(filename *string) { + + watcher, err := fsnotify.NewWatcher() + + if err != nil { + log.Fatal(err) + } + + defer watcher.Close() + + err = watcher.Add(*filename) + + if err != nil { + log.Fatal(err) + } + + done := make(chan bool) + + go func() { + for { + select { + case event, ok := <-watcher.Events: + if !ok { + return + } + if event.Op&fsnotify.Write == fsnotify.Write { + + Generate(filename) + } + case err, ok := <-watcher.Errors: + if !ok { + return + } + log.Printf("Error: %v\n", err) + } + } + }() + + fmt.Println("Observing changes...") + <-done +} diff --git a/internal/config/generator.go b/internal/config/generator.go index 7694b1c..405efff 100644 --- a/internal/config/generator.go +++ b/internal/config/generator.go @@ -30,3 +30,22 @@ func GenerateNginxConfig(subdomains []Subdomain) error { return nil } + +func Generate(configPath *string) { + + if CheckFileExistence(*configPath) { + + subdomains, err := LoadConfig(configPath) + + if err != nil { + log.Fatalf("Error loading configuration: %v", err) + } + + if err := GenerateNginxConfig(subdomains); err != nil { + log.Fatalf("Error generating config: %v", err) + } + } else { + fmt.Println("Please provide the path to the configuration file with --config.") + os.Exit(1) + } +} diff --git a/main.go b/main.go index 351d088..8495813 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "log" "os" "github.com/njavilas2015/qlub/internal/config" @@ -12,26 +11,17 @@ var version = "1.0.0" func main() { - showVersion, configPath := config.ParseFlags() + showVersion, configPath, watcher := config.ParseFlags() if *showVersion { fmt.Printf("Versión: %s\n", version) os.Exit(0) } - if config.CheckFileExistence(*configPath) { - - subdomains, err := config.LoadConfig(configPath) - - if err != nil { - log.Fatalf("Error al cargar la configuración: %v", err) - } - - if err := config.GenerateNginxConfig(subdomains); err != nil { - log.Fatalf("Error generating config: %v", err) - } + if *watcher { + config.Watcher(configPath) } else { - fmt.Println("Por favor proporciona la ruta al archivo de configuración con --config.") - os.Exit(1) + config.Generate(configPath) } + } diff --git a/subdomains.json b/subdomains.json index 661f159..01127bd 100644 --- a/subdomains.json +++ b/subdomains.json @@ -3,7 +3,7 @@ "name": "gestion.onbbu.ar", "port": "3000", "instances": [ - "192.168.1.101", + "192.168.10.101", "192.168.1.102", "192.168.1.103", "192.168.1.104",