consul: Support conditional policy fetch

This commit is contained in:
Armon Dadgar 2014-08-08 16:55:47 -07:00
parent 45f358e715
commit b5e22203fc
4 changed files with 41 additions and 5 deletions

View File

@ -69,7 +69,7 @@ func (s *Server) lookupACL(id, authDC string) (acl.ACL, error) {
} }
// Attempt to refresh the policy // Attempt to refresh the policy
args := structs.ACLSpecificRequest{ args := structs.ACLPolicyRequest{
Datacenter: authDC, Datacenter: authDC,
ACL: id, ACL: id,
} }

View File

@ -88,7 +88,7 @@ func (a *ACL) Get(args *structs.ACLSpecificRequest,
// GetPolicy is used to retrieve a compiled policy object with a TTL. Does not // GetPolicy is used to retrieve a compiled policy object with a TTL. Does not
// support a blocking query. // support a blocking query.
func (a *ACL) GetPolicy(args *structs.ACLSpecificRequest, reply *structs.ACLPolicy) error { func (a *ACL) GetPolicy(args *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
if done, err := a.srv.forward("ACL.GetPolicy", args, args, reply); done { if done, err := a.srv.forward("ACL.GetPolicy", args, args, reply); done {
return err return err
} }
@ -99,12 +99,20 @@ func (a *ACL) GetPolicy(args *structs.ACLSpecificRequest, reply *structs.ACLPoli
return err return err
} }
// Setup the response // Generate an ETag
conf := a.srv.config conf := a.srv.config
reply.Policy = policy etag := fmt.Sprintf("%s:%s", conf.ACLDefaultPolicy, policy.ID)
// Setup the response
reply.ETag = etag
reply.Root = conf.ACLDefaultPolicy reply.Root = conf.ACLDefaultPolicy
reply.TTL = conf.ACLTTL reply.TTL = conf.ACLTTL
a.srv.setQueryMeta(&reply.QueryMeta) a.srv.setQueryMeta(&reply.QueryMeta)
// Only send the policy on an Etag mis-match
if args.ETag != etag {
reply.Policy = policy
}
return nil return nil
} }

View File

@ -130,7 +130,7 @@ func TestACLEndpoint_GetPolicy(t *testing.T) {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }
getR := structs.ACLSpecificRequest{ getR := structs.ACLPolicyRequest{
Datacenter: "dc1", Datacenter: "dc1",
ACL: out, ACL: out,
} }
@ -145,6 +145,20 @@ func TestACLEndpoint_GetPolicy(t *testing.T) {
if acls.TTL != 30*time.Second { if acls.TTL != 30*time.Second {
t.Fatalf("bad: %v", acls) t.Fatalf("bad: %v", acls)
} }
// Do a conditional lookup with etag
getR.ETag = acls.ETag
var out2 structs.ACLPolicy
if err := client.Call("ACL.GetPolicy", &getR, &out2); err != nil {
t.Fatalf("err: %v", err)
}
if out2.Policy != nil {
t.Fatalf("Bad: %v", out2)
}
if out2.TTL != 30*time.Second {
t.Fatalf("bad: %v", out2)
}
} }
func TestACLEndpoint_List(t *testing.T) { func TestACLEndpoint_List(t *testing.T) {

View File

@ -466,12 +466,26 @@ func (r *ACLSpecificRequest) RequestDatacenter() string {
return r.Datacenter return r.Datacenter
} }
// ACLPolicyRequest is used to request an ACL by ID, conditionally
// filtering on an ID
type ACLPolicyRequest struct {
Datacenter string
ACL string
ETag string
QueryOptions
}
func (r *ACLPolicyRequest) RequestDatacenter() string {
return r.Datacenter
}
type IndexedACLs struct { type IndexedACLs struct {
ACLs ACLs ACLs ACLs
QueryMeta QueryMeta
} }
type ACLPolicy struct { type ACLPolicy struct {
ETag string
Root string Root string
Policy *acl.Policy Policy *acl.Policy
TTL time.Duration TTL time.Duration