[ARVADOS] created: 436613a082fbce366ba9f588796f95a113c7d244
Git user
git at public.curoverse.com
Fri Jul 14 15:48:46 EDT 2017
at 436613a082fbce366ba9f588796f95a113c7d244 (commit)
commit 436613a082fbce366ba9f588796f95a113c7d244
Author: radhika <radhika at curoverse.com>
Date: Fri Jul 14 15:47:11 2017 -0400
11906: keepstore ping
Arvados-DCO-1.1-Signed-off-by: Radhika Chippada <radhika at curoverse.com>
diff --git a/services/keepstore/config.go b/services/keepstore/config.go
index 19a614a..0a3ece4 100644
--- a/services/keepstore/config.go
+++ b/services/keepstore/config.go
@@ -40,6 +40,8 @@ type Config struct {
blobSigningKey []byte
systemAuthToken string
debugLogf func(string, ...interface{})
+
+ ManagementToken string
}
var theConfig = DefaultConfig()
diff --git a/services/keepstore/handler_test.go b/services/keepstore/handler_test.go
index 751a4a7..7429d7a 100644
--- a/services/keepstore/handler_test.go
+++ b/services/keepstore/handler_test.go
@@ -27,6 +27,7 @@ import (
"time"
"git.curoverse.com/arvados.git/sdk/go/arvados"
+ "git.curoverse.com/arvados.git/sdk/go/arvadostest"
)
// A RequestTester represents the parameters for an HTTP request to
@@ -827,6 +828,18 @@ func IssueRequest(rt *RequestTester) *httptest.ResponseRecorder {
return response
}
+func IssueHealthCheckRequest(rt *RequestTester) *httptest.ResponseRecorder {
+ response := httptest.NewRecorder()
+ body := bytes.NewReader(rt.requestBody)
+ req, _ := http.NewRequest(rt.method, rt.uri, body)
+ if rt.apiToken != "" {
+ req.Header.Set("Authorization", "Bearer "+rt.apiToken)
+ }
+ loggingRouter := MakeRESTRouter()
+ loggingRouter.ServeHTTP(response, req)
+ return response
+}
+
// ExpectStatusCode checks whether a response has the specified status code,
// and reports a test failure if not.
func ExpectStatusCode(
@@ -1140,3 +1153,61 @@ func TestUntrashHandlerWithNoWritableVolumes(t *testing.T) {
http.StatusNotFound,
response)
}
+
+func TestHealthCheckPing(t *testing.T) {
+ defer teardown()
+
+ KeepVM = MakeTestVolumeManager(2)
+ defer KeepVM.Close()
+
+ // ping when disabled
+ theConfig.ManagementToken = ""
+ pingReq := &RequestTester{
+ method: "GET",
+ uri: "/_health/ping",
+ }
+ response := IssueHealthCheckRequest(pingReq)
+ ExpectStatusCode(t,
+ "disabled",
+ http.StatusNotFound,
+ response)
+
+ // ping with no token
+ theConfig.ManagementToken = arvadostest.ManagementToken
+ pingReq = &RequestTester{
+ method: "GET",
+ uri: "/_health/ping",
+ }
+ response = IssueHealthCheckRequest(pingReq)
+ ExpectStatusCode(t,
+ "authorization required",
+ http.StatusUnauthorized,
+ response)
+
+ // ping with wrong token
+ pingReq = &RequestTester{
+ method: "GET",
+ uri: "/_health/ping",
+ apiToken: "youarenotwelcomehere",
+ }
+ response = IssueHealthCheckRequest(pingReq)
+ ExpectStatusCode(t,
+ "authorization error",
+ http.StatusForbidden,
+ response)
+
+ // ping with management token
+ pingReq = &RequestTester{
+ method: "GET",
+ uri: "/_health/ping",
+ apiToken: arvadostest.ManagementToken,
+ }
+ response = IssueHealthCheckRequest(pingReq)
+ ExpectStatusCode(t,
+ "",
+ http.StatusOK,
+ response)
+ if !strings.Contains(response.Body.String(), `{"health":"OK"}`) {
+ t.Errorf("expected response to include %s: got %s", `{"health":"OK"}`, response.Body.String())
+ }
+}
diff --git a/services/keepstore/handlers.go b/services/keepstore/handlers.go
index f197196..5e85ed6 100644
--- a/services/keepstore/handlers.go
+++ b/services/keepstore/handlers.go
@@ -78,6 +78,9 @@ func MakeRESTRouter() *router {
// Untrash moves blocks from trash back into store
rest.HandleFunc(`/untrash/{hash:[0-9a-f]{32}}`, UntrashHandler).Methods("PUT")
+ // Health check ping
+ rest.HandleFunc(`/_health/ping`, HealthCheckPingHandler).Methods("GET")
+
// Any request which does not match any of these routes gets
// 400 Bad Request.
rest.NotFoundHandler = http.HandlerFunc(BadRequestHandler)
@@ -617,6 +620,39 @@ func UntrashHandler(resp http.ResponseWriter, req *http.Request) {
}
}
+var pingResponseOK = map[string]string{"health": "OK"}
+
+// HealthCheckPingHandler processes "GET /_health/ping" requests
+func HealthCheckPingHandler(resp http.ResponseWriter, req *http.Request) {
+ healthCheckDo(resp, req, pingResponseOK)
+}
+
+func healthCheckDo(resp http.ResponseWriter, req *http.Request, v interface{}) {
+ msg, code := healthCheckAuth(resp, req)
+ if msg != "" {
+ http.Error(resp, msg, code)
+ return
+ }
+
+ ok, err := json.Marshal(v)
+ if err != nil {
+ http.Error(resp, err.Error(), 500)
+ }
+
+ resp.Write(ok)
+}
+
+func healthCheckAuth(resp http.ResponseWriter, req *http.Request) (string, int) {
+ if theConfig.ManagementToken == "" {
+ return "disabled", http.StatusNotFound
+ } else if h := req.Header.Get("Authorization"); h == "" {
+ return "authorization required", http.StatusUnauthorized
+ } else if h != "Bearer "+theConfig.ManagementToken {
+ return "authorization error", http.StatusForbidden
+ }
+ return "", 0
+}
+
// GetBlock and PutBlock implement lower-level code for handling
// blocks by rooting through volumes connected to the local machine.
// Once the handler has determined that system policy permits the
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list