Something went wrong. Try again.
Monorepo for Tangled
Something went wrong. Try again.
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103package storage
import ( "context" "errors" "fmt" "io" "strings"
awsconfig "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/s3/types")
type S3 struct { bucket string prefix string client *s3.Client}
func NewS3(ctx context.Context, bucket, prefix string) (*S3, error) { if bucket == "" { return nil, fmt.Errorf("storage: s3 backend requires a bucket") } sdkConfig, err := awsconfig.LoadDefaultConfig(ctx) if err != nil { return nil, fmt.Errorf("storage: load s3 config: %w", err) } client := s3.NewFromConfig(sdkConfig) versioning, err := client.GetBucketVersioning(ctx, &s3.GetBucketVersioningInput{ Bucket: &bucket, }) if err != nil { return nil, fmt.Errorf("storage: check s3 bucket versioning: %w", err) } if versioning.Status != "" { return nil, fmt.Errorf("storage: s3 cache bucket must not use versioning") } return &S3{ bucket: bucket, prefix: strings.Trim(prefix, "/"), client: client, }, nil}
func (s *S3) fullKey(key string) (string, error) { if err := ValidateKey(key); err != nil { return "", err } if s.prefix == "" { return key, nil } return s.prefix + "/" + key, nil}
func (s *S3) Get(ctx context.Context, key string) (io.ReadCloser, error) { full, err := s.fullKey(key) if err != nil { return nil, err } res, err := s.client.GetObject(ctx, &s3.GetObjectInput{ Bucket: &s.bucket, Key: &full, }) if err != nil { var nsk *types.NoSuchKey if errors.As(err, &nsk) { return nil, ErrNotExist } return nil, fmt.Errorf("storage: get %q: %w", key, err) } return res.Body, nil}
func (s *S3) Put(ctx context.Context, key string, r io.Reader) error { full, err := s.fullKey(key) if err != nil { return err } if _, err := s.client.PutObject(ctx, &s3.PutObjectInput{ Bucket: &s.bucket, Key: &full, Body: r, }); err != nil { return fmt.Errorf("storage: put %q: %w", key, err) } return nil}
func (s *S3) Delete(ctx context.Context, key string) error { full, err := s.fullKey(key) if err != nil { return err } if _, err := s.client.DeleteObject(ctx, &s3.DeleteObjectInput{ Bucket: &s.bucket, Key: &full, }); err != nil { return fmt.Errorf("storage: delete %q: %w", key, err) } return nil}