From ecc789ddb59ab7a0ceff8bdfc70b775923c73a8b Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 8 Apr 2018 14:45:55 +0100 Subject: [PATCH] agent/cache: ConnectCA roots caching type --- agent/cache/type_connect_ca.go | 2 -- agent/cache/type_connect_ca_test.go | 55 +++++++++++++++++++++++++++++ agent/structs/structs.go | 20 +++++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 agent/cache/type_connect_ca_test.go diff --git a/agent/cache/type_connect_ca.go b/agent/cache/type_connect_ca.go index 40bda72df..6a0a6699c 100644 --- a/agent/cache/type_connect_ca.go +++ b/agent/cache/type_connect_ca.go @@ -1,6 +1,5 @@ package cache -/* import ( "fmt" @@ -36,4 +35,3 @@ func (c *TypeCARoot) Fetch(opts FetchOptions, req Request) (FetchResult, error) result.Index = reply.QueryMeta.Index return result, nil } -*/ diff --git a/agent/cache/type_connect_ca_test.go b/agent/cache/type_connect_ca_test.go new file mode 100644 index 000000000..359449d21 --- /dev/null +++ b/agent/cache/type_connect_ca_test.go @@ -0,0 +1,55 @@ +package cache + +import ( + "testing" + "time" + + "github.com/hashicorp/consul/agent/structs" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +func TestTypeCARoot(t *testing.T) { + require := require.New(t) + rpc := TestRPC(t) + defer rpc.AssertExpectations(t) + typ := &TypeCARoot{RPC: rpc} + + // Expect the proper RPC call. This also sets the expected value + // since that is return-by-pointer in the arguments. + var resp *structs.IndexedCARoots + rpc.On("RPC", "ConnectCA.Roots", mock.Anything, mock.Anything).Return(nil). + Run(func(args mock.Arguments) { + req := args.Get(1).(*structs.DCSpecificRequest) + require.Equal(uint64(24), req.QueryOptions.MinQueryIndex) + require.Equal(1*time.Second, req.QueryOptions.MaxQueryTime) + + reply := args.Get(2).(*structs.IndexedCARoots) + reply.QueryMeta.Index = 48 + resp = reply + }) + + // Fetch + result, err := typ.Fetch(FetchOptions{ + MinIndex: 24, + Timeout: 1 * time.Second, + }, &structs.DCSpecificRequest{Datacenter: "dc1"}) + require.Nil(err) + require.Equal(FetchResult{ + Value: resp, + Index: 48, + }, result) +} + +func TestTypeCARoot_badReqType(t *testing.T) { + require := require.New(t) + rpc := TestRPC(t) + defer rpc.AssertExpectations(t) + typ := &TypeCARoot{RPC: rpc} + + // Fetch + _, err := typ.Fetch(FetchOptions{}, TestRequest(t, "foo", 64)) + require.NotNil(err) + require.Contains(err.Error(), "wrong type") + +} diff --git a/agent/structs/structs.go b/agent/structs/structs.go index 4f25e50f0..d40c90baa 100644 --- a/agent/structs/structs.go +++ b/agent/structs/structs.go @@ -6,6 +6,7 @@ import ( "math/rand" "reflect" "regexp" + "strconv" "strings" "time" @@ -14,6 +15,7 @@ import ( "github.com/hashicorp/go-msgpack/codec" "github.com/hashicorp/go-multierror" "github.com/hashicorp/serf/coordinate" + "github.com/mitchellh/hashstructure" ) type MessageType uint8 @@ -276,6 +278,24 @@ func (r *DCSpecificRequest) RequestDatacenter() string { return r.Datacenter } +func (r *DCSpecificRequest) CacheKey() string { + // To calculate the cache key we only hash the node filters. The + // datacenter is handled by the cache framework. The other fields are + // not, but should not be used in any cache types. + v, err := hashstructure.Hash(r.NodeMetaFilters, nil) + if err != nil { + // Empty string means do not cache. If we have an error we should + // just forward along to the server. + return "" + } + + return strconv.FormatUint(v, 10) +} + +func (r *DCSpecificRequest) CacheMinIndex() uint64 { + return r.QueryOptions.MinQueryIndex +} + // ServiceSpecificRequest is used to query about a specific service type ServiceSpecificRequest struct { Datacenter string