diff --git a/README.md b/README.md index 2fabb94..01d104a 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,8 @@ You can configure the daemon by: | Variable | Default | Description | |----------|---------|-------------| +| `APP_LISTEN_ADDR` | `:8080` | HTTP service address | +| `APP_NB_WORKERS` | `2` | The number of workers to start | | `APP_HOOK_TIMEOUT` | `10` | Hook maximum delay before timeout (in second) | | `APP_SCRIPTS_DIR` | `./scripts` | Scripts directory | | `APP_SCRIPTS_GIT_URL` | none | GIT repository that contains scripts (Note: this is only used by the Docker image or by using the Docker entrypoint script) | @@ -52,14 +54,17 @@ You can configure the daemon by: | `APP_NOTIFIER_TO` | none | Recipient of the notification | | `APP_HTTP_NOTIFIER_URL` | none | URL of the HTTP notifier | | `APP_SMTP_NOTIFIER_HOST` | none | Hostname of the SMTP relay | +| `APP_DEBUG` | `false` | Output debug logs | ### Using command parameters: | Parameter | Default | Description | |----------|---------|-------------| -| `-l
` | `:8080` | HTTP service address | -| `-n ` | `2` | The number of workers to start | -| `-d` | false | Output debug logs | +| `-l | --listen
` | `:8080` | HTTP service address | +| `-d | --debug` | false | Output debug logs | +| `--nb-workers ` | `2` | The number of workers to start | +| `--scripts ` | `./scripts` | Scripts directory | +| `--timeout ` | `10` | Hook maximum delay before timeout (in second) | ## Usage diff --git a/config.go b/config.go new file mode 100644 index 0000000..c101f24 --- /dev/null +++ b/config.go @@ -0,0 +1,52 @@ +package main + +import ( + "flag" + "os" + "strconv" +) + +// Config contain global configuration +type Config struct { + ListenAddr *string + NbWorkers *int + Debug *bool + Timeout *int + ScriptDir *string +} + +var config = &Config{ + ListenAddr: flag.String("listen", getEnv("LISTEN_ADDR", ":8080"), "HTTP service address (e.g.address, ':8080')"), + NbWorkers: flag.Int("nb-workers", getIntEnv("NB_WORKERS", 2), "The number of workers to start"), + Debug: flag.Bool("debug", getBoolEnv("DEBUG", false), "Output debug logs"), + Timeout: flag.Int("timeout", getIntEnv("HOOK_TIMEOUT", 10), "Hook maximum delay before timeout (in second)"), + ScriptDir: flag.String("scripts", getEnv("SCRIPTS_DIR", "scripts"), "Scripts directory"), +} + +func init() { + flag.StringVar(config.ListenAddr, "l", *config.ListenAddr, "HTTP service (e.g address: ':8080')") + flag.BoolVar(config.Debug, "d", *config.Debug, "Output debug logs") +} + +func getEnv(key, fallback string) string { + if value, ok := os.LookupEnv("APP_" + key); ok { + return value + } + return fallback +} + +func getIntEnv(key string, fallback int) int { + strValue := getEnv(key, strconv.Itoa(fallback)) + if value, err := strconv.Atoi(strValue); err == nil { + return value + } + return fallback +} + +func getBoolEnv(key string, fallback bool) bool { + strValue := getEnv(key, strconv.FormatBool(fallback)) + if value, err := strconv.ParseBool(strValue); err == nil { + return value + } + return fallback +} diff --git a/main.go b/main.go index 4a392bb..0f0bb97 100644 --- a/main.go +++ b/main.go @@ -29,17 +29,11 @@ var ( healthy int32 ) -var ( - listenAddr = flag.String("l", ":8080", "HTTP service address (e.g.address, ':8080')") - nbWorkers = flag.Int("n", 2, "The number of workers to start") - debug = flag.Bool("d", false, "Output debug logs") -) - func main() { flag.Parse() level := "info" - if *debug { + if *config.Debug { level = "debug" } logger.Init(level) @@ -47,7 +41,7 @@ func main() { logger.Debug.Println("Starting webhookd server...") router := http.NewServeMux() - router.Handle("/", api.Index()) + router.Handle("/", api.Index(*config.Timeout, *config.ScriptDir)) router.Handle("/healthz", healthz()) nextRequestID := func() string { @@ -55,14 +49,14 @@ func main() { } server := &http.Server{ - Addr: *listenAddr, + Addr: *config.ListenAddr, Handler: tracing(nextRequestID)(logging(logger.Debug)(router)), ErrorLog: logger.Error, } // Start the dispatcher. - logger.Debug.Printf("Starting the dispatcher (%d workers)...\n", *nbWorkers) - worker.StartDispatcher(*nbWorkers) + logger.Debug.Printf("Starting the dispatcher (%d workers)...\n", *config.NbWorkers) + worker.StartDispatcher(*config.NbWorkers) done := make(chan bool) quit := make(chan os.Signal, 1) @@ -83,10 +77,10 @@ func main() { close(done) }() - logger.Info.Println("Server is ready to handle requests at", *listenAddr) + logger.Info.Println("Server is ready to handle requests at", *config.ListenAddr) atomic.StoreInt32(&healthy, 1) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { - logger.Error.Fatalf("Could not listen on %s: %v\n", *listenAddr, err) + logger.Error.Fatalf("Could not listen on %s: %v\n", *config.ListenAddr, err) } <-done diff --git a/pkg/api/api.go b/pkg/api/api.go index 2a6747d..8eb2e68 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -4,30 +4,30 @@ import ( "fmt" "io/ioutil" "net/http" - "os" "strconv" "strings" - "github.com/ncarlier/webhookd/pkg/hook" "github.com/ncarlier/webhookd/pkg/logger" "github.com/ncarlier/webhookd/pkg/tools" "github.com/ncarlier/webhookd/pkg/worker" ) var ( - defaultTimeout = atoiFallback(os.Getenv("APP_HOOK_TIMEOUT"), 10) + defaultTimeout int + scriptDir string ) func atoiFallback(str string, fallback int) int { - value, err := strconv.Atoi(str) - if err != nil || value < 0 { - return fallback + if value, err := strconv.Atoi(str); err == nil && value > 0 { + return value } - return value + return fallback } // Index is the main handler of the API. -func Index() http.Handler { +func Index(timeout int, scrDir string) http.Handler { + defaultTimeout = timeout + scriptDir = scrDir return http.HandlerFunc(webhookHandler) } @@ -45,7 +45,7 @@ func webhookHandler(w http.ResponseWriter, r *http.Request) { // Get script location p := strings.TrimPrefix(r.URL.Path, "/") - script, err := hook.ResolveScript(p) + script, err := tools.ResolveScript(scriptDir, p) if err != nil { logger.Error.Println(err.Error()) http.Error(w, err.Error(), http.StatusNotFound) diff --git a/pkg/hook/script.go b/pkg/tools/script_resolver.go similarity index 59% rename from pkg/hook/script.go rename to pkg/tools/script_resolver.go index 7a58fcd..d73a83a 100644 --- a/pkg/hook/script.go +++ b/pkg/tools/script_resolver.go @@ -1,4 +1,4 @@ -package hook +package tools import ( "errors" @@ -9,17 +9,9 @@ import ( "github.com/ncarlier/webhookd/pkg/logger" ) -var ( - scriptsdir = os.Getenv("APP_SCRIPTS_DIR") -) - // ResolveScript is resolving the target script. -func ResolveScript(p string) (string, error) { - if scriptsdir == "" { - scriptsdir = "scripts" - } - - script := path.Join(scriptsdir, fmt.Sprintf("%s.sh", p)) +func ResolveScript(dir, name string) (string, error) { + script := path.Join(dir, fmt.Sprintf("%s.sh", name)) logger.Debug.Println("Resolving script: ", script, "...") if _, err := os.Stat(script); os.IsNotExist(err) { return "", errors.New("Script not found: " + script)