From 390f6ac7e3d64cff5848566c7a7334506ad0b970 Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Fri, 16 Mar 2018 22:19:37 +0530 Subject: [PATCH] Add /_/health endpoint to of-watchdog Introduce new endpoint `/_/health` to watchdog for health status of functions which checks for `/tmp/.lock` file Added tests for healthHandler Issues: https://github.com/openfaas/faas/issues/547 Signed-off-by: Vivek Singh --- main.go | 27 ++++++++++++++ requesthandler_test.go | 83 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 requesthandler_test.go diff --git a/main.go b/main.go index 3dd81d3d..9df5ab22 100644 --- a/main.go +++ b/main.go @@ -41,6 +41,7 @@ func main() { } http.HandleFunc("/", requestHandler) + http.HandleFunc("/_/health", makeHealthHandler()) log.Fatal(s.ListenAndServe()) } @@ -223,3 +224,29 @@ func makeHTTPRequestHandler(watchdogConfig config.WatchdogConfig) func(http.Resp } } + +func lockFilePresent() bool { + path := filepath.Join(os.TempDir(), ".lock") + if _, err := os.Stat(path); os.IsNotExist(err) { + return false + } + return true +} + +func makeHealthHandler() func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case http.MethodGet: + if lockFilePresent() == false { + w.WriteHeader(http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) + w.Write([]byte("OK")) + break + default: + w.WriteHeader(http.StatusMethodNotAllowed) + } + } +} diff --git a/requesthandler_test.go b/requesthandler_test.go new file mode 100644 index 00000000..871d1a22 --- /dev/null +++ b/requesthandler_test.go @@ -0,0 +1,83 @@ +package main + +import ( + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "testing" +) + +func TestHealthHandler_StatusOK_LockFilePresent(t *testing.T) { + rr := httptest.NewRecorder() + + present := lockFilePresent() + + if present == false { + if err := lock(); err != nil { + t.Fatal(err) + } + } + + req, err := http.NewRequest(http.MethodGet, "/_/health", nil) + if err != nil { + t.Fatal(err) + } + handler := makeHealthHandler() + handler(rr, req) + + required := http.StatusOK + if status := rr.Code; status != required { + t.Errorf("handler returned wrong status code - want: %v, got: %v", required, status) + } + +} + +func TestHealthHandler_StatusInternalServerError_LockFileNotPresent(t *testing.T) { + rr := httptest.NewRecorder() + + if lockFilePresent() == true { + if err := removeLockFile(); err != nil { + t.Fatal(err) + } + } + + req, err := http.NewRequest(http.MethodGet, "/_/health", nil) + if err != nil { + t.Fatal(err) + } + handler := makeHealthHandler() + handler(rr, req) + + required := http.StatusInternalServerError + if status := rr.Code; status != required { + t.Errorf("handler returned wrong status code - want: %v, got: %v", required, status) + } +} + +func TestHealthHandler_StatusMethodNotAllowed_ForWriteableVerbs(t *testing.T) { + rr := httptest.NewRecorder() + + verbs := []string{http.MethodPost, http.MethodPut, http.MethodDelete} + + for _, verb := range verbs { + req, err := http.NewRequest(verb, "/_/health", nil) + if err != nil { + t.Fatal(err) + } + + handler := makeHealthHandler() + handler(rr, req) + + required := http.StatusMethodNotAllowed + if status := rr.Code; status != required { + t.Errorf("handler returned wrong status code - want: %v, got: %v", required, status) + } + } +} + +func removeLockFile() error { + path := filepath.Join(os.TempDir(), ".lock") + removeErr := os.Remove(path) + return removeErr +}