2019-01-24 20:15:10 +00:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
2018-11-06 13:19:43 +00:00
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
2018-12-03 19:50:05 +00:00
|
|
|
package s3client
|
2018-11-06 13:19:43 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/zeebo/errs"
|
|
|
|
)
|
|
|
|
|
|
|
|
// UplinkError is class for minio errors
|
|
|
|
var UplinkError = errs.Class("uplink error")
|
|
|
|
|
|
|
|
// Uplink implements basic S3 Client with uplink
|
|
|
|
type Uplink struct {
|
|
|
|
conf Config
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewUplink creates new Client
|
|
|
|
func NewUplink(conf Config) (Client, error) {
|
|
|
|
client := &Uplink{conf}
|
|
|
|
|
|
|
|
cmd := client.cmd("setup",
|
|
|
|
"--overwrite",
|
|
|
|
"--api-key", client.conf.APIKey,
|
|
|
|
"--enc-key", client.conf.EncryptionKey,
|
|
|
|
"--satellite-addr", client.conf.Satellite)
|
|
|
|
|
|
|
|
_, err := cmd.Output()
|
|
|
|
if err != nil {
|
|
|
|
return nil, UplinkError.Wrap(fullExitError(err))
|
|
|
|
}
|
|
|
|
|
|
|
|
return client, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (client *Uplink) cmd(subargs ...string) *exec.Cmd {
|
|
|
|
args := []string{}
|
|
|
|
|
|
|
|
args = append(args, subargs...)
|
|
|
|
|
|
|
|
cmd := exec.Command("uplink", args...)
|
|
|
|
return cmd
|
|
|
|
}
|
|
|
|
|
|
|
|
// MakeBucket makes a new bucket
|
|
|
|
func (client *Uplink) MakeBucket(bucket, location string) error {
|
|
|
|
cmd := client.cmd("mb", "s3://"+bucket)
|
|
|
|
_, err := cmd.Output()
|
|
|
|
if err != nil {
|
|
|
|
return UplinkError.Wrap(fullExitError(err))
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveBucket removes a bucket
|
|
|
|
func (client *Uplink) RemoveBucket(bucket string) error {
|
|
|
|
cmd := client.cmd("rb", "s3://"+bucket)
|
|
|
|
_, err := cmd.Output()
|
|
|
|
if err != nil {
|
|
|
|
return UplinkError.Wrap(fullExitError(err))
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ListBuckets lists all buckets
|
|
|
|
func (client *Uplink) ListBuckets() ([]string, error) {
|
|
|
|
cmd := client.cmd("ls")
|
|
|
|
data, err := cmd.Output()
|
|
|
|
if err != nil {
|
|
|
|
return nil, UplinkError.Wrap(fullExitError(err))
|
|
|
|
}
|
|
|
|
|
|
|
|
names := strings.Split(strings.TrimRight(string(data), "\n"), "\n")
|
|
|
|
return names, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Upload uploads object data to the specified path
|
|
|
|
func (client *Uplink) Upload(bucket, objectName string, data []byte) error {
|
|
|
|
// TODO: add upload threshold
|
|
|
|
cmd := client.cmd("put", "s3://"+bucket+"/"+objectName)
|
|
|
|
cmd.Stdin = bytes.NewReader(data)
|
|
|
|
_, err := cmd.Output()
|
|
|
|
if err != nil {
|
|
|
|
return UplinkError.Wrap(fullExitError(err))
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Download downloads object data
|
|
|
|
func (client *Uplink) Download(bucket, objectName string, buffer []byte) ([]byte, error) {
|
|
|
|
cmd := client.cmd("cat", "s3://"+bucket+"/"+objectName)
|
|
|
|
|
|
|
|
buf := &bufferWriter{buffer[:0]}
|
|
|
|
cmd.Stdout = buf
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
|
|
|
|
err := cmd.Run()
|
|
|
|
if err != nil {
|
|
|
|
return nil, UplinkError.Wrap(fullExitError(err))
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf.data, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete deletes object
|
|
|
|
func (client *Uplink) Delete(bucket, objectName string) error {
|
|
|
|
cmd := client.cmd("rm", "s3://"+bucket+"/"+objectName)
|
|
|
|
_, err := cmd.Output()
|
|
|
|
if err != nil {
|
|
|
|
return UplinkError.Wrap(fullExitError(err))
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ListObjects lists objects
|
|
|
|
func (client *Uplink) ListObjects(bucket, prefix string) ([]string, error) {
|
|
|
|
cmd := client.cmd("ls", "s3://"+bucket+"/"+prefix)
|
|
|
|
data, err := cmd.Output()
|
|
|
|
if err != nil {
|
|
|
|
return nil, UplinkError.Wrap(fullExitError(err))
|
|
|
|
}
|
|
|
|
|
|
|
|
names := strings.Split(strings.TrimRight(string(data), "\n"), "\n")
|
|
|
|
return names, nil
|
|
|
|
}
|