using contexts constants in replace of string contexts

fix up endpoints
This commit is contained in:
Chelsea Holland Komlo
2017-08-11 14:44:46 +00:00
parent 01b3338b71
commit 4edc38d5c2
8 changed files with 88 additions and 107 deletions

View File

@@ -1,11 +1,12 @@
package contexts
// Context is a type which is searchable via a unique identifier.
type Context string
const (
Alloc Context = "allocs"
Eval Context = "evals"
Job Context = "jobs"
Node Context = "nodes"
All Context = ""
Allocs Context = "allocs"
Evals Context = "evals"
Jobs Context = "jobs"
Nodes Context = "nodes"
All Context = ""
)

View File

@@ -18,7 +18,7 @@ func (c *Client) Search() *Search {
// context is not specified, matches for all contexts are returned.
func (s *Search) PrefixSearch(prefix string, context c.Context) (*structs.SearchResponse, error) {
var resp structs.SearchResponse
req := &structs.SearchRequest{Prefix: prefix, Context: string(context)}
req := &structs.SearchRequest{Prefix: prefix, Context: context}
_, err := s.client.write("/v1/search", req, &resp, nil)
if err != nil {

View File

@@ -25,7 +25,7 @@ func TestSearch_List(t *testing.T) {
assert.Nil(err)
assert.NotEqual(0, resp.Index)
jobMatches := resp.Matches[contexts.jobs]
jobMatches := resp.Matches[contexts.Jobs]
assert.Equal(1, len(jobMatches))
assert.Equal(id, jobMatches[0])
}

View File

@@ -5,6 +5,7 @@ import (
"net/http/httptest"
"testing"
"github.com/hashicorp/nomad/api/contexts"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
a "github.com/stretchr/testify/assert"
@@ -14,7 +15,7 @@ func TestHTTP_SearchWithIllegalMethod(t *testing.T) {
assert := a.New(t)
t.Parallel()
httpTest(t, nil, func(s *TestAgent) {
req, err := http.NewRequest("DELETE", "/v1/resources", nil)
req, err := http.NewRequest("DELETE", "/v1/search", nil)
assert.Nil(err)
respW := httptest.NewRecorder()
@@ -44,7 +45,7 @@ func TestHTTP_Search_POST(t *testing.T) {
httpTest(t, nil, func(s *TestAgent) {
createJobForTest(testJob, s, t)
data := structs.SearchRequest{Prefix: testJobPrefix, Context: "jobs"}
data := structs.SearchRequest{Prefix: testJobPrefix, Context: contexts.Jobs}
req, err := http.NewRequest("POST", "/v1/search", encodeReq(data))
assert.Nil(err)
@@ -57,12 +58,12 @@ func TestHTTP_Search_POST(t *testing.T) {
assert.Equal(1, len(res.Matches))
j := res.Matches["jobs"]
j := res.Matches[contexts.Jobs]
assert.Equal(1, len(j))
assert.Equal(j[0], testJob)
assert.Equal(res.Truncations["job"], false)
assert.Equal(res.Truncations[contexts.Jobs], false)
assert.NotEqual("0", respW.HeaderMap.Get("X-Nomad-Index"))
})
}
@@ -76,7 +77,7 @@ func TestHTTP_Search_PUT(t *testing.T) {
httpTest(t, nil, func(s *TestAgent) {
createJobForTest(testJob, s, t)
data := structs.SearchRequest{Prefix: testJobPrefix, Context: "jobs"}
data := structs.SearchRequest{Prefix: testJobPrefix, Context: contexts.Jobs}
req, err := http.NewRequest("PUT", "/v1/search", encodeReq(data))
assert.Nil(err)
@@ -89,12 +90,12 @@ func TestHTTP_Search_PUT(t *testing.T) {
assert.Equal(1, len(res.Matches))
j := res.Matches["jobs"]
j := res.Matches[contexts.Jobs]
assert.Equal(1, len(j))
assert.Equal(j[0], testJob)
assert.Equal(res.Truncations["job"], false)
assert.Equal(res.Truncations[contexts.Jobs], false)
assert.NotEqual("0", respW.HeaderMap.Get("X-Nomad-Index"))
})
}
@@ -114,7 +115,7 @@ func TestHTTP_Search_MultipleJobs(t *testing.T) {
createJobForTest(testJobB, s, t)
createJobForTest(testJobC, s, t)
data := structs.SearchRequest{Prefix: testJobPrefix, Context: "jobs"}
data := structs.SearchRequest{Prefix: testJobPrefix, Context: contexts.Jobs}
req, err := http.NewRequest("POST", "/v1/search", encodeReq(data))
assert.Nil(err)
@@ -127,14 +128,14 @@ func TestHTTP_Search_MultipleJobs(t *testing.T) {
assert.Equal(1, len(res.Matches))
j := res.Matches["jobs"]
j := res.Matches[contexts.Jobs]
assert.Equal(2, len(j))
assert.Contains(j, testJobA)
assert.Contains(j, testJobB)
assert.NotContains(j, testJobC)
assert.Equal(res.Truncations["job"], false)
assert.Equal(res.Truncations[contexts.Jobs], false)
assert.NotEqual("0", respW.HeaderMap.Get("X-Nomad-Index"))
})
}
@@ -152,7 +153,7 @@ func TestHTTP_Search_Evaluation(t *testing.T) {
assert.Nil(err)
prefix := eval1.ID[:len(eval1.ID)-2]
data := structs.SearchRequest{Prefix: prefix, Context: "evals"}
data := structs.SearchRequest{Prefix: prefix, Context: contexts.Evals}
req, err := http.NewRequest("POST", "/v1/search", encodeReq(data))
assert.Nil(err)
@@ -165,12 +166,12 @@ func TestHTTP_Search_Evaluation(t *testing.T) {
assert.Equal(1, len(res.Matches))
j := res.Matches["evals"]
j := res.Matches[contexts.Evals]
assert.Equal(1, len(j))
assert.Contains(j, eval1.ID)
assert.NotContains(j, eval2.ID)
assert.Equal(res.Truncations["evals"], false)
assert.Equal(res.Truncations[contexts.Evals], false)
assert.Equal("9000", respW.HeaderMap.Get("X-Nomad-Index"))
})
}
@@ -186,7 +187,7 @@ func TestHTTP_Search_Allocations(t *testing.T) {
assert.Nil(err)
prefix := alloc.ID[:len(alloc.ID)-2]
data := structs.SearchRequest{Prefix: prefix, Context: "allocs"}
data := structs.SearchRequest{Prefix: prefix, Context: contexts.Allocs}
req, err := http.NewRequest("POST", "/v1/search", encodeReq(data))
assert.Nil(err)
@@ -199,11 +200,11 @@ func TestHTTP_Search_Allocations(t *testing.T) {
assert.Equal(1, len(res.Matches))
a := res.Matches["allocs"]
a := res.Matches[contexts.Allocs]
assert.Equal(1, len(a))
assert.Contains(a, alloc.ID)
assert.Equal(res.Truncations["allocs"], false)
assert.Equal(res.Truncations[contexts.Allocs], false)
assert.Equal("7000", respW.HeaderMap.Get("X-Nomad-Index"))
})
}
@@ -219,7 +220,7 @@ func TestHTTP_Search_Nodes(t *testing.T) {
assert.Nil(err)
prefix := node.ID[:len(node.ID)-2]
data := structs.SearchRequest{Prefix: prefix, Context: "nodes"}
data := structs.SearchRequest{Prefix: prefix, Context: contexts.Nodes}
req, err := http.NewRequest("POST", "/v1/search", encodeReq(data))
assert.Nil(err)
@@ -232,11 +233,11 @@ func TestHTTP_Search_Nodes(t *testing.T) {
assert.Equal(1, len(res.Matches))
n := res.Matches["nodes"]
n := res.Matches[contexts.Nodes]
assert.Equal(1, len(n))
assert.Contains(n, node.ID)
assert.Equal(res.Truncations["nodes"], false)
assert.Equal(res.Truncations[contexts.Nodes], false)
assert.Equal("6000", respW.HeaderMap.Get("X-Nomad-Index"))
})
}
@@ -246,7 +247,7 @@ func TestHTTP_Search_NoJob(t *testing.T) {
t.Parallel()
httpTest(t, nil, func(s *TestAgent) {
data := structs.SearchRequest{Prefix: "12345", Context: "jobs"}
data := structs.SearchRequest{Prefix: "12345", Context: contexts.Jobs}
req, err := http.NewRequest("POST", "/v1/search", encodeReq(data))
assert.Nil(err)
@@ -258,13 +259,13 @@ func TestHTTP_Search_NoJob(t *testing.T) {
res := resp.(structs.SearchResponse)
assert.Equal(1, len(res.Matches))
assert.Equal(0, len(res.Matches["jobs"]))
assert.Equal(0, len(res.Matches[contexts.Jobs]))
assert.Equal("0", respW.HeaderMap.Get("X-Nomad-Index"))
})
}
func TestHTTP_Search_NoContext(t *testing.T) {
func TestHTTP_Search_AllContext(t *testing.T) {
assert := a.New(t)
testJobID := "aaaaaaaa-e8f7-fd38-c855-ab94ceb89706"
@@ -279,7 +280,7 @@ func TestHTTP_Search_NoContext(t *testing.T) {
err := state.UpsertEvals(8000, []*structs.Evaluation{eval1})
assert.Nil(err)
data := structs.SearchRequest{Prefix: testJobPrefix}
data := structs.SearchRequest{Prefix: testJobPrefix, Context: contexts.All}
req, err := http.NewRequest("POST", "/v1/search", encodeReq(data))
assert.Nil(err)
@@ -290,8 +291,8 @@ func TestHTTP_Search_NoContext(t *testing.T) {
res := resp.(structs.SearchResponse)
matchedJobs := res.Matches["jobs"]
matchedEvals := res.Matches["evals"]
matchedJobs := res.Matches[contexts.Jobs]
matchedEvals := res.Matches[contexts.Evals]
assert.Equal(1, len(matchedJobs))
assert.Equal(1, len(matchedEvals))

View File

@@ -205,7 +205,7 @@ func (c *AllocStatusCommand) AutocompleteArgs() complete.Predictor {
if err != nil {
return []string{}
}
return resp.Matches[api.contexts.Allocs]
return resp.Matches[contexts.Allocs]
})
}

View File

@@ -4,6 +4,7 @@ import (
"fmt"
memdb "github.com/hashicorp/go-memdb"
c "github.com/hashicorp/nomad/api/contexts"
"github.com/hashicorp/nomad/nomad/state"
"github.com/hashicorp/nomad/nomad/structs"
)
@@ -14,13 +15,13 @@ const (
truncateLimit = 20
)
// allContexts are the available contexts which searched to find matches for a
// given prefix
// allContexts are the available contexts which are searched to find matches
// for a given prefix
var (
allContexts = []string{"allocs", "nodes", "jobs", "evals"}
allContexts = []c.Context{c.Allocs, c.Jobs, c.Nodes, c.Evals}
)
// Search endpoint is used to lookup matches for a given prefix and context
// Search endpoint is used to look up matches for a given prefix and context
type Search struct {
srv *Server
}
@@ -67,15 +68,15 @@ func (s *Search) getMatches(iter memdb.ResultIterator, prefix string) ([]string,
// getResourceIter takes a context and returns a memdb iterator specific to
// that context
func getResourceIter(context, prefix string, ws memdb.WatchSet, state *state.StateStore) (memdb.ResultIterator, error) {
func getResourceIter(context c.Context, prefix string, ws memdb.WatchSet, state *state.StateStore) (memdb.ResultIterator, error) {
switch context {
case "jobs":
case c.Jobs:
return state.JobsByIDPrefix(ws, prefix)
case "evals":
case c.Evals:
return state.EvalsByIDPrefix(ws, prefix)
case "allocs":
case c.Allocs:
return state.AllocsByIDPrefix(ws, prefix)
case "nodes":
case c.Nodes:
return state.NodesByIDPrefix(ws, prefix)
default:
return nil, fmt.Errorf("context must be one of %v; got %q", allContexts, context)
@@ -84,8 +85,8 @@ func getResourceIter(context, prefix string, ws memdb.WatchSet, state *state.Sta
// If the length of a prefix is odd, return a subset to the last even character
// This only applies to UUIDs, jobs are excluded
func roundUUIDDownIfOdd(prefix, context string) string {
if context == "job" {
func roundUUIDDownIfOdd(prefix string, context c.Context) string {
if context == c.Jobs {
return prefix
}
@@ -96,12 +97,12 @@ func roundUUIDDownIfOdd(prefix, context string) string {
return prefix[:l-1]
}
// List is used to list matches for a given prefix. Search returns jobs,
// evaluations, allocations, and/or nodes.
func (s *Search) List(args *structs.SearchRequest,
// PrefixSearch is used to list matches for a given prefix, and returns
// matching jobs, evaluations, allocations, and/or nodes.
func (s *Search) PrefixSearch(args *structs.SearchRequest,
reply *structs.SearchResponse) error {
reply.Matches = make(map[string][]string)
reply.Truncations = make(map[string]bool)
reply.Matches = make(map[c.Context][]string)
reply.Truncations = make(map[c.Context]bool)
// Setup the blocking query
opts := blockingOptions{
@@ -109,11 +110,11 @@ func (s *Search) List(args *structs.SearchRequest,
queryOpts: &structs.QueryOptions{},
run: func(ws memdb.WatchSet, state *state.StateStore) error {
iters := make(map[string]memdb.ResultIterator)
iters := make(map[c.Context]memdb.ResultIterator)
contexts := allContexts
if args.Context != "" {
contexts = []string{args.Context}
if args.Context != c.All {
contexts = []c.Context{args.Context}
}
for _, e := range contexts {
@@ -135,7 +136,7 @@ func (s *Search) List(args *structs.SearchRequest,
// will be used as the index of the response. Otherwise, the
// maximum index from all resources will be used.
for _, e := range contexts {
index, err := state.Index(e)
index, err := state.Index(string(e))
if err != nil {
return err
}

View File

@@ -5,6 +5,7 @@ import (
"testing"
msgpackrpc "github.com/hashicorp/net-rpc-msgpackrpc"
c "github.com/hashicorp/nomad/api/contexts"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/testutil"
@@ -25,7 +26,7 @@ func registerAndVerifyJob(s *Server, t *testing.T, prefix string, counter int) s
return job.ID
}
func TestSearch_List(t *testing.T) {
func TestSearch_PrefixSearch(t *testing.T) {
assert := assert.New(t)
prefix := "aaaaaaaa-e8f7-fd38-c855-ab94ceb8970"
@@ -42,11 +43,11 @@ func TestSearch_List(t *testing.T) {
req := &structs.SearchRequest{
Prefix: prefix,
Context: "jobs",
Context: c.Jobs,
}
var resp structs.SearchResponse
if err := msgpackrpc.CallWithCodec(codec, "Search.List", req, &resp); err != nil {
if err := msgpackrpc.CallWithCodec(codec, "Search.PrefixSearch", req, &resp); err != nil {
t.Fatalf("err: %v", err)
}
@@ -56,7 +57,7 @@ func TestSearch_List(t *testing.T) {
}
// truncate should limit results to 20
func TestSearch_List_Truncate(t *testing.T) {
func TestSearch_PrefixSearch_Truncate(t *testing.T) {
assert := assert.New(t)
prefix := "aaaaaaaa-e8f7-fd38-c855-ab94ceb8970"
@@ -75,11 +76,11 @@ func TestSearch_List_Truncate(t *testing.T) {
req := &structs.SearchRequest{
Prefix: prefix,
Context: "jobs",
Context: c.Jobs,
}
var resp structs.SearchResponse
if err := msgpackrpc.CallWithCodec(codec, "Search.List", req, &resp); err != nil {
if err := msgpackrpc.CallWithCodec(codec, "Search.PrefixSearch", req, &resp); err != nil {
t.Fatalf("err: %v", err)
}
@@ -88,7 +89,7 @@ func TestSearch_List_Truncate(t *testing.T) {
assert.Equal(uint64(jobIndex), resp.Index)
}
func TestSearch_List_Evals(t *testing.T) {
func TestSearch_PrefixSearch_Evals(t *testing.T) {
assert := assert.New(t)
t.Parallel()
s := testServer(t, func(c *Config) {
@@ -106,11 +107,11 @@ func TestSearch_List_Evals(t *testing.T) {
req := &structs.SearchRequest{
Prefix: prefix,
Context: "evals",
Context: c.Evals,
}
var resp structs.SearchResponse
if err := msgpackrpc.CallWithCodec(codec, "Search.List", req, &resp); err != nil {
if err := msgpackrpc.CallWithCodec(codec, "Search.PrefixSearch", req, &resp); err != nil {
t.Fatalf("err: %v", err)
}
@@ -121,7 +122,7 @@ func TestSearch_List_Evals(t *testing.T) {
assert.Equal(uint64(2000), resp.Index)
}
func TestSearch_List_Allocation(t *testing.T) {
func TestSearch_PrefixSearch_Allocation(t *testing.T) {
assert := assert.New(t)
t.Parallel()
s := testServer(t, func(c *Config) {
@@ -147,11 +148,11 @@ func TestSearch_List_Allocation(t *testing.T) {
req := &structs.SearchRequest{
Prefix: prefix,
Context: "allocs",
Context: c.Allocs,
}
var resp structs.SearchResponse
if err := msgpackrpc.CallWithCodec(codec, "Search.List", req, &resp); err != nil {
if err := msgpackrpc.CallWithCodec(codec, "Search.PrefixSearch", req, &resp); err != nil {
t.Fatalf("err: %v", err)
}
@@ -162,7 +163,7 @@ func TestSearch_List_Allocation(t *testing.T) {
assert.Equal(uint64(90), resp.Index)
}
func TestSearch_List_Node(t *testing.T) {
func TestSearch_PrefixSearch_Node(t *testing.T) {
assert := assert.New(t)
t.Parallel()
s := testServer(t, func(c *Config) {
@@ -184,11 +185,11 @@ func TestSearch_List_Node(t *testing.T) {
req := &structs.SearchRequest{
Prefix: prefix,
Context: "nodes",
Context: c.Nodes,
}
var resp structs.SearchResponse
if err := msgpackrpc.CallWithCodec(codec, "Search.List", req, &resp); err != nil {
if err := msgpackrpc.CallWithCodec(codec, "Search.PrefixSearch", req, &resp); err != nil {
t.Fatalf("err: %v", err)
}
@@ -199,31 +200,7 @@ func TestSearch_List_Node(t *testing.T) {
assert.Equal(uint64(100), resp.Index)
}
func TestSearch_List_InvalidContext(t *testing.T) {
assert := assert.New(t)
t.Parallel()
s := testServer(t, func(c *Config) {
c.NumSchedulers = 0
})
defer s.Shutdown()
codec := rpcClient(t, s)
testutil.WaitForLeader(t, s.RPC)
req := &structs.SearchRequest{
Prefix: "anyPrefix",
Context: "invalid",
}
var resp structs.SearchResponse
err := msgpackrpc.CallWithCodec(codec, "Search.List", req, &resp)
assert.Equal(err.Error(), "context must be one of [allocs nodes jobs evals]; got \"invalid\"")
assert.Equal(uint64(0), resp.Index)
}
func TestSearch_List_NoContext(t *testing.T) {
func TestSearch_PrefixSearch_AllContext(t *testing.T) {
assert := assert.New(t)
t.Parallel()
s := testServer(t, func(c *Config) {
@@ -251,11 +228,11 @@ func TestSearch_List_NoContext(t *testing.T) {
req := &structs.SearchRequest{
Prefix: prefix,
Context: "",
Context: c.All,
}
var resp structs.SearchResponse
if err := msgpackrpc.CallWithCodec(codec, "Search.List", req, &resp); err != nil {
if err := msgpackrpc.CallWithCodec(codec, "Search.PrefixSearch", req, &resp); err != nil {
t.Fatalf("err: %v", err)
}
@@ -269,7 +246,7 @@ func TestSearch_List_NoContext(t *testing.T) {
}
// Tests that the top 20 matches are returned when no prefix is set
func TestSearch_List_NoPrefix(t *testing.T) {
func TestSearch_PrefixSearch_NoPrefix(t *testing.T) {
assert := assert.New(t)
prefix := "aaaaaaaa-e8f7-fd38-c855-ab94ceb8970"
@@ -287,11 +264,11 @@ func TestSearch_List_NoPrefix(t *testing.T) {
req := &structs.SearchRequest{
Prefix: "",
Context: "jobs",
Context: c.Jobs,
}
var resp structs.SearchResponse
if err := msgpackrpc.CallWithCodec(codec, "Search.List", req, &resp); err != nil {
if err := msgpackrpc.CallWithCodec(codec, "Search.PrefixSearch", req, &resp); err != nil {
t.Fatalf("err: %v", err)
}
@@ -302,7 +279,7 @@ func TestSearch_List_NoPrefix(t *testing.T) {
// Tests that the zero matches are returned when a prefix has no matching
// results
func TestSearch_List_NoMatches(t *testing.T) {
func TestSearch_PrefixSearch_NoMatches(t *testing.T) {
assert := assert.New(t)
prefix := "aaaaaaaa-e8f7-fd38-c855-ab94ceb8970"
@@ -318,11 +295,11 @@ func TestSearch_List_NoMatches(t *testing.T) {
req := &structs.SearchRequest{
Prefix: prefix,
Context: "jobs",
Context: c.Jobs,
}
var resp structs.SearchResponse
if err := msgpackrpc.CallWithCodec(codec, "Search.List", req, &resp); err != nil {
if err := msgpackrpc.CallWithCodec(codec, "Search.PrefixSearch", req, &resp); err != nil {
t.Fatalf("err: %v", err)
}
@@ -332,7 +309,7 @@ func TestSearch_List_NoMatches(t *testing.T) {
// Prefixes can only be looked up if their length is a power of two. For
// prefixes which are an odd length, use the length-1 characters.
func TestSearch_List_RoundDownToEven(t *testing.T) {
func TestSearch_PrefixSearch_RoundDownToEven(t *testing.T) {
assert := assert.New(t)
id1 := "aaafaaaa-e8f7-fd38-c855-ab94ceb89"
id2 := "aaafeaaa-e8f7-fd38-c855-ab94ceb89"
@@ -352,11 +329,11 @@ func TestSearch_List_RoundDownToEven(t *testing.T) {
req := &structs.SearchRequest{
Prefix: prefix,
Context: "jobs",
Context: c.Jobs,
}
var resp structs.SearchResponse
if err := msgpackrpc.CallWithCodec(codec, "Search.List", req, &resp); err != nil {
if err := msgpackrpc.CallWithCodec(codec, "Search.PrefixSearch", req, &resp); err != nil {
t.Fatalf("err: %v", err)
}

View File

@@ -24,6 +24,7 @@ import (
"github.com/hashicorp/consul/api"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-version"
"github.com/hashicorp/nomad/api/contexts"
"github.com/hashicorp/nomad/helper"
"github.com/hashicorp/nomad/helper/args"
"github.com/mitchellh/copystructure"
@@ -235,11 +236,11 @@ type NodeSpecificRequest struct {
// the match list is truncated specific to each type of context.
type SearchResponse struct {
// Map of context types to ids which match a specified prefix
Matches map[string][]string
Matches map[contexts.Context][]string
// Truncations indicates whether the matches for a particular context have
// been truncated
Truncations map[string]bool
Truncations map[contexts.Context]bool
QueryMeta
}
@@ -255,7 +256,7 @@ type SearchRequest struct {
// Context is the type that can be matched against. A context can be a job,
// node, evaluation, allocation, or empty (indicated every context should be
// matched)
Context string
Context contexts.Context
}
// JobRegisterRequest is used for Job.Register endpoint