agent: Support key listing with seperator

This commit is contained in:
Armon Dadgar 2014-04-28 16:55:11 -07:00 committed by Jack Pearkes
parent a325630d7a
commit 790a753d7d
2 changed files with 106 additions and 1 deletions

View File

@ -19,10 +19,21 @@ func (s *HTTPServer) KVSEndpoint(resp http.ResponseWriter, req *http.Request) (i
// Pull out the key name, validation left to each sub-handler
args.Key = strings.TrimPrefix(req.URL.Path, "/v1/kv/")
// Check for a key list
keyList := false
params := req.URL.Query()
if _, ok := params["keys"]; ok {
keyList = true
}
// Switch on the method
switch req.Method {
case "GET":
return s.KVSGet(resp, req, &args)
if keyList {
return s.KVSGetKeys(resp, req, &args)
} else {
return s.KVSGet(resp, req, &args)
}
case "PUT":
return s.KVSPut(resp, req, &args)
case "DELETE":
@ -60,6 +71,38 @@ func (s *HTTPServer) KVSGet(resp http.ResponseWriter, req *http.Request, args *s
return out.Entries, nil
}
// KVSGetKeys handles a GET request for keys
func (s *HTTPServer) KVSGetKeys(resp http.ResponseWriter, req *http.Request, args *structs.KeyRequest) (interface{}, error) {
// Check for a seperator
var sep string
params := req.URL.Query()
if _, ok := params["seperator"]; ok {
sep = params.Get("seperator")
}
// Construct the args
listArgs := structs.KeyListRequest{
Datacenter: args.Datacenter,
Prefix: args.Key,
Seperator: sep,
QueryOptions: args.QueryOptions,
}
// Make the RPC
var out structs.IndexedKeyList
if err := s.agent.RPC("KVS.ListKeys", &listArgs, &out); err != nil {
return nil, err
}
setMeta(resp, &out.QueryMeta)
// Check if we get a not found
if len(out.Keys) == 0 {
resp.WriteHeader(404)
return nil, nil
}
return out.Keys, nil
}
// KVSPut handles a PUT request
func (s *HTTPServer) KVSPut(resp http.ResponseWriter, req *http.Request, args *structs.KeyRequest) (interface{}, error) {
if missingKey(resp, args) {

View File

@ -7,6 +7,7 @@ import (
"net/http"
"net/http/httptest"
"os"
"reflect"
"testing"
"time"
)
@ -281,3 +282,64 @@ func TestKVSEndpoint_CAS(t *testing.T) {
t.Fatalf("bad: %v", d)
}
}
func TestKVSEndpoint_ListKeys(t *testing.T) {
dir, srv := makeHTTPServer(t)
defer os.RemoveAll(dir)
defer srv.Shutdown()
defer srv.agent.Shutdown()
// Wait for a leader
time.Sleep(100 * time.Millisecond)
keys := []string{
"bar",
"baz",
"foo/sub1",
"foo/sub2",
"zip",
}
for _, key := range keys {
buf := bytes.NewBuffer([]byte("test"))
req, err := http.NewRequest("PUT", "/v1/kv/"+key, buf)
if err != nil {
t.Fatalf("err: %v", err)
}
resp := httptest.NewRecorder()
obj, err := srv.KVSEndpoint(resp, req)
if err != nil {
t.Fatalf("err: %v", err)
}
if res := obj.(bool); !res {
t.Fatalf("should work")
}
}
{
// Get all the keys
req, err := http.NewRequest("GET", "/v1/kv/?keys&seperator=/", nil)
if err != nil {
t.Fatalf("err: %v", err)
}
resp := httptest.NewRecorder()
obj, err := srv.KVSEndpoint(resp, req)
if err != nil {
t.Fatalf("err: %v", err)
}
assertIndex(t, resp)
res, ok := obj.([]string)
if !ok {
t.Fatalf("should work")
}
expect := []string{"bar", "baz", "foo/", "zip"}
if !reflect.DeepEqual(res, expect) {
t.Fatalf("bad: %v", res)
}
}
}