feat(config): improve configuration flags

This commit is contained in:
Nicolas Carlier 2018-07-23 08:33:18 +00:00 committed by Nicolas Carlier
parent d9158c7ef5
commit fbf8794d0a
5 changed files with 79 additions and 36 deletions

View File

@ -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 <address>` | `:8080` | HTTP service address |
| `-n <workers>` | `2` | The number of workers to start |
| `-d` | false | Output debug logs |
| `-l | --listen <address>` | `:8080` | HTTP service address |
| `-d | --debug` | false | Output debug logs |
| `--nb-workers <workers>` | `2` | The number of workers to start |
| `--scripts <dir>` | `./scripts` | Scripts directory |
| `--timeout <timeout>` | `10` | Hook maximum delay before timeout (in second) |
## Usage

52
config.go Normal file
View File

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

20
main.go
View File

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

View File

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

View File

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