88 lines
2.0 KiB
Go
88 lines
2.0 KiB
Go
/*
|
|
Package s3 implements a non-hierarchical file store using Amazon s3. A file
|
|
store uses a single bucket. Each file is an object with its UUID as the name.
|
|
The file name is stored in the user-defined object metadata x-amz-meta-filename.
|
|
*/
|
|
package s3
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"io/fs"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/minio/minio-go/v7"
|
|
"github.com/minio/minio-go/v7/pkg/credentials"
|
|
)
|
|
|
|
type FS struct {
|
|
client *minio.Client
|
|
bucket string
|
|
}
|
|
|
|
// New ``connects'' to an s3 endpoint and creates a file store using the
|
|
// specified bucket. The bucket is created if it doesn't exist.
|
|
func New(endpoint string, secure bool, id, secret, bucket, location string) (*FS, error) {
|
|
var fs FS
|
|
var err error
|
|
fs.client, err = minio.New(endpoint, &minio.Options{
|
|
Creds: credentials.NewStaticV4(id, secret, ""),
|
|
Secure: secure,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ctx := context.TODO()
|
|
|
|
err = fs.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{
|
|
Region: location,
|
|
})
|
|
if err != nil {
|
|
if exists, err := fs.client.BucketExists(ctx, bucket); err != nil || !exists {
|
|
return nil, err
|
|
}
|
|
}
|
|
fs.bucket = bucket
|
|
|
|
return &fs, nil
|
|
}
|
|
|
|
func (fs *FS) Store(id uuid.UUID, name, contentType string, data io.Reader) error {
|
|
ctx := context.TODO()
|
|
_, err := fs.client.PutObject(ctx, fs.bucket, id.String(), data, -1, minio.PutObjectOptions{
|
|
UserMetadata: map[string]string{
|
|
"filename": name,
|
|
},
|
|
ContentType: contentType,
|
|
})
|
|
return err
|
|
}
|
|
|
|
func (fs *FS) RemoveUUID(id uuid.UUID) error {
|
|
ctx := context.TODO()
|
|
return fs.client.RemoveObject(ctx, fs.bucket, id.String(), minio.RemoveObjectOptions{})
|
|
}
|
|
|
|
// TODO: implement
|
|
func (fs *FS) Open(name string) (fs.File, error) {
|
|
return nil, errors.New("not implemented")
|
|
}
|
|
|
|
func (fs *FS) OpenUUID(id uuid.UUID) (fs.File, error) {
|
|
ctx := context.TODO()
|
|
|
|
object, err := fs.client.GetObject(ctx, fs.bucket, id.String(), minio.GetObjectOptions{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return File{Object: object}, nil
|
|
}
|
|
|
|
// TODO: do some checking
|
|
func (fs *FS) Check() error {
|
|
return nil
|
|
}
|