add serviceResource to reasoner interface

first round of reasoner changes: introduces the serviceResource
struct and swaps out that getter for the individual service and
resource getters.

Only makes a pass on easy-to-update code.  Following PRs will focus
on logical updates (tag handling, reason evaluattion, etc).
This commit is contained in:
ryanfkeepers 2023-08-14 14:44:57 -06:00
parent 48aae5d485
commit 62c6fe29ec
12 changed files with 443 additions and 289 deletions

View File

@ -220,7 +220,10 @@ func (suite *BackupBasesUnitSuite) TestMergeBackupBases() {
reasons := make([]identity.Reasoner, 0, len(i.cat)) reasons := make([]identity.Reasoner, 0, len(i.cat))
for _, c := range i.cat { for _, c := range i.cat {
reasons = append(reasons, NewReason("", ro, path.ExchangeService, c)) reasons = append(reasons, NewReason(
"",
[]path.ServiceResource{{ProtectedResource: ro, Service: path.ExchangeService}},
c))
} }
m := makeManifest(baseID, "", "b"+baseID, reasons...) m := makeManifest(baseID, "", "b"+baseID, reasons...)
@ -245,7 +248,10 @@ func (suite *BackupBasesUnitSuite) TestMergeBackupBases() {
reasons := make([]identity.Reasoner, 0, len(i.cat)) reasons := make([]identity.Reasoner, 0, len(i.cat))
for _, c := range i.cat { for _, c := range i.cat {
reasons = append(reasons, NewReason("", ro, path.ExchangeService, c)) reasons = append(reasons, NewReason(
"",
[]path.ServiceResource{{ProtectedResource: ro, Service: path.ExchangeService}},
c))
} }
m := makeManifest(baseID, "", "a"+baseID, reasons...) m := makeManifest(baseID, "", "a"+baseID, reasons...)
@ -480,7 +486,7 @@ func (suite *BackupBasesUnitSuite) TestFixupAndVerify() {
ro := "resource_owner" ro := "resource_owner"
makeMan := func(pct path.CategoryType, id, incmpl, bID string) ManifestEntry { makeMan := func(pct path.CategoryType, id, incmpl, bID string) ManifestEntry {
r := NewReason("", ro, path.ExchangeService, pct) r := NewReason("", []path.ServiceResource{{ProtectedResource: ro, Service: path.ExchangeService}}, pct)
return makeManifest(id, incmpl, bID, r) return makeManifest(id, incmpl, bID, r)
} }
@ -690,11 +696,17 @@ func (suite *BackupBasesUnitSuite) TestFixupAndVerify() {
res := validMail1() res := validMail1()
res.mergeBases[0].Reasons = append( res.mergeBases[0].Reasons = append(
res.mergeBases[0].Reasons, res.mergeBases[0].Reasons,
NewReason("", ro, path.ExchangeService, path.ContactsCategory)) NewReason(
"",
[]path.ServiceResource{{ProtectedResource: ro, Service: path.ExchangeService}},
path.ContactsCategory))
res.assistBases[0].Reasons = append( res.assistBases[0].Reasons = append(
res.assistBases[0].Reasons, res.assistBases[0].Reasons,
NewReason("", ro, path.ExchangeService, path.ContactsCategory)) NewReason(
"",
[]path.ServiceResource{{ProtectedResource: ro, Service: path.ExchangeService}},
path.ContactsCategory))
return res return res
}(), }(),
@ -702,11 +714,17 @@ func (suite *BackupBasesUnitSuite) TestFixupAndVerify() {
res := validMail1() res := validMail1()
res.mergeBases[0].Reasons = append( res.mergeBases[0].Reasons = append(
res.mergeBases[0].Reasons, res.mergeBases[0].Reasons,
NewReason("", ro, path.ExchangeService, path.ContactsCategory)) NewReason(
"",
[]path.ServiceResource{{ProtectedResource: ro, Service: path.ExchangeService}},
path.ContactsCategory))
res.assistBases[0].Reasons = append( res.assistBases[0].Reasons = append(
res.assistBases[0].Reasons, res.assistBases[0].Reasons,
NewReason("", ro, path.ExchangeService, path.ContactsCategory)) NewReason(
"",
[]path.ServiceResource{{ProtectedResource: ro, Service: path.ExchangeService}},
path.ContactsCategory))
res.assistBases = append(res.mergeBases, res.assistBases...) res.assistBases = append(res.mergeBases, res.assistBases...)

View File

@ -31,15 +31,14 @@ const (
) )
func NewReason( func NewReason(
tenant, resource string, tenant string,
service path.ServiceType, srs []path.ServiceResource,
category path.CategoryType, category path.CategoryType,
) identity.Reasoner { ) identity.Reasoner {
return reason{ return reason{
tenant: tenant, tenant: tenant,
resource: resource, serviceResources: srs,
service: service, category: category,
category: category,
} }
} }
@ -47,22 +46,17 @@ type reason struct {
// tenant appears here so that when this is moved to an inject package nothing // tenant appears here so that when this is moved to an inject package nothing
// needs changed. However, kopia itself is blind to the fields in the reason // needs changed. However, kopia itself is blind to the fields in the reason
// struct and relies on helper functions to get the information it needs. // struct and relies on helper functions to get the information it needs.
tenant string tenant string
resource string serviceResources []path.ServiceResource
service path.ServiceType category path.CategoryType
category path.CategoryType
} }
func (r reason) Tenant() string { func (r reason) Tenant() string {
return r.tenant return r.tenant
} }
func (r reason) ProtectedResource() string { func (r reason) ServiceResources() []path.ServiceResource {
return r.resource return r.ServiceResources()
}
func (r reason) Service() path.ServiceType {
return r.service
} }
func (r reason) Category() path.CategoryType { func (r reason) Category() path.CategoryType {
@ -72,8 +66,7 @@ func (r reason) Category() path.CategoryType {
func (r reason) SubtreePath() (path.Path, error) { func (r reason) SubtreePath() (path.Path, error) {
p, err := path.BuildPrefix( p, err := path.BuildPrefix(
r.Tenant(), r.Tenant(),
r.ProtectedResource(), r.ServiceResources(),
r.Service(),
r.Category()) r.Category())
return p, clues.Wrap(err, "building path").OrNil() return p, clues.Wrap(err, "building path").OrNil()
@ -88,7 +81,13 @@ func tagKeys(r identity.Reasoner) []string {
// reasonKey returns the concatenation of the ProtectedResource, Service, and Category. // reasonKey returns the concatenation of the ProtectedResource, Service, and Category.
func reasonKey(r identity.Reasoner) string { func reasonKey(r identity.Reasoner) string {
return r.ProtectedResource() + r.Service().String() + r.Category().String() var rk string
for _, sr := range r.ServiceResources() {
rk += sr.ProtectedResource + sr.Service.String()
}
return rk + r.Category().String()
} }
type BackupEntry struct { type BackupEntry struct {
@ -412,7 +411,7 @@ func (b *baseFinder) FindBases(
for _, searchReason := range reasons { for _, searchReason := range reasons {
ictx := clues.Add( ictx := clues.Add(
ctx, ctx,
"search_service", searchReason.Service().String(), "search_service", path.ServiceResourcesToServices(searchReason.ServiceResources()),
"search_category", searchReason.Category().String()) "search_category", searchReason.Category().String())
logger.Ctx(ictx).Info("searching for previous manifests") logger.Ctx(ictx).Info("searching for previous manifests")

View File

@ -47,22 +47,22 @@ var (
testAllUsersAllCats = []identity.Reasoner{ testAllUsersAllCats = []identity.Reasoner{
// User1 email and events. // User1 email and events.
NewReason("", testUser1, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser1, Service: path.ExchangeService}}, path.EmailCategory),
NewReason("", testUser1, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser1, Service: path.ExchangeService}}, path.EventsCategory),
// User2 email and events. // User2 email and events.
NewReason("", testUser2, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser2, Service: path.ExchangeService}}, path.EmailCategory),
NewReason("", testUser2, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser2, Service: path.ExchangeService}}, path.EventsCategory),
// User3 email and events. // User3 email and events.
NewReason("", testUser3, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser3, Service: path.ExchangeService}}, path.EmailCategory),
NewReason("", testUser3, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser3, Service: path.ExchangeService}}, path.EventsCategory),
} }
testAllUsersMail = []identity.Reasoner{ testAllUsersMail = []identity.Reasoner{
NewReason("", testUser1, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser1, Service: path.ExchangeService}}, path.EmailCategory),
NewReason("", testUser2, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser2, Service: path.ExchangeService}}, path.EmailCategory),
NewReason("", testUser3, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser3, Service: path.ExchangeService}}, path.EmailCategory),
} }
testUser1Mail = []identity.Reasoner{ testUser1Mail = []identity.Reasoner{
NewReason("", testUser1, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser1, Service: path.ExchangeService}}, path.EmailCategory),
} }
) )
@ -294,7 +294,7 @@ func (suite *BaseFinderUnitSuite) TestNoResult_NoBackupsOrSnapshots() {
bg: mockEmptyModelGetter{}, bg: mockEmptyModelGetter{},
} }
reasons := []identity.Reasoner{ reasons := []identity.Reasoner{
NewReason("", "a-user", path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: "a-user", Service: path.ExchangeService}}, path.EmailCategory),
} }
bb := bf.FindBases(ctx, reasons, nil) bb := bf.FindBases(ctx, reasons, nil)
@ -313,7 +313,7 @@ func (suite *BaseFinderUnitSuite) TestNoResult_ErrorListingSnapshots() {
bg: mockEmptyModelGetter{}, bg: mockEmptyModelGetter{},
} }
reasons := []identity.Reasoner{ reasons := []identity.Reasoner{
NewReason("", "a-user", path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: "a-user", Service: path.ExchangeService}}, path.EmailCategory),
} }
bb := bf.FindBases(ctx, reasons, nil) bb := bf.FindBases(ctx, reasons, nil)
@ -602,26 +602,26 @@ func (suite *BaseFinderUnitSuite) TestGetBases() {
}, },
expectedBaseReasons: map[int][]identity.Reasoner{ expectedBaseReasons: map[int][]identity.Reasoner{
0: { 0: {
NewReason("", testUser1, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser1, Service: path.ExchangeService}}, path.EmailCategory),
NewReason("", testUser2, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser2, Service: path.ExchangeService}}, path.EmailCategory),
NewReason("", testUser3, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser3, Service: path.ExchangeService}}, path.EmailCategory),
}, },
1: { 1: {
NewReason("", testUser1, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser1, Service: path.ExchangeService}}, path.EventsCategory),
NewReason("", testUser2, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser3, Service: path.ExchangeService}}, path.EventsCategory),
NewReason("", testUser3, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser3, Service: path.ExchangeService}}, path.EventsCategory),
}, },
}, },
expectedAssistManifestReasons: map[int][]identity.Reasoner{ expectedAssistManifestReasons: map[int][]identity.Reasoner{
0: { 0: {
NewReason("", testUser1, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser1, Service: path.ExchangeService}}, path.EmailCategory),
NewReason("", testUser2, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser2, Service: path.ExchangeService}}, path.EmailCategory),
NewReason("", testUser3, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser3, Service: path.ExchangeService}}, path.EmailCategory),
}, },
1: { 1: {
NewReason("", testUser1, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser1, Service: path.ExchangeService}}, path.EventsCategory),
NewReason("", testUser2, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser2, Service: path.ExchangeService}}, path.EventsCategory),
NewReason("", testUser3, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser3, Service: path.ExchangeService}}, path.EventsCategory),
}, },
}, },
backupData: []backupInfo{ backupData: []backupInfo{
@ -667,36 +667,36 @@ func (suite *BaseFinderUnitSuite) TestGetBases() {
}, },
expectedBaseReasons: map[int][]identity.Reasoner{ expectedBaseReasons: map[int][]identity.Reasoner{
2: { 2: {
NewReason("", testUser1, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser1, Service: path.ExchangeService}}, path.EmailCategory),
NewReason("", testUser2, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser2, Service: path.ExchangeService}}, path.EmailCategory),
NewReason("", testUser1, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser1, Service: path.ExchangeService}}, path.EventsCategory),
NewReason("", testUser2, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser2, Service: path.ExchangeService}}, path.EventsCategory),
}, },
}, },
expectedAssistManifestReasons: map[int][]identity.Reasoner{ expectedAssistManifestReasons: map[int][]identity.Reasoner{
0: { 0: {
NewReason("", testUser1, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser1, Service: path.ExchangeService}}, path.EventsCategory),
NewReason("", testUser2, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser2, Service: path.ExchangeService}}, path.EventsCategory),
}, },
1: { 1: {
NewReason("", testUser1, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser1, Service: path.ExchangeService}}, path.EmailCategory),
NewReason("", testUser2, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser2, Service: path.ExchangeService}}, path.EmailCategory),
}, },
2: { 2: {
NewReason("", testUser1, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser1, Service: path.ExchangeService}}, path.EmailCategory),
NewReason("", testUser2, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser2, Service: path.ExchangeService}}, path.EmailCategory),
NewReason("", testUser1, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser1, Service: path.ExchangeService}}, path.EventsCategory),
NewReason("", testUser2, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser2, Service: path.ExchangeService}}, path.EventsCategory),
}, },
}, },
expectedAssistReasons: map[int][]identity.Reasoner{ expectedAssistReasons: map[int][]identity.Reasoner{
0: { 0: {
NewReason("", testUser1, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser1, Service: path.ExchangeService}}, path.EventsCategory),
NewReason("", testUser2, path.ExchangeService, path.EventsCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser2, Service: path.ExchangeService}}, path.EventsCategory),
}, },
1: { 1: {
NewReason("", testUser1, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser1, Service: path.ExchangeService}}, path.EmailCategory),
NewReason("", testUser2, path.ExchangeService, path.EmailCategory), NewReason("", []path.ServiceResource{{ProtectedResource: testUser2, Service: path.ExchangeService}}, path.EmailCategory),
}, },
}, },
backupData: []backupInfo{ backupData: []backupInfo{

View File

@ -196,14 +196,16 @@ func (cp *corsoProgress) FinishedFile(relativePath string, err error) {
return return
} }
ctx := clues.Add(cp.ctx,
"services", path.ServiceResourcesToResources(d.repoPath.ServiceResources()),
"category", d.repoPath.Category().String())
// These items were sourced from a base snapshot or were cached in kopia so we // These items were sourced from a base snapshot or were cached in kopia so we
// never had to materialize their details in-memory. // never had to materialize their details in-memory.
if d.info == nil || d.cached { if d.info == nil || d.cached {
if d.prevPath == nil { if d.prevPath == nil {
cp.errs.AddRecoverable(cp.ctx, clues.New("item sourced from previous backup with no previous path"). cp.errs.AddRecoverable(ctx, clues.New("item sourced from previous backup with no previous path").
With( WithClues(ctx).
"service", d.repoPath.Service().String(),
"category", d.repoPath.Category().String()).
Label(fault.LabelForceNoBackupCreation)) Label(fault.LabelForceNoBackupCreation))
return return
@ -219,9 +221,7 @@ func (cp *corsoProgress) FinishedFile(relativePath string, err error) {
d.locationPath) d.locationPath)
if err != nil { if err != nil {
cp.errs.AddRecoverable(cp.ctx, clues.Wrap(err, "adding item to merge list"). cp.errs.AddRecoverable(cp.ctx, clues.Wrap(err, "adding item to merge list").
With( WithClues(ctx).
"service", d.repoPath.Service().String(),
"category", d.repoPath.Category().String()).
Label(fault.LabelForceNoBackupCreation)) Label(fault.LabelForceNoBackupCreation))
} }
@ -235,9 +235,7 @@ func (cp *corsoProgress) FinishedFile(relativePath string, err error) {
*d.info) *d.info)
if err != nil { if err != nil {
cp.errs.AddRecoverable(cp.ctx, clues.New("adding item to details"). cp.errs.AddRecoverable(cp.ctx, clues.New("adding item to details").
With( WithClues(ctx).
"service", d.repoPath.Service().String(),
"category", d.repoPath.Category().String()).
Label(fault.LabelForceNoBackupCreation)) Label(fault.LabelForceNoBackupCreation))
return return

View File

@ -724,8 +724,10 @@ func TestKopiaIntegrationSuite(t *testing.T) {
func (suite *KopiaIntegrationSuite) SetupSuite() { func (suite *KopiaIntegrationSuite) SetupSuite() {
tmp, err := path.Build( tmp, err := path.Build(
testTenant, testTenant,
testUser, []path.ServiceResource{{
path.ExchangeService, ProtectedResource: testUser,
Service: path.ExchangeService,
}},
path.EmailCategory, path.EmailCategory,
false, false,
testInboxDir) testInboxDir)
@ -736,8 +738,10 @@ func (suite *KopiaIntegrationSuite) SetupSuite() {
tmp, err = path.Build( tmp, err = path.Build(
testTenant, testTenant,
testUser, []path.ServiceResource{{
path.ExchangeService, ProtectedResource: testUser,
Service: path.ExchangeService,
}},
path.EmailCategory, path.EmailCategory,
false, false,
testArchiveDir) testArchiveDir)
@ -804,14 +808,12 @@ func (suite *KopiaIntegrationSuite) TestBackupCollections() {
reasons := []identity.Reasoner{ reasons := []identity.Reasoner{
NewReason( NewReason(
testTenant, testTenant,
suite.storePath1.ResourceOwner(), suite.storePath1.ServiceResources(),
suite.storePath1.Service(),
suite.storePath1.Category(), suite.storePath1.Category(),
), ),
NewReason( NewReason(
testTenant, testTenant,
suite.storePath2.ResourceOwner(), suite.storePath2.ServiceResources(),
suite.storePath2.Service(),
suite.storePath2.Category(), suite.storePath2.Category(),
), ),
} }
@ -1052,8 +1054,10 @@ func (suite *KopiaIntegrationSuite) TestBackupCollections() {
func (suite *KopiaIntegrationSuite) TestBackupCollections_NoDetailsForMeta() { func (suite *KopiaIntegrationSuite) TestBackupCollections_NoDetailsForMeta() {
tmp, err := path.Build( tmp, err := path.Build(
testTenant, testTenant,
testUser, []path.ServiceResource{{
path.OneDriveService, ProtectedResource: testUser,
Service: path.OneDriveService,
}},
path.FilesCategory, path.FilesCategory,
false, false,
testInboxDir) testInboxDir)
@ -1079,8 +1083,7 @@ func (suite *KopiaIntegrationSuite) TestBackupCollections_NoDetailsForMeta() {
reasons := []identity.Reasoner{ reasons := []identity.Reasoner{
NewReason( NewReason(
testTenant, testTenant,
storePath.ResourceOwner(), storePath.ServiceResources(),
storePath.Service(),
storePath.Category()), storePath.Category()),
} }
@ -1258,7 +1261,13 @@ func (suite *KopiaIntegrationSuite) TestRestoreAfterCompressionChange() {
w := &Wrapper{k} w := &Wrapper{k}
r := NewReason(testTenant, testUser, path.ExchangeService, path.EmailCategory) r := NewReason(
testTenant,
[]path.ServiceResource{{
ProtectedResource: testUser,
Service: path.ExchangeService,
}},
path.EmailCategory)
dc1 := exchMock.NewCollection(suite.storePath1, suite.locPath1, 1) dc1 := exchMock.NewCollection(suite.storePath1, suite.locPath1, 1)
dc2 := exchMock.NewCollection(suite.storePath2, suite.locPath2, 1) dc2 := exchMock.NewCollection(suite.storePath2, suite.locPath2, 1)
@ -1347,7 +1356,13 @@ func (suite *KopiaIntegrationSuite) TestBackupCollections_ReaderError() {
loc1 := path.Builder{}.Append(suite.storePath1.Folders()...) loc1 := path.Builder{}.Append(suite.storePath1.Folders()...)
loc2 := path.Builder{}.Append(suite.storePath2.Folders()...) loc2 := path.Builder{}.Append(suite.storePath2.Folders()...)
r := NewReason(testTenant, testUser, path.ExchangeService, path.EmailCategory) r := NewReason(
testTenant,
[]path.ServiceResource{{
ProtectedResource: testUser,
Service: path.ExchangeService,
}},
path.EmailCategory)
collections := []data.BackupCollection{ collections := []data.BackupCollection{
&mockBackupCollection{ &mockBackupCollection{
@ -1507,8 +1522,10 @@ func TestKopiaSimpleRepoIntegrationSuite(t *testing.T) {
func (suite *KopiaSimpleRepoIntegrationSuite) SetupSuite() { func (suite *KopiaSimpleRepoIntegrationSuite) SetupSuite() {
tmp, err := path.Build( tmp, err := path.Build(
testTenant, testTenant,
testUser, []path.ServiceResource{{
path.ExchangeService, ProtectedResource: testUser,
Service: path.ExchangeService,
}},
path.EmailCategory, path.EmailCategory,
false, false,
testInboxDir) testInboxDir)
@ -1518,8 +1535,10 @@ func (suite *KopiaSimpleRepoIntegrationSuite) SetupSuite() {
tmp, err = path.Build( tmp, err = path.Build(
testTenant, testTenant,
testUser, []path.ServiceResource{{
path.ExchangeService, ProtectedResource: testUser,
Service: path.ExchangeService,
}},
path.EmailCategory, path.EmailCategory,
false, false,
testArchiveDir) testArchiveDir)
@ -1619,7 +1638,13 @@ func (suite *KopiaSimpleRepoIntegrationSuite) SetupTest() {
collections = append(collections, collection) collections = append(collections, collection)
} }
r := NewReason(testTenant, testUser, path.ExchangeService, path.EmailCategory) r := NewReason(
testTenant,
[]path.ServiceResource{{
ProtectedResource: testUser,
Service: path.ExchangeService,
}},
path.EmailCategory)
stats, deets, _, err := suite.w.ConsumeBackupCollections( stats, deets, _, err := suite.w.ConsumeBackupCollections(
suite.ctx, suite.ctx,
@ -1657,7 +1682,13 @@ func (c *i64counter) Count(i int64) {
} }
func (suite *KopiaSimpleRepoIntegrationSuite) TestBackupExcludeItem() { func (suite *KopiaSimpleRepoIntegrationSuite) TestBackupExcludeItem() {
r := NewReason(testTenant, testUser, path.ExchangeService, path.EmailCategory) r := NewReason(
testTenant,
[]path.ServiceResource{{
ProtectedResource: testUser,
Service: path.ExchangeService,
}},
path.EmailCategory)
man, err := suite.w.c.LoadSnapshot(suite.ctx, suite.snapshotID) man, err := suite.w.c.LoadSnapshot(suite.ctx, suite.snapshotID)
require.NoError(suite.T(), err, "getting base snapshot: %v", clues.ToCore(err)) require.NoError(suite.T(), err, "getting base snapshot: %v", clues.ToCore(err))
@ -1800,8 +1831,10 @@ func (suite *KopiaSimpleRepoIntegrationSuite) TestBackupExcludeItem() {
func (suite *KopiaSimpleRepoIntegrationSuite) TestProduceRestoreCollections() { func (suite *KopiaSimpleRepoIntegrationSuite) TestProduceRestoreCollections() {
doesntExist, err := path.Build( doesntExist, err := path.Build(
testTenant, testTenant,
testUser, []path.ServiceResource{{
path.ExchangeService, ProtectedResource: testUser,
Service: path.ExchangeService,
}},
path.EmailCategory, path.EmailCategory,
true, true,
"subdir", "foo") "subdir", "foo")
@ -1934,8 +1967,10 @@ func (suite *KopiaSimpleRepoIntegrationSuite) TestProduceRestoreCollections() {
func (suite *KopiaSimpleRepoIntegrationSuite) TestProduceRestoreCollections_PathChanges() { func (suite *KopiaSimpleRepoIntegrationSuite) TestProduceRestoreCollections_PathChanges() {
rp1, err := path.Build( rp1, err := path.Build(
testTenant, testTenant,
testUser, []path.ServiceResource{{
path.ExchangeService, ProtectedResource: testUser,
Service: path.ExchangeService,
}},
path.EmailCategory, path.EmailCategory,
false, false,
"corso_restore", "Inbox") "corso_restore", "Inbox")
@ -1943,8 +1978,10 @@ func (suite *KopiaSimpleRepoIntegrationSuite) TestProduceRestoreCollections_Path
rp2, err := path.Build( rp2, err := path.Build(
testTenant, testTenant,
testUser, []path.ServiceResource{{
path.ExchangeService, ProtectedResource: testUser,
Service: path.ExchangeService,
}},
path.EmailCategory, path.EmailCategory,
false, false,
"corso_restore", "Archive") "corso_restore", "Archive")
@ -2057,8 +2094,10 @@ func (suite *KopiaSimpleRepoIntegrationSuite) TestProduceRestoreCollections_Fetc
rp1, err := path.Build( rp1, err := path.Build(
testTenant, testTenant,
testUser, []path.ServiceResource{{
path.ExchangeService, ProtectedResource: testUser,
Service: path.ExchangeService,
}},
path.EmailCategory, path.EmailCategory,
false, false,
"corso_restore", "Inbox") "corso_restore", "Inbox")

View File

@ -460,13 +460,17 @@ func (suite *BackupOpUnitSuite) TestBackupOperation_ConsumeBackupDataCollections
emailReason = kopia.NewReason( emailReason = kopia.NewReason(
tenant, tenant,
resourceOwner, []path.ServiceResource{{
path.ExchangeService, ProtectedResource: resourceOwner,
Service: path.ExchangeService,
}},
path.EmailCategory) path.EmailCategory)
contactsReason = kopia.NewReason( contactsReason = kopia.NewReason(
tenant, tenant,
resourceOwner, []path.ServiceResource{{
path.ExchangeService, ProtectedResource: resourceOwner,
Service: path.ExchangeService,
}},
path.ContactsCategory) path.ContactsCategory)
reasons = []identity.Reasoner{ reasons = []identity.Reasoner{
@ -617,13 +621,11 @@ func (suite *BackupOpUnitSuite) TestBackupOperation_MergeBackupDetails_AddsItems
pathReason1 = kopia.NewReason( pathReason1 = kopia.NewReason(
"", "",
itemPath1.ResourceOwner(), itemPath1.ServiceResources(),
itemPath1.Service(),
itemPath1.Category()) itemPath1.Category())
pathReason3 = kopia.NewReason( pathReason3 = kopia.NewReason(
"", "",
itemPath3.ResourceOwner(), itemPath3.ServiceResources(),
itemPath3.Service(),
itemPath3.Category()) itemPath3.Category())
time1 = time.Now() time1 = time.Now()
@ -1240,8 +1242,7 @@ func (suite *BackupOpUnitSuite) TestBackupOperation_MergeBackupDetails_AddsFolde
pathReason1 = kopia.NewReason( pathReason1 = kopia.NewReason(
"", "",
itemPath1.ResourceOwner(), itemPath1.ServiceResources(),
itemPath1.Service(),
itemPath1.Category()) itemPath1.Category())
backup1 = kopia.BackupEntry{ backup1 = kopia.BackupEntry{

View File

@ -145,8 +145,7 @@ func collectMetadata(
Append(fn). Append(fn).
ToServiceCategoryMetadataPath( ToServiceCategoryMetadataPath(
tenantID, tenantID,
reason.ProtectedResource(), reason.ServiceResources(),
reason.Service(),
reason.Category(), reason.Category(),
true) true)
if err != nil { if err != nil {

View File

@ -112,7 +112,13 @@ func (suite *OperationsManifestsUnitSuite) TestCollectMetadata() {
name: "single reason, single file", name: "single reason, single file",
manID: "single single", manID: "single single",
reasons: []identity.Reasoner{ reasons: []identity.Reasoner{
kopia.NewReason(tid, ro, path.ExchangeService, path.EmailCategory), kopia.NewReason(
tid,
[]path.ServiceResource{{
ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.EmailCategory),
}, },
expectPaths: func(t *testing.T, files []string) []path.Path { expectPaths: func(t *testing.T, files []string) []path.Path {
ps := make([]path.Path, 0, len(files)) ps := make([]path.Path, 0, len(files))
@ -131,7 +137,13 @@ func (suite *OperationsManifestsUnitSuite) TestCollectMetadata() {
name: "single reason, multiple files", name: "single reason, multiple files",
manID: "single multi", manID: "single multi",
reasons: []identity.Reasoner{ reasons: []identity.Reasoner{
kopia.NewReason(tid, ro, path.ExchangeService, path.EmailCategory), kopia.NewReason(
tid,
[]path.ServiceResource{{
ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.EmailCategory),
}, },
expectPaths: func(t *testing.T, files []string) []path.Path { expectPaths: func(t *testing.T, files []string) []path.Path {
ps := make([]path.Path, 0, len(files)) ps := make([]path.Path, 0, len(files))
@ -150,8 +162,20 @@ func (suite *OperationsManifestsUnitSuite) TestCollectMetadata() {
name: "multiple reasons, single file", name: "multiple reasons, single file",
manID: "multi single", manID: "multi single",
reasons: []identity.Reasoner{ reasons: []identity.Reasoner{
kopia.NewReason(tid, ro, path.ExchangeService, path.EmailCategory), kopia.NewReason(
kopia.NewReason(tid, ro, path.ExchangeService, path.ContactsCategory), tid,
[]path.ServiceResource{{
ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.EmailCategory),
kopia.NewReason(
tid,
[]path.ServiceResource{{
ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.ContactsCategory),
}, },
expectPaths: func(t *testing.T, files []string) []path.Path { expectPaths: func(t *testing.T, files []string) []path.Path {
ps := make([]path.Path, 0, len(files)) ps := make([]path.Path, 0, len(files))
@ -173,8 +197,20 @@ func (suite *OperationsManifestsUnitSuite) TestCollectMetadata() {
name: "multiple reasons, multiple file", name: "multiple reasons, multiple file",
manID: "multi multi", manID: "multi multi",
reasons: []identity.Reasoner{ reasons: []identity.Reasoner{
kopia.NewReason(tid, ro, path.ExchangeService, path.EmailCategory), kopia.NewReason(
kopia.NewReason(tid, ro, path.ExchangeService, path.ContactsCategory), tid,
[]path.ServiceResource{{
ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.EmailCategory),
kopia.NewReason(
tid,
[]path.ServiceResource{{
ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.ContactsCategory),
}, },
expectPaths: func(t *testing.T, files []string) []path.Path { expectPaths: func(t *testing.T, files []string) []path.Path {
ps := make([]path.Path, 0, len(files)) ps := make([]path.Path, 0, len(files))
@ -226,7 +262,13 @@ func buildReasons(
for _, cat := range cats { for _, cat := range cats {
reasons = append( reasons = append(
reasons, reasons,
kopia.NewReason("", ro, service, cat)) kopia.NewReason(
"",
[]path.ServiceResource{{
ProtectedResource: ro,
Service: service,
}},
cat))
} }
return reasons return reasons
@ -283,7 +325,13 @@ func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata() {
}, },
rp: mockRestoreProducer{}, rp: mockRestoreProducer{},
reasons: []identity.Reasoner{ reasons: []identity.Reasoner{
kopia.NewReason("", ro, path.ExchangeService, path.EmailCategory), kopia.NewReason(
"",
[]path.ServiceResource{{
ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.EmailCategory),
}, },
getMeta: false, getMeta: false,
assertErr: assert.NoError, assertErr: assert.NoError,
@ -304,7 +352,13 @@ func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata() {
}, },
rp: mockRestoreProducer{}, rp: mockRestoreProducer{},
reasons: []identity.Reasoner{ reasons: []identity.Reasoner{
kopia.NewReason("", ro, path.ExchangeService, path.EmailCategory), kopia.NewReason(
"",
[]path.ServiceResource{{
ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.EmailCategory),
}, },
getMeta: true, getMeta: true,
assertErr: assert.NoError, assertErr: assert.NoError,
@ -332,8 +386,20 @@ func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata() {
}, },
}, },
reasons: []identity.Reasoner{ reasons: []identity.Reasoner{
kopia.NewReason("", ro, path.ExchangeService, path.EmailCategory), kopia.NewReason(
kopia.NewReason("", ro, path.ExchangeService, path.ContactsCategory), "",
[]path.ServiceResource{{
ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.EmailCategory),
kopia.NewReason(
"",
[]path.ServiceResource{{
ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.ContactsCategory),
}, },
getMeta: true, getMeta: true,
assertErr: assert.NoError, assertErr: assert.NoError,
@ -379,7 +445,13 @@ func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata() {
}, },
}, },
reasons: []identity.Reasoner{ reasons: []identity.Reasoner{
kopia.NewReason("", ro, path.ExchangeService, path.EmailCategory), kopia.NewReason(
"",
[]path.ServiceResource{{
ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.EmailCategory),
}, },
getMeta: true, getMeta: true,
assertErr: assert.NoError, assertErr: assert.NoError,
@ -409,7 +481,13 @@ func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata() {
}, },
}, },
reasons: []identity.Reasoner{ reasons: []identity.Reasoner{
kopia.NewReason("", ro, path.ExchangeService, path.EmailCategory), kopia.NewReason(
"",
[]path.ServiceResource{{
ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.EmailCategory),
}, },
getMeta: true, getMeta: true,
dropAssist: true, dropAssist: true,
@ -438,7 +516,13 @@ func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata() {
}, },
}, },
reasons: []identity.Reasoner{ reasons: []identity.Reasoner{
kopia.NewReason("", ro, path.ExchangeService, path.EmailCategory), kopia.NewReason(
"",
[]path.ServiceResource{{
ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.EmailCategory),
}, },
getMeta: true, getMeta: true,
assertErr: assert.NoError, assertErr: assert.NoError,
@ -460,7 +544,13 @@ func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata() {
}, },
rp: mockRestoreProducer{err: assert.AnError}, rp: mockRestoreProducer{err: assert.AnError},
reasons: []identity.Reasoner{ reasons: []identity.Reasoner{
kopia.NewReason("", ro, path.ExchangeService, path.EmailCategory), kopia.NewReason(
"",
[]path.ServiceResource{{
ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.EmailCategory),
}, },
getMeta: true, getMeta: true,
assertErr: assert.Error, assertErr: assert.Error,
@ -566,14 +656,18 @@ func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata_Fallb
emailReason := kopia.NewReason( emailReason := kopia.NewReason(
"", "",
ro, []path.ServiceResource{{
path.ExchangeService, ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.EmailCategory) path.EmailCategory)
fbEmailReason := kopia.NewReason( fbEmailReason := kopia.NewReason(
"", "",
fbro, []path.ServiceResource{{
path.ExchangeService, ProtectedResource: fbro,
Service: path.ExchangeService,
}},
path.EmailCategory) path.EmailCategory)
table := []struct { table := []struct {
@ -880,11 +974,23 @@ func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata_Fallb
}, },
reasons: []identity.Reasoner{ reasons: []identity.Reasoner{
emailReason, emailReason,
kopia.NewReason("", ro, path.ExchangeService, path.ContactsCategory), kopia.NewReason(
"",
[]path.ServiceResource{{
ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.ContactsCategory),
}, },
fallbackReasons: []identity.Reasoner{ fallbackReasons: []identity.Reasoner{
fbEmailReason, fbEmailReason,
kopia.NewReason("", fbro, path.ExchangeService, path.ContactsCategory), kopia.NewReason(
"",
[]path.ServiceResource{{
ProtectedResource: fbro,
Service: path.ExchangeService,
}},
path.ContactsCategory),
}, },
getMeta: true, getMeta: true,
assertErr: assert.NoError, assertErr: assert.NoError,
@ -916,7 +1022,13 @@ func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata_Fallb
}, },
reasons: []identity.Reasoner{emailReason}, reasons: []identity.Reasoner{emailReason},
fallbackReasons: []identity.Reasoner{ fallbackReasons: []identity.Reasoner{
kopia.NewReason("", fbro, path.ExchangeService, path.ContactsCategory), kopia.NewReason(
"",
[]path.ServiceResource{{
ProtectedResource: fbro,
Service: path.ExchangeService,
}},
path.ContactsCategory),
}, },
getMeta: true, getMeta: true,
assertErr: assert.NoError, assertErr: assert.NoError,
@ -951,11 +1063,23 @@ func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata_Fallb
}, },
reasons: []identity.Reasoner{ reasons: []identity.Reasoner{
emailReason, emailReason,
kopia.NewReason("", ro, path.ExchangeService, path.ContactsCategory), kopia.NewReason(
"",
[]path.ServiceResource{{
ProtectedResource: ro,
Service: path.ExchangeService,
}},
path.ContactsCategory),
}, },
fallbackReasons: []identity.Reasoner{ fallbackReasons: []identity.Reasoner{
fbEmailReason, fbEmailReason,
kopia.NewReason("", fbro, path.ExchangeService, path.ContactsCategory), kopia.NewReason(
"",
[]path.ServiceResource{{
ProtectedResource: fbro,
Service: path.ExchangeService,
}},
path.ContactsCategory),
}, },
getMeta: true, getMeta: true,
assertErr: assert.NoError, assertErr: assert.NoError,

View File

@ -7,8 +7,7 @@ import "github.com/alcionai/corso/src/pkg/path"
// categories which are held within the backup. // categories which are held within the backup.
type Reasoner interface { type Reasoner interface {
Tenant() string Tenant() string
ProtectedResource() string ServiceResources() []path.ServiceResource
Service() path.ServiceType
Category() path.CategoryType Category() path.CategoryType
// SubtreePath returns the path prefix for data in existing backups that have // SubtreePath returns the path prefix for data in existing backups that have
// parameters (tenant, protected resourced, etc) that match this Reasoner. // parameters (tenant, protected resourced, etc) that match this Reasoner.

View File

@ -85,6 +85,16 @@ func ServiceResourcesToResources(srs []ServiceResource) []string {
return prs return prs
} }
func ServiceResourcesToServices(srs []ServiceResource) []ServiceType {
sts := make([]ServiceType, len(srs))
for i := range srs {
sts[i] = srs[i].Service
}
return sts
}
func ServiceResourcesMatchServices(srs []ServiceResource, sts []ServiceType) bool { func ServiceResourcesMatchServices(srs []ServiceResource, sts []ServiceType) bool {
return slices.EqualFunc(srs, sts, func(sr ServiceResource, st ServiceType) bool { return slices.EqualFunc(srs, sts, func(sr ServiceResource, st ServiceType) bool {
return sr.Service == st return sr.Service == st

View File

@ -15,22 +15,17 @@ import (
var _ identity.Reasoner = &backupReason{} var _ identity.Reasoner = &backupReason{}
type backupReason struct { type backupReason struct {
category path.CategoryType category path.CategoryType
resource string serviceResources []path.ServiceResource
service path.ServiceType tenant string
tenant string
} }
func (br backupReason) Tenant() string { func (br backupReason) Tenant() string {
return br.tenant return br.tenant
} }
func (br backupReason) ProtectedResource() string { func (br backupReason) ServiceResources() []path.ServiceResource {
return br.resource return br.serviceResources
}
func (br backupReason) Service() path.ServiceType {
return br.service
} }
func (br backupReason) Category() path.CategoryType { func (br backupReason) Category() path.CategoryType {
@ -40,13 +35,18 @@ func (br backupReason) Category() path.CategoryType {
func (br backupReason) SubtreePath() (path.Path, error) { func (br backupReason) SubtreePath() (path.Path, error) {
return path.BuildPrefix( return path.BuildPrefix(
br.tenant, br.tenant,
br.resource, br.serviceResources,
br.service,
br.category) br.category)
} }
func (br backupReason) key() string { func (br backupReason) key() string {
return br.category.String() + br.resource + br.service.String() + br.tenant var k string
for _, sr := range br.serviceResources {
k += sr.ProtectedResource + sr.Service.String()
}
return br.category.String() + k + br.tenant
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -22,17 +22,17 @@ func TestReasonsUnitSuite(t *testing.T) {
func (suite *ReasonsUnitSuite) TestReasonsFor_thorough() { func (suite *ReasonsUnitSuite) TestReasonsFor_thorough() {
var ( var (
tenantID = "tid" tenantID = "tid"
exchange = path.ExchangeService.String() pstExchange = path.ExchangeService
email = path.EmailCategory.String() exchange = pstExchange.String()
contacts = path.ContactsCategory.String() email = path.EmailCategory.String()
contacts = path.ContactsCategory.String()
) )
type expect struct { type expect struct {
tenant string tenant string
resource string serviceResources []path.ServiceResource
category string category string
service string
subtreePath string subtreePath string
subtreePathHadErr bool subtreePathHadErr bool
} }
@ -69,10 +69,12 @@ func (suite *ReasonsUnitSuite) TestReasonsFor_thorough() {
useName: true, useName: true,
expect: []expect{ expect: []expect{
{ {
tenant: tenantID, tenant: tenantID,
resource: "timbubba", serviceResources: []path.ServiceResource{{
ProtectedResource: "timbubba",
Service: pstExchange,
}},
category: email, category: email,
service: exchange,
subtreePath: stpFor("timbubba", email, exchange), subtreePath: stpFor("timbubba", email, exchange),
}, },
}, },
@ -86,10 +88,12 @@ func (suite *ReasonsUnitSuite) TestReasonsFor_thorough() {
}, },
expect: []expect{ expect: []expect{
{ {
tenant: tenantID, tenant: tenantID,
resource: "bubba", serviceResources: []path.ServiceResource{{
ProtectedResource: "bubba",
Service: pstExchange,
}},
category: email, category: email,
service: exchange,
subtreePath: stpFor("bubba", email, exchange), subtreePath: stpFor("bubba", email, exchange),
}, },
}, },
@ -103,10 +107,12 @@ func (suite *ReasonsUnitSuite) TestReasonsFor_thorough() {
}, },
expect: []expect{ expect: []expect{
{ {
tenant: tenantID, tenant: tenantID,
resource: "tachoma dhaume", serviceResources: []path.ServiceResource{{
ProtectedResource: "tachoma dhaume",
Service: pstExchange,
}},
category: email, category: email,
service: exchange,
subtreePath: stpFor("tachoma dhaume", email, exchange), subtreePath: stpFor("tachoma dhaume", email, exchange),
}, },
}, },
@ -122,10 +128,12 @@ func (suite *ReasonsUnitSuite) TestReasonsFor_thorough() {
}, },
expect: []expect{ expect: []expect{
{ {
tenant: tenantID, tenant: tenantID,
resource: "vyng vang zoombah", serviceResources: []path.ServiceResource{{
ProtectedResource: "vyng vang zoombah",
Service: pstExchange,
}},
category: email, category: email,
service: exchange,
subtreePath: stpFor("vyng vang zoombah", email, exchange), subtreePath: stpFor("vyng vang zoombah", email, exchange),
}, },
}, },
@ -140,10 +148,12 @@ func (suite *ReasonsUnitSuite) TestReasonsFor_thorough() {
}, },
expect: []expect{ expect: []expect{
{ {
tenant: tenantID, tenant: tenantID,
resource: "fat billie", serviceResources: []path.ServiceResource{{
ProtectedResource: "fat billie",
Service: pstExchange,
}},
category: email, category: email,
service: exchange,
subtreePath: stpFor("fat billie", email, exchange), subtreePath: stpFor("fat billie", email, exchange),
}, },
}, },
@ -158,10 +168,12 @@ func (suite *ReasonsUnitSuite) TestReasonsFor_thorough() {
}, },
expect: []expect{ expect: []expect{
{ {
tenant: tenantID, tenant: tenantID,
resource: "seathane", serviceResources: []path.ServiceResource{{
ProtectedResource: "seathane",
Service: pstExchange,
}},
category: email, category: email,
service: exchange,
subtreePath: stpFor("seathane", email, exchange), subtreePath: stpFor("seathane", email, exchange),
}, },
}, },
@ -176,17 +188,21 @@ func (suite *ReasonsUnitSuite) TestReasonsFor_thorough() {
}, },
expect: []expect{ expect: []expect{
{ {
tenant: tenantID, tenant: tenantID,
resource: "perell", serviceResources: []path.ServiceResource{{
ProtectedResource: "perell",
Service: pstExchange,
}},
category: email, category: email,
service: exchange,
subtreePath: stpFor("perell", email, exchange), subtreePath: stpFor("perell", email, exchange),
}, },
{ {
tenant: tenantID, tenant: tenantID,
resource: "perell", serviceResources: []path.ServiceResource{{
ProtectedResource: "perell",
Service: pstExchange,
}},
category: contacts, category: contacts,
service: exchange,
subtreePath: stpFor("perell", contacts, exchange), subtreePath: stpFor("perell", contacts, exchange),
}, },
}, },
@ -211,8 +227,7 @@ func (suite *ReasonsUnitSuite) TestReasonsFor_thorough() {
results = append(results, expect{ results = append(results, expect{
tenant: r.Tenant(), tenant: r.Tenant(),
resource: r.ProtectedResource(), serviceResources: r.ServiceResources(),
service: r.Service().String(),
category: r.Category().String(), category: r.Category().String(),
subtreePath: stpStr, subtreePath: stpStr,
subtreePathHadErr: err != nil, subtreePathHadErr: err != nil,
@ -225,150 +240,103 @@ func (suite *ReasonsUnitSuite) TestReasonsFor_thorough() {
} }
func (suite *ReasonsUnitSuite) TestReasonsFor_serviceChecks() { func (suite *ReasonsUnitSuite) TestReasonsFor_serviceChecks() {
var ( var tenantID = "tid"
tenantID = "tid"
exchange = path.ExchangeService.String()
email = path.EmailCategory.String()
contacts = path.ContactsCategory.String()
)
type expect struct { type expect struct {
tenant string tenant string
resource string serviceResources []path.ServiceResource
category string category string
service string
subtreePath string subtreePath string
subtreePathHadErr bool subtreePathHadErr bool
} }
stpFor := func(resource, category, service string) string { stpFor := func(
return path.Builder{}.Append(tenantID, service, resource, category).String() resource string,
service path.ServiceType,
category path.CategoryType,
) string {
return path.Builder{}.Append(tenantID, service.String(), resource, category.String()).String()
} }
table := []struct { table := []struct {
name string name string
sel func() ExchangeRestore sel func() servicerCategorizerProvider
useName bool useName bool
expect []expect expect []expect
}{ }{
{ {
name: "no scopes", name: "exchange",
sel: func() ExchangeRestore { sel: func() servicerCategorizerProvider {
return *NewExchangeRestore([]string{"timbo"}) sel := *NewExchangeRestore([]string{"hadrian"})
},
expect: []expect{},
},
{
name: "only includes",
sel: func() ExchangeRestore {
sel := *NewExchangeRestore([]string{"bubba"})
sel.Include(sel.MailFolders(Any())) sel.Include(sel.MailFolders(Any()))
return sel return sel
}, },
expect: []expect{ expect: []expect{
{ {
tenant: tenantID, tenant: tenantID,
resource: "bubba", serviceResources: []path.ServiceResource{{
category: email, ProtectedResource: "hadrian",
service: exchange, Service: path.ExchangeService,
subtreePath: stpFor("bubba", email, exchange), }},
category: path.EmailCategory.String(),
subtreePath: stpFor("hadrian", path.ExchangeService, path.EmailCategory),
}, },
}, },
}, },
{ {
name: "only filters", name: "onedrive",
sel: func() ExchangeRestore { sel: func() servicerCategorizerProvider {
sel := *NewExchangeRestore([]string{"tachoma dhaume"}) sel := *NewOneDriveRestore([]string{"hella"})
sel.Filter(sel.MailFolders(Any())) sel.Filter(sel.Folders(Any()))
return sel return sel
}, },
expect: []expect{ expect: []expect{
{ {
tenant: tenantID, tenant: tenantID,
resource: "tachoma dhaume", serviceResources: []path.ServiceResource{{
category: email, ProtectedResource: "hella",
service: exchange, Service: path.OneDriveService,
subtreePath: stpFor("tachoma dhaume", email, exchange), }},
category: path.FilesCategory.String(),
subtreePath: stpFor("hella", path.OneDriveService, path.FilesCategory),
}, },
}, },
}, },
{ {
name: "duplicate includes and filters", name: "sharepoint",
sel: func() ExchangeRestore { sel: func() servicerCategorizerProvider {
sel := *NewExchangeRestore([]string{"vyng vang zoombah"}) sel := *NewSharePointRestore([]string{"lem king"})
sel.Include(sel.MailFolders(Any())) sel.Include(sel.LibraryFolders(Any()))
sel.Filter(sel.MailFolders(Any()))
return sel return sel
}, },
expect: []expect{ expect: []expect{
{ {
tenant: tenantID, tenant: tenantID,
resource: "vyng vang zoombah", serviceResources: []path.ServiceResource{{
category: email, ProtectedResource: "lem king",
service: exchange, Service: path.SharePointService,
subtreePath: stpFor("vyng vang zoombah", email, exchange), }},
category: path.EmailCategory.String(),
subtreePath: stpFor("lem king", path.SharePointService, path.LibrariesCategory),
}, },
}, },
}, },
{ {
name: "duplicate includes", name: "groups",
sel: func() ExchangeRestore { sel: func() servicerCategorizerProvider {
sel := *NewExchangeRestore([]string{"fat billie"}) sel := *NewGroupsRestore([]string{"fero feritas"})
sel.Include(sel.MailFolders(Any()), sel.MailFolders(Any())) sel.Include(sel.TODO(Any()))
return sel return sel
}, },
expect: []expect{ expect: []expect{
{ {
tenant: tenantID, tenant: tenantID,
resource: "fat billie", serviceResources: []path.ServiceResource{{
category: email, ProtectedResource: "fero feritas",
service: exchange, Service: path.GroupsService,
subtreePath: stpFor("fat billie", email, exchange), }},
}, category: path.EmailCategory.String(),
}, subtreePath: stpFor("fero feritas", path.GroupsService, path.LibrariesCategory),
},
{
name: "duplicate filters",
sel: func() ExchangeRestore {
sel := *NewExchangeRestore([]string{"seathane"})
sel.Filter(sel.MailFolders(Any()), sel.MailFolders(Any()))
return sel
},
expect: []expect{
{
tenant: tenantID,
resource: "seathane",
category: email,
service: exchange,
subtreePath: stpFor("seathane", email, exchange),
},
},
},
{
name: "no duplicates",
sel: func() ExchangeRestore {
sel := *NewExchangeRestore([]string{"perell"})
sel.Include(sel.MailFolders(Any()), sel.ContactFolders(Any()))
return sel
},
expect: []expect{
{
tenant: tenantID,
resource: "perell",
category: email,
service: exchange,
subtreePath: stpFor("perell", email, exchange),
},
{
tenant: tenantID,
resource: "perell",
category: contacts,
service: exchange,
subtreePath: stpFor("perell", contacts, exchange),
}, },
}, },
}, },
@ -392,8 +360,7 @@ func (suite *ReasonsUnitSuite) TestReasonsFor_serviceChecks() {
results = append(results, expect{ results = append(results, expect{
tenant: r.Tenant(), tenant: r.Tenant(),
resource: r.ProtectedResource(), serviceResources: r.ServiceResources(),
service: r.Service().String(),
category: r.Category().String(), category: r.Category().String(),
subtreePath: stpStr, subtreePath: stpStr,
subtreePathHadErr: err != nil, subtreePathHadErr: err != nil,