diff --git a/src/pkg/backup/backup.go b/src/pkg/backup/backup.go index 6a9a27a7b..4a6674d7b 100644 --- a/src/pkg/backup/backup.go +++ b/src/pkg/backup/backup.go @@ -14,6 +14,7 @@ import ( "github.com/alcionai/corso/src/internal/common/str" "github.com/alcionai/corso/src/internal/model" "github.com/alcionai/corso/src/internal/stats" + "github.com/alcionai/corso/src/internal/version" "github.com/alcionai/corso/src/pkg/fault" "github.com/alcionai/corso/src/pkg/selectors" ) @@ -72,7 +73,7 @@ var _ print.Printable = &Backup{} func New( snapshotID, streamStoreID, status string, - version int, + backupVersion int, id model.StableID, selector selectors.Selector, ownerID, ownerName string, @@ -118,7 +119,7 @@ func New( ResourceOwnerID: ownerID, ResourceOwnerName: ownerName, - Version: version, + Version: backupVersion, SnapshotID: snapshotID, StreamStoreID: streamStoreID, @@ -141,6 +142,26 @@ func New( } } +// Type returns the type of the backup according to the value stored in the +// Backup's tags. Backup type is used during base finding to determine if a +// given backup is eligible to be used for the upcoming incremental backup. +func (b Backup) Type() string { + t, ok := b.Tags[model.BackupTypeTag] + + // Older backups didn't set the backup type tag because we only persisted + // backup models for the MergeBackup type. Corso started adding the backup + // type tag when it was producing v8 backups. Any backup newer than that that + // doesn't have a backup type should just return an empty type and let the + // caller figure out what to do. + if !ok && + b.Version != version.NoBackup && + b.Version <= version.All8MigrateUserPNToID { + t = model.MergeBackup + } + + return t +} + // -------------------------------------------------------------------------------- // CLI Output // -------------------------------------------------------------------------------- diff --git a/src/pkg/backup/backup_test.go b/src/pkg/backup/backup_test.go index c1ce6f1cf..f9de49e70 100644 --- a/src/pkg/backup/backup_test.go +++ b/src/pkg/backup/backup_test.go @@ -1,6 +1,7 @@ package backup_test import ( + "fmt" "strconv" "testing" "time" @@ -14,6 +15,7 @@ import ( "github.com/alcionai/corso/src/internal/model" "github.com/alcionai/corso/src/internal/stats" "github.com/alcionai/corso/src/internal/tester" + "github.com/alcionai/corso/src/internal/version" "github.com/alcionai/corso/src/pkg/backup" "github.com/alcionai/corso/src/pkg/selectors" ) @@ -26,6 +28,84 @@ func TestBackupUnitSuite(t *testing.T) { suite.Run(t, &BackupUnitSuite{Suite: tester.NewUnitSuite(t)}) } +func (suite *BackupUnitSuite) TestBackup_Type() { + table := []struct { + name string + // versionStart is the first version to run this test on. Together with + // versionEnd this allows more compact test definition when the behavior is + // the same for multiple versions. + versionStart int + // versionEnd is the final version to run this test on. Together with + // versionStart this allows more compact test definition when the behavior + // is the same for multiple versions. + versionEnd int + // Take a map so that we can have check not having the tag at all vs. having + // an empty value. + inputTags map[string]string + expect string + }{ + { + name: "NoVersion Returns Empty Type If Untagged", + versionStart: version.NoBackup, + versionEnd: version.NoBackup, + }, + { + name: "PreTag Versions Returns Merge Type If Untagged", + versionStart: 0, + versionEnd: version.All8MigrateUserPNToID, + expect: model.MergeBackup, + }, + { + name: "Tag Versions Returns Merge Type If Tagged", + versionStart: version.All8MigrateUserPNToID, + versionEnd: version.Backup, + inputTags: map[string]string{ + model.BackupTypeTag: model.MergeBackup, + }, + expect: model.MergeBackup, + }, + { + name: "Tag Versions Returns Assist Type If Tagged", + versionStart: version.All8MigrateUserPNToID, + versionEnd: version.Backup, + inputTags: map[string]string{ + model.BackupTypeTag: model.AssistBackup, + }, + expect: model.AssistBackup, + }, + { + name: "Tag Versions Returns Empty Type If Untagged", + versionStart: version.Groups9Update, + versionEnd: version.Backup, + }, + { + name: "All Versions Returns Empty Type If Empty Tag", + versionStart: 0, + versionEnd: version.Backup, + inputTags: map[string]string{ + model.BackupTypeTag: "", + }, + }, + } + + for _, test := range table { + suite.Run(test.name, func() { + for v := test.versionStart; v <= test.versionEnd; v++ { + suite.Run(fmt.Sprintf("Version%d", v), func() { + bup := backup.Backup{ + BaseModel: model.BaseModel{ + Tags: test.inputTags, + }, + Version: v, + } + + assert.Equal(suite.T(), test.expect, bup.Type()) + }) + } + }) + } +} + func stubBackup(t time.Time, ownerID, ownerName string) backup.Backup { sel := selectors.NewExchangeBackup([]string{"test"}) sel.Include(sel.AllData())