Add sites metadata in Groups backup (#4184)

Add sites metadata (previous paths) under `groupID/libraries/sites/previouspath`.

<!-- PR description-->

---

#### 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

<!--- Please check the type of change your PR introduces: --->
- [x] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Supportability/Tests
- [ ] 💻 CI/Deployment
- [ ] 🧹 Tech Debt/Cleanup

#### Issue(s)

<!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. -->
* #<issue>

#### Test Plan

<!-- How will this be tested prior to merging.-->
- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
Abin Simon 2023-09-07 10:29:31 +05:30 committed by GitHub
parent bf1b290e2a
commit f742318319
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 138 additions and 11 deletions

View File

@ -13,6 +13,7 @@ import (
inMock "github.com/alcionai/corso/src/internal/common/idname/mock"
"github.com/alcionai/corso/src/internal/m365/resource"
"github.com/alcionai/corso/src/internal/m365/service/exchange"
odConsts "github.com/alcionai/corso/src/internal/m365/service/onedrive/consts"
"github.com/alcionai/corso/src/internal/m365/service/sharepoint"
"github.com/alcionai/corso/src/internal/operations/inject"
"github.com/alcionai/corso/src/internal/tester"
@ -473,6 +474,7 @@ func (suite *SPCollectionIntgSuite) TestCreateSharePointCollection_Lists() {
type GroupsCollectionIntgSuite struct {
tester.Suite
connector *Controller
tenantID string
user string
}
@ -485,13 +487,21 @@ func TestGroupsCollectionIntgSuite(t *testing.T) {
}
func (suite *GroupsCollectionIntgSuite) SetupSuite() {
ctx, flush := tester.NewContext(suite.T())
t := suite.T()
ctx, flush := tester.NewContext(t)
defer flush()
suite.connector = newController(ctx, suite.T(), resource.Sites, path.GroupsService)
suite.user = tconfig.M365UserID(suite.T())
suite.connector = newController(ctx, t, resource.Sites, path.GroupsService)
suite.user = tconfig.M365UserID(t)
tester.LogTimeOfTest(suite.T())
acct := tconfig.NewM365Account(t)
creds, err := acct.M365Config()
require.NoError(t, err, clues.ToCore(err))
suite.tenantID = creds.AzureTenantID
tester.LogTimeOfTest(t)
}
func (suite *GroupsCollectionIntgSuite) TestCreateGroupsCollection_SharePoint() {
@ -535,14 +545,37 @@ func (suite *GroupsCollectionIntgSuite) TestCreateGroupsCollection_SharePoint()
// but it should be more than one.
assert.Greater(t, len(collections), 1)
// TODO(meain): Switch to using BuildMetadata
// https://github.com/alcionai/corso/pull/4184#discussion_r1316139701
p, err := path.Builder{}.ToServiceCategoryMetadataPath(
suite.tenantID,
groupID,
path.GroupsService,
path.LibrariesCategory,
false)
require.NoError(t, err, clues.ToCore(err))
p, err = p.Append(false, odConsts.SitesPathDir)
require.NoError(t, err, clues.ToCore(err))
foundSitesMetadata := false
for _, coll := range collections {
sitesMetadataCollection := coll.FullPath().String() == p.String()
for object := range coll.Items(ctx, fault.New(true)) {
if object.ID() == "previouspath" && sitesMetadataCollection {
foundSitesMetadata = true
}
buf := &bytes.Buffer{}
_, err := buf.ReadFrom(object.ToReader())
assert.NoError(t, err, "reading item", clues.ToCore(err))
}
}
assert.True(t, foundSitesMetadata, "missing sites metadata")
status := ctrl.Wait()
assert.NotZero(t, status.Successes)
t.Log(status.String())

View File

@ -65,7 +65,7 @@ func (h groupBackupHandler) MetadataPathPrefix(tenantID string) (path.Path, erro
p, err = p.Append(false, odConsts.SitesPathDir, h.siteID)
if err != nil {
return nil, clues.Wrap(err, "appending sites to metadata path")
return nil, clues.Wrap(err, "appending site id to metadata path")
}
return p, nil
@ -86,6 +86,17 @@ func (h groupBackupHandler) CanonicalPath(
)
}
func (h groupBackupHandler) SitePathPrefix(tenantID string) (path.Path, error) {
return path.Build(
tenantID,
h.groupID,
h.service,
path.LibrariesCategory,
false,
odConsts.SitesPathDir,
h.siteID)
}
func (h groupBackupHandler) IsAllPass() bool {
return h.scope.IsAny(selectors.GroupsLibraryFolder)
}

View File

@ -49,6 +49,35 @@ func (suite *GroupBackupHandlerUnitSuite) TestPathPrefix() {
}
}
func (suite *GroupBackupHandlerUnitSuite) TestSitePathPrefix() {
tenantID, resourceOwner := "tenant", "resourceOwner"
table := []struct {
name string
expect string
expectErr assert.ErrorAssertionFunc
}{
{
name: "group",
expect: "tenant/groups/resourceOwner/libraries/sites/site-id",
expectErr: assert.NoError,
},
}
for _, test := range table {
suite.Run(test.name, func() {
t := suite.T()
h := NewGroupBackupHandler(resourceOwner, "site-id", api.Drives{}, nil)
result, err := h.SitePathPrefix(tenantID)
test.expectErr(t, err, clues.ToCore(err))
if result != nil {
assert.Equal(t, test.expect, result.String())
}
})
}
}
func (suite *GroupBackupHandlerUnitSuite) TestMetadataPathPrefix() {
tenantID, resourceOwner := "tenant", "resourceOwner"

View File

@ -13,6 +13,7 @@ import (
"github.com/alcionai/corso/src/internal/m365/collection/groups"
"github.com/alcionai/corso/src/internal/m365/collection/site"
"github.com/alcionai/corso/src/internal/m365/graph"
odConsts "github.com/alcionai/corso/src/internal/m365/service/onedrive/consts"
"github.com/alcionai/corso/src/internal/m365/support"
"github.com/alcionai/corso/src/internal/observe"
"github.com/alcionai/corso/src/internal/operations/inject"
@ -41,6 +42,7 @@ func ProduceBackupCollections(
categories = map[path.CategoryType]struct{}{}
ssmb = prefixmatcher.NewStringSetBuilder()
canUsePreviousBackup bool
sitesPreviousPaths = map[string]string{}
)
ctx = clues.Add(
@ -78,15 +80,23 @@ func ProduceBackupCollections(
Selector: bpc.Selector,
}
dbcs, canUsePreviousBackup, err = site.CollectLibraries(
ctx,
sbpc,
drive.NewGroupBackupHandler(
bh := drive.NewGroupBackupHandler(
bpc.ProtectedResource.ID(),
ptr.Val(resp.GetId()),
ac.Drives(),
scope,
),
scope)
cp, err := bh.SitePathPrefix(creds.AzureTenantID)
if err != nil {
return nil, nil, false, clues.Wrap(err, "getting canonical path")
}
sitesPreviousPaths[ptr.Val(resp.GetId())] = cp.String()
dbcs, canUsePreviousBackup, err = site.CollectLibraries(
ctx,
sbpc,
bh,
creds.AzureTenantID,
ssmb,
su,
@ -133,5 +143,49 @@ func ProduceBackupCollections(
collections = append(collections, baseCols...)
}
// Add metadata about sites
md, err := getSitesMetadataCollection(
creds.AzureTenantID,
bpc.ProtectedResource.ID(),
sitesPreviousPaths,
su)
if err != nil {
return nil, nil, false, err
}
collections = append(collections, md)
return collections, ssmb.ToReader(), canUsePreviousBackup, el.Failure()
}
func getSitesMetadataCollection(
tenantID, groupID string,
sites map[string]string,
su support.StatusUpdater,
) (data.BackupCollection, error) {
// TODO(meain): Switch to using BuildMetadata
// https://github.com/alcionai/corso/pull/4184#discussion_r1316139701
p, err := path.Builder{}.ToServiceCategoryMetadataPath(
tenantID,
groupID,
path.GroupsService,
path.LibrariesCategory,
false)
if err != nil {
return nil, clues.Wrap(err, "making metadata path")
}
p, err = p.Append(false, odConsts.SitesPathDir)
if err != nil {
return nil, clues.Wrap(err, "appending sites to metadata path")
}
md, err := graph.MakeMetadataCollection(
p,
[]graph.MetadataCollectionEntry{
graph.NewMetadataEntry(graph.PreviousPathFileName, sites),
},
su)
return md, err
}