mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-20 03:11:46 +00:00
71301983bd
* feat: add read-only EC2 platform inventory for account termination * fix: drop placement-group member instance IDs from the platform inventory reply
112 lines
3.1 KiB
Go
112 lines
3.1 KiB
Go
// Package readonlystore wraps an object store or a JetStream KV bucket so that
|
|
// any write fails the test. It exists to prove a code path is read-only, which
|
|
// an assertion on the final store contents cannot: a write that is undone
|
|
// before the check would pass it.
|
|
package readonlystore
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
"github.com/aws/aws-sdk-go/service/s3"
|
|
"github.com/mulgadc/spinifex/spinifex/providers/objectstore"
|
|
"github.com/nats-io/nats.go/jetstream"
|
|
)
|
|
|
|
// ErrWrite is returned by every write after the test has been failed.
|
|
var ErrWrite = errors.New("write to a read-only store")
|
|
|
|
// ObjectStore fails the test on any write and records every key it reads.
|
|
type ObjectStore struct {
|
|
objectstore.ObjectStore
|
|
|
|
t testing.TB
|
|
|
|
mu sync.Mutex
|
|
gets []string
|
|
}
|
|
|
|
var _ objectstore.ObjectStore = (*ObjectStore)(nil)
|
|
|
|
// NewObjectStore wraps inner for t.
|
|
func NewObjectStore(t testing.TB, inner objectstore.ObjectStore) *ObjectStore {
|
|
return &ObjectStore{ObjectStore: inner, t: t}
|
|
}
|
|
|
|
func (s *ObjectStore) GetObject(ctx context.Context, in *s3.GetObjectInput) (*s3.GetObjectOutput, error) {
|
|
s.mu.Lock()
|
|
s.gets = append(s.gets, aws.StringValue(in.Key))
|
|
s.mu.Unlock()
|
|
return s.ObjectStore.GetObject(ctx, in)
|
|
}
|
|
|
|
// Gets returns every key read so far.
|
|
func (s *ObjectStore) Gets() []string {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
return append([]string(nil), s.gets...)
|
|
}
|
|
|
|
func (s *ObjectStore) PutObject(_ context.Context, in *s3.PutObjectInput) (*s3.PutObjectOutput, error) {
|
|
s.t.Errorf("read-only store: PutObject %s", aws.StringValue(in.Key))
|
|
return nil, ErrWrite
|
|
}
|
|
|
|
func (s *ObjectStore) DeleteObject(_ context.Context, in *s3.DeleteObjectInput) (*s3.DeleteObjectOutput, error) {
|
|
s.t.Errorf("read-only store: DeleteObject %s", aws.StringValue(in.Key))
|
|
return nil, ErrWrite
|
|
}
|
|
|
|
func (s *ObjectStore) EnsureBucket(_ context.Context, bucket string) error {
|
|
s.t.Errorf("read-only store: EnsureBucket %s", bucket)
|
|
return ErrWrite
|
|
}
|
|
|
|
// KV fails the test on any write to the wrapped bucket.
|
|
type KV struct {
|
|
jetstream.KeyValue
|
|
|
|
t testing.TB
|
|
}
|
|
|
|
// NewKV wraps inner for t.
|
|
func NewKV(t testing.TB, inner jetstream.KeyValue) *KV {
|
|
return &KV{KeyValue: inner, t: t}
|
|
}
|
|
|
|
func (k *KV) write(op, key string) error {
|
|
k.t.Errorf("read-only KV %s: %s %s", k.Bucket(), op, key)
|
|
return ErrWrite
|
|
}
|
|
|
|
func (k *KV) Put(_ context.Context, key string, _ []byte) (uint64, error) {
|
|
return 0, k.write("Put", key)
|
|
}
|
|
|
|
func (k *KV) PutString(_ context.Context, key string, _ string) (uint64, error) {
|
|
return 0, k.write("PutString", key)
|
|
}
|
|
|
|
func (k *KV) Create(_ context.Context, key string, _ []byte, _ ...jetstream.KVCreateOpt) (uint64, error) {
|
|
return 0, k.write("Create", key)
|
|
}
|
|
|
|
func (k *KV) Update(_ context.Context, key string, _ []byte, _ uint64) (uint64, error) {
|
|
return 0, k.write("Update", key)
|
|
}
|
|
|
|
func (k *KV) Delete(_ context.Context, key string, _ ...jetstream.KVDeleteOpt) error {
|
|
return k.write("Delete", key)
|
|
}
|
|
|
|
func (k *KV) Purge(_ context.Context, key string, _ ...jetstream.KVDeleteOpt) error {
|
|
return k.write("Purge", key)
|
|
}
|
|
|
|
func (k *KV) PurgeDeletes(_ context.Context, _ ...jetstream.KVPurgeOpt) error {
|
|
return k.write("PurgeDeletes", "")
|
|
}
|