123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- // Copyright (C) 2024 The Syncthing Authors.
- //
- // This Source Code Form is subject to the terms of the Mozilla Public
- // License, v. 2.0. If a copy of the MPL was not distributed with this file,
- // You can obtain one at https://mozilla.org/MPL/2.0/.
- package s3
- import (
- "context"
- "io"
- "time"
- "github.com/aws/aws-sdk-go/aws"
- "github.com/aws/aws-sdk-go/aws/credentials"
- "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"
- "github.com/syncthing/syncthing/internal/blob"
- )
- var _ blob.Store = (*Session)(nil)
- type Session struct {
- bucket string
- s3sess *session.Session
- }
- type Object = s3.Object
- func NewSession(endpoint, region, bucket, accessKeyID, secretKey string) (*Session, error) {
- sess, err := session.NewSession(&aws.Config{
- Region: aws.String(region),
- Endpoint: aws.String(endpoint),
- Credentials: credentials.NewStaticCredentials(accessKeyID, secretKey, ""),
- S3ForcePathStyle: aws.Bool(true),
- })
- if err != nil {
- return nil, err
- }
- return &Session{
- bucket: bucket,
- s3sess: sess,
- }, nil
- }
- func (s *Session) Upload(_ context.Context, key string, r io.Reader) error {
- uploader := s3manager.NewUploader(s.s3sess)
- _, err := uploader.Upload(&s3manager.UploadInput{
- Bucket: aws.String(s.bucket),
- Key: aws.String(key),
- Body: r,
- })
- return err
- }
- func (s *Session) Download(_ context.Context, key string, w blob.Writer) error {
- downloader := s3manager.NewDownloader(s.s3sess)
- _, err := downloader.Download(w, &s3.GetObjectInput{
- Bucket: aws.String(s.bucket),
- Key: aws.String(key),
- })
- return err
- }
- func (s *Session) LatestKey(_ context.Context) (string, error) {
- var latestKey string
- var lastModified time.Time
- if err := s.list(func(obj *Object) bool {
- if latestKey == "" || obj.LastModified.After(lastModified) {
- latestKey = *obj.Key
- lastModified = *obj.LastModified
- }
- return true
- }); err != nil {
- return "", err
- }
- return latestKey, nil
- }
- func (s *Session) list(fn func(*Object) bool) error {
- svc := s3.New(s.s3sess)
- opts := &s3.ListObjectsV2Input{
- Bucket: aws.String(s.bucket),
- }
- for {
- resp, err := svc.ListObjectsV2(opts)
- if err != nil {
- return err
- }
- for _, item := range resp.Contents {
- if !fn(item) {
- return nil
- }
- }
- if resp.NextContinuationToken == nil || *resp.NextContinuationToken == "" {
- break
- }
- opts.ContinuationToken = resp.NextContinuationToken
- }
- return nil
- }
|