2018-10-01 12:29:27 +01:00
|
|
|
// Copyright (C) 2018 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
2018-12-03 19:50:05 +00:00
|
|
|
package s3client
|
2018-09-28 13:40:08 +01:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
|
|
|
|
minio "github.com/minio/minio-go"
|
|
|
|
"github.com/zeebo/errs"
|
|
|
|
)
|
|
|
|
|
|
|
|
// MinioError is class for minio errors
|
|
|
|
var MinioError = errs.Class("minio error")
|
|
|
|
|
|
|
|
// Minio implements basic S3 Client with minio
|
|
|
|
type Minio struct {
|
|
|
|
api *minio.Client
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewMinio creates new Client
|
|
|
|
func NewMinio(conf Config) (Client, error) {
|
2018-11-06 13:19:43 +00:00
|
|
|
api, err := minio.New(conf.S3Gateway, conf.AccessKey, conf.SecretKey, !conf.NoSSL)
|
2018-09-28 13:40:08 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, MinioError.Wrap(err)
|
|
|
|
}
|
|
|
|
return &Minio{api}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// MakeBucket makes a new bucket
|
|
|
|
func (client *Minio) MakeBucket(bucket, location string) error {
|
|
|
|
err := client.api.MakeBucket(bucket, location)
|
|
|
|
if err != nil {
|
|
|
|
return MinioError.Wrap(err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveBucket removes a bucket
|
|
|
|
func (client *Minio) RemoveBucket(bucket string) error {
|
|
|
|
err := client.api.RemoveBucket(bucket)
|
|
|
|
if err != nil {
|
|
|
|
return MinioError.Wrap(err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ListBuckets lists all buckets
|
|
|
|
func (client *Minio) ListBuckets() ([]string, error) {
|
|
|
|
buckets, err := client.api.ListBuckets()
|
|
|
|
if err != nil {
|
|
|
|
return nil, MinioError.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
names := []string{}
|
|
|
|
for _, bucket := range buckets {
|
|
|
|
names = append(names, bucket.Name)
|
|
|
|
}
|
|
|
|
return names, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Upload uploads object data to the specified path
|
|
|
|
func (client *Minio) Upload(bucket, objectName string, data []byte) error {
|
|
|
|
_, err := client.api.PutObject(
|
|
|
|
bucket, objectName,
|
|
|
|
bytes.NewReader(data), int64(len(data)),
|
|
|
|
minio.PutObjectOptions{ContentType: "application/octet-stream"})
|
|
|
|
if err != nil {
|
|
|
|
return MinioError.Wrap(err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// UploadMultipart uses multipart uploads, has hardcoded threshold
|
|
|
|
func (client *Minio) UploadMultipart(bucket, objectName string, data []byte, threshold int) error {
|
|
|
|
_, err := client.api.PutObject(
|
|
|
|
bucket, objectName,
|
|
|
|
bytes.NewReader(data), -1,
|
|
|
|
minio.PutObjectOptions{ContentType: "application/octet-stream"})
|
|
|
|
if err != nil {
|
|
|
|
return MinioError.Wrap(err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Download downloads object data
|
|
|
|
func (client *Minio) Download(bucket, objectName string, buffer []byte) ([]byte, error) {
|
|
|
|
reader, err := client.api.GetObject(bucket, objectName, minio.GetObjectOptions{})
|
|
|
|
if err != nil {
|
|
|
|
return nil, MinioError.Wrap(err)
|
|
|
|
}
|
|
|
|
defer func() { _ = reader.Close() }()
|
|
|
|
|
|
|
|
n, err := reader.Read(buffer[:cap(buffer)])
|
|
|
|
if err != io.EOF {
|
|
|
|
rest, err := ioutil.ReadAll(reader)
|
|
|
|
if err == io.EOF {
|
|
|
|
err = nil
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return nil, MinioError.Wrap(err)
|
|
|
|
}
|
|
|
|
buffer = append(buffer, rest...)
|
|
|
|
n = len(buffer)
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer = buffer[:n]
|
|
|
|
return buffer, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete deletes object
|
|
|
|
func (client *Minio) Delete(bucket, objectName string) error {
|
|
|
|
err := client.api.RemoveObject(bucket, objectName)
|
|
|
|
if err != nil {
|
|
|
|
return MinioError.Wrap(err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ListObjects lists objects
|
|
|
|
func (client *Minio) ListObjects(bucket, prefix string) ([]string, error) {
|
|
|
|
doneCh := make(chan struct{})
|
|
|
|
defer close(doneCh)
|
|
|
|
|
|
|
|
names := []string{}
|
2018-10-06 13:26:35 +01:00
|
|
|
for message := range client.api.ListObjects(bucket, prefix, false, doneCh) {
|
2018-09-28 13:40:08 +01:00
|
|
|
names = append(names, message.Key)
|
|
|
|
}
|
|
|
|
|
|
|
|
return names, nil
|
|
|
|
}
|