add locality indexer partitioning (#11016)
* convert `Roles` index to use `indexerSingle` * split authmethod write indexer to oss and ent * add index locality * add locality unit tests * move intFromBool to be available for oss * use Bool func * refactor `aclTokenList` to merge func
This commit is contained in:
parent
def2d9d96d
commit
1f23bdf388
|
@ -711,13 +711,12 @@ func (s *Store) ACLTokenList(ws memdb.WatchSet, local, global bool, policy, role
|
||||||
// all tokens so our checks just ensure that global == local
|
// all tokens so our checks just ensure that global == local
|
||||||
|
|
||||||
needLocalityFilter := false
|
needLocalityFilter := false
|
||||||
|
|
||||||
if policy == "" && role == "" && methodName == "" {
|
if policy == "" && role == "" && methodName == "" {
|
||||||
if global == local {
|
if global == local {
|
||||||
iter, err = aclTokenListAll(tx, entMeta)
|
iter, err = aclTokenListAll(tx, entMeta)
|
||||||
} else if global {
|
|
||||||
iter, err = aclTokenListGlobal(tx, entMeta)
|
|
||||||
} else {
|
} else {
|
||||||
iter, err = aclTokenListLocal(tx, entMeta)
|
iter, err = aclTokenList(tx, entMeta, local)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if policy != "" && role == "" && methodName == "" {
|
} else if policy != "" && role == "" && methodName == "" {
|
||||||
|
@ -1769,3 +1768,25 @@ func aclAuthMethodDeleteTxn(tx WriteTxn, idx uint64, name string, entMeta *struc
|
||||||
|
|
||||||
return aclAuthMethodDeleteWithMethod(tx, method, idx)
|
return aclAuthMethodDeleteWithMethod(tx, method, idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func aclTokenList(tx ReadTxn, entMeta *structs.EnterpriseMeta, locality bool) (memdb.ResultIterator, error) {
|
||||||
|
// TODO: accept non-pointer value
|
||||||
|
if entMeta == nil {
|
||||||
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
||||||
|
}
|
||||||
|
// if the namespace is the wildcard that will also be handled as the local index uses
|
||||||
|
// the NamespaceMultiIndex instead of the NamespaceIndex
|
||||||
|
q := BoolQuery{
|
||||||
|
Value: locality,
|
||||||
|
EnterpriseMeta: *entMeta,
|
||||||
|
}
|
||||||
|
return tx.Get(tableACLTokens, indexLocality, q)
|
||||||
|
}
|
||||||
|
|
||||||
|
// intFromBool returns 1 if cond is true, 0 otherwise.
|
||||||
|
func intFromBool(cond bool) byte {
|
||||||
|
if cond {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
|
@ -78,14 +78,6 @@ func aclTokenListAll(tx ReadTxn, _ *structs.EnterpriseMeta) (memdb.ResultIterato
|
||||||
return tx.Get(tableACLTokens, "id")
|
return tx.Get(tableACLTokens, "id")
|
||||||
}
|
}
|
||||||
|
|
||||||
func aclTokenListLocal(tx ReadTxn, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
|
||||||
return tx.Get(tableACLTokens, "local", true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func aclTokenListGlobal(tx ReadTxn, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
|
||||||
return tx.Get(tableACLTokens, "local", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func aclTokenListByPolicy(tx ReadTxn, policy string, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
func aclTokenListByPolicy(tx ReadTxn, policy string, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
||||||
return tx.Get(tableACLTokens, indexPolicies, Query{Value: policy})
|
return tx.Get(tableACLTokens, indexPolicies, Query{Value: policy})
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ const (
|
||||||
indexPolicies = "policies"
|
indexPolicies = "policies"
|
||||||
indexRoles = "roles"
|
indexRoles = "roles"
|
||||||
indexAuthMethod = "authmethod"
|
indexAuthMethod = "authmethod"
|
||||||
indexLocal = "local"
|
indexLocality = "locality"
|
||||||
indexName = "name"
|
indexName = "name"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -75,17 +75,13 @@ func tokensTableSchema() *memdb.TableSchema {
|
||||||
writeIndex: writeIndex(indexAuthMethodFromACLToken),
|
writeIndex: writeIndex(indexAuthMethodFromACLToken),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
indexLocal: {
|
indexLocality: {
|
||||||
Name: indexLocal,
|
Name: indexLocality,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: &memdb.ConditionalIndex{
|
Indexer: indexerSingle{
|
||||||
Conditional: func(obj interface{}) (bool, error) {
|
readIndex: readIndex(indexFromBoolQuery),
|
||||||
if token, ok := obj.(*structs.ACLToken); ok {
|
writeIndex: writeIndex(indexLocalFromACLToken),
|
||||||
return token.Local, nil
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"expires-global": {
|
"expires-global": {
|
||||||
|
@ -406,3 +402,24 @@ func indexRolesFromACLToken(raw interface{}) ([][]byte, error) {
|
||||||
|
|
||||||
return vals, nil
|
return vals, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func indexFromBoolQuery(raw interface{}) ([]byte, error) {
|
||||||
|
q, ok := raw.(BoolQuery)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("unexpected type %T for BoolQuery index", raw)
|
||||||
|
}
|
||||||
|
var b indexBuilder
|
||||||
|
b.Bool(q.Value)
|
||||||
|
return b.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func indexLocalFromACLToken(raw interface{}) ([]byte, error) {
|
||||||
|
p, ok := raw.(*structs.ACLToken)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("unexpected type %T for structs.ACLPolicy index", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
var b indexBuilder
|
||||||
|
b.Bool(p.Local)
|
||||||
|
return b.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
|
@ -133,3 +133,7 @@ func (b *indexBuilder) Raw(v []byte) {
|
||||||
func (b *indexBuilder) Bytes() []byte {
|
func (b *indexBuilder) Bytes() []byte {
|
||||||
return (*bytes.Buffer)(b).Bytes()
|
return (*bytes.Buffer)(b).Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *indexBuilder) Bool(v bool) {
|
||||||
|
b.Raw([]byte{intFromBool(v)})
|
||||||
|
}
|
||||||
|
|
|
@ -96,6 +96,18 @@ type BoolQuery struct {
|
||||||
structs.EnterpriseMeta
|
structs.EnterpriseMeta
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NamespaceOrDefault exists because structs.EnterpriseMeta uses a pointer
|
||||||
|
// receiver for this method. Remove once that is fixed.
|
||||||
|
func (q BoolQuery) NamespaceOrDefault() string {
|
||||||
|
return q.EnterpriseMeta.NamespaceOrDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
// PartitionOrDefault exists because structs.EnterpriseMeta uses a pointer
|
||||||
|
// receiver for this method. Remove once that is fixed.
|
||||||
|
func (q BoolQuery) PartitionOrDefault() string {
|
||||||
|
return q.EnterpriseMeta.PartitionOrDefault()
|
||||||
|
}
|
||||||
|
|
||||||
// KeyValueQuery is a type used to query for both a key and a value that may
|
// KeyValueQuery is a type used to query for both a key and a value that may
|
||||||
// include an enterprise identifier.
|
// include an enterprise identifier.
|
||||||
type KeyValueQuery struct {
|
type KeyValueQuery struct {
|
||||||
|
|
Loading…
Reference in New Issue