diff --git a/gateway/Dockerfile.build b/gateway/Dockerfile.build index 7e719e2387435b4109a59a08f58f94135ac7a2dc..76536426fcdfb0fd39b908cc9e4d16b0d3465bff 100644 --- a/gateway/Dockerfile.build +++ b/gateway/Dockerfile.build @@ -10,13 +10,16 @@ FROM golang:1.7.5 WORKDIR /go/src/github.com/alexellis/faas/gateway -COPY vendor vendor +COPY vendor vendor -COPY handlers handlers -COPY metrics metrics -COPY requests requests -COPY tests tests -COPY server.go . +COPY handlers handlers +COPY metrics metrics +COPY requests requests +COPY tests tests +COPY server.go . +COPY readconfig.go . +COPY config_test.go . -RUN go test -v ./tests && \ +RUN go test && \ + go test -v ./tests && \ CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . diff --git a/gateway/Dockerfile.build.armhf b/gateway/Dockerfile.build.armhf index 748cff21d2b32d6038add5da974bcfa9efa1953b..6facfaeca2806e8cf3450030b7b7149656954055 100644 --- a/gateway/Dockerfile.build.armhf +++ b/gateway/Dockerfile.build.armhf @@ -10,12 +10,15 @@ RUN go get -d github.com/Sirupsen/logrus WORKDIR /go/src/github.com/alexellis/faas/gateway -COPY metrics metrics -COPY requests requests -COPY tests tests -COPY handlers handlers +COPY metrics metrics +COPY requests requests +COPY tests tests +COPY handlers handlers -COPY server.go . +COPY server.go . +COPY readconfig.go . +COPY config_test.go . -RUN go test -v ./tests && \ +RUN go test && \ + go test -v ./tests && \ CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . diff --git a/gateway/Dockerfile.multistage b/gateway/Dockerfile.multistage index 561492f5d60ac9814c8697c671296956e8e81644..b4cf782d950d362dda724fb3928221a9ddbad6fc 100644 --- a/gateway/Dockerfile.multistage +++ b/gateway/Dockerfile.multistage @@ -1,13 +1,15 @@ FROM golang:1.7.5 WORKDIR /go/src/github.com/alexellis/faas/gateway -COPY vendor vendor - -COPY handlers handlers -COPY metrics metrics -COPY requests requests -COPY tests tests -COPY server.go . +COPY vendor vendor + +COPY handlers handlers +COPY metrics metrics +COPY requests requests +COPY tests tests +COPY server.go . +COPY readconfig.go . +COPY config_test.go . RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o gateway . diff --git a/gateway/Dockerfile.newbuild b/gateway/Dockerfile.newbuild index 44a10d726985cc7858372f9e7075cc86af59aaf5..1effa537edb403bc689519e31520938500143a8e 100644 --- a/gateway/Dockerfile.newbuild +++ b/gateway/Dockerfile.newbuild @@ -2,13 +2,15 @@ FROM golang:1.7.5 # RUN mkdir -p /go/src/github.com/alexellis/faas/gateway WORKDIR /go/src/github.com/alexellis/faas/gateway -COPY vendor vendor +COPY vendor vendor -COPY handlers handlers -COPY metrics metrics -COPY requests requests -COPY tests tests -COPY server.go . +COPY handlers handlers +COPY metrics metrics +COPY requests requests +COPY tests tests +COPY server.go . +COPY readconfig.go . +COPY config_test.go . RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o gateway . diff --git a/gateway/config_test.go b/gateway/config_test.go new file mode 100644 index 0000000000000000000000000000000000000000..588be9fa28f6316f73ed2741424c818871765a14 --- /dev/null +++ b/gateway/config_test.go @@ -0,0 +1,61 @@ +// Copyright (c) Alex Ellis 2017. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +package main + +import ( + "testing" + "time" +) + +type EnvBucket struct { + Items map[string]string +} + +func NewEnvBucket() EnvBucket { + return EnvBucket{ + Items: make(map[string]string), + } +} + +func (e EnvBucket) Getenv(key string) string { + return e.Items[key] +} + +func (e EnvBucket) Setenv(key string, value string) { + e.Items[key] = value +} + +func TestRead_EmptyTimeoutConfig(t *testing.T) { + defaults := NewEnvBucket() + readConfig := ReadConfig{} + + config := readConfig.Read(defaults) + + if (config.readTimeout) != time.Duration(8)*time.Second { + t.Log("readTimeout incorrect") + t.Fail() + } + if (config.writeTimeout) != time.Duration(8)*time.Second { + t.Log("writeTimeout incorrect") + t.Fail() + } +} + +func TestRead_ReadAndWriteTimeoutConfig(t *testing.T) { + defaults := NewEnvBucket() + defaults.Setenv("read_timeout", "10") + defaults.Setenv("write_timeout", "60") + + readConfig := ReadConfig{} + config := readConfig.Read(defaults) + + if (config.readTimeout) != time.Duration(10)*time.Second { + t.Logf("readTimeout incorrect, got: %d\n", config.readTimeout) + t.Fail() + } + if (config.writeTimeout) != time.Duration(60)*time.Second { + t.Logf("writeTimeout incorrect, got: %d\n", config.writeTimeout) + t.Fail() + } +} diff --git a/gateway/readconfig.go b/gateway/readconfig.go new file mode 100644 index 0000000000000000000000000000000000000000..c91dfd4813918c65f193066f5a8b74fb52181f16 --- /dev/null +++ b/gateway/readconfig.go @@ -0,0 +1,61 @@ +package main + +import ( + "os" + "strconv" + "time" +) + +// OsEnv implements interface to wrap os.Getenv +type OsEnv struct { +} + +// Getenv wraps os.Getenv +func (OsEnv) Getenv(key string) string { + return os.Getenv(key) +} + +// HasEnv provides interface for os.Getenv +type HasEnv interface { + Getenv(key string) string +} + +// ReadConfig constitutes config from env variables +type ReadConfig struct { +} + +func parseBoolValue(val string) bool { + if val == "true" { + return true + } + return false +} + +func parseIntValue(val string, fallback int) int { + if len(val) > 0 { + parsedVal, parseErr := strconv.Atoi(val) + if parseErr == nil && parsedVal >= 0 { + return parsedVal + } + } + return fallback +} + +// Read fetches config from environmental variables. +func (ReadConfig) Read(hasEnv HasEnv) GatewayConfig { + cfg := GatewayConfig{} + + readTimeout := parseIntValue(hasEnv.Getenv("read_timeout"), 8) + writeTimeout := parseIntValue(hasEnv.Getenv("write_timeout"), 8) + + cfg.readTimeout = time.Duration(readTimeout) * time.Second + cfg.writeTimeout = time.Duration(writeTimeout) * time.Second + + return cfg +} + +// GatewayConfig for the process. +type GatewayConfig struct { + readTimeout time.Duration + writeTimeout time.Duration +} diff --git a/gateway/server.go b/gateway/server.go index b011e1cc6685d1e65d6c09f516a25e798e2ec48d..2840706a782574d83aba82a0648ff34e581fd440 100644 --- a/gateway/server.go +++ b/gateway/server.go @@ -4,7 +4,6 @@ import ( "context" "log" "net/http" - "time" "github.com/Sirupsen/logrus" faasHandlers "github.com/alexellis/faas/gateway/handlers" @@ -20,6 +19,13 @@ func main() { logger := logrus.Logger{} logrus.SetFormatter(&logrus.TextFormatter{}) + osEnv := OsEnv{} + readConfig := ReadConfig{} + config := readConfig.Read(osEnv) + + log.Printf("HTTP Read Timeout: %s", config.readTimeout) + log.Printf("HTTP Write Timeout: %s", config.writeTimeout) + var dockerClient *client.Client var err error dockerClient, err = client.NewEnvClient() @@ -30,7 +36,7 @@ func main() { if err != nil { log.Fatal("Error with Docker server.\n", err) } - log.Printf("API version: %s, %s\n", dockerVersion.APIVersion, dockerVersion.Version) + log.Printf("Docker API version: %s, %s\n", dockerVersion.APIVersion, dockerVersion.Version) metricsOptions := metrics.BuildMetricsOptions() metrics.RegisterMetrics(metricsOptions) @@ -61,14 +67,12 @@ func main() { r.Handle("/", http.RedirectHandler("/ui/", http.StatusMovedPermanently)).Methods("GET") - readTimeout := 8 * time.Second - writeTimeout := 8 * time.Second tcpPort := 8080 s := &http.Server{ Addr: fmt.Sprintf(":%d", tcpPort), - ReadTimeout: readTimeout, - WriteTimeout: writeTimeout, + ReadTimeout: config.readTimeout, + WriteTimeout: config.writeTimeout, MaxHeaderBytes: http.DefaultMaxHeaderBytes, // 1MB - can be overridden by setting Server.MaxHeaderBytes. Handler: r, }