158 lines
3.8 KiB
Go
158 lines
3.8 KiB
Go
|
package drivers
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"io/ioutil"
|
||
|
|
||
|
"github.com/minio/minio-go/v7"
|
||
|
"github.com/minio/minio-go/v7/pkg/credentials"
|
||
|
)
|
||
|
|
||
|
// S3Driver provides basic interface for S3 storage compatible with Driver interface
|
||
|
type S3Driver struct {
|
||
|
// S3 storage related things
|
||
|
S3AccessKey string
|
||
|
S3SecretKey string
|
||
|
S3Endpoint string
|
||
|
S3SSL bool
|
||
|
Bucket string
|
||
|
}
|
||
|
|
||
|
// Returns S3 client structure
|
||
|
func (s *S3Driver) getMinioClient() (*minio.Client, error) {
|
||
|
client, err := minio.New(s.S3Endpoint, &minio.Options{
|
||
|
Creds: credentials.NewStaticV4(s.S3AccessKey, s.S3SecretKey, ""),
|
||
|
Secure: s.S3SSL,
|
||
|
})
|
||
|
|
||
|
if err == nil {
|
||
|
return client, s.prepareBucket(client)
|
||
|
}
|
||
|
|
||
|
return client, err
|
||
|
}
|
||
|
|
||
|
// Create configured bucket if it doesn't exist
|
||
|
func (s *S3Driver) prepareBucket(client *minio.Client) error {
|
||
|
bucketInfos, err := client.ListBuckets(context.Background())
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
var found bool
|
||
|
for _, info := range bucketInfos {
|
||
|
if info.Name == s.Bucket {
|
||
|
found = true
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if !found {
|
||
|
err = client.MakeBucket(context.Background(), s.Bucket, minio.MakeBucketOptions{})
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Create creates a new object in the storage with given body
|
||
|
func (s S3Driver) Create(key string, filePath string) error {
|
||
|
client, err := s.getMinioClient()
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("getting minio client error: %v", err)
|
||
|
}
|
||
|
|
||
|
_, err = client.FPutObject(context.TODO(), s.Bucket, key, filePath, minio.PutObjectOptions{})
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("copying object into S3 error: %v", err)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Get copies file from S3 into a local file
|
||
|
// filePath tells the method where the file should be stored
|
||
|
func (s S3Driver) Get(key string, filePath string) error {
|
||
|
client, err := s.getMinioClient()
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("getting minio client error: %v", err)
|
||
|
}
|
||
|
|
||
|
err = client.FGetObject(context.TODO(), s.Bucket, key, filePath, minio.GetObjectOptions{})
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("getting the object from S3 error: %v", err)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Write writes content of body into key
|
||
|
func (s S3Driver) Write(key string, body []byte) error {
|
||
|
client, err := s.getMinioClient()
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("getting minio client error: %v", err)
|
||
|
}
|
||
|
|
||
|
_, err = client.PutObject(context.TODO(), s.Bucket, key, bytes.NewReader(body), int64(len(body)), minio.PutObjectOptions{})
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("getting the object from S3 error: %v", err)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Read returns content of given key
|
||
|
func (s S3Driver) Read(key string) ([]byte, error) {
|
||
|
client, err := s.getMinioClient()
|
||
|
if err != nil {
|
||
|
return []byte(""), fmt.Errorf("getting minio client error: %v", err)
|
||
|
}
|
||
|
|
||
|
object, err := client.GetObject(context.TODO(), s.Bucket, key, minio.GetObjectOptions{})
|
||
|
if err != nil {
|
||
|
return []byte(""), fmt.Errorf("getting the object from S3 error: %v", err)
|
||
|
}
|
||
|
|
||
|
body, err := ioutil.ReadAll(object)
|
||
|
if err != nil {
|
||
|
return []byte(""), fmt.Errorf("reading the object from S3 error: %v", err)
|
||
|
}
|
||
|
|
||
|
return body, nil
|
||
|
}
|
||
|
|
||
|
// List returns list of objects in fiven prefix
|
||
|
func (s S3Driver) List(prefix string) ([]string, error) {
|
||
|
keys := []string{}
|
||
|
|
||
|
client, err := s.getMinioClient()
|
||
|
if err != nil {
|
||
|
return keys, fmt.Errorf("getting minio client error: %v", err)
|
||
|
}
|
||
|
|
||
|
for info := range client.ListObjects(context.TODO(), s.Bucket, minio.ListObjectsOptions{Prefix: ""}) {
|
||
|
keys = append(keys, info.Key)
|
||
|
}
|
||
|
|
||
|
return keys, nil
|
||
|
}
|
||
|
|
||
|
// Delete deletes one object
|
||
|
func (s S3Driver) Delete(key string) error {
|
||
|
client, err := s.getMinioClient()
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("getting minio client error: %v", err)
|
||
|
}
|
||
|
|
||
|
err = client.RemoveObject(context.Background(), s.Bucket, key, minio.RemoveObjectOptions{})
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("removing object error: %v", err)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|