/
amazon.go
123 lines (113 loc) · 3.23 KB
/
amazon.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package storage
import (
"bytes"
"io/ioutil"
pathutil "path"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
)
// AmazonS3Backend is a storage backend for Amazon S3
type AmazonS3Backend struct {
Bucket string
Client *s3.S3
Downloader *s3manager.Downloader
Prefix string
Uploader *s3manager.Uploader
SSE string
}
// NewAmazonS3Backend creates a new instance of AmazonS3Backend
func NewAmazonS3Backend(bucket string, prefix string, region string, endpoint string, sse string) *AmazonS3Backend {
service := s3.New(session.New(), &aws.Config{
Region: aws.String(region),
Endpoint: aws.String(endpoint),
DisableSSL: aws.Bool(strings.HasPrefix(endpoint, "http://")),
S3ForcePathStyle: aws.Bool(endpoint != ""),
})
b := &AmazonS3Backend{
Bucket: bucket,
Client: service,
Downloader: s3manager.NewDownloaderWithClient(service),
Prefix: cleanPrefix(prefix),
Uploader: s3manager.NewUploaderWithClient(service),
SSE: sse,
}
return b
}
// ListObjects lists all objects in Amazon S3 bucket, at prefix
func (b AmazonS3Backend) ListObjects(prefix string) ([]Object, error) {
var objects []Object
prefix = pathutil.Join(b.Prefix, prefix)
s3Input := &s3.ListObjectsInput{
Bucket: aws.String(b.Bucket),
Prefix: aws.String(prefix),
}
for {
s3Result, err := b.Client.ListObjects(s3Input)
if err != nil {
return objects, err
}
for _, obj := range s3Result.Contents {
path := removePrefixFromObjectPath(prefix, *obj.Key)
if objectPathIsInvalid(path) {
continue
}
object := Object{
Path: path,
Content: []byte{},
LastModified: *obj.LastModified,
}
objects = append(objects, object)
}
if !*s3Result.IsTruncated {
break
}
s3Input.Marker = s3Result.Contents[len(s3Result.Contents)-1].Key
}
return objects, nil
}
// GetObject retrieves an object from Amazon S3 bucket, at prefix
func (b AmazonS3Backend) GetObject(path string) (Object, error) {
var object Object
object.Path = path
var content []byte
s3Input := &s3.GetObjectInput{
Bucket: aws.String(b.Bucket),
Key: aws.String(pathutil.Join(b.Prefix, path)),
}
s3Result, err := b.Client.GetObject(s3Input)
if err != nil {
return object, err
}
content, err = ioutil.ReadAll(s3Result.Body)
if err != nil {
return object, err
}
object.Content = content
object.LastModified = *s3Result.LastModified
return object, nil
}
// PutObject uploads an object to Amazon S3 bucket, at prefix
func (b AmazonS3Backend) PutObject(path string, content []byte) error {
s3Input := &s3manager.UploadInput{
Bucket: aws.String(b.Bucket),
Key: aws.String(pathutil.Join(b.Prefix, path)),
Body: bytes.NewBuffer(content),
}
if b.SSE != "" {
s3Input.ServerSideEncryption = aws.String(b.SSE)
}
_, err := b.Uploader.Upload(s3Input)
return err
}
// DeleteObject removes an object from Amazon S3 bucket, at prefix
func (b AmazonS3Backend) DeleteObject(path string) error {
s3Input := &s3.DeleteObjectInput{
Bucket: aws.String(b.Bucket),
Key: aws.String(pathutil.Join(b.Prefix, path)),
}
_, err := b.Client.DeleteObject(s3Input)
return err
}