added mock s3 implementation
This commit is contained in:
parent
bead881af2
commit
60817c2249
141
internal/s3/mock.go
Normal file
141
internal/s3/mock.go
Normal file
@ -0,0 +1,141 @@
|
||||
package s3
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"git.kapelle.org/niklas/s3browser/internal/types"
|
||||
)
|
||||
|
||||
type mockS3 struct {
|
||||
buckets []string
|
||||
objects map[types.ID]mockObject
|
||||
}
|
||||
|
||||
type mockObject struct {
|
||||
content []byte
|
||||
contentType string
|
||||
lastMod time.Time
|
||||
}
|
||||
|
||||
type mockObjectReader struct {
|
||||
*bytes.Reader
|
||||
}
|
||||
|
||||
func (r mockObjectReader) Close() error {
|
||||
// NOOP
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewMockS3(buckets []string) (S3Service, error) {
|
||||
return &mockS3{
|
||||
buckets: buckets,
|
||||
objects: map[types.ID]mockObject{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *mockS3) ListBuckets(ctx context.Context) ([]Bucket, error) {
|
||||
var rtn []Bucket
|
||||
for _, v := range m.buckets {
|
||||
rtn = append(rtn, Bucket(v))
|
||||
}
|
||||
|
||||
return rtn, nil
|
||||
}
|
||||
|
||||
func (m *mockS3) ListObjects(ctx context.Context, id types.ID) ([]types.File, []types.Directory, error) {
|
||||
var files []types.File
|
||||
var dirs []types.Directory
|
||||
|
||||
for k, v := range m.objects {
|
||||
if k.Bucket == id.Bucket {
|
||||
if k.Parent().Key == id.Key {
|
||||
if k.IsDirectory() {
|
||||
dirs = append(dirs, *mockObjToDir(v, k))
|
||||
} else {
|
||||
files = append(files, *mockObjToFile(v, k))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return files, dirs, nil
|
||||
}
|
||||
|
||||
func (m *mockS3) GetObject(ctx context.Context, id types.ID) (Object, error) {
|
||||
mockObj, exist := m.objects[id]
|
||||
|
||||
if !exist {
|
||||
return nil, fmt.Errorf("Object not found")
|
||||
}
|
||||
|
||||
reader := bytes.NewReader(mockObj.content)
|
||||
|
||||
return mockObjectReader{reader}, nil
|
||||
}
|
||||
|
||||
func (m *mockS3) PutObject(ctx context.Context, id types.ID, reader io.Reader, objectSize int64) error {
|
||||
content, err := ioutil.ReadAll(reader)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.objects[id] = mockObject{
|
||||
content: content,
|
||||
lastMod: time.Now(),
|
||||
contentType: "application/octet-stream", // TODO: detect MIME type or dont its just a mock after all
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockS3) CopyObject(ctx context.Context, src types.ID, dest types.ID) error {
|
||||
srcObj, exist := m.objects[src]
|
||||
|
||||
if !exist {
|
||||
return fmt.Errorf("Object not found")
|
||||
}
|
||||
|
||||
m.objects[dest] = srcObj
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockS3) StatObject(ctx context.Context, id types.ID) (*types.File, error) {
|
||||
mockObj, exist := m.objects[id]
|
||||
|
||||
if !exist {
|
||||
return nil, fmt.Errorf("Object not found")
|
||||
}
|
||||
|
||||
return mockObjToFile(mockObj, id), nil
|
||||
}
|
||||
|
||||
func (m *mockS3) RemoveObject(ctx context.Context, id types.ID) error {
|
||||
delete(m.objects, id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func mockObjToFile(mockObj mockObject, id types.ID) *types.File {
|
||||
return &types.File{
|
||||
ID: id,
|
||||
Name: id.Name(),
|
||||
Size: int64(len(mockObj.content)),
|
||||
ContentType: mockObj.contentType,
|
||||
LastModified: mockObj.lastMod,
|
||||
ETag: fmt.Sprintf("%x", md5.Sum(mockObj.content)),
|
||||
}
|
||||
}
|
||||
|
||||
func mockObjToDir(mockObj mockObject, id types.ID) *types.Directory {
|
||||
return &types.Directory{
|
||||
ID: id,
|
||||
Name: id.Name(),
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user