Convert logical.InmemStorage to a wrapper around physical/inmem.

The original reason for the split was physical's dependencies, but those
haven't been onerous for a long time. Meanwhile it's a totally separate
implementation so we could be getting faulty results from tests. Get rid
of it and use the unified physical/inmem.
This commit is contained in:
Jeff Mitchell 2018-02-12 11:16:13 -05:00
parent 2ff01bb3ec
commit 609648de4f
2 changed files with 63 additions and 50 deletions

View file

@ -2,10 +2,10 @@ package logical
import ( import (
"context" "context"
"strings"
"sync" "sync"
radix "github.com/armon/go-radix" "github.com/hashicorp/vault/physical"
"github.com/hashicorp/vault/physical/inmem"
) )
// InmemStorage implements Storage and stores all data in memory. It is // InmemStorage implements Storage and stores all data in memory. It is
@ -13,79 +13,55 @@ import (
// having to load all of physical's dependencies (which are legion) just to // having to load all of physical's dependencies (which are legion) just to
// have some testing storage. // have some testing storage.
type InmemStorage struct { type InmemStorage struct {
sync.RWMutex underlying physical.Backend
root *radix.Tree once sync.Once
once sync.Once
} }
func (s *InmemStorage) Get(ctx context.Context, key string) (*StorageEntry, error) { func (s *InmemStorage) Get(ctx context.Context, key string) (*StorageEntry, error) {
s.once.Do(s.init) s.once.Do(s.init)
s.RLock() entry, err := s.underlying.Get(ctx, key)
defer s.RUnlock() if err != nil {
return nil, err
if raw, ok := s.root.Get(key); ok {
se := raw.(*StorageEntry)
return &StorageEntry{
Key: se.Key,
Value: se.Value,
}, nil
} }
if entry == nil {
return nil, nil return nil, nil
}
return &StorageEntry{
Key: entry.Key,
Value: entry.Value,
SealWrap: entry.SealWrap,
}, nil
} }
func (s *InmemStorage) Put(ctx context.Context, entry *StorageEntry) error { func (s *InmemStorage) Put(ctx context.Context, entry *StorageEntry) error {
s.once.Do(s.init) s.once.Do(s.init)
s.Lock() return s.underlying.Put(ctx, &physical.Entry{
defer s.Unlock() Key: entry.Key,
Value: entry.Value,
s.root.Insert(entry.Key, &StorageEntry{ SealWrap: entry.SealWrap,
Key: entry.Key,
Value: entry.Value,
}) })
return nil
} }
func (s *InmemStorage) Delete(ctx context.Context, key string) error { func (s *InmemStorage) Delete(ctx context.Context, key string) error {
s.once.Do(s.init) s.once.Do(s.init)
s.Lock() return s.underlying.Delete(ctx, key)
defer s.Unlock()
s.root.Delete(key)
return nil
} }
func (s *InmemStorage) List(ctx context.Context, prefix string) ([]string, error) { func (s *InmemStorage) List(ctx context.Context, prefix string) ([]string, error) {
s.once.Do(s.init) s.once.Do(s.init)
s.RLock() return s.underlying.List(ctx, prefix)
defer s.RUnlock() }
var out []string func (s *InmemStorage) Underlying() *inmem.InmemBackend {
seen := make(map[string]interface{}) s.once.Do(s.init)
walkFn := func(s string, v interface{}) bool {
trimmed := strings.TrimPrefix(s, prefix)
sep := strings.Index(trimmed, "/")
if sep == -1 {
out = append(out, trimmed)
} else {
trimmed = trimmed[:sep+1]
if _, ok := seen[trimmed]; !ok {
out = append(out, trimmed)
seen[trimmed] = struct{}{}
}
}
return false
}
s.root.WalkPrefix(prefix, walkFn)
return out, nil
return s.underlying.(*inmem.InmemBackend)
} }
func (s *InmemStorage) init() { func (s *InmemStorage) init() {
s.root = radix.New() s.underlying, _ = inmem.NewInmem(nil, nil)
} }

View file

@ -2,8 +2,10 @@ package inmem
import ( import (
"context" "context"
"errors"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"github.com/hashicorp/vault/physical" "github.com/hashicorp/vault/physical"
log "github.com/mgutz/logxi/v1" log "github.com/mgutz/logxi/v1"
@ -19,6 +21,13 @@ var _ physical.Lock = (*InmemLock)(nil)
var _ physical.Transactional = (*TransactionalInmemBackend)(nil) var _ physical.Transactional = (*TransactionalInmemBackend)(nil)
var _ physical.Transactional = (*TransactionalInmemHABackend)(nil) var _ physical.Transactional = (*TransactionalInmemHABackend)(nil)
var (
PutDisabledError = errors.New("put operations disabled in inmem backend")
GetDisabledError = errors.New("get operations disabled in inmem backend")
DeleteDisabledError = errors.New("delete operations disabled in inmem backend")
ListDisabledError = errors.New("list operations disabled in inmem backend")
)
// InmemBackend is an in-memory only physical backend. It is useful // InmemBackend is an in-memory only physical backend. It is useful
// for testing and development situations where the data is not // for testing and development situations where the data is not
// expected to be durable. // expected to be durable.
@ -27,6 +36,10 @@ type InmemBackend struct {
root *radix.Tree root *radix.Tree
permitPool *physical.PermitPool permitPool *physical.PermitPool
logger log.Logger logger log.Logger
FailGet *uint32
FailPut *uint32
FailDelete *uint32
FailList *uint32
} }
type TransactionalInmemBackend struct { type TransactionalInmemBackend struct {
@ -39,6 +52,10 @@ func NewInmem(_ map[string]string, logger log.Logger) (physical.Backend, error)
root: radix.New(), root: radix.New(),
permitPool: physical.NewPermitPool(physical.DefaultParallelOperations), permitPool: physical.NewPermitPool(physical.DefaultParallelOperations),
logger: logger, logger: logger,
FailGet: new(uint32),
FailPut: new(uint32),
FailDelete: new(uint32),
FailList: new(uint32),
} }
return in, nil return in, nil
} }
@ -51,6 +68,10 @@ func NewTransactionalInmem(_ map[string]string, logger log.Logger) (physical.Bac
root: radix.New(), root: radix.New(),
permitPool: physical.NewPermitPool(1), permitPool: physical.NewPermitPool(1),
logger: logger, logger: logger,
FailGet: new(uint32),
FailPut: new(uint32),
FailDelete: new(uint32),
FailList: new(uint32),
}, },
} }
return in, nil return in, nil
@ -68,6 +89,10 @@ func (i *InmemBackend) Put(ctx context.Context, entry *physical.Entry) error {
} }
func (i *InmemBackend) PutInternal(ctx context.Context, entry *physical.Entry) error { func (i *InmemBackend) PutInternal(ctx context.Context, entry *physical.Entry) error {
if i.FailPut != nil && atomic.LoadUint32(i.FailPut) != 0 {
return PutDisabledError
}
i.root.Insert(entry.Key, entry.Value) i.root.Insert(entry.Key, entry.Value)
return nil return nil
} }
@ -84,6 +109,10 @@ func (i *InmemBackend) Get(ctx context.Context, key string) (*physical.Entry, er
} }
func (i *InmemBackend) GetInternal(ctx context.Context, key string) (*physical.Entry, error) { func (i *InmemBackend) GetInternal(ctx context.Context, key string) (*physical.Entry, error) {
if i.FailGet != nil && atomic.LoadUint32(i.FailGet) != 0 {
return nil, GetDisabledError
}
if raw, ok := i.root.Get(key); ok { if raw, ok := i.root.Get(key); ok {
return &physical.Entry{ return &physical.Entry{
Key: key, Key: key,
@ -105,6 +134,10 @@ func (i *InmemBackend) Delete(ctx context.Context, key string) error {
} }
func (i *InmemBackend) DeleteInternal(ctx context.Context, key string) error { func (i *InmemBackend) DeleteInternal(ctx context.Context, key string) error {
if i.FailDelete != nil && atomic.LoadUint32(i.FailDelete) != 0 {
return DeleteDisabledError
}
i.root.Delete(key) i.root.Delete(key)
return nil return nil
} }
@ -122,6 +155,10 @@ func (i *InmemBackend) List(ctx context.Context, prefix string) ([]string, error
} }
func (i *InmemBackend) ListInternal(prefix string) ([]string, error) { func (i *InmemBackend) ListInternal(prefix string) ([]string, error) {
if i.FailList != nil && atomic.LoadUint32(i.FailList) != 0 {
return nil, ListDisabledError
}
var out []string var out []string
seen := make(map[string]interface{}) seen := make(map[string]interface{})
walkFn := func(s string, v interface{}) bool { walkFn := func(s string, v interface{}) bool {