Merge branch '14287-controller-structure'
[arvados.git] / services / keepproxy / keepproxy.go
index 7baadab9b9356c3e7d5360e75506d90b7dd74c0d..f8aa6c4aa7db3df87e7e598aaa901e8e3e91763c 100644 (file)
@@ -26,10 +26,10 @@ import (
        "git.curoverse.com/arvados.git/sdk/go/health"
        "git.curoverse.com/arvados.git/sdk/go/httpserver"
        "git.curoverse.com/arvados.git/sdk/go/keepclient"
-       log "github.com/Sirupsen/logrus"
        "github.com/coreos/go-systemd/daemon"
        "github.com/ghodss/yaml"
        "github.com/gorilla/mux"
+       log "github.com/sirupsen/logrus"
 )
 
 var version = "dev"
@@ -152,7 +152,7 @@ func main() {
                }
                err = f.Sync()
                if err != nil {
-                       log.Fatal("sync(%s): %s", cfg.PIDFile, err)
+                       log.Fatalf("sync(%s): %s", cfg.PIDFile, err)
                }
        }
 
@@ -274,6 +274,14 @@ func CheckAuthorizationHeader(kc *keepclient.KeepClient, cache *ApiTokenCache, r
        return true, tok
 }
 
+// We need to make a private copy of the default http transport early
+// in initialization, then make copies of our private copy later. It
+// won't be safe to copy http.DefaultTransport itself later, because
+// its private mutexes might have already been used. (Without this,
+// the test suite sometimes panics "concurrent map writes" in
+// net/http.(*Transport).removeIdleConnLocked().)
+var defaultTransport = *(http.DefaultTransport.(*http.Transport))
+
 type proxyHandler struct {
        http.Handler
        *keepclient.KeepClient
@@ -287,7 +295,7 @@ type proxyHandler struct {
 func MakeRESTRouter(enable_get bool, enable_put bool, kc *keepclient.KeepClient, timeout time.Duration, mgmtToken string) http.Handler {
        rest := mux.NewRouter()
 
-       transport := *(http.DefaultTransport.(*http.Transport))
+       transport := defaultTransport
        transport.DialContext = (&net.Dialer{
                Timeout:   keepclient.DefaultConnectTimeout,
                KeepAlive: keepclient.DefaultKeepAlive,
@@ -479,6 +487,15 @@ func (h *proxyHandler) Put(resp http.ResponseWriter, req *http.Request) {
 
        locatorIn := mux.Vars(req)["locator"]
 
+       // Check if the client specified storage classes
+       if req.Header.Get("X-Keep-Storage-Classes") != "" {
+               var scl []string
+               for _, sc := range strings.Split(req.Header.Get("X-Keep-Storage-Classes"), ",") {
+                       scl = append(scl, strings.Trim(sc, " "))
+               }
+               kc.StorageClasses = scl
+       }
+
        _, err = fmt.Sscanf(req.Header.Get("Content-Length"), "%d", &expectLength)
        if err != nil || expectLength < 0 {
                err = LengthRequiredError
@@ -524,7 +541,7 @@ func (h *proxyHandler) Put(resp http.ResponseWriter, req *http.Request) {
        if locatorIn == "" {
                bytes, err2 := ioutil.ReadAll(req.Body)
                if err2 != nil {
-                       _ = errors.New(fmt.Sprintf("Error reading request body: %s", err2))
+                       err = fmt.Errorf("Error reading request body: %s", err2)
                        status = http.StatusInternalServerError
                        return
                }