Make memdb indexers generic (#13558)
We have many indexer functions in Consul which take interface{} and type assert before building the index. We can use generics to get rid of the initial plumbing and pass around functions with better defined signatures. This has two benefits: 1) Less verbosity; 2) Developers can parse the argument types to memdb schemas without having to introspect the function for the type assertion.
This commit is contained in:
parent
dc19b9f46f
commit
aaf3c051f2
|
@ -7,7 +7,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
memdb "github.com/hashicorp/go-memdb"
|
"github.com/hashicorp/go-memdb"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/acl"
|
"github.com/hashicorp/consul/acl"
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
|
@ -209,18 +209,13 @@ func (s *Store) ACLAuthMethodUpsertValidateEnterprise(method *structs.ACLAuthMet
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexAuthMethodFromACLToken(raw interface{}) ([]byte, error) {
|
func indexAuthMethodFromACLToken(t *structs.ACLToken) ([]byte, error) {
|
||||||
p, ok := raw.(*structs.ACLToken)
|
if t.AuthMethod == "" {
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ACLToken index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.AuthMethod == "" {
|
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.String(strings.ToLower(p.AuthMethod))
|
b.String(strings.ToLower(t.AuthMethod))
|
||||||
|
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/go-memdb"
|
"github.com/hashicorp/go-memdb"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/acl"
|
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -36,18 +35,18 @@ func tokensTableSchema() *memdb.TableSchema {
|
||||||
// DEPRECATED (ACL-Legacy-Compat) - we should not AllowMissing here once legacy compat is removed
|
// DEPRECATED (ACL-Legacy-Compat) - we should not AllowMissing here once legacy compat is removed
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[string, *structs.ACLToken]{
|
||||||
readIndex: readIndex(indexFromUUIDString),
|
readIndex: indexFromUUIDString,
|
||||||
writeIndex: writeIndex(indexAccessorIDFromACLToken),
|
writeIndex: indexAccessorIDFromACLToken,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
indexID: {
|
indexID: {
|
||||||
Name: indexID,
|
Name: indexID,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[string, *structs.ACLToken]{
|
||||||
readIndex: readIndex(indexFromStringCaseSensitive),
|
readIndex: indexFromStringCaseSensitive,
|
||||||
writeIndex: writeIndex(indexSecretIDFromACLToken),
|
writeIndex: indexSecretIDFromACLToken,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
indexPolicies: {
|
indexPolicies: {
|
||||||
|
@ -55,58 +54,58 @@ func tokensTableSchema() *memdb.TableSchema {
|
||||||
// Need to allow missing for the anonymous token
|
// Need to allow missing for the anonymous token
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerMulti{
|
Indexer: indexerMulti[Query, *structs.ACLToken]{
|
||||||
readIndex: readIndex(indexFromUUIDQuery),
|
readIndex: indexFromUUIDQuery,
|
||||||
writeIndexMulti: writeIndexMulti(indexPoliciesFromACLToken),
|
writeIndexMulti: indexPoliciesFromACLToken,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
indexRoles: {
|
indexRoles: {
|
||||||
Name: indexRoles,
|
Name: indexRoles,
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerMulti{
|
Indexer: indexerMulti[Query, *structs.ACLToken]{
|
||||||
readIndex: readIndex(indexFromUUIDQuery),
|
readIndex: indexFromUUIDQuery,
|
||||||
writeIndexMulti: writeIndexMulti(indexRolesFromACLToken),
|
writeIndexMulti: indexRolesFromACLToken,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
indexAuthMethod: {
|
indexAuthMethod: {
|
||||||
Name: indexAuthMethod,
|
Name: indexAuthMethod,
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[AuthMethodQuery, *structs.ACLToken]{
|
||||||
readIndex: readIndex(indexFromAuthMethodQuery),
|
readIndex: indexFromAuthMethodQuery,
|
||||||
writeIndex: writeIndex(indexAuthMethodFromACLToken),
|
writeIndex: indexAuthMethodFromACLToken,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
indexLocality: {
|
indexLocality: {
|
||||||
Name: indexLocality,
|
Name: indexLocality,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[BoolQuery, *structs.ACLToken]{
|
||||||
readIndex: readIndex(indexFromBoolQuery),
|
readIndex: indexFromBoolQuery,
|
||||||
writeIndex: writeIndex(indexLocalFromACLToken),
|
writeIndex: indexLocalFromACLToken,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
indexExpiresGlobal: {
|
indexExpiresGlobal: {
|
||||||
Name: indexExpiresGlobal,
|
Name: indexExpiresGlobal,
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[*TimeQuery, *structs.ACLToken]{
|
||||||
readIndex: readIndex(indexFromTimeQuery),
|
readIndex: indexFromTimeQuery,
|
||||||
writeIndex: writeIndex(indexExpiresGlobalFromACLToken),
|
writeIndex: indexExpiresGlobalFromACLToken,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
indexExpiresLocal: {
|
indexExpiresLocal: {
|
||||||
Name: indexExpiresLocal,
|
Name: indexExpiresLocal,
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[*TimeQuery, *structs.ACLToken]{
|
||||||
readIndex: readIndex(indexFromTimeQuery),
|
readIndex: indexFromTimeQuery,
|
||||||
writeIndex: writeIndex(indexExpiresLocalFromACLToken),
|
writeIndex: indexExpiresLocalFromACLToken,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
//DEPRECATED (ACL-Legacy-Compat) - This index is only needed while we support upgrading v1 to v2 acls
|
// DEPRECATED (ACL-Legacy-Compat) - This index is only needed while we support upgrading v1 to v2 acls
|
||||||
// This table indexes all the ACL tokens that do not have an AccessorID
|
// This table indexes all the ACL tokens that do not have an AccessorID
|
||||||
// TODO(ACL-Legacy-Compat): remove in phase 2
|
// TODO(ACL-Legacy-Compat): remove in phase 2
|
||||||
"needs-upgrade": {
|
"needs-upgrade": {
|
||||||
|
@ -142,7 +141,7 @@ func policiesTableSchema() *memdb.TableSchema {
|
||||||
Name: indexName,
|
Name: indexName,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingleWithPrefix{
|
Indexer: indexerSingleWithPrefix[Query, *structs.ACLPolicy, any]{
|
||||||
readIndex: indexFromQuery,
|
readIndex: indexFromQuery,
|
||||||
writeIndex: indexNameFromACLPolicy,
|
writeIndex: indexNameFromACLPolicy,
|
||||||
prefixIndex: prefixIndexFromQuery,
|
prefixIndex: prefixIndexFromQuery,
|
||||||
|
@ -152,12 +151,7 @@ func policiesTableSchema() *memdb.TableSchema {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexNameFromACLPolicy(raw interface{}) ([]byte, error) {
|
func indexNameFromACLPolicy(p *structs.ACLPolicy) ([]byte, error) {
|
||||||
p, ok := raw.(*structs.ACLPolicy)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ACLPolicy index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Name == "" {
|
if p.Name == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
@ -183,7 +177,7 @@ func rolesTableSchema() *memdb.TableSchema {
|
||||||
Name: indexName,
|
Name: indexName,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingleWithPrefix{
|
Indexer: indexerSingleWithPrefix[Query, *structs.ACLRole, any]{
|
||||||
readIndex: indexFromQuery,
|
readIndex: indexFromQuery,
|
||||||
writeIndex: indexNameFromACLRole,
|
writeIndex: indexNameFromACLRole,
|
||||||
prefixIndex: prefixIndexFromQuery,
|
prefixIndex: prefixIndexFromQuery,
|
||||||
|
@ -194,7 +188,7 @@ func rolesTableSchema() *memdb.TableSchema {
|
||||||
// Need to allow missing for the anonymous token
|
// Need to allow missing for the anonymous token
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerMulti{
|
Indexer: indexerMulti[Query, *structs.ACLRole]{
|
||||||
readIndex: indexFromUUIDQuery,
|
readIndex: indexFromUUIDQuery,
|
||||||
writeIndexMulti: multiIndexPolicyFromACLRole,
|
writeIndexMulti: multiIndexPolicyFromACLRole,
|
||||||
},
|
},
|
||||||
|
@ -203,75 +197,43 @@ func rolesTableSchema() *memdb.TableSchema {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexNameFromACLRole(raw interface{}) ([]byte, error) {
|
func indexNameFromACLRole(r *structs.ACLRole) ([]byte, error) {
|
||||||
p, ok := raw.(*structs.ACLRole)
|
if r.Name == "" {
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ACLRole index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Name == "" {
|
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.String(strings.ToLower(p.Name))
|
b.String(strings.ToLower(r.Name))
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromUUIDQuery(raw interface{}) ([]byte, error) {
|
func indexFromUUIDQuery(q Query) ([]byte, error) {
|
||||||
q, ok := raw.(Query)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for UUIDQuery index", raw)
|
|
||||||
}
|
|
||||||
return uuidStringToBytes(q.Value)
|
return uuidStringToBytes(q.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func prefixIndexFromUUIDQuery(arg interface{}) ([]byte, error) {
|
func prefixIndexFromUUIDWithPeerQuery(q Query) ([]byte, error) {
|
||||||
switch v := arg.(type) {
|
var b indexBuilder
|
||||||
case *acl.EnterpriseMeta:
|
peername := q.PeerOrEmpty()
|
||||||
return nil, nil
|
if peername == "" {
|
||||||
case acl.EnterpriseMeta:
|
b.String(structs.LocalPeerKeyword)
|
||||||
return nil, nil
|
} else {
|
||||||
case Query:
|
b.String(strings.ToLower(peername))
|
||||||
return variableLengthUUIDStringToBytes(v.Value)
|
|
||||||
}
|
}
|
||||||
|
uuidBytes, err := variableLengthUUIDStringToBytes(q.Value)
|
||||||
return nil, fmt.Errorf("unexpected type %T for Query prefix index", arg)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return append(b.Bytes(), uuidBytes...), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func prefixIndexFromUUIDWithPeerQuery(arg interface{}) ([]byte, error) {
|
func multiIndexPolicyFromACLRole(r *structs.ACLRole) ([][]byte, error) {
|
||||||
switch v := arg.(type) {
|
count := len(r.Policies)
|
||||||
case Query:
|
|
||||||
var b indexBuilder
|
|
||||||
peername := v.PeerOrEmpty()
|
|
||||||
if peername == "" {
|
|
||||||
b.String(structs.LocalPeerKeyword)
|
|
||||||
} else {
|
|
||||||
b.String(strings.ToLower(peername))
|
|
||||||
}
|
|
||||||
uuidBytes, err := variableLengthUUIDStringToBytes(v.Value)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return append(b.Bytes(), uuidBytes...), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for Query prefix index", arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func multiIndexPolicyFromACLRole(raw interface{}) ([][]byte, error) {
|
|
||||||
role, ok := raw.(*structs.ACLRole)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ACLRole index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
count := len(role.Policies)
|
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
vals := make([][]byte, 0, count)
|
vals := make([][]byte, 0, count)
|
||||||
for _, link := range role.Policies {
|
for _, link := range r.Policies {
|
||||||
v, err := uuidStringToBytes(link.ID)
|
v, err := uuidStringToBytes(link.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -290,16 +252,16 @@ func bindingRulesTableSchema() *memdb.TableSchema {
|
||||||
Name: indexID,
|
Name: indexID,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[string, *structs.ACLBindingRule]{
|
||||||
readIndex: readIndex(indexFromUUIDString),
|
readIndex: indexFromUUIDString,
|
||||||
writeIndex: writeIndex(indexIDFromACLBindingRule),
|
writeIndex: indexIDFromACLBindingRule,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
indexAuthMethod: {
|
indexAuthMethod: {
|
||||||
Name: indexAuthMethod,
|
Name: indexAuthMethod,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[Query, *structs.ACLBindingRule]{
|
||||||
readIndex: indexFromQuery,
|
readIndex: indexFromQuery,
|
||||||
writeIndex: indexAuthMethodFromACLBindingRule,
|
writeIndex: indexAuthMethodFromACLBindingRule,
|
||||||
},
|
},
|
||||||
|
@ -308,12 +270,8 @@ func bindingRulesTableSchema() *memdb.TableSchema {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexIDFromACLBindingRule(raw interface{}) ([]byte, error) {
|
func indexIDFromACLBindingRule(r *structs.ACLBindingRule) ([]byte, error) {
|
||||||
p, ok := raw.(*structs.ACLBindingRule)
|
vv, err := uuidStringToBytes(r.ID)
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ACLBindingRule index", raw)
|
|
||||||
}
|
|
||||||
vv, err := uuidStringToBytes(p.ID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -321,27 +279,18 @@ func indexIDFromACLBindingRule(raw interface{}) ([]byte, error) {
|
||||||
return vv, err
|
return vv, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexAuthMethodFromACLBindingRule(raw interface{}) ([]byte, error) {
|
func indexAuthMethodFromACLBindingRule(r *structs.ACLBindingRule) ([]byte, error) {
|
||||||
p, ok := raw.(*structs.ACLBindingRule)
|
if r.AuthMethod == "" {
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ACLBindingRule index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.AuthMethod == "" {
|
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.String(strings.ToLower(p.AuthMethod))
|
b.String(strings.ToLower(r.AuthMethod))
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromUUIDString(raw interface{}) ([]byte, error) {
|
func indexFromUUIDString(raw string) ([]byte, error) {
|
||||||
index, ok := raw.(string)
|
uuid, err := uuidStringToBytes(raw)
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for UUID string index", raw)
|
|
||||||
}
|
|
||||||
uuid, err := uuidStringToBytes(index)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -350,17 +299,12 @@ func indexFromUUIDString(raw interface{}) ([]byte, error) {
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexAccessorIDFromACLToken(raw interface{}) ([]byte, error) {
|
func indexAccessorIDFromACLToken(t *structs.ACLToken) ([]byte, error) {
|
||||||
p, ok := raw.(*structs.ACLToken)
|
if t.AccessorID == "" {
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ACLToken index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.AccessorID == "" {
|
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
uuid, err := uuidStringToBytes(p.AccessorID)
|
uuid, err := uuidStringToBytes(t.AccessorID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -369,37 +313,23 @@ func indexAccessorIDFromACLToken(raw interface{}) ([]byte, error) {
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexSecretIDFromACLToken(raw interface{}) ([]byte, error) {
|
func indexSecretIDFromACLToken(t *structs.ACLToken) ([]byte, error) {
|
||||||
p, ok := raw.(*structs.ACLToken)
|
if t.SecretID == "" {
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ACLToken index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.SecretID == "" {
|
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.String(p.SecretID)
|
b.String(t.SecretID)
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromStringCaseSensitive(raw interface{}) ([]byte, error) {
|
func indexFromStringCaseSensitive(s string) ([]byte, error) {
|
||||||
q, ok := raw.(string)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for string prefix query", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.String(q)
|
b.String(s)
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexPoliciesFromACLToken(raw interface{}) ([][]byte, error) {
|
func indexPoliciesFromACLToken(token *structs.ACLToken) ([][]byte, error) {
|
||||||
token, ok := raw.(*structs.ACLToken)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ACLToken index", raw)
|
|
||||||
}
|
|
||||||
links := token.Policies
|
links := token.Policies
|
||||||
|
|
||||||
numLinks := len(links)
|
numLinks := len(links)
|
||||||
|
@ -420,11 +350,7 @@ func indexPoliciesFromACLToken(raw interface{}) ([][]byte, error) {
|
||||||
return vals, nil
|
return vals, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexRolesFromACLToken(raw interface{}) ([][]byte, error) {
|
func indexRolesFromACLToken(token *structs.ACLToken) ([][]byte, error) {
|
||||||
token, ok := raw.(*structs.ACLToken)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ACLToken index", raw)
|
|
||||||
}
|
|
||||||
links := token.Roles
|
links := token.Roles
|
||||||
|
|
||||||
numLinks := len(links)
|
numLinks := len(links)
|
||||||
|
@ -445,63 +371,45 @@ func indexRolesFromACLToken(raw interface{}) ([][]byte, error) {
|
||||||
return vals, nil
|
return vals, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromBoolQuery(raw interface{}) ([]byte, error) {
|
func indexFromBoolQuery(q BoolQuery) ([]byte, error) {
|
||||||
q, ok := raw.(BoolQuery)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for BoolQuery index", raw)
|
|
||||||
}
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.Bool(q.Value)
|
b.Bool(q.Value)
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexLocalFromACLToken(raw interface{}) ([]byte, error) {
|
func indexLocalFromACLToken(token *structs.ACLToken) ([]byte, error) {
|
||||||
p, ok := raw.(*structs.ACLToken)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ACLPolicy index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.Bool(p.Local)
|
b.Bool(token.Local)
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromTimeQuery(arg interface{}) ([]byte, error) {
|
func indexFromTimeQuery(q *TimeQuery) ([]byte, error) {
|
||||||
p, ok := arg.(*TimeQuery)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for TimeQuery index", arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.Time(p.Value)
|
b.Time(q.Value)
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexExpiresLocalFromACLToken(raw interface{}) ([]byte, error) {
|
func indexExpiresLocalFromACLToken(token *structs.ACLToken) ([]byte, error) {
|
||||||
return indexExpiresFromACLToken(raw, true)
|
return indexExpiresFromACLToken(token, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexExpiresGlobalFromACLToken(raw interface{}) ([]byte, error) {
|
func indexExpiresGlobalFromACLToken(token *structs.ACLToken) ([]byte, error) {
|
||||||
return indexExpiresFromACLToken(raw, false)
|
return indexExpiresFromACLToken(token, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexExpiresFromACLToken(raw interface{}, local bool) ([]byte, error) {
|
func indexExpiresFromACLToken(t *structs.ACLToken, local bool) ([]byte, error) {
|
||||||
p, ok := raw.(*structs.ACLToken)
|
if t.Local != local {
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ACLToken index", raw)
|
|
||||||
}
|
|
||||||
if p.Local != local {
|
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
if !p.HasExpirationTime() {
|
if !t.HasExpirationTime() {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
if p.ExpirationTime.Unix() < 0 {
|
if t.ExpirationTime.Unix() < 0 {
|
||||||
return nil, fmt.Errorf("token expiration time cannot be before the unix epoch: %s", p.ExpirationTime)
|
return nil, fmt.Errorf("token expiration time cannot be before the unix epoch: %s", t.ExpirationTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.Time(*p.ExpirationTime)
|
b.Time(*t.ExpirationTime)
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,7 +421,7 @@ func authMethodsTableSchema() *memdb.TableSchema {
|
||||||
Name: indexID,
|
Name: indexID,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[Query, *structs.ACLAuthMethod]{
|
||||||
readIndex: indexFromQuery,
|
readIndex: indexFromQuery,
|
||||||
writeIndex: indexNameFromACLAuthMethod,
|
writeIndex: indexNameFromACLAuthMethod,
|
||||||
},
|
},
|
||||||
|
@ -522,17 +430,12 @@ func authMethodsTableSchema() *memdb.TableSchema {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexNameFromACLAuthMethod(raw interface{}) ([]byte, error) {
|
func indexNameFromACLAuthMethod(m *structs.ACLAuthMethod) ([]byte, error) {
|
||||||
p, ok := raw.(*structs.ACLAuthMethod)
|
if m.Name == "" {
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ACLAuthMethod index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Name == "" {
|
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.String(strings.ToLower(p.Name))
|
b.String(strings.ToLower(m.Name))
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,14 +7,14 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
memdb "github.com/hashicorp/go-memdb"
|
"github.com/hashicorp/go-memdb"
|
||||||
"github.com/hashicorp/go-uuid"
|
"github.com/hashicorp/go-uuid"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/acl"
|
"github.com/hashicorp/consul/acl"
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
"github.com/hashicorp/consul/lib"
|
"github.com/hashicorp/consul/lib"
|
||||||
pbacl "github.com/hashicorp/consul/proto/pbacl"
|
"github.com/hashicorp/consul/proto/pbacl"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -3702,18 +3702,18 @@ func TestTokenPoliciesIndex(t *testing.T) {
|
||||||
Name: "global",
|
Name: "global",
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[*TimeQuery, *structs.ACLToken]{
|
||||||
readIndex: readIndex(indexFromTimeQuery),
|
readIndex: indexFromTimeQuery,
|
||||||
writeIndex: writeIndex(indexExpiresGlobalFromACLToken),
|
writeIndex: indexExpiresGlobalFromACLToken,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
localIndex := &memdb.IndexSchema{
|
localIndex := &memdb.IndexSchema{
|
||||||
Name: "local",
|
Name: "local",
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[*TimeQuery, *structs.ACLToken]{
|
||||||
readIndex: readIndex(indexFromTimeQuery),
|
readIndex: indexFromTimeQuery,
|
||||||
writeIndex: writeIndex(indexExpiresLocalFromACLToken),
|
writeIndex: indexExpiresLocalFromACLToken,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
schema := &memdb.DBSchema{
|
schema := &memdb.DBSchema{
|
||||||
|
|
|
@ -47,7 +47,7 @@ func nodesTableSchema() *memdb.TableSchema {
|
||||||
Name: indexID,
|
Name: indexID,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingleWithPrefix{
|
Indexer: indexerSingleWithPrefix[Query, *structs.Node, any]{
|
||||||
readIndex: indexWithPeerName(indexFromQuery),
|
readIndex: indexWithPeerName(indexFromQuery),
|
||||||
writeIndex: indexWithPeerName(indexFromNode),
|
writeIndex: indexWithPeerName(indexFromNode),
|
||||||
prefixIndex: prefixIndexFromQueryWithPeer,
|
prefixIndex: prefixIndexFromQueryWithPeer,
|
||||||
|
@ -57,7 +57,7 @@ func nodesTableSchema() *memdb.TableSchema {
|
||||||
Name: indexUUID,
|
Name: indexUUID,
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingleWithPrefix{
|
Indexer: indexerSingleWithPrefix[Query, *structs.Node, Query]{
|
||||||
readIndex: indexWithPeerName(indexFromUUIDQuery),
|
readIndex: indexWithPeerName(indexFromUUIDQuery),
|
||||||
writeIndex: indexWithPeerName(indexIDFromNode),
|
writeIndex: indexWithPeerName(indexIDFromNode),
|
||||||
prefixIndex: prefixIndexFromUUIDWithPeerQuery,
|
prefixIndex: prefixIndexFromUUIDWithPeerQuery,
|
||||||
|
@ -67,7 +67,7 @@ func nodesTableSchema() *memdb.TableSchema {
|
||||||
Name: indexMeta,
|
Name: indexMeta,
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerMulti{
|
Indexer: indexerMulti[KeyValueQuery, *structs.Node]{
|
||||||
readIndex: indexWithPeerName(indexFromKeyValueQuery),
|
readIndex: indexWithPeerName(indexFromKeyValueQuery),
|
||||||
writeIndexMulti: multiIndexWithPeerName(indexMetaFromNode),
|
writeIndexMulti: multiIndexWithPeerName(indexMetaFromNode),
|
||||||
},
|
},
|
||||||
|
@ -76,12 +76,7 @@ func nodesTableSchema() *memdb.TableSchema {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromNode(raw interface{}) ([]byte, error) {
|
func indexFromNode(n *structs.Node) ([]byte, error) {
|
||||||
n, ok := raw.(*structs.Node)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.Node index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.Node == "" {
|
if n.Node == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
@ -91,12 +86,7 @@ func indexFromNode(raw interface{}) ([]byte, error) {
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexIDFromNode(raw interface{}) ([]byte, error) {
|
func indexIDFromNode(n *structs.Node) ([]byte, error) {
|
||||||
n, ok := raw.(*structs.Node)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.Node index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.ID == "" {
|
if n.ID == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
@ -109,12 +99,7 @@ func indexIDFromNode(raw interface{}) ([]byte, error) {
|
||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexMetaFromNode(raw interface{}) ([][]byte, error) {
|
func indexMetaFromNode(n *structs.Node) ([][]byte, error) {
|
||||||
n, ok := raw.(*structs.Node)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.Node index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: this is case-sensitive!
|
// NOTE: this is case-sensitive!
|
||||||
|
|
||||||
vals := make([][]byte, 0, len(n.Meta))
|
vals := make([][]byte, 0, len(n.Meta))
|
||||||
|
@ -145,7 +130,7 @@ func servicesTableSchema() *memdb.TableSchema {
|
||||||
Name: indexID,
|
Name: indexID,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingleWithPrefix{
|
Indexer: indexerSingleWithPrefix[NodeServiceQuery, *structs.ServiceNode, any]{
|
||||||
readIndex: indexWithPeerName(indexFromNodeServiceQuery),
|
readIndex: indexWithPeerName(indexFromNodeServiceQuery),
|
||||||
writeIndex: indexWithPeerName(indexFromServiceNode),
|
writeIndex: indexWithPeerName(indexFromServiceNode),
|
||||||
prefixIndex: prefixIndexFromQueryWithPeer,
|
prefixIndex: prefixIndexFromQueryWithPeer,
|
||||||
|
@ -155,7 +140,7 @@ func servicesTableSchema() *memdb.TableSchema {
|
||||||
Name: indexNode,
|
Name: indexNode,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[Query, nodeIdentifier]{
|
||||||
readIndex: indexWithPeerName(indexFromQuery),
|
readIndex: indexWithPeerName(indexFromQuery),
|
||||||
writeIndex: indexWithPeerName(indexFromNodeIdentity),
|
writeIndex: indexWithPeerName(indexFromNodeIdentity),
|
||||||
},
|
},
|
||||||
|
@ -164,7 +149,7 @@ func servicesTableSchema() *memdb.TableSchema {
|
||||||
Name: indexService,
|
Name: indexService,
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[Query, *structs.ServiceNode]{
|
||||||
readIndex: indexWithPeerName(indexFromQuery),
|
readIndex: indexWithPeerName(indexFromQuery),
|
||||||
writeIndex: indexWithPeerName(indexServiceNameFromServiceNode),
|
writeIndex: indexWithPeerName(indexServiceNameFromServiceNode),
|
||||||
},
|
},
|
||||||
|
@ -173,7 +158,7 @@ func servicesTableSchema() *memdb.TableSchema {
|
||||||
Name: indexConnect,
|
Name: indexConnect,
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[Query, *structs.ServiceNode]{
|
||||||
readIndex: indexWithPeerName(indexFromQuery),
|
readIndex: indexWithPeerName(indexFromQuery),
|
||||||
writeIndex: indexWithPeerName(indexConnectNameFromServiceNode),
|
writeIndex: indexWithPeerName(indexConnectNameFromServiceNode),
|
||||||
},
|
},
|
||||||
|
@ -182,7 +167,7 @@ func servicesTableSchema() *memdb.TableSchema {
|
||||||
Name: indexKind,
|
Name: indexKind,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[Query, *structs.ServiceNode]{
|
||||||
readIndex: indexWithPeerName(indexFromQuery),
|
readIndex: indexWithPeerName(indexFromQuery),
|
||||||
writeIndex: indexWithPeerName(indexKindFromServiceNode),
|
writeIndex: indexWithPeerName(indexKindFromServiceNode),
|
||||||
},
|
},
|
||||||
|
@ -191,24 +176,14 @@ func servicesTableSchema() *memdb.TableSchema {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromNodeServiceQuery(arg interface{}) ([]byte, error) {
|
func indexFromNodeServiceQuery(q NodeServiceQuery) ([]byte, error) {
|
||||||
q, ok := arg.(NodeServiceQuery)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for NodeServiceQuery index", arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.String(strings.ToLower(q.Node))
|
b.String(strings.ToLower(q.Node))
|
||||||
b.String(strings.ToLower(q.Service))
|
b.String(strings.ToLower(q.Service))
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromServiceNode(raw interface{}) ([]byte, error) {
|
func indexFromServiceNode(n *structs.ServiceNode) ([]byte, error) {
|
||||||
n, ok := raw.(*structs.ServiceNode)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ServiceNode index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.Node == "" {
|
if n.Node == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
@ -219,14 +194,17 @@ func indexFromServiceNode(raw interface{}) ([]byte, error) {
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromNodeIdentity(raw interface{}) ([]byte, error) {
|
type nodeIdentifier interface {
|
||||||
n, ok := raw.(interface {
|
partitionIndexable
|
||||||
NodeIdentity() structs.Identity
|
peerIndexable
|
||||||
})
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for index, type must provide NodeIdentity()", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
NodeIdentity() structs.Identity
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ nodeIdentifier = (*structs.HealthCheck)(nil)
|
||||||
|
var _ nodeIdentifier = (*structs.ServiceNode)(nil)
|
||||||
|
|
||||||
|
func indexFromNodeIdentity(n nodeIdentifier) ([]byte, error) {
|
||||||
id := n.NodeIdentity()
|
id := n.NodeIdentity()
|
||||||
if id.ID == "" {
|
if id.ID == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
|
@ -237,12 +215,7 @@ func indexFromNodeIdentity(raw interface{}) ([]byte, error) {
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexServiceNameFromServiceNode(raw interface{}) ([]byte, error) {
|
func indexServiceNameFromServiceNode(n *structs.ServiceNode) ([]byte, error) {
|
||||||
n, ok := raw.(*structs.ServiceNode)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ServiceNode index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.Node == "" {
|
if n.Node == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
@ -252,12 +225,7 @@ func indexServiceNameFromServiceNode(raw interface{}) ([]byte, error) {
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexConnectNameFromServiceNode(raw interface{}) ([]byte, error) {
|
func indexConnectNameFromServiceNode(n *structs.ServiceNode) ([]byte, error) {
|
||||||
n, ok := raw.(*structs.ServiceNode)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ServiceNode index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
name, ok := connectNameFromServiceNode(n)
|
name, ok := connectNameFromServiceNode(n)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
|
@ -284,33 +252,23 @@ func connectNameFromServiceNode(sn *structs.ServiceNode) (string, bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexKindFromServiceNode(raw interface{}) ([]byte, error) {
|
func indexKindFromServiceNode(n *structs.ServiceNode) ([]byte, error) {
|
||||||
n, ok := raw.(*structs.ServiceNode)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.ServiceNode index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.String(strings.ToLower(string(n.ServiceKind)))
|
b.String(strings.ToLower(string(n.ServiceKind)))
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexWithPeerName adds peer name to the index.
|
// indexWithPeerName adds peer name to the index.
|
||||||
func indexWithPeerName(
|
func indexWithPeerName[T peerIndexable](
|
||||||
fn func(interface{}) ([]byte, error),
|
fn func(T) ([]byte, error),
|
||||||
) func(interface{}) ([]byte, error) {
|
) func(T) ([]byte, error) {
|
||||||
return func(raw interface{}) ([]byte, error) {
|
return func(e T) ([]byte, error) {
|
||||||
v, err := fn(raw)
|
v, err := fn(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
n, ok := raw.(peerIndexable)
|
peername := e.PeerOrEmpty()
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("type must be peerIndexable: %T", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
peername := n.PeerOrEmpty()
|
|
||||||
if peername == "" {
|
if peername == "" {
|
||||||
peername = structs.LocalPeerKeyword
|
peername = structs.LocalPeerKeyword
|
||||||
}
|
}
|
||||||
|
@ -322,20 +280,20 @@ func indexWithPeerName(
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiIndexWithPeerName adds peer name to multiple indices, and returns multiple indices.
|
// multiIndexWithPeerName adds peer name to multiple indices, and returns multiple indices.
|
||||||
func multiIndexWithPeerName(
|
func multiIndexWithPeerName[T any](
|
||||||
fn func(interface{}) ([][]byte, error),
|
fn func(T) ([][]byte, error),
|
||||||
) func(interface{}) ([][]byte, error) {
|
) func(T) ([][]byte, error) {
|
||||||
return func(raw interface{}) ([][]byte, error) {
|
return func(raw T) ([][]byte, error) {
|
||||||
|
n, ok := any(raw).(peerIndexable)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("type must be peerIndexable: %T", raw)
|
||||||
|
}
|
||||||
|
|
||||||
results, err := fn(raw)
|
results, err := fn(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
n, ok := raw.(peerIndexable)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("type must be peerIndexable: %T", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
peername := n.PeerOrEmpty()
|
peername := n.PeerOrEmpty()
|
||||||
if peername == "" {
|
if peername == "" {
|
||||||
peername = structs.LocalPeerKeyword
|
peername = structs.LocalPeerKeyword
|
||||||
|
@ -361,7 +319,7 @@ func checksTableSchema() *memdb.TableSchema {
|
||||||
Name: indexID,
|
Name: indexID,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingleWithPrefix{
|
Indexer: indexerSingleWithPrefix[NodeCheckQuery, *structs.HealthCheck, any]{
|
||||||
readIndex: indexWithPeerName(indexFromNodeCheckQuery),
|
readIndex: indexWithPeerName(indexFromNodeCheckQuery),
|
||||||
writeIndex: indexWithPeerName(indexFromHealthCheck),
|
writeIndex: indexWithPeerName(indexFromHealthCheck),
|
||||||
prefixIndex: prefixIndexFromQueryWithPeer,
|
prefixIndex: prefixIndexFromQueryWithPeer,
|
||||||
|
@ -371,7 +329,7 @@ func checksTableSchema() *memdb.TableSchema {
|
||||||
Name: indexStatus,
|
Name: indexStatus,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[Query, *structs.HealthCheck]{
|
||||||
readIndex: indexWithPeerName(indexFromQuery),
|
readIndex: indexWithPeerName(indexFromQuery),
|
||||||
writeIndex: indexWithPeerName(indexStatusFromHealthCheck),
|
writeIndex: indexWithPeerName(indexStatusFromHealthCheck),
|
||||||
},
|
},
|
||||||
|
@ -380,7 +338,7 @@ func checksTableSchema() *memdb.TableSchema {
|
||||||
Name: indexService,
|
Name: indexService,
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[Query, *structs.HealthCheck]{
|
||||||
readIndex: indexWithPeerName(indexFromQuery),
|
readIndex: indexWithPeerName(indexFromQuery),
|
||||||
writeIndex: indexWithPeerName(indexServiceNameFromHealthCheck),
|
writeIndex: indexWithPeerName(indexServiceNameFromHealthCheck),
|
||||||
},
|
},
|
||||||
|
@ -389,7 +347,7 @@ func checksTableSchema() *memdb.TableSchema {
|
||||||
Name: indexNode,
|
Name: indexNode,
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[Query, nodeIdentifier]{
|
||||||
readIndex: indexWithPeerName(indexFromQuery),
|
readIndex: indexWithPeerName(indexFromQuery),
|
||||||
writeIndex: indexWithPeerName(indexFromNodeIdentity),
|
writeIndex: indexWithPeerName(indexFromNodeIdentity),
|
||||||
},
|
},
|
||||||
|
@ -398,7 +356,7 @@ func checksTableSchema() *memdb.TableSchema {
|
||||||
Name: indexNodeService,
|
Name: indexNodeService,
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[NodeServiceQuery, *structs.HealthCheck]{
|
||||||
readIndex: indexWithPeerName(indexFromNodeServiceQuery),
|
readIndex: indexWithPeerName(indexFromNodeServiceQuery),
|
||||||
writeIndex: indexWithPeerName(indexNodeServiceFromHealthCheck),
|
writeIndex: indexWithPeerName(indexNodeServiceFromHealthCheck),
|
||||||
},
|
},
|
||||||
|
@ -407,28 +365,18 @@ func checksTableSchema() *memdb.TableSchema {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromNodeCheckQuery(raw interface{}) ([]byte, error) {
|
func indexFromNodeCheckQuery(q NodeCheckQuery) ([]byte, error) {
|
||||||
hc, ok := raw.(NodeCheckQuery)
|
if q.Node == "" || q.CheckID == "" {
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for NodeCheckQuery index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if hc.Node == "" || hc.CheckID == "" {
|
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.String(strings.ToLower(hc.Node))
|
b.String(strings.ToLower(q.Node))
|
||||||
b.String(strings.ToLower(hc.CheckID))
|
b.String(strings.ToLower(q.CheckID))
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromHealthCheck(raw interface{}) ([]byte, error) {
|
func indexFromHealthCheck(hc *structs.HealthCheck) ([]byte, error) {
|
||||||
hc, ok := raw.(*structs.HealthCheck)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.HealthCheck index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if hc.Node == "" || hc.CheckID == "" {
|
if hc.Node == "" || hc.CheckID == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
@ -439,12 +387,7 @@ func indexFromHealthCheck(raw interface{}) ([]byte, error) {
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexNodeServiceFromHealthCheck(raw interface{}) ([]byte, error) {
|
func indexNodeServiceFromHealthCheck(hc *structs.HealthCheck) ([]byte, error) {
|
||||||
hc, ok := raw.(*structs.HealthCheck)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.HealthCheck index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if hc.Node == "" {
|
if hc.Node == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
@ -455,12 +398,7 @@ func indexNodeServiceFromHealthCheck(raw interface{}) ([]byte, error) {
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexStatusFromHealthCheck(raw interface{}) ([]byte, error) {
|
func indexStatusFromHealthCheck(hc *structs.HealthCheck) ([]byte, error) {
|
||||||
hc, ok := raw.(*structs.HealthCheck)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.HealthCheck index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if hc.Status == "" {
|
if hc.Status == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
@ -470,12 +408,7 @@ func indexStatusFromHealthCheck(raw interface{}) ([]byte, error) {
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexServiceNameFromHealthCheck(raw interface{}) ([]byte, error) {
|
func indexServiceNameFromHealthCheck(hc *structs.HealthCheck) ([]byte, error) {
|
||||||
hc, ok := raw.(*structs.HealthCheck)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.HealthCheck index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if hc.ServiceName == "" {
|
if hc.ServiceName == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
@ -761,7 +694,7 @@ func kindServiceNameTableSchema() *memdb.TableSchema {
|
||||||
Name: indexID,
|
Name: indexID,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[any, any]{
|
||||||
readIndex: indexFromKindServiceName,
|
readIndex: indexFromKindServiceName,
|
||||||
writeIndex: indexFromKindServiceName,
|
writeIndex: indexFromKindServiceName,
|
||||||
},
|
},
|
||||||
|
@ -770,7 +703,7 @@ func kindServiceNameTableSchema() *memdb.TableSchema {
|
||||||
Name: indexKind,
|
Name: indexKind,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[enterpriseIndexable, enterpriseIndexable]{
|
||||||
readIndex: indexFromKindServiceNameKindOnly,
|
readIndex: indexFromKindServiceNameKindOnly,
|
||||||
writeIndex: indexFromKindServiceNameKindOnly,
|
writeIndex: indexFromKindServiceNameKindOnly,
|
||||||
},
|
},
|
||||||
|
@ -798,7 +731,7 @@ func (q KindServiceNameQuery) PartitionOrDefault() string {
|
||||||
return q.EnterpriseMeta.PartitionOrDefault()
|
return q.EnterpriseMeta.PartitionOrDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromKindServiceNameKindOnly(raw interface{}) ([]byte, error) {
|
func indexFromKindServiceNameKindOnly(raw enterpriseIndexable) ([]byte, error) {
|
||||||
switch x := raw.(type) {
|
switch x := raw.(type) {
|
||||||
case *KindServiceName:
|
case *KindServiceName:
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/go-memdb"
|
"github.com/hashicorp/go-memdb"
|
||||||
|
@ -27,7 +26,7 @@ func configTableSchema() *memdb.TableSchema {
|
||||||
Name: indexID,
|
Name: indexID,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingleWithPrefix{
|
Indexer: indexerSingleWithPrefix[any, structs.ConfigEntry, any]{
|
||||||
readIndex: indexFromConfigEntryKindName,
|
readIndex: indexFromConfigEntryKindName,
|
||||||
writeIndex: indexFromConfigEntry,
|
writeIndex: indexFromConfigEntry,
|
||||||
prefixIndex: indexFromConfigEntryKindName,
|
prefixIndex: indexFromConfigEntryKindName,
|
||||||
|
@ -55,12 +54,30 @@ func configTableSchema() *memdb.TableSchema {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromConfigEntry(raw interface{}) ([]byte, error) {
|
// configEntryIndexable is required because while structs.ConfigEntry
|
||||||
c, ok := raw.(structs.ConfigEntry)
|
// has a GetEnterpriseMeta method, it does not directly expose the
|
||||||
if !ok {
|
// required NamespaceOrDefault and PartitionOrDefault methods of
|
||||||
return nil, fmt.Errorf("type must be structs.ConfigEntry: %T", raw)
|
// enterpriseIndexable.
|
||||||
}
|
//
|
||||||
|
// Config entries that embed *acl.EnterpriseMeta will automatically
|
||||||
|
// implement this interface.
|
||||||
|
type configEntryIndexable interface {
|
||||||
|
structs.ConfigEntry
|
||||||
|
enterpriseIndexable
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ configEntryIndexable = (*structs.ExportedServicesConfigEntry)(nil)
|
||||||
|
var _ configEntryIndexable = (*structs.IngressGatewayConfigEntry)(nil)
|
||||||
|
var _ configEntryIndexable = (*structs.MeshConfigEntry)(nil)
|
||||||
|
var _ configEntryIndexable = (*structs.ProxyConfigEntry)(nil)
|
||||||
|
var _ configEntryIndexable = (*structs.ServiceConfigEntry)(nil)
|
||||||
|
var _ configEntryIndexable = (*structs.ServiceIntentionsConfigEntry)(nil)
|
||||||
|
var _ configEntryIndexable = (*structs.ServiceResolverConfigEntry)(nil)
|
||||||
|
var _ configEntryIndexable = (*structs.ServiceRouterConfigEntry)(nil)
|
||||||
|
var _ configEntryIndexable = (*structs.ServiceSplitterConfigEntry)(nil)
|
||||||
|
var _ configEntryIndexable = (*structs.TerminatingGatewayConfigEntry)(nil)
|
||||||
|
|
||||||
|
func indexFromConfigEntry(c structs.ConfigEntry) ([]byte, error) {
|
||||||
if c.GetName() == "" || c.GetKind() == "" {
|
if c.GetName() == "" || c.GetKind() == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
@ -73,12 +90,7 @@ func indexFromConfigEntry(raw interface{}) ([]byte, error) {
|
||||||
|
|
||||||
// indexKindFromConfigEntry indexes kinds without a namespace for any config
|
// indexKindFromConfigEntry indexes kinds without a namespace for any config
|
||||||
// entries that span all namespaces.
|
// entries that span all namespaces.
|
||||||
func indexKindFromConfigEntry(raw interface{}) ([]byte, error) {
|
func indexKindFromConfigEntry(c configEntryIndexable) ([]byte, error) {
|
||||||
c, ok := raw.(structs.ConfigEntry)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("type must be structs.ConfigEntry: %T", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.GetKind() == "" {
|
if c.GetKind() == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,7 @@ import (
|
||||||
|
|
||||||
const tableCoordinates = "coordinates"
|
const tableCoordinates = "coordinates"
|
||||||
|
|
||||||
func indexFromCoordinate(raw interface{}) ([]byte, error) {
|
func indexFromCoordinate(c *structs.Coordinate) ([]byte, error) {
|
||||||
c, ok := raw.(*structs.Coordinate)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.Coordinate index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Node == "" {
|
if c.Node == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
@ -29,12 +24,7 @@ func indexFromCoordinate(raw interface{}) ([]byte, error) {
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexNodeFromCoordinate(raw interface{}) ([]byte, error) {
|
func indexNodeFromCoordinate(c *structs.Coordinate) ([]byte, error) {
|
||||||
c, ok := raw.(*structs.Coordinate)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.Coordinate index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Node == "" {
|
if c.Node == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
@ -44,12 +34,7 @@ func indexNodeFromCoordinate(raw interface{}) ([]byte, error) {
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromCoordinateQuery(raw interface{}) ([]byte, error) {
|
func indexFromCoordinateQuery(q CoordinateQuery) ([]byte, error) {
|
||||||
q, ok := raw.(CoordinateQuery)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for CoordinateQuery index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if q.Node == "" {
|
if q.Node == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
@ -80,7 +65,7 @@ func coordinatesTableSchema() *memdb.TableSchema {
|
||||||
Name: indexID,
|
Name: indexID,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingleWithPrefix{
|
Indexer: indexerSingleWithPrefix[CoordinateQuery, *structs.Coordinate, any]{
|
||||||
readIndex: indexFromCoordinateQuery,
|
readIndex: indexFromCoordinateQuery,
|
||||||
writeIndex: indexFromCoordinate,
|
writeIndex: indexFromCoordinate,
|
||||||
prefixIndex: prefixIndexFromQueryNoNamespace,
|
prefixIndex: prefixIndexFromQueryNoNamespace,
|
||||||
|
@ -90,7 +75,7 @@ func coordinatesTableSchema() *memdb.TableSchema {
|
||||||
Name: indexNode,
|
Name: indexNode,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[Query, *structs.Coordinate]{
|
||||||
readIndex: indexFromQuery,
|
readIndex: indexFromQuery,
|
||||||
writeIndex: indexNodeFromCoordinate,
|
writeIndex: indexNodeFromCoordinate,
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,32 +15,42 @@ import (
|
||||||
// indexerSingle implements both memdb.Indexer and memdb.SingleIndexer. It may
|
// indexerSingle implements both memdb.Indexer and memdb.SingleIndexer. It may
|
||||||
// be used in a memdb.IndexSchema to specify functions that generate the index
|
// be used in a memdb.IndexSchema to specify functions that generate the index
|
||||||
// value for memdb.Txn operations.
|
// value for memdb.Txn operations.
|
||||||
type indexerSingle struct {
|
//
|
||||||
|
// R represents the type used to generate the read index.
|
||||||
|
// W represents the type used to generate the write index.
|
||||||
|
type indexerSingle[R, W any] struct {
|
||||||
// readIndex is used by memdb for Txn.Get, Txn.First, and other operations
|
// readIndex is used by memdb for Txn.Get, Txn.First, and other operations
|
||||||
// that read data.
|
// that read data.
|
||||||
readIndex
|
readIndex[R]
|
||||||
// writeIndex is used by memdb for Txn.Insert, Txn.Delete, for operations
|
// writeIndex is used by memdb for Txn.Insert, Txn.Delete, for operations
|
||||||
// that write data to the index.
|
// that write data to the index.
|
||||||
writeIndex
|
writeIndex[W]
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexerMulti implements both memdb.Indexer and memdb.MultiIndexer. It may
|
// indexerMulti implements both memdb.Indexer and memdb.MultiIndexer. It may
|
||||||
// be used in a memdb.IndexSchema to specify functions that generate the index
|
// be used in a memdb.IndexSchema to specify functions that generate the index
|
||||||
// value for memdb.Txn operations.
|
// value for memdb.Txn operations.
|
||||||
type indexerMulti struct {
|
//
|
||||||
|
// R represents the type used to generate the read index.
|
||||||
|
// W represents the type used to generate the write index.
|
||||||
|
type indexerMulti[R, W any] struct {
|
||||||
// readIndex is used by memdb for Txn.Get, Txn.First, and other operations
|
// readIndex is used by memdb for Txn.Get, Txn.First, and other operations
|
||||||
// that read data.
|
// that read data.
|
||||||
readIndex
|
readIndex[R]
|
||||||
// writeIndexMulti is used by memdb for Txn.Insert, Txn.Delete, for operations
|
// writeIndexMulti is used by memdb for Txn.Insert, Txn.Delete, for operations
|
||||||
// that write data to the index.
|
// that write data to the index.
|
||||||
writeIndexMulti
|
writeIndexMulti[W]
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexerSingleWithPrefix is a indexerSingle which also supports prefix queries.
|
// indexerSingleWithPrefix is a indexerSingle which also supports prefix queries.
|
||||||
type indexerSingleWithPrefix struct {
|
//
|
||||||
readIndex
|
// R represents the type used to generate the read index.
|
||||||
writeIndex
|
// W represents the type used to generate the write index.
|
||||||
prefixIndex
|
// P represents the type used to generate the prefix index.
|
||||||
|
type indexerSingleWithPrefix[R, W, P any] struct {
|
||||||
|
readIndex[R]
|
||||||
|
writeIndex[W]
|
||||||
|
prefixIndex[P]
|
||||||
}
|
}
|
||||||
|
|
||||||
// readIndex implements memdb.Indexer. It exists so that a function can be used
|
// readIndex implements memdb.Indexer. It exists so that a function can be used
|
||||||
|
@ -48,13 +58,18 @@ type indexerSingleWithPrefix struct {
|
||||||
//
|
//
|
||||||
// Unlike memdb.Indexer, a readIndex function accepts only a single argument. To
|
// Unlike memdb.Indexer, a readIndex function accepts only a single argument. To
|
||||||
// generate an index from multiple values, use a struct type with multiple fields.
|
// generate an index from multiple values, use a struct type with multiple fields.
|
||||||
type readIndex func(arg interface{}) ([]byte, error)
|
type readIndex[R any] func(arg R) ([]byte, error)
|
||||||
|
|
||||||
func (f readIndex) FromArgs(args ...interface{}) ([]byte, error) {
|
func (f readIndex[R]) FromArgs(args ...interface{}) ([]byte, error) {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return nil, fmt.Errorf("index supports only a single arg")
|
return nil, fmt.Errorf("index supports only a single arg")
|
||||||
}
|
}
|
||||||
return f(args[0])
|
arg, ok := args[0].(R)
|
||||||
|
if !ok {
|
||||||
|
var typ R
|
||||||
|
return nil, fmt.Errorf("unexpected type %T, does not implement %T", args[0], typ)
|
||||||
|
}
|
||||||
|
return f(arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
var errMissingValueForIndex = fmt.Errorf("object is missing a value for this index")
|
var errMissingValueForIndex = fmt.Errorf("object is missing a value for this index")
|
||||||
|
@ -65,10 +80,15 @@ var errMissingValueForIndex = fmt.Errorf("object is missing a value for this ind
|
||||||
// Instead of a bool return value, writeIndex expects errMissingValueForIndex to
|
// Instead of a bool return value, writeIndex expects errMissingValueForIndex to
|
||||||
// indicate that an index could not be build for the object. It will translate
|
// indicate that an index could not be build for the object. It will translate
|
||||||
// this error into a false value to satisfy the memdb.SingleIndexer interface.
|
// this error into a false value to satisfy the memdb.SingleIndexer interface.
|
||||||
type writeIndex func(raw interface{}) ([]byte, error)
|
type writeIndex[W any] func(raw W) ([]byte, error)
|
||||||
|
|
||||||
func (f writeIndex) FromObject(raw interface{}) (bool, []byte, error) {
|
func (f writeIndex[W]) FromObject(raw interface{}) (bool, []byte, error) {
|
||||||
v, err := f(raw)
|
obj, ok := raw.(W)
|
||||||
|
if !ok {
|
||||||
|
var typ W
|
||||||
|
return false, nil, fmt.Errorf("unexpected type %T, does not implement %T", raw, typ)
|
||||||
|
}
|
||||||
|
v, err := f(obj)
|
||||||
if errors.Is(err, errMissingValueForIndex) {
|
if errors.Is(err, errMissingValueForIndex) {
|
||||||
return false, nil, nil
|
return false, nil, nil
|
||||||
}
|
}
|
||||||
|
@ -81,10 +101,15 @@ func (f writeIndex) FromObject(raw interface{}) (bool, []byte, error) {
|
||||||
// Instead of a bool return value, writeIndexMulti expects errMissingValueForIndex to
|
// Instead of a bool return value, writeIndexMulti expects errMissingValueForIndex to
|
||||||
// indicate that an index could not be build for the object. It will translate
|
// indicate that an index could not be build for the object. It will translate
|
||||||
// this error into a false value to satisfy the memdb.MultiIndexer interface.
|
// this error into a false value to satisfy the memdb.MultiIndexer interface.
|
||||||
type writeIndexMulti func(raw interface{}) ([][]byte, error)
|
type writeIndexMulti[W any] func(raw W) ([][]byte, error)
|
||||||
|
|
||||||
func (f writeIndexMulti) FromObject(raw interface{}) (bool, [][]byte, error) {
|
func (f writeIndexMulti[W]) FromObject(raw interface{}) (bool, [][]byte, error) {
|
||||||
v, err := f(raw)
|
obj, ok := raw.(W)
|
||||||
|
if !ok {
|
||||||
|
var typ W
|
||||||
|
return false, nil, fmt.Errorf("unexpected type %T, does not implement %T", raw, typ)
|
||||||
|
}
|
||||||
|
v, err := f(obj)
|
||||||
if errors.Is(err, errMissingValueForIndex) {
|
if errors.Is(err, errMissingValueForIndex) {
|
||||||
return false, nil, nil
|
return false, nil, nil
|
||||||
}
|
}
|
||||||
|
@ -93,13 +118,18 @@ func (f writeIndexMulti) FromObject(raw interface{}) (bool, [][]byte, error) {
|
||||||
|
|
||||||
// prefixIndex implements memdb.PrefixIndexer. It exists so that a function
|
// prefixIndex implements memdb.PrefixIndexer. It exists so that a function
|
||||||
// can be used to provide this interface.
|
// can be used to provide this interface.
|
||||||
type prefixIndex func(args interface{}) ([]byte, error)
|
type prefixIndex[P any] func(args P) ([]byte, error)
|
||||||
|
|
||||||
func (f prefixIndex) PrefixFromArgs(args ...interface{}) ([]byte, error) {
|
func (f prefixIndex[P]) PrefixFromArgs(args ...interface{}) ([]byte, error) {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return nil, fmt.Errorf("index supports only a single arg")
|
return nil, fmt.Errorf("index supports only a single arg")
|
||||||
}
|
}
|
||||||
return f(args[0])
|
arg, ok := args[0].(P)
|
||||||
|
if !ok {
|
||||||
|
var typ P
|
||||||
|
return nil, fmt.Errorf("unexpected type %T, does not implement %T", args[0], typ)
|
||||||
|
}
|
||||||
|
return f(arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
const null = "\x00"
|
const null = "\x00"
|
||||||
|
@ -159,12 +189,7 @@ var _ singleValueID = (*Query)(nil)
|
||||||
var _ singleValueID = (*structs.Session)(nil)
|
var _ singleValueID = (*structs.Session)(nil)
|
||||||
|
|
||||||
// indexFromIDValue creates an index key from any struct that implements singleValueID
|
// indexFromIDValue creates an index key from any struct that implements singleValueID
|
||||||
func indexFromIDValueLowerCase(raw interface{}) ([]byte, error) {
|
func indexFromIDValueLowerCase(e singleValueID) ([]byte, error) {
|
||||||
e, ok := raw.(singleValueID)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T, does not implement singleValueID", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := strings.ToLower(e.IDValue())
|
v := strings.ToLower(e.IDValue())
|
||||||
if v == "" {
|
if v == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
|
@ -176,11 +201,7 @@ func indexFromIDValueLowerCase(raw interface{}) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexFromIDValue creates an index key from any struct that implements singleValueID
|
// indexFromIDValue creates an index key from any struct that implements singleValueID
|
||||||
func indexFromMultiValueID(raw interface{}) ([]byte, error) {
|
func indexFromMultiValueID(e multiValueID) ([]byte, error) {
|
||||||
e, ok := raw.(multiValueID)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T, does not implement multiValueID", raw)
|
|
||||||
}
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
for _, v := range e.IDValue() {
|
for _, v := range e.IDValue() {
|
||||||
if v == "" {
|
if v == "" {
|
||||||
|
|
|
@ -41,12 +41,7 @@ func kvsTableSchema() *memdb.TableSchema {
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexFromIDValue creates an index key from any struct that implements singleValueID
|
// indexFromIDValue creates an index key from any struct that implements singleValueID
|
||||||
func indexFromIDValue(raw interface{}) ([]byte, error) {
|
func indexFromIDValue(e singleValueID) ([]byte, error) {
|
||||||
e, ok := raw.(singleValueID)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T, does not implement singleValueID", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := e.IDValue()
|
v := e.IDValue()
|
||||||
if v == "" {
|
if v == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
|
|
|
@ -13,11 +13,11 @@ import (
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func kvsIndexer() indexerSingleWithPrefix {
|
func kvsIndexer() indexerSingleWithPrefix[singleValueID, singleValueID, any] {
|
||||||
return indexerSingleWithPrefix{
|
return indexerSingleWithPrefix[singleValueID, singleValueID, any]{
|
||||||
readIndex: readIndex(indexFromIDValue),
|
readIndex: indexFromIDValue,
|
||||||
writeIndex: writeIndex(indexFromIDValue),
|
writeIndex: indexFromIDValue,
|
||||||
prefixIndex: prefixIndex(prefixIndexForIDValue),
|
prefixIndex: prefixIndexForIDValue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,16 +27,16 @@ func peeringTableSchema() *memdb.TableSchema {
|
||||||
Name: indexID,
|
Name: indexID,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[string, *pbpeering.Peering]{
|
||||||
readIndex: readIndex(indexFromUUIDString),
|
readIndex: indexFromUUIDString,
|
||||||
writeIndex: writeIndex(indexIDFromPeering),
|
writeIndex: indexIDFromPeering,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
indexName: {
|
indexName: {
|
||||||
Name: indexName,
|
Name: indexName,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingleWithPrefix{
|
Indexer: indexerSingleWithPrefix[Query, *pbpeering.Peering, any]{
|
||||||
readIndex: indexPeeringFromQuery,
|
readIndex: indexPeeringFromQuery,
|
||||||
writeIndex: indexFromPeering,
|
writeIndex: indexFromPeering,
|
||||||
prefixIndex: prefixIndexFromQueryNoNamespace,
|
prefixIndex: prefixIndexFromQueryNoNamespace,
|
||||||
|
@ -46,7 +46,7 @@ func peeringTableSchema() *memdb.TableSchema {
|
||||||
Name: indexDeleted,
|
Name: indexDeleted,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[BoolQuery, *pbpeering.Peering]{
|
||||||
readIndex: indexDeletedFromBoolQuery,
|
readIndex: indexDeletedFromBoolQuery,
|
||||||
writeIndex: indexDeletedFromPeering,
|
writeIndex: indexDeletedFromPeering,
|
||||||
},
|
},
|
||||||
|
@ -63,7 +63,7 @@ func peeringTrustBundlesTableSchema() *memdb.TableSchema {
|
||||||
Name: indexID,
|
Name: indexID,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingleWithPrefix{
|
Indexer: indexerSingleWithPrefix[Query, *pbpeering.PeeringTrustBundle, any]{
|
||||||
readIndex: indexPeeringFromQuery, // same as peering table since we'll use the query.Value
|
readIndex: indexPeeringFromQuery, // same as peering table since we'll use the query.Value
|
||||||
writeIndex: indexFromPeeringTrustBundle,
|
writeIndex: indexFromPeeringTrustBundle,
|
||||||
prefixIndex: prefixIndexFromQueryNoNamespace,
|
prefixIndex: prefixIndexFromQueryNoNamespace,
|
||||||
|
@ -73,12 +73,7 @@ func peeringTrustBundlesTableSchema() *memdb.TableSchema {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexIDFromPeering(raw interface{}) ([]byte, error) {
|
func indexIDFromPeering(p *pbpeering.Peering) ([]byte, error) {
|
||||||
p, ok := raw.(*pbpeering.Peering)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for pbpeering.Peering index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.ID == "" {
|
if p.ID == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
@ -92,12 +87,7 @@ func indexIDFromPeering(raw interface{}) ([]byte, error) {
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexDeletedFromPeering(raw interface{}) ([]byte, error) {
|
func indexDeletedFromPeering(p *pbpeering.Peering) ([]byte, error) {
|
||||||
p, ok := raw.(*pbpeering.Peering)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for *pbpeering.Peering index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.Bool(!p.IsActive())
|
b.Bool(!p.IsActive())
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
|
|
|
@ -10,23 +10,13 @@ import (
|
||||||
"github.com/hashicorp/consul/proto/pbpeering"
|
"github.com/hashicorp/consul/proto/pbpeering"
|
||||||
)
|
)
|
||||||
|
|
||||||
func indexPeeringFromQuery(raw interface{}) ([]byte, error) {
|
func indexPeeringFromQuery(q Query) ([]byte, error) {
|
||||||
q, ok := raw.(Query)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for Query index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.String(strings.ToLower(q.Value))
|
b.String(strings.ToLower(q.Value))
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromPeering(raw interface{}) ([]byte, error) {
|
func indexFromPeering(p *pbpeering.Peering) ([]byte, error) {
|
||||||
p, ok := raw.(*pbpeering.Peering)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for structs.Peering index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Name == "" {
|
if p.Name == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
@ -36,12 +26,7 @@ func indexFromPeering(raw interface{}) ([]byte, error) {
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromPeeringTrustBundle(raw interface{}) ([]byte, error) {
|
func indexFromPeeringTrustBundle(ptb *pbpeering.PeeringTrustBundle) ([]byte, error) {
|
||||||
ptb, ok := raw.(*pbpeering.PeeringTrustBundle)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for pbpeering.PeeringTrustBundle index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ptb.PeerName == "" {
|
if ptb.PeerName == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,12 +60,7 @@ func (q MultiQuery) PartitionOrDefault() string {
|
||||||
|
|
||||||
// indexFromQuery builds an index key where Query.Value is lowercase, and is
|
// indexFromQuery builds an index key where Query.Value is lowercase, and is
|
||||||
// a required value.
|
// a required value.
|
||||||
func indexFromQuery(arg interface{}) ([]byte, error) {
|
func indexFromQuery(q Query) ([]byte, error) {
|
||||||
q, ok := arg.(Query)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for Query index", arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.String(strings.ToLower(q.Value))
|
b.String(strings.ToLower(q.Value))
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
|
@ -164,12 +159,8 @@ func (q KeyValueQuery) PartitionOrDefault() string {
|
||||||
return q.EnterpriseMeta.PartitionOrDefault()
|
return q.EnterpriseMeta.PartitionOrDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromKeyValueQuery(arg interface{}) ([]byte, error) {
|
func indexFromKeyValueQuery(q KeyValueQuery) ([]byte, error) {
|
||||||
// NOTE: this is case-sensitive!
|
// NOTE: this is case-sensitive!
|
||||||
q, ok := arg.(KeyValueQuery)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for Query index", arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.String(q.Key)
|
b.String(q.Key)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func prefixIndexFromQuery(arg interface{}) ([]byte, error) {
|
func prefixIndexFromQuery(arg any) ([]byte, error) {
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
switch v := arg.(type) {
|
switch v := arg.(type) {
|
||||||
case *acl.EnterpriseMeta:
|
case *acl.EnterpriseMeta:
|
||||||
|
@ -29,7 +29,7 @@ func prefixIndexFromQuery(arg interface{}) ([]byte, error) {
|
||||||
return nil, fmt.Errorf("unexpected type %T for Query prefix index", arg)
|
return nil, fmt.Errorf("unexpected type %T for Query prefix index", arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func prefixIndexFromQueryWithPeer(arg interface{}) ([]byte, error) {
|
func prefixIndexFromQueryWithPeer(arg any) ([]byte, error) {
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
switch v := arg.(type) {
|
switch v := arg.(type) {
|
||||||
case *acl.EnterpriseMeta:
|
case *acl.EnterpriseMeta:
|
||||||
|
@ -58,12 +58,7 @@ func prefixIndexFromQueryNoNamespace(arg interface{}) ([]byte, error) {
|
||||||
|
|
||||||
// indexFromAuthMethodQuery builds an index key where Query.Value is lowercase, and is
|
// indexFromAuthMethodQuery builds an index key where Query.Value is lowercase, and is
|
||||||
// a required value.
|
// a required value.
|
||||||
func indexFromAuthMethodQuery(arg interface{}) ([]byte, error) {
|
func indexFromAuthMethodQuery(q AuthMethodQuery) ([]byte, error) {
|
||||||
q, ok := arg.(AuthMethodQuery)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for Query index", arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.String(strings.ToLower(q.Value))
|
b.String(strings.ToLower(q.Value))
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
|
|
|
@ -84,7 +84,7 @@ func indexTableSchema() *memdb.TableSchema {
|
||||||
Name: indexID,
|
Name: indexID,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: true,
|
Unique: true,
|
||||||
Indexer: indexerSingle{
|
Indexer: indexerSingle[string, *IndexEntry]{
|
||||||
readIndex: indexFromString,
|
readIndex: indexFromString,
|
||||||
writeIndex: indexNameFromIndexEntry,
|
writeIndex: indexNameFromIndexEntry,
|
||||||
},
|
},
|
||||||
|
@ -93,39 +93,37 @@ func indexTableSchema() *memdb.TableSchema {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexNameFromIndexEntry(raw interface{}) ([]byte, error) {
|
func indexNameFromIndexEntry(e *IndexEntry) ([]byte, error) {
|
||||||
p, ok := raw.(*IndexEntry)
|
if e.Key == "" {
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for IndexEntry index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Key == "" {
|
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.String(strings.ToLower(p.Key))
|
b.String(strings.ToLower(e.Key))
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexFromString(raw interface{}) ([]byte, error) {
|
func indexFromString(s string) ([]byte, error) {
|
||||||
q, ok := raw.(string)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for string prefix query", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.String(strings.ToLower(q))
|
b.String(strings.ToLower(s))
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexDeletedFromBoolQuery(raw interface{}) ([]byte, error) {
|
func indexDeletedFromBoolQuery(q BoolQuery) ([]byte, error) {
|
||||||
q, ok := raw.(BoolQuery)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T for BoolQuery index", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
b.Bool(q.Value)
|
b.Bool(q.Value)
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type enterpriseIndexable interface {
|
||||||
|
partitionIndexable
|
||||||
|
namespaceIndexable
|
||||||
|
}
|
||||||
|
|
||||||
|
type partitionIndexable interface {
|
||||||
|
PartitionOrDefault() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type namespaceIndexable interface {
|
||||||
|
NamespaceOrDefault() string
|
||||||
|
}
|
||||||
|
|
|
@ -19,12 +19,7 @@ const (
|
||||||
indexNodeCheck = "node_check"
|
indexNodeCheck = "node_check"
|
||||||
)
|
)
|
||||||
|
|
||||||
func indexFromSession(raw interface{}) ([]byte, error) {
|
func indexFromSession(e *structs.Session) ([]byte, error) {
|
||||||
e, ok := raw.(*structs.Session)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T, does not implement *structs.Session", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := strings.ToLower(e.ID)
|
v := strings.ToLower(e.ID)
|
||||||
if v == "" {
|
if v == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
|
@ -86,12 +81,7 @@ func sessionChecksTableSchema() *memdb.TableSchema {
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexNodeFromSession creates an index key from *structs.Session
|
// indexNodeFromSession creates an index key from *structs.Session
|
||||||
func indexNodeFromSession(raw interface{}) ([]byte, error) {
|
func indexNodeFromSession(e *structs.Session) ([]byte, error) {
|
||||||
e, ok := raw.(*structs.Session)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T, does not implement *structs.Session", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := strings.ToLower(e.Node)
|
v := strings.ToLower(e.Node)
|
||||||
if v == "" {
|
if v == "" {
|
||||||
return nil, errMissingValueForIndex
|
return nil, errMissingValueForIndex
|
||||||
|
@ -103,12 +93,7 @@ func indexNodeFromSession(raw interface{}) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexFromNodeCheckIDSession creates an index key from sessionCheck
|
// indexFromNodeCheckIDSession creates an index key from sessionCheck
|
||||||
func indexFromNodeCheckIDSession(raw interface{}) ([]byte, error) {
|
func indexFromNodeCheckIDSession(e *sessionCheck) ([]byte, error) {
|
||||||
e, ok := raw.(*sessionCheck)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T, does not implement sessionCheck", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
v := strings.ToLower(e.Node)
|
v := strings.ToLower(e.Node)
|
||||||
if v == "" {
|
if v == "" {
|
||||||
|
@ -132,12 +117,7 @@ func indexFromNodeCheckIDSession(raw interface{}) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexSessionCheckFromSession creates an index key from sessionCheck
|
// indexSessionCheckFromSession creates an index key from sessionCheck
|
||||||
func indexSessionCheckFromSession(raw interface{}) ([]byte, error) {
|
func indexSessionCheckFromSession(e *sessionCheck) ([]byte, error) {
|
||||||
e, ok := raw.(*sessionCheck)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T, does not implement *sessionCheck", raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
v := strings.ToLower(e.Session)
|
v := strings.ToLower(e.Session)
|
||||||
if v == "" {
|
if v == "" {
|
||||||
|
|
|
@ -14,48 +14,44 @@ import (
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
func sessionIndexer() indexerSingleWithPrefix {
|
func sessionIndexer() indexerSingleWithPrefix[Query, *structs.Session, any] {
|
||||||
return indexerSingleWithPrefix{
|
return indexerSingleWithPrefix[Query, *structs.Session, any]{
|
||||||
readIndex: readIndex(indexFromQuery),
|
readIndex: indexFromQuery,
|
||||||
writeIndex: writeIndex(indexFromSession),
|
writeIndex: indexFromSession,
|
||||||
prefixIndex: prefixIndex(prefixIndexFromQuery),
|
prefixIndex: prefixIndexFromQuery,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nodeSessionsIndexer() indexerSingle {
|
func nodeSessionsIndexer() indexerSingle[singleValueID, *structs.Session] {
|
||||||
return indexerSingle{
|
return indexerSingle[singleValueID, *structs.Session]{
|
||||||
readIndex: readIndex(indexFromIDValueLowerCase),
|
readIndex: indexFromIDValueLowerCase,
|
||||||
writeIndex: writeIndex(indexNodeFromSession),
|
writeIndex: indexNodeFromSession,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func idCheckIndexer() indexerSingle {
|
func idCheckIndexer() indexerSingle[*sessionCheck, *sessionCheck] {
|
||||||
return indexerSingle{
|
return indexerSingle[*sessionCheck, *sessionCheck]{
|
||||||
readIndex: indexFromNodeCheckIDSession,
|
readIndex: indexFromNodeCheckIDSession,
|
||||||
writeIndex: indexFromNodeCheckIDSession,
|
writeIndex: indexFromNodeCheckIDSession,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sessionCheckIndexer() indexerSingle {
|
func sessionCheckIndexer() indexerSingle[Query, *sessionCheck] {
|
||||||
return indexerSingle{
|
return indexerSingle[Query, *sessionCheck]{
|
||||||
readIndex: indexFromQuery,
|
readIndex: indexFromQuery,
|
||||||
writeIndex: indexSessionCheckFromSession,
|
writeIndex: indexSessionCheckFromSession,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nodeChecksIndexer() indexerSingle {
|
func nodeChecksIndexer() indexerSingle[multiValueID, *sessionCheck] {
|
||||||
return indexerSingle{
|
return indexerSingle[multiValueID, *sessionCheck]{
|
||||||
readIndex: indexFromMultiValueID,
|
readIndex: indexFromMultiValueID,
|
||||||
writeIndex: indexFromNodeCheckID,
|
writeIndex: indexFromNodeCheckID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexFromNodeCheckID creates an index key from a sessionCheck structure
|
// indexFromNodeCheckID creates an index key from a sessionCheck structure
|
||||||
func indexFromNodeCheckID(raw interface{}) ([]byte, error) {
|
func indexFromNodeCheckID(e *sessionCheck) ([]byte, error) {
|
||||||
e, ok := raw.(*sessionCheck)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected type %T, does not implement *structs.Session", raw)
|
|
||||||
}
|
|
||||||
var b indexBuilder
|
var b indexBuilder
|
||||||
v := strings.ToLower(e.Node)
|
v := strings.ToLower(e.Node)
|
||||||
if v == "" {
|
if v == "" {
|
||||||
|
|
Loading…
Reference in New Issue