Have kopia package generate tags during backup based on Reasons (#3869)

Move tag generation from the backup op to the
kopia package. This makes it match the pattern
that finding base backups uses where a set of
Reasons and a separate set of additional tags
are provided

---

#### Does this PR need a docs update or release note?

- [ ]  Yes, it's included
- [ ] 🕐 Yes, but in a later PR
- [x]  No

#### Type of change

- [ ] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Supportability/Tests
- [ ] 💻 CI/Deployment
- [x] 🧹 Tech Debt/Cleanup

#### Issue(s)

* #2360

#### Test Plan

- [x] 💪 Manual
- [x]  Unit test
- [x] 💚 E2E
This commit is contained in:
ashmrtn 2023-07-21 15:49:42 -07:00 committed by GitHub
parent 7677299ace
commit 62d4c68c04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 50 additions and 49 deletions

View File

@ -39,8 +39,6 @@ type Reasoner interface {
// SubtreePath returns the path prefix for data in existing backups that have
// parameters (tenant, protected resourced, etc) that match this Reasoner.
SubtreePath() (path.Path, error)
// TODO(ashmrtn): Remove this when kopia generates tags from Reasons.
TagKeys() []string
}
func NewReason(
@ -92,9 +90,7 @@ func (r reason) SubtreePath() (path.Path, error) {
return p, clues.Wrap(err, "building path").OrNil()
}
// TODO(ashmrtn): Remove this when kopia generates tags based off Reasons. Here
// at the moment so things compile.
func (r reason) TagKeys() []string {
func tagKeys(r Reasoner) []string {
return []string{
r.ProtectedResource(),
serviceCatString(r.Service(), r.Category()),
@ -334,7 +330,7 @@ func (b *baseFinder) getBase(
) (*BackupEntry, *ManifestEntry, []ManifestEntry, error) {
allTags := map[string]string{}
for _, k := range r.TagKeys() {
for _, k := range tagKeys(r) {
allTags[k] = ""
}

View File

@ -15,6 +15,7 @@ type (
BackupConsumer interface {
ConsumeBackupCollections(
ctx context.Context,
backupReasons []kopia.Reasoner,
bases []kopia.IncrementalBase,
cs []data.BackupCollection,
pmr prefixmatcher.StringSetReader,

View File

@ -17,6 +17,7 @@ import (
"github.com/kopia/kopia/snapshot/policy"
"github.com/kopia/kopia/snapshot/snapshotfs"
"github.com/kopia/kopia/snapshot/snapshotmaintenance"
"golang.org/x/exp/maps"
"github.com/alcionai/corso/src/internal/common/prefixmatcher"
"github.com/alcionai/corso/src/internal/common/ptr"
@ -145,10 +146,11 @@ type IncrementalBase struct {
// complete backup of all data.
func (w Wrapper) ConsumeBackupCollections(
ctx context.Context,
backupReasons []Reasoner,
previousSnapshots []IncrementalBase,
collections []data.BackupCollection,
globalExcludeSet prefixmatcher.StringSetReader,
tags map[string]string,
additionalTags map[string]string,
buildTreeWithBase bool,
errs *fault.Bus,
) (*BackupStats, *details.Builder, DetailsMergeInfoer, error) {
@ -190,6 +192,19 @@ func (w Wrapper) ConsumeBackupCollections(
return nil, nil, nil, clues.Wrap(err, "building kopia directories")
}
// Add some extra tags so we can look things up by reason.
tags := maps.Clone(additionalTags)
if tags == nil {
// Some platforms seem to return nil if the input is nil.
tags = map[string]string{}
}
for _, r := range backupReasons {
for _, k := range tagKeys(r) {
tags[k] = ""
}
}
s, err := w.makeSnapshotWithRoot(
ctx,
previousSnapshots,

View File

@ -718,15 +718,17 @@ func (suite *KopiaIntegrationSuite) TestBackupCollections() {
),
}
for _, r := range reasons {
for _, k := range r.TagKeys() {
tags[k] = ""
}
}
expectedTags := map[string]string{}
maps.Copy(expectedTags, normalizeTagKVs(tags))
maps.Copy(expectedTags, tags)
for _, r := range reasons {
for _, k := range tagKeys(r) {
expectedTags[k] = ""
}
}
expectedTags = normalizeTagKVs(expectedTags)
table := []struct {
name string
@ -757,6 +759,7 @@ func (suite *KopiaIntegrationSuite) TestBackupCollections() {
stats, deets, _, err := suite.w.ConsumeBackupCollections(
suite.ctx,
reasons,
prevSnaps,
collections,
nil,
@ -847,15 +850,17 @@ func (suite *KopiaIntegrationSuite) TestBackupCollections_NoDetailsForMeta() {
storePath.Category()),
}
for _, r := range reasons {
for _, k := range r.TagKeys() {
tags[k] = ""
}
}
expectedTags := map[string]string{}
maps.Copy(expectedTags, normalizeTagKVs(tags))
maps.Copy(expectedTags, tags)
for _, r := range reasons {
for _, k := range tagKeys(r) {
expectedTags[k] = ""
}
}
expectedTags = normalizeTagKVs(expectedTags)
table := []struct {
name string
@ -942,6 +947,7 @@ func (suite *KopiaIntegrationSuite) TestBackupCollections_NoDetailsForMeta() {
stats, deets, prevShortRefs, err := suite.w.ConsumeBackupCollections(
suite.ctx,
reasons,
prevSnaps,
collections,
nil,
@ -1018,13 +1024,8 @@ func (suite *KopiaIntegrationSuite) TestRestoreAfterCompressionChange() {
w := &Wrapper{k}
tags := map[string]string{}
r := NewReason(testTenant, testUser, path.ExchangeService, path.EmailCategory)
for _, k := range r.TagKeys() {
tags[k] = ""
}
dc1 := exchMock.NewCollection(suite.storePath1, suite.locPath1, 1)
dc2 := exchMock.NewCollection(suite.storePath2, suite.locPath2, 1)
@ -1036,10 +1037,11 @@ func (suite *KopiaIntegrationSuite) TestRestoreAfterCompressionChange() {
stats, _, _, err := w.ConsumeBackupCollections(
ctx,
[]Reasoner{r},
nil,
[]data.BackupCollection{dc1, dc2},
nil,
tags,
nil,
true,
fault.New(true))
require.NoError(t, err, clues.ToCore(err))
@ -1110,13 +1112,8 @@ func (suite *KopiaIntegrationSuite) TestBackupCollections_ReaderError() {
loc1 := path.Builder{}.Append(suite.storePath1.Folders()...)
loc2 := path.Builder{}.Append(suite.storePath2.Folders()...)
tags := map[string]string{}
r := NewReason(testTenant, testUser, path.ExchangeService, path.EmailCategory)
for _, k := range r.TagKeys() {
tags[k] = ""
}
collections := []data.BackupCollection{
&mockBackupCollection{
path: suite.storePath1,
@ -1158,10 +1155,11 @@ func (suite *KopiaIntegrationSuite) TestBackupCollections_ReaderError() {
stats, deets, _, err := suite.w.ConsumeBackupCollections(
suite.ctx,
[]Reasoner{r},
nil,
collections,
nil,
tags,
nil,
true,
fault.New(true))
require.Error(t, err, clues.ToCore(err))
@ -1233,6 +1231,7 @@ func (suite *KopiaIntegrationSuite) TestBackupCollectionsHandlesNoCollections()
s, d, _, err := suite.w.ConsumeBackupCollections(
ctx,
nil,
nil,
test.collections,
nil,
nil,
@ -1385,19 +1384,15 @@ func (suite *KopiaSimpleRepoIntegrationSuite) SetupTest() {
collections = append(collections, collection)
}
tags := map[string]string{}
r := NewReason(testTenant, testUser, path.ExchangeService, path.EmailCategory)
for _, k := range r.TagKeys() {
tags[k] = ""
}
stats, deets, _, err := suite.w.ConsumeBackupCollections(
suite.ctx,
[]Reasoner{r},
nil,
collections,
nil,
tags,
nil,
false,
fault.New(true))
require.NoError(t, err, clues.ToCore(err))
@ -1443,12 +1438,6 @@ func (suite *KopiaSimpleRepoIntegrationSuite) TestBackupExcludeItem() {
man, err := suite.w.c.LoadSnapshot(suite.ctx, suite.snapshotID)
require.NoError(suite.T(), err, "getting base snapshot: %v", clues.ToCore(err))
tags := map[string]string{}
for _, k := range r.TagKeys() {
tags[k] = ""
}
table := []struct {
name string
excludeItem bool
@ -1537,6 +1526,7 @@ func (suite *KopiaSimpleRepoIntegrationSuite) TestBackupExcludeItem() {
stats, _, _, err := suite.w.ConsumeBackupCollections(
suite.ctx,
[]Reasoner{r},
[]IncrementalBase{
{
Manifest: man,
@ -1547,7 +1537,7 @@ func (suite *KopiaSimpleRepoIntegrationSuite) TestBackupExcludeItem() {
},
test.cols(),
excluded,
tags,
nil,
true,
fault.New(true))
require.NoError(t, err, clues.ToCore(err))

View File

@ -495,12 +495,6 @@ func consumeBackupCollections(
kopia.TagBackupCategory: "",
}
for _, reason := range reasons {
for _, k := range reason.TagKeys() {
tags[k] = ""
}
}
// AssistBases should be the upper bound for how many snapshots we pass in.
bases := make([]kopia.IncrementalBase, 0, len(bbs.AssistBases()))
// Track IDs we've seen already so we don't accidentally duplicate some
@ -578,6 +572,7 @@ func consumeBackupCollections(
kopiaStats, deets, itemsSourcedFromBase, err := bc.ConsumeBackupCollections(
ctx,
reasons,
bases,
cs,
pmr,

View File

@ -107,6 +107,7 @@ func checkPaths(t *testing.T, expected, got []path.Path) {
type mockBackupConsumer struct {
checkFunc func(
backupReasons []kopia.Reasoner,
bases []kopia.IncrementalBase,
cs []data.BackupCollection,
tags map[string]string,
@ -115,6 +116,7 @@ type mockBackupConsumer struct {
func (mbu mockBackupConsumer) ConsumeBackupCollections(
ctx context.Context,
backupReasons []kopia.Reasoner,
bases []kopia.IncrementalBase,
cs []data.BackupCollection,
excluded prefixmatcher.StringSetReader,
@ -123,7 +125,7 @@ func (mbu mockBackupConsumer) ConsumeBackupCollections(
errs *fault.Bus,
) (*kopia.BackupStats, *details.Builder, kopia.DetailsMergeInfoer, error) {
if mbu.checkFunc != nil {
mbu.checkFunc(bases, cs, tags, buildTreeWithBase)
mbu.checkFunc(backupReasons, bases, cs, tags, buildTreeWithBase)
}
return &kopia.BackupStats{}, &details.Builder{}, nil, nil
@ -537,6 +539,7 @@ func (suite *BackupOpUnitSuite) TestBackupOperation_ConsumeBackupDataCollections
mbu := &mockBackupConsumer{
checkFunc: func(
backupReasons []kopia.Reasoner,
bases []kopia.IncrementalBase,
cs []data.BackupCollection,
tags map[string]string,

View File

@ -234,6 +234,7 @@ func write(
backupStats, _, _, err := bup.ConsumeBackupCollections(
ctx,
nil,
nil,
dbcs,
prefixmatcher.NopReader[map[string]struct{}](),
nil,