From 81a289d8bc94b8fc57cd9731526abc96fcfd1b19 Mon Sep 17 00:00:00 2001 From: ashmrtn <3891298+ashmrtn@users.noreply.github.com> Date: Tue, 27 Jun 2023 08:25:54 -0700 Subject: [PATCH] Allow opening S3 repo at a specific point-in-time (#3657) Thread the PointInTime argument through corso to kopia so that S3 repos can be opened at a specific point if they're using versioning and object locking This only allows SDK access to the feature at the moment and no changes are made to enable immutable backups. This is just low hanging fruit since it's wiring CLI changes will need more thought as we ideally only want to enable this behavior for a subset of S3 commands (restore, details, list) Manually tested opening a repo with some hacky CLI code to wire up flags --- #### Does this PR need a docs update or release note? - [ ] :white_check_mark: Yes, it's included - [ ] :clock1: Yes, but in a later PR - [x] :no_entry: No #### Type of change - [x] :sunflower: Feature - [ ] :bug: Bugfix - [ ] :world_map: Documentation - [ ] :robot: Supportability/Tests - [ ] :computer: CI/Deployment - [ ] :broom: Tech Debt/Cleanup #### Issue(s) * #3519 #### Test Plan - [x] :muscle: Manual - [ ] :zap: Unit test - [ ] :green_heart: E2E --- src/internal/kopia/conn.go | 12 ++++++++---- src/internal/kopia/s3.go | 8 +++++++- src/pkg/control/repository/repo.go | 7 +++++++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/internal/kopia/conn.go b/src/internal/kopia/conn.go index 30870a1b3..d5356a152 100644 --- a/src/internal/kopia/conn.go +++ b/src/internal/kopia/conn.go @@ -71,7 +71,7 @@ func NewConn(s storage.Storage) *conn { } func (w *conn) Initialize(ctx context.Context, opts repository.Options) error { - bst, err := blobStoreByProvider(ctx, w.storage) + bst, err := blobStoreByProvider(ctx, opts, w.storage) if err != nil { return clues.Wrap(err, "initializing storage") } @@ -111,7 +111,7 @@ func (w *conn) Initialize(ctx context.Context, opts repository.Options) error { } func (w *conn) Connect(ctx context.Context, opts repository.Options) error { - bst, err := blobStoreByProvider(ctx, w.storage) + bst, err := blobStoreByProvider(ctx, opts, w.storage) if err != nil { return clues.Wrap(err, "initializing storage") } @@ -174,10 +174,14 @@ func (w *conn) commonConnect( return nil } -func blobStoreByProvider(ctx context.Context, s storage.Storage) (blob.Storage, error) { +func blobStoreByProvider( + ctx context.Context, + opts repository.Options, + s storage.Storage, +) (blob.Storage, error) { switch s.Provider { case storage.ProviderS3: - return s3BlobStorage(ctx, s) + return s3BlobStorage(ctx, opts, s) default: return nil, clues.New("storage provider details are required").WithClues(ctx) } diff --git a/src/internal/kopia/s3.go b/src/internal/kopia/s3.go index 3e0baead9..6868fa8f8 100644 --- a/src/internal/kopia/s3.go +++ b/src/internal/kopia/s3.go @@ -7,6 +7,7 @@ import ( "github.com/kopia/kopia/repo/blob" "github.com/kopia/kopia/repo/blob/s3" + "github.com/alcionai/corso/src/pkg/control/repository" "github.com/alcionai/corso/src/pkg/storage" ) @@ -14,7 +15,11 @@ const ( defaultS3Endpoint = "s3.amazonaws.com" // matches kopia's default value ) -func s3BlobStorage(ctx context.Context, s storage.Storage) (blob.Storage, error) { +func s3BlobStorage( + ctx context.Context, + repoOpts repository.Options, + s storage.Storage, +) (blob.Storage, error) { cfg, err := s.S3Config() if err != nil { return nil, clues.Stack(err).WithClues(ctx) @@ -36,6 +41,7 @@ func s3BlobStorage(ctx context.Context, s storage.Storage) (blob.Storage, error) RoleARN: s.Role, RoleDuration: s.SessionDuration, TLSHandshakeTimeout: 60, + PointInTime: repoOpts.ViewTimestamp, } store, err := s3.New(ctx, &opts, false) diff --git a/src/pkg/control/repository/repo.go b/src/pkg/control/repository/repo.go index aab97948a..b65f8715b 100644 --- a/src/pkg/control/repository/repo.go +++ b/src/pkg/control/repository/repo.go @@ -1,9 +1,16 @@ package repository +import ( + "time" +) + // Repo represents options that are specific to the repo storing backed up data. type Options struct { User string `json:"user"` Host string `json:"host"` + // ViewTimestamp is the time at which the repo should be opened at if + // immutable backups are being used. If nil then the current time is used. + ViewTimestamp *time.Time `json:"viewTimestamp"` } type Maintenance struct {