87 lines
2.3 KiB
Go
87 lines
2.3 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/aws/aws-sdk-go-v2/aws"
|
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
|
)
|
|
|
|
var S3Client S3
|
|
|
|
type S3 interface {
|
|
GetPresignedURL(ctx context.Context, key, contentType string, expiry time.Duration) (string, error)
|
|
DoesFileExist(ctx context.Context, key string) (bool, error)
|
|
}
|
|
|
|
type S3Concrete struct {
|
|
S3Client *s3.Client
|
|
Bucket string
|
|
}
|
|
|
|
func (svc S3Concrete) GetPresignedURL(ctx context.Context, key, contentType string, expiry time.Duration) (string, error) {
|
|
presignClient := s3.NewPresignClient(svc.S3Client)
|
|
|
|
request, err := presignClient.PresignPutObject(ctx, &s3.PutObjectInput{
|
|
Bucket: &svc.Bucket,
|
|
Key: &key,
|
|
ContentType: &contentType,
|
|
}, s3.WithPresignExpires(expiry))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return request.URL, nil
|
|
}
|
|
|
|
func (svc S3Concrete) DoesFileExist(ctx context.Context, key string) (bool, error) {
|
|
_, error := svc.S3Client.HeadObject(ctx, &s3.HeadObjectInput{
|
|
Bucket: &svc.Bucket,
|
|
Key: &key,
|
|
})
|
|
|
|
if error != nil {
|
|
return false, error
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
// AssertSuccessfulConnection verifies that the bucket is reachable and that
|
|
// the configured credentials can get, put, and presign objects in it. It
|
|
// panics with a descriptive message on the first check that fails, since the
|
|
// service cannot function without these permissions.
|
|
func (svc S3Concrete) AssertSuccessfulConnection(ctx context.Context) {
|
|
if _, err := svc.S3Client.HeadBucket(ctx, &s3.HeadBucketInput{
|
|
Bucket: &svc.Bucket,
|
|
}); err != nil {
|
|
panic(fmt.Errorf("s3: cannot connect to bucket %q: %w", svc.Bucket, err))
|
|
}
|
|
|
|
const probeKey = ".s3-connectivity-check"
|
|
|
|
if _, err := svc.S3Client.PutObject(ctx, &s3.PutObjectInput{
|
|
Bucket: &svc.Bucket,
|
|
Key: aws.String(probeKey),
|
|
Body: strings.NewReader("ok"),
|
|
}); err != nil {
|
|
panic(fmt.Errorf("s3: missing permission to put objects in bucket %q: %w", svc.Bucket, err))
|
|
}
|
|
|
|
object, err := svc.S3Client.GetObject(ctx, &s3.GetObjectInput{
|
|
Bucket: &svc.Bucket,
|
|
Key: aws.String(probeKey),
|
|
})
|
|
if err != nil {
|
|
panic(fmt.Errorf("s3: missing permission to get objects from bucket %q: %w", svc.Bucket, err))
|
|
}
|
|
object.Body.Close()
|
|
|
|
if _, err := svc.GetPresignedURL(ctx, probeKey, "text/plain", time.Minute); err != nil {
|
|
panic(fmt.Errorf("s3: cannot create presigned urls for bucket %q: %w", svc.Bucket, err))
|
|
}
|
|
}
|