diff --git a/src/internal/kopia/backup_bases.go b/src/internal/kopia/backup_bases.go index 18624236b..e96024692 100644 --- a/src/internal/kopia/backup_bases.go +++ b/src/internal/kopia/backup_bases.go @@ -12,30 +12,7 @@ import ( "github.com/alcionai/corso/src/pkg/logger" ) -// TODO(ashmrtn): Move this into some inject package. Here to avoid import -// cycles. -type BackupBases interface { - // ConvertToAssistBase converts the base with the given item data snapshot ID - // from a merge base to an assist base. - ConvertToAssistBase(manifestID manifest.ID) - Backups() []BackupEntry - UniqueAssistBackups() []BackupEntry - MinBackupVersion() int - MergeBases() []ManifestEntry - DisableMergeBases() - UniqueAssistBases() []ManifestEntry - DisableAssistBases() - MergeBackupBases( - ctx context.Context, - other BackupBases, - reasonToKey func(identity.Reasoner) string, - ) BackupBases - // SnapshotAssistBases returns the set of bases to use for kopia assisted - // incremental snapshot operations. It consists of the union of merge bases - // and assist bases. If DisableAssistBases has been called then it returns - // nil. - SnapshotAssistBases() []ManifestEntry -} +var _ backup.BackupBases = &backupBases{} type backupBases struct { // backups and mergeBases should be modified together as they relate similar diff --git a/src/internal/kopia/base_finder.go b/src/internal/kopia/base_finder.go index 4a8a7631a..a77a350ed 100644 --- a/src/internal/kopia/base_finder.go +++ b/src/internal/kopia/base_finder.go @@ -17,19 +17,6 @@ import ( "github.com/alcionai/corso/src/pkg/store" ) -const ( - // Kopia does not do comparisons properly for empty tags right now so add some - // placeholder value to them. - defaultTagValue = "0" - - // Kopia CLI prefixes all user tags with "tag:"[1]. Maintaining this will - // ensure we don't accidentally take reserved tags and that tags can be - // displayed with kopia CLI. - // (permalinks) - // [1] https://github.com/kopia/kopia/blob/05e729a7858a6e86cb48ba29fb53cb6045efce2b/cli/command_snapshot_create.go#L169 - userTagPrefix = "tag:" -) - func NewReason( tenant, resource string, service path.ServiceType, @@ -91,44 +78,10 @@ func reasonKey(r identity.Reasoner) string { return r.ProtectedResource() + r.Service().String() + r.Category().String() } -type BackupEntry struct { - *backup.Backup - Reasons []identity.Reasoner -} - -type ManifestEntry struct { - *snapshot.Manifest - // Reasons contains the ResourceOwners and Service/Categories that caused this - // snapshot to be selected as a base. We can't reuse OwnersCats here because - // it's possible some ResourceOwners will have a subset of the Categories as - // the reason for selecting a snapshot. For example: - // 1. backup user1 email,contacts -> B1 - // 2. backup user1 contacts -> B2 (uses B1 as base) - // 3. backup user1 email,contacts,events (uses B1 for email, B2 for contacts) - Reasons []identity.Reasoner -} - -func (me ManifestEntry) GetTag(key string) (string, bool) { - k, _ := makeTagKV(key) - v, ok := me.Tags[k] - - return v, ok -} - func serviceCatString(s path.ServiceType, c path.CategoryType) string { return s.String() + c.String() } -// MakeTagKV normalizes the provided key to protect it from clobbering -// similarly named tags from non-user input (user inputs are still open -// to collisions amongst eachother). -// Returns the normalized Key plus a default value. If you're embedding a -// key-only tag, the returned default value msut be used instead of an -// empty string. -func makeTagKV(k string) (string, string) { - return userTagPrefix + k, defaultTagValue -} - func normalizeTagKVs(tags map[string]string) map[string]string { t2 := make(map[string]string, len(tags)) diff --git a/src/pkg/backup/backup_bases.go b/src/pkg/backup/backup_bases.go new file mode 100644 index 000000000..bf977f7ea --- /dev/null +++ b/src/pkg/backup/backup_bases.go @@ -0,0 +1,110 @@ +package backup + +import ( + "context" + + "github.com/kopia/kopia/repo/manifest" + "github.com/kopia/kopia/snapshot" + + "github.com/alcionai/corso/src/pkg/backup/identity" + "github.com/alcionai/corso/src/pkg/path" +) + +const ( + // Kopia does not do comparisons properly for empty tags right now so add some + // placeholder value to them. + legacyDefaultTagValue = "0" + + // Kopia CLI prefixes all user tags with "tag:"[1]. Maintaining this will + // ensure we don't accidentally take reserved tags and that tags can be + // displayed with kopia CLI. + // (permalinks) + // [1] https://github.com/kopia/kopia/blob/05e729a7858a6e86cb48ba29fb53cb6045efce2b/cli/command_snapshot_create.go#L169 + LegacyUserTagPrefix = "tag:" + + tenantIDKey = "tenant" + resourceIDKey = "resource" + serviceCatPrefix = "sc-" + + // Sentinel value for tags. Could technically be empty but we'll store + // something for now. + //nolint + defaultTagValue = "1" +) + +func serviceCatString( + service path.ServiceType, + category path.CategoryType, +) string { + return serviceCatPrefix + service.String() + category.String() +} + +// reasonTags returns the set of key-value pairs that can be used as tags to +// represent this Reason. +// nolint +func reasonTags(r identity.Reasoner) map[string]string { + return map[string]string{ + tenantIDKey: r.Tenant(), + resourceIDKey: r.ProtectedResource(), + serviceCatString(r.Service(), r.Category()): defaultTagValue, + } +} + +// nolint +type BackupEntry struct { + *Backup + Reasons []identity.Reasoner +} + +type ManifestEntry struct { + *snapshot.Manifest + // Reasons contains the ResourceOwners and Service/Categories that caused this + // snapshot to be selected as a base. We can't reuse OwnersCats here because + // it's possible some ResourceOwners will have a subset of the Categories as + // the reason for selecting a snapshot. For example: + // 1. backup user1 email,contacts -> B1 + // 2. backup user1 contacts -> B2 (uses B1 as base) + // 3. backup user1 email,contacts,events (uses B1 for email, B2 for contacts) + Reasons []identity.Reasoner +} + +// MakeTagKV normalizes the provided key to protect it from clobbering +// similarly named tags from non-user input (user inputs are still open +// to collisions amongst eachother). +// Returns the normalized Key plus a default value. If you're embedding a +// key-only tag, the returned default value msut be used instead of an +// empty string. +func MakeTagKV(k string) (string, string) { + return LegacyUserTagPrefix + k, legacyDefaultTagValue +} + +func (me ManifestEntry) GetTag(key string) (string, bool) { + k, _ := MakeTagKV(key) + v, ok := me.Tags[k] + + return v, ok +} + +// nolint +type BackupBases interface { + // ConvertToAssistBase converts the base with the given item data snapshot ID + // from a merge base to an assist base. + ConvertToAssistBase(manifestID manifest.ID) + Backups() []BackupEntry + UniqueAssistBackups() []BackupEntry + MinBackupVersion() int + MergeBases() []ManifestEntry + DisableMergeBases() + UniqueAssistBases() []ManifestEntry + DisableAssistBases() + MergeBackupBases( + ctx context.Context, + other BackupBases, + reasonToKey func(identity.Reasoner) string, + ) BackupBases + // SnapshotAssistBases returns the set of bases to use for kopia assisted + // incremental snapshot operations. It consists of the union of merge bases + // and assist bases. If DisableAssistBases has been called then it returns + // nil. + SnapshotAssistBases() []ManifestEntry +}