diff --git a/agent/consul/state/acl.go b/agent/consul/state/acl.go index bebe9996c1..e618ea25fa 100644 --- a/agent/consul/state/acl.go +++ b/agent/consul/state/acl.go @@ -1371,7 +1371,8 @@ func aclRoleSetTxn(tx *txn, idx uint64, role *structs.ACLRole, allowMissing bool } // ensure the name is unique (cannot conflict with another role with a different ID) - _, nameMatch, err := aclRoleGetByName(tx, role.Name, &role.EnterpriseMeta) + q := Query{EnterpriseMeta: role.EnterpriseMeta, Value: role.Name} + nameMatch, err := tx.First(tableACLRoles, indexName, q) if err != nil { return fmt.Errorf("failed acl role lookup: %v", err) } @@ -1424,6 +1425,15 @@ func (s *Store) ACLRoleGetByName(ws memdb.WatchSet, name string, entMeta *struct return s.aclRoleGet(ws, name, aclRoleGetByName, entMeta) } +func aclRoleGetByName(tx ReadTxn, name string, entMeta *structs.EnterpriseMeta) (<-chan struct{}, interface{}, error) { + // TODO: accept non-pointer value + if entMeta == nil { + entMeta = structs.DefaultEnterpriseMeta() + } + q := Query{EnterpriseMeta: *entMeta, Value: name} + return tx.FirstWatch(tableACLRoles, indexName, q) +} + func (s *Store) ACLRoleBatchGet(ws memdb.WatchSet, ids []string) (uint64, structs.ACLRoles, error) { tx := s.db.Txn(false) defer tx.Abort() @@ -1488,7 +1498,7 @@ func (s *Store) ACLRoleList(ws memdb.WatchSet, policy string, entMeta *structs.E if policy != "" { iter, err = aclRoleListByPolicy(tx, policy, entMeta) } else { - iter, err = aclRoleList(tx, entMeta) + iter, err = tx.Get(tableACLRoles, indexName+"_prefix", entMeta) } if err != nil { diff --git a/agent/consul/state/acl_oss.go b/agent/consul/state/acl_oss.go index f53c5bd507..92abc2eae5 100644 --- a/agent/consul/state/acl_oss.go +++ b/agent/consul/state/acl_oss.go @@ -38,6 +38,21 @@ func indexNameFromACLPolicy(raw interface{}) ([]byte, error) { return b.Bytes(), nil } +func indexNameFromACLRole(raw interface{}) ([]byte, error) { + p, ok := raw.(*structs.ACLRole) + if !ok { + return nil, fmt.Errorf("unexpected type %T for structs.ACLRole index", raw) + } + + if p.Name == "" { + return nil, errMissingValueForIndex + } + + var b indexBuilder + b.String(strings.ToLower(p.Name)) + return b.Bytes(), nil +} + func aclPolicyGetByID(tx ReadTxn, id string, _ *structs.EnterpriseMeta) (<-chan struct{}, interface{}, error) { return tx.FirstWatch(tableACLPolicies, indexID, id) } @@ -159,14 +174,6 @@ func aclRoleGetByID(tx ReadTxn, id string, _ *structs.EnterpriseMeta) (<-chan st return tx.FirstWatch(tableACLRoles, indexID, id) } -func aclRoleGetByName(tx ReadTxn, name string, _ *structs.EnterpriseMeta) (<-chan struct{}, interface{}, error) { - return tx.FirstWatch(tableACLRoles, indexName, name) -} - -func aclRoleList(tx ReadTxn, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) { - return tx.Get(tableACLRoles, indexID) -} - func aclRoleListByPolicy(tx ReadTxn, policy string, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) { return tx.Get(tableACLRoles, indexPolicies, policy) } diff --git a/agent/consul/state/acl_oss_test.go b/agent/consul/state/acl_oss_test.go index 6d4b094177..39cb3846fb 100644 --- a/agent/consul/state/acl_oss_test.go +++ b/agent/consul/state/acl_oss_test.go @@ -56,7 +56,7 @@ func testIndexerTableACLRoles() map[string]indexerTestCase { }, indexName: { read: indexValue{ - source: "RoLe", + source: Query{Value: "RoLe"}, expected: []byte("role\x00"), }, write: indexValue{ diff --git a/agent/consul/state/acl_schema.go b/agent/consul/state/acl_schema.go index 0126b5b90b..c692596bca 100644 --- a/agent/consul/state/acl_schema.go +++ b/agent/consul/state/acl_schema.go @@ -151,9 +151,10 @@ func rolesTableSchema() *memdb.TableSchema { Name: indexName, AllowMissing: false, Unique: true, - Indexer: &memdb.StringFieldIndex{ - Field: "Name", - Lowercase: true, + Indexer: indexerSingleWithPrefix{ + readIndex: readIndex(indexFromQuery), + writeIndex: writeIndex(indexNameFromACLRole), + prefixIndex: prefixIndex(prefixIndexFromQuery), }, }, indexPolicies: { diff --git a/agent/consul/state/testdata/TestStateStoreSchema.golden b/agent/consul/state/testdata/TestStateStoreSchema.golden index 4a6b752557..227f947e26 100644 --- a/agent/consul/state/testdata/TestStateStoreSchema.golden +++ b/agent/consul/state/testdata/TestStateStoreSchema.golden @@ -18,7 +18,7 @@ table=acl-roles index=id unique indexer=github.com/hashicorp/go-memdb.UUIDFieldIndex Field=ID index=name unique - indexer=github.com/hashicorp/go-memdb.StringFieldIndex Field=Name Lowercase=true + indexer=github.com/hashicorp/consul/agent/consul/state.indexerSingleWithPrefix readIndex=github.com/hashicorp/consul/agent/consul/state.indexFromQuery writeIndex=github.com/hashicorp/consul/agent/consul/state.indexNameFromACLRole prefixIndex=github.com/hashicorp/consul/agent/consul/state.prefixIndexFromQuery index=policies allow-missing indexer=github.com/hashicorp/consul/agent/consul/state.RolePoliciesIndex