/
storage.go
121 lines (103 loc) · 2.93 KB
/
storage.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
package storage
import (
"context"
"errors"
"fmt"
"io"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/smithy-go"
)
type Storage struct {
s3Client *s3.Client
bucketName string
}
func NewStorage(awsConfig aws.Config, bucketName string) *Storage {
return &Storage{
s3Client: s3.NewFromConfig(awsConfig),
bucketName: bucketName,
}
}
func (s *Storage) Get(key string) (io.ReadCloser, int64, error) {
input := s3.GetObjectInput{
Bucket: aws.String(s.bucketName),
Key: aws.String(key),
}
result, err := s.s3Client.GetObject(context.TODO(), &input)
if err != nil {
var apiErr smithy.APIError
if errors.As(err, &apiErr) {
return nil, 0, fmt.Errorf(
"failed to get object (code: %s, message: %s, fault: %s)",
apiErr.ErrorCode(), apiErr.ErrorMessage(), apiErr.ErrorFault().String(),
)
}
return nil, 0, fmt.Errorf("failed to get object: %w", err)
}
return result.Body, result.ContentLength, nil
}
func (s *Storage) Put(key string, reader io.Reader) (*string, error) {
input := s3.PutObjectInput{
Body: reader,
Bucket: aws.String(s.bucketName),
Key: aws.String(key),
}
result, err := s.s3Client.PutObject(context.TODO(), &input)
if err != nil {
var apiErr smithy.APIError
if errors.As(err, &apiErr) {
return nil, fmt.Errorf(
"failed to put object (code: %s, message: %s, fault: %s)",
apiErr.ErrorCode(), apiErr.ErrorMessage(), apiErr.ErrorFault().String(),
)
}
return nil, fmt.Errorf("failed to put object: %w", err)
}
return result.ETag, nil
}
func (s *Storage) Move(sourceKey string, targetKey string) error {
if _, err := s.copy(sourceKey, targetKey); err != nil {
return err
}
if err := s.delete(sourceKey); err != nil {
return err
}
return nil
}
func (s *Storage) copy(sourceKey string, targetKey string) (*string, error) {
input := s3.CopyObjectInput{
Bucket: aws.String(s.bucketName),
CopySource: aws.String(s.bucketName + "/" + sourceKey),
Key: aws.String(targetKey),
}
result, err := s.s3Client.CopyObject(context.TODO(), &input)
if err != nil {
var apiErr smithy.APIError
if errors.As(err, &apiErr) {
return nil, fmt.Errorf(
"failed to copy object (code: %s, message: %s, fault: %s)",
apiErr.ErrorCode(), apiErr.ErrorMessage(), apiErr.ErrorFault().String(),
)
}
return nil, fmt.Errorf("failed to copy object: %w", err)
}
return result.CopyObjectResult.ETag, nil
}
func (s *Storage) delete(key string) error {
input := s3.DeleteObjectInput{
Bucket: aws.String(s.bucketName),
Key: aws.String(key),
}
_, err := s.s3Client.DeleteObject(context.TODO(), &input)
if err != nil {
var apiErr smithy.APIError
if errors.As(err, &apiErr) {
return fmt.Errorf(
"failed to delete object (code: %s, message: %s, fault: %s)",
apiErr.ErrorCode(), apiErr.ErrorMessage(), apiErr.ErrorFault().String(),
)
}
return fmt.Errorf("failed to delete object: %w", err)
}
return nil
}