Merge branch 'wtsi/13809-root_url-protocol-port-configuration'
[arvados.git] / services / keepstore / handlers.go
index bd88acb5a914a67d79bf7b423952bf175ec267bd..c31ab9c2e38fde497f451e95c2a99437735e4455 100644 (file)
@@ -1,3 +1,7 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
 package main
 
 // REST handlers for Keep are implemented here.
@@ -25,8 +29,8 @@ import (
 
        "github.com/gorilla/mux"
 
+       "git.curoverse.com/arvados.git/sdk/go/health"
        "git.curoverse.com/arvados.git/sdk/go/httpserver"
-       log "github.com/Sirupsen/logrus"
 )
 
 type router struct {
@@ -36,49 +40,57 @@ type router struct {
 
 // MakeRESTRouter returns a new router that forwards all Keep requests
 // to the appropriate handlers.
-func MakeRESTRouter() *router {
-       rest := mux.NewRouter()
-       rtr := &router{Router: rest}
+func MakeRESTRouter() http.Handler {
+       rtr := &router{Router: mux.NewRouter()}
 
-       rest.HandleFunc(
+       rtr.HandleFunc(
                `/{hash:[0-9a-f]{32}}`, GetBlockHandler).Methods("GET", "HEAD")
-       rest.HandleFunc(
+       rtr.HandleFunc(
                `/{hash:[0-9a-f]{32}}+{hints}`,
                GetBlockHandler).Methods("GET", "HEAD")
 
-       rest.HandleFunc(`/{hash:[0-9a-f]{32}}`, PutBlockHandler).Methods("PUT")
-       rest.HandleFunc(`/{hash:[0-9a-f]{32}}`, DeleteHandler).Methods("DELETE")
+       rtr.HandleFunc(`/{hash:[0-9a-f]{32}}`, PutBlockHandler).Methods("PUT")
+       rtr.HandleFunc(`/{hash:[0-9a-f]{32}}`, DeleteHandler).Methods("DELETE")
        // List all blocks stored here. Privileged client only.
-       rest.HandleFunc(`/index`, rtr.IndexHandler).Methods("GET", "HEAD")
+       rtr.HandleFunc(`/index`, rtr.IndexHandler).Methods("GET", "HEAD")
        // List blocks stored here whose hash has the given prefix.
        // Privileged client only.
-       rest.HandleFunc(`/index/{prefix:[0-9a-f]{0,32}}`, rtr.IndexHandler).Methods("GET", "HEAD")
+       rtr.HandleFunc(`/index/{prefix:[0-9a-f]{0,32}}`, rtr.IndexHandler).Methods("GET", "HEAD")
 
        // Internals/debugging info (runtime.MemStats)
-       rest.HandleFunc(`/debug.json`, rtr.DebugHandler).Methods("GET", "HEAD")
+       rtr.HandleFunc(`/debug.json`, rtr.DebugHandler).Methods("GET", "HEAD")
 
        // List volumes: path, device number, bytes used/avail.
-       rest.HandleFunc(`/status.json`, rtr.StatusHandler).Methods("GET", "HEAD")
+       rtr.HandleFunc(`/status.json`, rtr.StatusHandler).Methods("GET", "HEAD")
 
        // List mounts: UUID, readonly, tier, device ID, ...
-       rest.HandleFunc(`/mounts`, rtr.MountsHandler).Methods("GET")
-       rest.HandleFunc(`/mounts/{uuid}/blocks`, rtr.IndexHandler).Methods("GET")
-       rest.HandleFunc(`/mounts/{uuid}/blocks/`, rtr.IndexHandler).Methods("GET")
+       rtr.HandleFunc(`/mounts`, rtr.MountsHandler).Methods("GET")
+       rtr.HandleFunc(`/mounts/{uuid}/blocks`, rtr.IndexHandler).Methods("GET")
+       rtr.HandleFunc(`/mounts/{uuid}/blocks/`, rtr.IndexHandler).Methods("GET")
 
        // Replace the current pull queue.
-       rest.HandleFunc(`/pull`, PullHandler).Methods("PUT")
+       rtr.HandleFunc(`/pull`, PullHandler).Methods("PUT")
 
        // Replace the current trash queue.
-       rest.HandleFunc(`/trash`, TrashHandler).Methods("PUT")
+       rtr.HandleFunc(`/trash`, TrashHandler).Methods("PUT")
 
        // Untrash moves blocks from trash back into store
-       rest.HandleFunc(`/untrash/{hash:[0-9a-f]{32}}`, UntrashHandler).Methods("PUT")
+       rtr.HandleFunc(`/untrash/{hash:[0-9a-f]{32}}`, UntrashHandler).Methods("PUT")
+
+       rtr.Handle("/_health/{check}", &health.Handler{
+               Token:  theConfig.ManagementToken,
+               Prefix: "/_health/",
+       }).Methods("GET")
 
        // Any request which does not match any of these routes gets
        // 400 Bad Request.
-       rest.NotFoundHandler = http.HandlerFunc(BadRequestHandler)
+       rtr.NotFoundHandler = http.HandlerFunc(BadRequestHandler)
+
+       rtr.limiter = httpserver.NewRequestLimiter(theConfig.MaxRequests, rtr)
 
-       return rtr
+       stack := httpserver.Instrument(nil, nil,
+               httpserver.AddRequestIDs(httpserver.LogRequests(nil, rtr.limiter)))
+       return stack.ServeAPI(stack)
 }
 
 // BadRequestHandler is a HandleFunc to address bad requests.
@@ -281,7 +293,7 @@ func (rtr *router) MountsHandler(resp http.ResponseWriter, req *http.Request) {
 
 // PoolStatus struct
 type PoolStatus struct {
-       Alloc uint64 `json:"BytesAllocated"`
+       Alloc uint64 `json:"BytesAllocatedCumulative"`
        Cap   int    `json:"BuffersMax"`
        Len   int    `json:"BuffersInUse"`
 }
@@ -301,6 +313,7 @@ type NodeStatus struct {
        TrashQueue      WorkQueueStatus
        RequestsCurrent int
        RequestsMax     int
+       Version         string
 }
 
 var st NodeStatus
@@ -336,6 +349,7 @@ func (rtr *router) StatusHandler(resp http.ResponseWriter, req *http.Request) {
 
 // populate the given NodeStatus struct with current values.
 func (rtr *router) readNodeStatus(st *NodeStatus) {
+       st.Version = version
        vols := KeepVM.AllReadable()
        if cap(st.Volumes) < len(vols) {
                st.Volumes = make([]*volumeStatusEnt, len(vols))
@@ -494,7 +508,7 @@ type PullRequest struct {
        Servers []string `json:"servers"`
 
        // Destination mount, or "" for "anywhere"
-       MountUUID string
+       MountUUID string `json:"mount_uuid"`
 }
 
 // PullHandler processes "PUT /pull" requests for the data manager.
@@ -527,13 +541,13 @@ func PullHandler(resp http.ResponseWriter, req *http.Request) {
        pullq.ReplaceQueue(plist)
 }
 
-// TrashRequest consists of a block locator and it's Mtime
+// TrashRequest consists of a block locator and its Mtime
 type TrashRequest struct {
        Locator    string `json:"locator"`
        BlockMtime int64  `json:"block_mtime"`
 
        // Target mount, or "" for "everywhere"
-       MountUUID string
+       MountUUID string `json:"mount_uuid"`
 }
 
 // TrashHandler processes /trash requests.