Added webserver tests

This commit is contained in:
2022-04-06 12:46:02 +02:00
parent 16c5e37a8c
commit 3492884cb1
8 changed files with 449 additions and 136 deletions
+27 -17
View File
@@ -5,7 +5,7 @@ import (
"net/http"
"time"
"github.com/go-chi/chi"
"github.com/go-chi/render"
log "scm.yoorie.de/go-lib/gelf"
)
@@ -16,6 +16,7 @@ type healthChecker struct {
message string
healthy bool
lastChecked time.Time
startTime time.Time
period int
ticker *time.Ticker
done chan bool
@@ -23,9 +24,15 @@ type healthChecker struct {
checkFunc func() (bool, string)
}
type HealthData struct {
Message string `json:"message,omitempty"`
LastChecked time.Time `json:"lastChecked"`
}
func newHealthChecker(checkFunction func() (bool, string)) *healthChecker {
hc := &healthChecker{}
hc.checkFunc = checkFunction
hc.startTime = time.Now()
return hc
}
@@ -66,40 +73,43 @@ func (h *healthChecker) doCheck() {
h.lastChecked = time.Now()
}
// Routes add routes for liveness and readyness probes
/* Routes add routes for liveness and readyness probes
func (h *healthChecker) Routes() *chi.Mux {
router := chi.NewRouter()
router.Get("/healthz", h.healthyEndpoint)
router.Get("/readyz", h.readinessEndpoint)
return router
}
}*/
/*
GetHealthyEndpoint is this service healthy
*/
func (h *healthChecker) healthyEndpoint(response http.ResponseWriter, req *http.Request) {
func (h *healthChecker) healthyEndpoint(responseWriter http.ResponseWriter, request *http.Request) {
t := time.Now()
status := http.StatusOK
healtData := &HealthData{
Message: "service up and running",
LastChecked: h.lastChecked,
}
if t.Sub(h.lastChecked) > (time.Second * time.Duration(2*h.period)) {
h.healthy = false
h.message = "Healthcheck not running"
}
response.Header().Add("Content-Type", "application/json")
if h.healthy {
response.WriteHeader(http.StatusOK)
message := fmt.Sprintf(`{ "message": "service up and running", "lastCheck": "%s" }`, h.lastChecked.String())
response.Write([]byte(message))
} else {
response.WriteHeader(http.StatusServiceUnavailable)
message := fmt.Sprintf(`{ "message": "service is unavailable: %s", "lastCheck": "%s" }`, h.message, h.lastChecked.String())
response.Write([]byte(message))
if !h.healthy {
status = http.StatusServiceUnavailable
healtData.Message = fmt.Sprintf("service is unavailable: %s", h.message)
}
responseWriter.WriteHeader(status)
render.JSON(responseWriter, request, healtData)
}
/*
GetReadinessEndpoint is this service ready for taking requests
*/
func (h *healthChecker) readinessEndpoint(response http.ResponseWriter, req *http.Request) {
response.Header().Add("Content-Type", "application/json")
response.WriteHeader(http.StatusOK)
response.Write([]byte(`{ "message": "service started" }`))
func (h *healthChecker) readinessEndpoint(responseWriter http.ResponseWriter, request *http.Request) {
render.JSON(responseWriter, request, &HealthData{
Message: "service is ready",
LastChecked: h.startTime,
})
}
+38 -14
View File
@@ -4,6 +4,7 @@ import (
"compress/flate"
"context"
"crypto/tls"
"errors"
"fmt"
"net/http"
"os"
@@ -11,6 +12,7 @@ import (
"strconv"
"time"
"github.com/creasty/defaults"
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
"github.com/go-chi/cors"
@@ -21,11 +23,11 @@ import (
type WebServerConfiguration struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
Port int `default:"7080" yaml:"port"`
SslPort int `yaml:"sslport"`
SslCert string `yaml:"sslcert"`
SslKey string `yaml:"sslkey"`
HealthCheckPeriod int `yaml:"healthcheckperiod"`
HealthCheckPeriod int `default:"30" yaml:"healthcheckperiod"`
CertificateGenerationParams TLSCertificateGenerationParams `yaml:"tlsgenerationparams"`
}
@@ -39,7 +41,6 @@ type WebServer struct {
serviceConfig *WebServerConfiguration
sslsrv *http.Server
srv *http.Server
ssl bool
healthChecker *healthChecker
router *chi.Mux
healthRouter *chi.Mux
@@ -47,6 +48,17 @@ type WebServer struct {
HealthCheck func() (bool, string)
}
func NewWebServer(config *WebServerConfiguration) (*WebServer, error) {
if config == nil {
return nil, errors.New("config may not be null")
}
defaults.Set(config)
return &WebServer{
serviceConfig: config,
mounts: make(map[string]http.Handler),
}, nil
}
func (server *WebServer) healthRoutes() *chi.Mux {
compressor := middleware.NewCompressor(flate.DefaultCompression)
router := chi.NewRouter()
@@ -55,10 +67,15 @@ func (server *WebServer) healthRoutes() *chi.Mux {
compressor.Handler,
middleware.Recoverer,
)
router.Mount("/", server.healthChecker.Routes())
router.Get("/healthz", server.healthChecker.healthyEndpoint)
router.Get("/readyz", server.healthChecker.readinessEndpoint)
return router
}
func (server *WebServer) isSsl() bool {
return server.serviceConfig.SslPort > 0
}
func (server *WebServer) Mount(pattern string, handler http.Handler) {
server.mounts[pattern] = handler
}
@@ -83,6 +100,8 @@ func (server *WebServer) routes() *chi.Mux {
for pattern, handler := range server.mounts {
router.Mount(pattern, handler)
}
// clean map
server.mounts = make(map[string]http.Handler)
return router
}
@@ -157,22 +176,27 @@ func (server *WebServer) performHealthCheck() (bool, string) {
return true, ""
}
func (server *WebServer) Start(config *WebServerConfiguration) error {
server.serviceConfig = config
hc := newHealthChecker(server.performHealthCheck)
hc.start(config.HealthCheckPeriod)
func (server *WebServer) Start() error {
if server.serviceConfig == nil {
return errors.New("use NewWebServer(config) for initialising the web server")
}
if len(server.mounts) == 0 {
return errors.New("No mounts points added")
}
server.ssl = server.serviceConfig.SslPort > 0
if server.ssl {
server.healthChecker = newHealthChecker(server.performHealthCheck)
server.healthChecker.start(server.serviceConfig.HealthCheckPeriod)
ssl := server.isSsl()
if ssl {
log.Debugf("Running in SSL mode")
}
server.router = server.routes()
server.healthRouter = server.healthRoutes()
server.router = server.routes()
server.DebugRoutes("Main", server.router)
server.DebugRoutes("Health", server.healthRouter)
if server.ssl {
if ssl {
err := server.setupSsl()
if err != nil {
return err
@@ -268,7 +292,7 @@ func (server *WebServer) Stop() {
log.Info("Shutting down server ...")
server.srv.Shutdown(ctx)
if server.ssl {
if server.isSsl() {
server.sslsrv.Shutdown(ctx)
}
log.Info("Server has been shutted down")