From 6042df075fba7d8113586181cd0ab332b5304aaa Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sat, 8 Apr 2023 12:53:43 +0200 Subject: [PATCH] migrations: Fix S3 backend detection --- internal/backend/limiter/limiter_backend.go | 2 ++ internal/backend/logger/log.go | 2 ++ internal/backend/retry/backend_retry.go | 4 +++ internal/backend/sema/backend.go | 4 +++ internal/cache/backend.go | 4 +++ internal/migrations/s3_layout.go | 29 +++++++++++---------- internal/migrations/s3_layout_test.go | 27 +++++++++++++++++++ internal/restic/backend.go | 5 ++++ 8 files changed, 63 insertions(+), 14 deletions(-) create mode 100644 internal/migrations/s3_layout_test.go diff --git a/internal/backend/limiter/limiter_backend.go b/internal/backend/limiter/limiter_backend.go index f1b508327..7fcca59cc 100644 --- a/internal/backend/limiter/limiter_backend.go +++ b/internal/backend/limiter/limiter_backend.go @@ -46,6 +46,8 @@ func (r rateLimitedBackend) Load(ctx context.Context, h restic.Handle, length in }) } +func (r rateLimitedBackend) Unwrap() restic.Backend { return r.Backend } + type limitedReader struct { io.Reader writerTo io.WriterTo diff --git a/internal/backend/logger/log.go b/internal/backend/logger/log.go index 4623d8021..6c860cfae 100644 --- a/internal/backend/logger/log.go +++ b/internal/backend/logger/log.go @@ -75,3 +75,5 @@ func (be *Backend) Close() error { debug.Log(" close err %v", err) return err } + +func (be *Backend) Unwrap() restic.Backend { return be.Backend } diff --git a/internal/backend/retry/backend_retry.go b/internal/backend/retry/backend_retry.go index b5f2706f4..9c51efedc 100644 --- a/internal/backend/retry/backend_retry.go +++ b/internal/backend/retry/backend_retry.go @@ -191,3 +191,7 @@ func (be *Backend) List(ctx context.Context, t restic.FileType, fn func(restic.F return err } + +func (be *Backend) Unwrap() restic.Backend { + return be.Backend +} diff --git a/internal/backend/sema/backend.go b/internal/backend/sema/backend.go index 4b6f55b50..9f6dfbadd 100644 --- a/internal/backend/sema/backend.go +++ b/internal/backend/sema/backend.go @@ -85,3 +85,7 @@ func (be *SemaphoreBackend) Remove(ctx context.Context, h restic.Handle) error { return be.Backend.Remove(ctx, h) } + +func (be *SemaphoreBackend) Unwrap() restic.Backend { + return be.Backend +} diff --git a/internal/cache/backend.go b/internal/cache/backend.go index a707f8243..08ec1facd 100644 --- a/internal/cache/backend.go +++ b/internal/cache/backend.go @@ -211,3 +211,7 @@ func (b *Backend) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo, e func (b *Backend) IsNotExist(err error) bool { return b.Backend.IsNotExist(err) } + +func (b *Backend) Unwrap() restic.Backend { + return b.Backend +} diff --git a/internal/migrations/s3_layout.go b/internal/migrations/s3_layout.go index d42b94bf8..a5293ef16 100644 --- a/internal/migrations/s3_layout.go +++ b/internal/migrations/s3_layout.go @@ -8,7 +8,6 @@ import ( "github.com/restic/restic/internal/backend/layout" "github.com/restic/restic/internal/backend/s3" - "github.com/restic/restic/internal/cache" "github.com/restic/restic/internal/debug" "github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/restic" @@ -22,24 +21,26 @@ func init() { // "default" layout. type S3Layout struct{} -func toS3Backend(repo restic.Repository) *s3.Backend { - b := repo.Backend() - // unwrap cache - if be, ok := b.(*cache.Backend); ok { - b = be.Backend - } +func toS3Backend(b restic.Backend) *s3.Backend { + for b != nil { + if be, ok := b.(*s3.Backend); ok { + return be + } - be, ok := b.(*s3.Backend) - if !ok { - debug.Log("backend is not s3") - return nil + if be, ok := b.(restic.BackendUnwrapper); ok { + b = be.Unwrap() + } else { + // not the backend we're looking for + break + } } - return be + debug.Log("backend is not s3") + return nil } // Check tests whether the migration can be applied. func (m *S3Layout) Check(ctx context.Context, repo restic.Repository) (bool, string, error) { - be := toS3Backend(repo) + be := toS3Backend(repo.Backend()) if be == nil { debug.Log("backend is not s3") return false, "backend is not s3", nil @@ -91,7 +92,7 @@ func (m *S3Layout) moveFiles(ctx context.Context, be *s3.Backend, l layout.Layou // Apply runs the migration. func (m *S3Layout) Apply(ctx context.Context, repo restic.Repository) error { - be := toS3Backend(repo) + be := toS3Backend(repo.Backend()) if be == nil { debug.Log("backend is not s3") return errors.New("backend is not s3") diff --git a/internal/migrations/s3_layout_test.go b/internal/migrations/s3_layout_test.go new file mode 100644 index 000000000..ad0eedea6 --- /dev/null +++ b/internal/migrations/s3_layout_test.go @@ -0,0 +1,27 @@ +package migrations + +import ( + "testing" + + "github.com/restic/restic/internal/backend/mock" + "github.com/restic/restic/internal/backend/s3" + "github.com/restic/restic/internal/cache" + "github.com/restic/restic/internal/test" +) + +func TestS3UnwrapBackend(t *testing.T) { + // toS3Backend(b restic.Backend) *s3.Backend + + m := mock.NewBackend() + test.Assert(t, toS3Backend(m) == nil, "mock backend is not an s3 backend") + + // uninitialized fake backend for testing + s3 := &s3.Backend{} + test.Assert(t, toS3Backend(s3) == s3, "s3 was not returned") + + c := &cache.Backend{Backend: s3} + test.Assert(t, toS3Backend(c) == s3, "failed to unwrap s3 backend") + + c.Backend = m + test.Assert(t, toS3Backend(c) == nil, "a wrapped mock backend is not an s3 backend") +} diff --git a/internal/restic/backend.go b/internal/restic/backend.go index bc139fc8b..b01071132 100644 --- a/internal/restic/backend.go +++ b/internal/restic/backend.go @@ -70,6 +70,11 @@ type Backend interface { Delete(ctx context.Context) error } +type BackendUnwrapper interface { + // Unwrap returns the underlying backend or nil if there is none. + Unwrap() Backend +} + // FileInfo is contains information about a file in the backend. type FileInfo struct { Size int64