diff options
author | James Fargher <jfargher@gitlab.com> | 2024-01-15 01:34:09 +0300 |
---|---|---|
committer | James Fargher <jfargher@gitlab.com> | 2024-01-16 02:25:17 +0300 |
commit | c8126c6c41c013fd857b1c9ba36fb837e4b843f3 (patch) | |
tree | 25b9ddaa383b233e639c02c5edb3e8ddf5fc5925 | |
parent | 96b75e53b61c476029d510270daa1d5dfc444a09 (diff) |
backup: Write latest manifest file
Manifests currently cannot restore the "latest" backup because it would
require an expensive object-storage directory traversal. So instead it
defers to the pointer layout. The problem with this is that you then
loose manifest only features like setting the default branch properly.
Here we write two manifests: the normal backup manifest as before and an
additional "latest" manifest file. This latest manifest is overwritten
on each backup taken.
For WORM we would ideally not overwrite any files, but until this is
implemented we need something to fill the latest restore gap.
Changelog: changed
-rw-r--r-- | internal/backup/locator.go | 29 | ||||
-rw-r--r-- | internal/backup/locator_test.go | 9 |
2 files changed, 27 insertions, 11 deletions
diff --git a/internal/backup/locator.go b/internal/backup/locator.go index 1e1c42550..216037aea 100644 --- a/internal/backup/locator.go +++ b/internal/backup/locator.go @@ -294,17 +294,10 @@ func (l ManifestLocator) Commit(ctx context.Context, backup *Backup) (returnErr return err } - f, err := l.Sink.GetWriter(ctx, manifestPath(backup.Repository, backup.ID)) - if err != nil { + if err := l.writeManifest(ctx, backup, backup.ID); err != nil { return fmt.Errorf("manifest: commit: %w", err) } - defer func() { - if err := f.Close(); err != nil && returnErr == nil { - returnErr = fmt.Errorf("manifest: commit: %w", err) - } - }() - - if err := toml.NewEncoder(f).Encode(backup); err != nil { + if err := l.writeManifest(ctx, backup, "+latest"); err != nil { return fmt.Errorf("manifest: commit: %w", err) } @@ -340,6 +333,24 @@ func (l ManifestLocator) Find(ctx context.Context, repo storage.Repository, back return &backup, nil } +func (l ManifestLocator) writeManifest(ctx context.Context, backup *Backup, backupID string) (returnErr error) { + f, err := l.Sink.GetWriter(ctx, manifestPath(backup.Repository, backupID)) + if err != nil { + return fmt.Errorf("write manifest: %w", err) + } + defer func() { + if err := f.Close(); err != nil && returnErr == nil { + returnErr = fmt.Errorf("write manifest: %w", err) + } + }() + + if err := toml.NewEncoder(f).Encode(backup); err != nil { + return fmt.Errorf("write manifest: %w", err) + } + + return nil +} + func manifestPath(repo storage.Repository, backupID string) string { storageName := repo.GetStorageName() // Other locators strip the .git suffix off of relative paths. This suffix diff --git a/internal/backup/locator_test.go b/internal/backup/locator_test.go index 90cac3664..cca9ee8e8 100644 --- a/internal/backup/locator_test.go +++ b/internal/backup/locator_test.go @@ -470,7 +470,9 @@ custom_hooks_path = '%[1]s/%[2]s/001.custom_hooks.tar' require.NoError(t, l.Commit(ctx, incremental)) manifest := testhelper.MustReadFile(t, filepath.Join(backupPath, "manifests", repo.StorageName, repo.RelativePath, backupID+".toml")) - require.Equal(t, fmt.Sprintf(`object_format = 'sha1' + latestManifest := testhelper.MustReadFile(t, filepath.Join(backupPath, "manifests", repo.StorageName, repo.RelativePath, "+latest.toml")) + + expectedManifest := fmt.Sprintf(`object_format = 'sha1' [[steps]] bundle_path = '%[1]s/%[2]s/001.bundle' @@ -482,7 +484,10 @@ bundle_path = '%[1]s/%[2]s/002.bundle' ref_path = '%[1]s/%[2]s/002.refs' previous_ref_path = '%[1]s/%[2]s/001.refs' custom_hooks_path = '%[1]s/%[2]s/002.custom_hooks.tar' -`, repo.RelativePath, backupID), string(manifest)) +`, repo.RelativePath, backupID) + + require.Equal(t, expectedManifest, string(manifest)) + require.Equal(t, expectedManifest, string(latestManifest)) }) } |