add fault/clues to exchange data_collections (#2381)

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

- [x]  No 

## Type of change

- [x] 🧹 Tech Debt/Cleanup

## Issue(s)

* #1970

## Test Plan

- [x]  Unit test
- [x] 💚 E2E
This commit is contained in:
Keepers 2023-02-13 11:19:46 -07:00 committed by GitHub
parent 680ec2b751
commit 89fb764526
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 50 additions and 32 deletions

View File

@ -19,6 +19,7 @@ import (
"github.com/alcionai/corso/src/pkg/account" "github.com/alcionai/corso/src/pkg/account"
"github.com/alcionai/corso/src/pkg/backup/details" "github.com/alcionai/corso/src/pkg/backup/details"
"github.com/alcionai/corso/src/pkg/control" "github.com/alcionai/corso/src/pkg/control"
"github.com/alcionai/corso/src/pkg/fault"
"github.com/alcionai/corso/src/pkg/logger" "github.com/alcionai/corso/src/pkg/logger"
"github.com/alcionai/corso/src/pkg/path" "github.com/alcionai/corso/src/pkg/path"
"github.com/alcionai/corso/src/pkg/selectors" "github.com/alcionai/corso/src/pkg/selectors"
@ -38,6 +39,7 @@ func (gc *GraphConnector) DataCollections(
sels selectors.Selector, sels selectors.Selector,
metadata []data.RestoreCollection, metadata []data.RestoreCollection,
ctrlOpts control.Options, ctrlOpts control.Options,
errs *fault.Errors,
) ([]data.BackupCollection, map[string]struct{}, error) { ) ([]data.BackupCollection, map[string]struct{}, error) {
ctx, end := D.Span(ctx, "gc:dataCollections", D.Index("service", sels.Service.String())) ctx, end := D.Span(ctx, "gc:dataCollections", D.Index("service", sels.Service.String()))
defer end() defer end()
@ -65,7 +67,8 @@ func (gc *GraphConnector) DataCollections(
gc.credentials, gc.credentials,
// gc.Service, // gc.Service,
gc.UpdateStatus, gc.UpdateStatus,
ctrlOpts) ctrlOpts,
errs)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -14,6 +14,7 @@ import (
"github.com/alcionai/corso/src/internal/connector/sharepoint" "github.com/alcionai/corso/src/internal/connector/sharepoint"
"github.com/alcionai/corso/src/internal/tester" "github.com/alcionai/corso/src/internal/tester"
"github.com/alcionai/corso/src/pkg/control" "github.com/alcionai/corso/src/pkg/control"
"github.com/alcionai/corso/src/pkg/fault"
"github.com/alcionai/corso/src/pkg/path" "github.com/alcionai/corso/src/pkg/path"
"github.com/alcionai/corso/src/pkg/selectors" "github.com/alcionai/corso/src/pkg/selectors"
) )
@ -105,7 +106,8 @@ func (suite *ConnectorDataCollectionIntegrationSuite) TestExchangeDataCollection
nil, nil,
connector.credentials, connector.credentials,
connector.UpdateStatus, connector.UpdateStatus,
control.Options{}) control.Options{},
fault.New(true))
require.NoError(t, err) require.NoError(t, err)
assert.Empty(t, excludes) assert.Empty(t, excludes)
@ -201,7 +203,12 @@ func (suite *ConnectorDataCollectionIntegrationSuite) TestDataCollections_invali
for _, test := range tests { for _, test := range tests {
suite.T().Run(test.name, func(t *testing.T) { suite.T().Run(test.name, func(t *testing.T) {
collections, excludes, err := connector.DataCollections(ctx, test.getSelector(t), nil, control.Options{}) collections, excludes, err := connector.DataCollections(
ctx,
test.getSelector(t),
nil,
control.Options{},
fault.New(true))
assert.Error(t, err) assert.Error(t, err)
assert.Empty(t, collections) assert.Empty(t, collections)
assert.Empty(t, excludes) assert.Empty(t, excludes)
@ -325,7 +332,12 @@ func (suite *ConnectorCreateSharePointCollectionIntegrationSuite) TestCreateShar
sel := selectors.NewSharePointBackup(siteIDs) sel := selectors.NewSharePointBackup(siteIDs)
sel.Include(sel.Libraries([]string{"foo"}, selectors.PrefixMatch())) sel.Include(sel.Libraries([]string{"foo"}, selectors.PrefixMatch()))
cols, excludes, err := gc.DataCollections(ctx, sel.Selector, nil, control.Options{}) cols, excludes, err := gc.DataCollections(
ctx,
sel.Selector,
nil,
control.Options{},
fault.New(true))
require.NoError(t, err) require.NoError(t, err)
assert.Len(t, cols, 1) assert.Len(t, cols, 1)
// No excludes yet as this isn't an incremental backup. // No excludes yet as this isn't an incremental backup.
@ -351,7 +363,12 @@ func (suite *ConnectorCreateSharePointCollectionIntegrationSuite) TestCreateShar
sel := selectors.NewSharePointBackup(siteIDs) sel := selectors.NewSharePointBackup(siteIDs)
sel.Include(sel.Lists(selectors.Any(), selectors.PrefixMatch())) sel.Include(sel.Lists(selectors.Any(), selectors.PrefixMatch()))
cols, excludes, err := gc.DataCollections(ctx, sel.Selector, nil, control.Options{}) cols, excludes, err := gc.DataCollections(
ctx,
sel.Selector,
nil,
control.Options{},
fault.New(true))
require.NoError(t, err) require.NoError(t, err)
assert.Less(t, 0, len(cols)) assert.Less(t, 0, len(cols))
// No excludes yet as this isn't an incremental backup. // No excludes yet as this isn't an incremental backup.

View File

@ -3,9 +3,8 @@ package exchange
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"github.com/hashicorp/go-multierror" "github.com/alcionai/clues"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/alcionai/corso/src/internal/connector/exchange/api" "github.com/alcionai/corso/src/internal/connector/exchange/api"
@ -15,6 +14,7 @@ import (
"github.com/alcionai/corso/src/internal/observe" "github.com/alcionai/corso/src/internal/observe"
"github.com/alcionai/corso/src/pkg/account" "github.com/alcionai/corso/src/pkg/account"
"github.com/alcionai/corso/src/pkg/control" "github.com/alcionai/corso/src/pkg/control"
"github.com/alcionai/corso/src/pkg/fault"
"github.com/alcionai/corso/src/pkg/path" "github.com/alcionai/corso/src/pkg/path"
"github.com/alcionai/corso/src/pkg/selectors" "github.com/alcionai/corso/src/pkg/selectors"
) )
@ -90,7 +90,7 @@ func parseMetadataCollections(
for { for {
select { select {
case <-ctx.Done(): case <-ctx.Done():
return nil, errors.Wrap(ctx.Err(), "parsing collection metadata") return nil, clues.Wrap(ctx.Err(), "parsing collection metadata").WithClues(ctx)
case item, ok := <-items: case item, ok := <-items:
if !ok { if !ok {
@ -105,13 +105,13 @@ func parseMetadataCollections(
err := json.NewDecoder(item.ToReader()).Decode(&m) err := json.NewDecoder(item.ToReader()).Decode(&m)
if err != nil { if err != nil {
return nil, errors.New("decoding metadata json") return nil, clues.New("decoding metadata json").WithClues(ctx)
} }
switch item.UUID() { switch item.UUID() {
case graph.PreviousPathFileName: case graph.PreviousPathFileName:
if _, ok := found[category]["path"]; ok { if _, ok := found[category]["path"]; ok {
return nil, errors.Errorf("multiple versions of %s path metadata", category) return nil, clues.Wrap(clues.New(category.String()), "multiple versions of path metadata").WithClues(ctx)
} }
for k, p := range m { for k, p := range m {
@ -122,7 +122,7 @@ func parseMetadataCollections(
case graph.DeltaURLsFileName: case graph.DeltaURLsFileName:
if _, ok := found[category]["delta"]; ok { if _, ok := found[category]["delta"]; ok {
return nil, errors.Errorf("multiple versions of %s delta metadata", category) return nil, clues.Wrap(clues.New(category.String()), "multiple versions of delta metadata").WithClues(ctx)
} }
for k, d := range m { for k, d := range m {
@ -167,16 +167,16 @@ func DataCollections(
acct account.M365Config, acct account.M365Config,
su support.StatusUpdater, su support.StatusUpdater,
ctrlOpts control.Options, ctrlOpts control.Options,
errs *fault.Errors,
) ([]data.BackupCollection, map[string]struct{}, error) { ) ([]data.BackupCollection, map[string]struct{}, error) {
eb, err := selector.ToExchangeBackup() eb, err := selector.ToExchangeBackup()
if err != nil { if err != nil {
return nil, nil, errors.Wrap(err, "exchangeDataCollection: parsing selector") return nil, nil, clues.Wrap(err, "exchange dataCollection selector").WithClues(ctx)
} }
var ( var (
user = selector.DiscreteOwner user = selector.DiscreteOwner
collections = []data.BackupCollection{} collections = []data.BackupCollection{}
errs error
) )
cdps, err := parseMetadataCollections(ctx, metadata) cdps, err := parseMetadataCollections(ctx, metadata)
@ -185,26 +185,27 @@ func DataCollections(
} }
for _, scope := range eb.Scopes() { for _, scope := range eb.Scopes() {
dps := cdps[scope.Category().PathType()] if errs.Failed() {
break
}
dcs, err := createCollections( dcs, err := createCollections(
ctx, ctx,
acct, acct,
user, user,
scope, scope,
dps, cdps[scope.Category().PathType()],
ctrlOpts, ctrlOpts,
su) su)
if err != nil { if err != nil {
return nil, nil, support.WrapAndAppend(user, err, errs) errs.Add(err)
continue
} }
collections = append(collections, dcs...) collections = append(collections, dcs...)
} }
// Exchange does not require adding items to the global exclude list so always return collections, nil, errs.Err()
// return nil.
return collections, nil, errs
} }
func getterByType(ac api.Client, category path.CategoryType) (addedAndRemovedItemIDsGetter, error) { func getterByType(ac api.Client, category path.CategoryType) (addedAndRemovedItemIDsGetter, error) {
@ -216,7 +217,7 @@ func getterByType(ac api.Client, category path.CategoryType) (addedAndRemovedIte
case path.ContactsCategory: case path.ContactsCategory:
return ac.Contacts(), nil return ac.Contacts(), nil
default: default:
return nil, fmt.Errorf("category %s not supported by getFetchIDFunc", category) return nil, clues.Wrap(clues.New(category.String()), "category not supported")
} }
} }
@ -233,7 +234,6 @@ func createCollections(
su support.StatusUpdater, su support.StatusUpdater,
) ([]data.BackupCollection, error) { ) ([]data.BackupCollection, error) {
var ( var (
errs *multierror.Error
allCollections = make([]data.BackupCollection, 0) allCollections = make([]data.BackupCollection, 0)
ac = api.Client{Credentials: creds} ac = api.Client{Credentials: creds}
category = scope.Category().PathType() category = scope.Category().PathType()
@ -241,7 +241,7 @@ func createCollections(
getter, err := getterByType(ac, category) getter, err := getterByType(ac, category)
if err != nil { if err != nil {
return nil, err return nil, clues.Stack(err).WithClues(ctx)
} }
// Create collection of ExchangeDataCollection // Create collection of ExchangeDataCollection
@ -262,7 +262,7 @@ func createCollections(
resolver, err := PopulateExchangeContainerResolver(ctx, qp) resolver, err := PopulateExchangeContainerResolver(ctx, qp)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "getting folder cache") return nil, errors.Wrap(err, "populating container cache")
} }
err = filterContainersAndFillCollections( err = filterContainersAndFillCollections(
@ -275,7 +275,6 @@ func createCollections(
scope, scope,
dps, dps,
ctrlOpts) ctrlOpts)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "filling collections") return nil, errors.Wrap(err, "filling collections")
} }
@ -286,5 +285,5 @@ func createCollections(
allCollections = append(allCollections, coll) allCollections = append(allCollections, coll)
} }
return allCollections, errs.ErrorOrNil() return allCollections, nil
} }

View File

@ -469,7 +469,7 @@ func runRestoreBackupTest(
RestorePermissions: true, RestorePermissions: true,
ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, ToggleFeatures: control.Toggles{EnablePermissionsBackup: true},
}, },
) fault.New(true))
require.NoError(t, err) require.NoError(t, err)
// No excludes yet because this isn't an incremental backup. // No excludes yet because this isn't an incremental backup.
assert.Empty(t, excludes) assert.Empty(t, excludes)
@ -597,7 +597,7 @@ func runRestoreBackupTestVersion0(
RestorePermissions: true, RestorePermissions: true,
ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, ToggleFeatures: control.Toggles{EnablePermissionsBackup: true},
}, },
) fault.New(true))
require.NoError(t, err) require.NoError(t, err)
// No excludes yet because this isn't an incremental backup. // No excludes yet because this isn't an incremental backup.
assert.Empty(t, excludes) assert.Empty(t, excludes)
@ -1544,7 +1544,7 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames
RestorePermissions: true, RestorePermissions: true,
ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, ToggleFeatures: control.Toggles{EnablePermissionsBackup: true},
}, },
) fault.New(true))
require.NoError(t, err) require.NoError(t, err)
// No excludes yet because this isn't an incremental backup. // No excludes yet because this isn't an incremental backup.
assert.Empty(t, excludes) assert.Empty(t, excludes)

View File

@ -244,7 +244,7 @@ func (op *BackupOperation) do(
return nil, errors.Wrap(err, "connectng to m365") return nil, errors.Wrap(err, "connectng to m365")
} }
cs, excludes, err := produceBackupDataCollections(ctx, gc, op.Selectors, mdColls, op.Options) cs, excludes, err := produceBackupDataCollections(ctx, gc, op.Selectors, mdColls, op.Options, op.Errors)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "producing backup data collections") return nil, errors.Wrap(err, "producing backup data collections")
} }
@ -313,6 +313,7 @@ func produceBackupDataCollections(
sel selectors.Selector, sel selectors.Selector,
metadata []data.RestoreCollection, metadata []data.RestoreCollection,
ctrlOpts control.Options, ctrlOpts control.Options,
errs *fault.Errors,
) ([]data.BackupCollection, map[string]struct{}, error) { ) ([]data.BackupCollection, map[string]struct{}, error) {
complete, closer := observe.MessageWithCompletion(ctx, observe.Safe("Discovering items to backup")) complete, closer := observe.MessageWithCompletion(ctx, observe.Safe("Discovering items to backup"))
defer func() { defer func() {
@ -321,9 +322,7 @@ func produceBackupDataCollections(
closer() closer()
}() }()
cols, excludes, errs := gc.DataCollections(ctx, sel, metadata, ctrlOpts) return gc.DataCollections(ctx, sel, metadata, ctrlOpts, errs)
return cols, excludes, errs
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------