// Copyright (C) The Arvados Authors. All rights reserved. // // SPDX-License-Identifier: AGPL-3.0 package keepstore import ( "context" "encoding/json" "net/http" . "gopkg.in/check.v1" ) func (s *routerSuite) TestMounts(c *C) { router, cancel := testRouter(c, s.cluster, nil) defer cancel() router.keepstore.mountsW[0].BlockWrite(context.Background(), fooHash, []byte("foo")) router.keepstore.mountsW[1].BlockWrite(context.Background(), barHash, []byte("bar")) resp := call(router, "GET", "/mounts", s.cluster.SystemRootToken, nil, nil) c.Check(resp.Code, Equals, http.StatusOK) c.Log(resp.Body.String()) var mntList []struct { UUID string `json:"uuid"` DeviceID string `json:"device_id"` ReadOnly bool `json:"read_only"` Replication int `json:"replication"` StorageClasses map[string]bool `json:"storage_classes"` } err := json.Unmarshal(resp.Body.Bytes(), &mntList) c.Assert(err, IsNil) c.Assert(mntList, HasLen, 2) for _, m := range mntList { c.Check(len(m.UUID), Equals, 27) c.Check(m.UUID[:12], Equals, "zzzzz-nyw5e-") c.Check(m.DeviceID, Matches, "0x[0-9a-f]+") c.Check(m.ReadOnly, Equals, false) c.Check(m.Replication, Equals, 1) c.Check(m.StorageClasses, HasLen, 1) for k := range m.StorageClasses { c.Check(k, Matches, "testclass.*") } } c.Check(mntList[0].UUID, Not(Equals), mntList[1].UUID) c.Logf("=== bad auth") for _, tok := range []string{"", "xyzzy"} { resp = call(router, "GET", "/mounts/"+mntList[1].UUID+"/blocks", tok, nil, nil) if tok == "" { c.Check(resp.Code, Equals, http.StatusUnauthorized) c.Check(resp.Body.String(), Equals, "Unauthorized\n") } else { c.Check(resp.Code, Equals, http.StatusForbidden) c.Check(resp.Body.String(), Equals, "Forbidden\n") } } c.Logf("=== nonexistent mount UUID") resp = call(router, "GET", "/mounts/X/blocks", s.cluster.SystemRootToken, nil, nil) c.Check(resp.Code, Equals, http.StatusNotFound) c.Logf("=== complete index of first mount") resp = call(router, "GET", "/mounts/"+mntList[0].UUID+"/blocks", s.cluster.SystemRootToken, nil, nil) c.Check(resp.Code, Equals, http.StatusOK) c.Check(resp.Body.String(), Matches, fooHash+`\+[0-9]+ [0-9]+\n\n`) c.Logf("=== partial index of first mount (one block matches prefix)") resp = call(router, "GET", "/mounts/"+mntList[0].UUID+"/blocks?prefix="+fooHash[:2], s.cluster.SystemRootToken, nil, nil) c.Check(resp.Code, Equals, http.StatusOK) c.Check(resp.Body.String(), Matches, fooHash+`\+[0-9]+ [0-9]+\n\n`) c.Logf("=== complete index of second mount (note trailing slash)") resp = call(router, "GET", "/mounts/"+mntList[1].UUID+"/blocks/", s.cluster.SystemRootToken, nil, nil) c.Check(resp.Code, Equals, http.StatusOK) c.Check(resp.Body.String(), Matches, barHash+`\+[0-9]+ [0-9]+\n\n`) c.Logf("=== partial index of second mount (no blocks match prefix)") resp = call(router, "GET", "/mounts/"+mntList[1].UUID+"/blocks/?prefix="+fooHash[:2], s.cluster.SystemRootToken, nil, nil) c.Check(resp.Code, Equals, http.StatusOK) c.Check(resp.Body.String(), Equals, "\n") }