diff --git a/src/internal/connector/discovery/api/users.go b/src/internal/connector/discovery/api/users.go index 05c1f27f0..ea4b268f6 100644 --- a/src/internal/connector/discovery/api/users.go +++ b/src/internal/connector/discovery/api/users.go @@ -97,7 +97,7 @@ func (c Users) GetAll(ctx context.Context, errs *fault.Bus) ([]models.Userable, resp, err = service.Client().Users().Get(ctx, userOptions(&userFilterNoGuests)) if err != nil { - return nil, clues.Wrap(err, "getting all users").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "getting all users") } iter, err := msgraphgocore.NewPageIterator( @@ -105,7 +105,7 @@ func (c Users) GetAll(ctx context.Context, errs *fault.Bus) ([]models.Userable, service.Adapter(), models.CreateUserCollectionResponseFromDiscriminatorValue) if err != nil { - return nil, clues.Wrap(err, "creating users iterator").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "creating users iterator") } var ( @@ -120,7 +120,7 @@ func (c Users) GetAll(ctx context.Context, errs *fault.Bus) ([]models.Userable, u, err := validateUser(item) if err != nil { - el.AddRecoverable(clues.Wrap(err, "validating user").WithClues(ctx).With(graph.ErrData(err)...)) + el.AddRecoverable(graph.Wrap(ctx, err, "validating user")) } else { us = append(us, u) } @@ -129,7 +129,7 @@ func (c Users) GetAll(ctx context.Context, errs *fault.Bus) ([]models.Userable, } if err := iter.Iterate(ctx, iterator); err != nil { - return nil, clues.Wrap(err, "iterating all users").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "iterating all users") } return us, el.Failure() @@ -144,7 +144,7 @@ func (c Users) GetByID(ctx context.Context, userID string) (models.Userable, err resp, err = c.stable.Client().UsersById(userID).Get(ctx, nil) if err != nil { - return nil, clues.Wrap(err, "getting user").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "getting user") } return resp, err @@ -163,7 +163,7 @@ func (c Users) GetInfo(ctx context.Context, userID string) (*UserInfo, error) { if err != nil { if !graph.IsErrExchangeMailFolderNotFound(err) { - return nil, clues.Wrap(err, "getting user's mail folder").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "getting user's mail folder") } delete(userInfo.DiscoveredServices, path.ExchangeService) diff --git a/src/internal/connector/exchange/api/contacts.go b/src/internal/connector/exchange/api/contacts.go index 35e5b5a35..3caa0c480 100644 --- a/src/internal/connector/exchange/api/contacts.go +++ b/src/internal/connector/exchange/api/contacts.go @@ -49,7 +49,7 @@ func (c Contacts) CreateContactFolder( mdl, err := c.stable.Client().UsersById(user).ContactFolders().Post(ctx, requestBody, nil) if err != nil { - return nil, clues.Wrap(err, "creating contact folder").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "creating contact folder") } return mdl, nil @@ -62,7 +62,7 @@ func (c Contacts) DeleteContainer( ) error { err := c.stable.Client().UsersById(user).ContactFoldersById(folderID).Delete(ctx, nil) if err != nil { - return clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return graph.Stack(ctx, err) } return nil @@ -76,7 +76,7 @@ func (c Contacts) GetItem( ) (serialization.Parsable, *details.ExchangeInfo, error) { cont, err := c.stable.Client().UsersById(user).ContactsById(itemID).Get(ctx, nil) if err != nil { - return nil, nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, nil, graph.Stack(ctx, err) } return cont, ContactInfo(cont), nil @@ -88,12 +88,12 @@ func (c Contacts) GetContainerByID( ) (graph.Container, error) { ofcf, err := optionsForContactFolderByID([]string{"displayName", "parentFolderId"}) if err != nil { - return nil, clues.Wrap(err, "setting contact folder options").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "setting contact folder options") } resp, err := c.stable.Client().UsersById(userID).ContactFoldersById(dirID).Get(ctx, ofcf) if err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err) } return resp, nil @@ -112,17 +112,14 @@ func (c Contacts) EnumerateContainers( ) error { service, err := c.service() if err != nil { - return clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return graph.Stack(ctx, err) } fields := []string{"displayName", "parentFolderId"} ofcf, err := optionsForContactChildFolders(fields) if err != nil { - return clues.Wrap(err, "setting contact child folder options"). - WithClues(ctx). - With(graph.ErrData(err)...). - With("options_fields", fields) + return graph.Wrap(ctx, err, "setting contact child folder options") } el := errs.Local() @@ -138,7 +135,7 @@ func (c Contacts) EnumerateContainers( resp, err := builder.Get(ctx, ofcf) if err != nil { - return clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return graph.Stack(ctx, err) } for _, fold := range resp.GetValue() { @@ -147,11 +144,7 @@ func (c Contacts) EnumerateContainers( } if err := checkIDAndName(fold); err != nil { - el.AddRecoverable(clues.Stack(err). - WithClues(ctx). - With(graph.ErrData(err)...). - Label(fault.LabelForceNoBackupCreation)) - + errs.AddRecoverable(graph.Stack(ctx, err).Label(fault.LabelForceNoBackupCreation)) continue } @@ -162,11 +155,7 @@ func (c Contacts) EnumerateContainers( temp := graph.NewCacheFolder(fold, nil, nil) if err := fn(temp); err != nil { - el.AddRecoverable(clues.Stack(err). - WithClues(fctx). - With(graph.ErrData(err)...). - Label(fault.LabelForceNoBackupCreation)) - + errs.AddRecoverable(graph.Stack(fctx, err).Label(fault.LabelForceNoBackupCreation)) continue } } @@ -197,7 +186,7 @@ type contactPager struct { func (p *contactPager) getPage(ctx context.Context) (api.DeltaPageLinker, error) { resp, err := p.builder.Get(ctx, p.options) if err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err) } return resp, nil @@ -217,7 +206,7 @@ func (c Contacts) GetAddedAndRemovedItemIDs( ) ([]string, []string, DeltaUpdate, error) { service, err := c.service() if err != nil { - return nil, nil, DeltaUpdate{}, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, nil, DeltaUpdate{}, graph.Stack(ctx, err) } var resetDelta bool @@ -232,7 +221,7 @@ func (c Contacts) GetAddedAndRemovedItemIDs( return nil, nil, DeltaUpdate{}, - clues.Wrap(err, "setting contact folder options").WithClues(ctx).With(graph.ErrData(err)...) + graph.Wrap(ctx, err, "setting contact folder options") } if len(oldDelta) > 0 { @@ -250,7 +239,7 @@ func (c Contacts) GetAddedAndRemovedItemIDs( // only return on error if it is NOT a delta issue. // on bad deltas we retry the call with the regular builder if !graph.IsErrInvalidDelta(err) { - return nil, nil, DeltaUpdate{}, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, nil, DeltaUpdate{}, graph.Stack(ctx, err) } resetDelta = true @@ -303,12 +292,12 @@ func (c Contacts) Serialize( defer writer.Close() if err = writer.WriteObjectValue("", contact); err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err) } bs, err := writer.GetSerializedContent() if err != nil { - return nil, clues.Wrap(err, "serializing contact").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "serializing contact") } return bs, nil diff --git a/src/internal/connector/exchange/api/events.go b/src/internal/connector/exchange/api/events.go index 93f9eec0d..49dd66041 100644 --- a/src/internal/connector/exchange/api/events.go +++ b/src/internal/connector/exchange/api/events.go @@ -50,7 +50,7 @@ func (c Events) CreateCalendar( mdl, err := c.stable.Client().UsersById(user).Calendars().Post(ctx, requestbody, nil) if err != nil { - return nil, clues.Wrap(err, "creating calendar").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "creating calendar") } return mdl, nil @@ -64,7 +64,7 @@ func (c Events) DeleteContainer( ) error { err := c.stable.Client().UsersById(user).CalendarsById(calendarID).Delete(ctx, nil) if err != nil { - return clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return graph.Stack(ctx, err) } return nil @@ -76,17 +76,17 @@ func (c Events) GetContainerByID( ) (graph.Container, error) { service, err := c.service() if err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err) } ofc, err := optionsForCalendarsByID([]string{"name", "owner"}) if err != nil { - return nil, clues.Wrap(err, "setting event calendar options").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "setting event calendar options") } cal, err := service.Client().UsersById(userID).CalendarsById(containerID).Get(ctx, ofc) if err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err).WithClues(ctx) } return graph.CalendarDisplayable{Calendarable: cal}, nil @@ -105,7 +105,7 @@ func (c Events) GetItem( event, err = c.stable.Client().UsersById(user).EventsById(itemID).Get(ctx, nil) if err != nil { - return nil, nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, nil, graph.Stack(ctx, err) } if *event.GetHasAttachments() || HasAttachments(event.GetBody()) { @@ -122,7 +122,7 @@ func (c Events) GetItem( Attachments(). Get(ctx, options) if err != nil { - return nil, nil, clues.Wrap(err, "event attachment download").WithClues(ctx).With(graph.ErrData(err)...) + return nil, nil, graph.Wrap(ctx, err, "event attachment download") } event.SetAttachments(attached.GetValue()) @@ -144,12 +144,12 @@ func (c Events) EnumerateContainers( ) error { service, err := c.service() if err != nil { - return clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return graph.Stack(ctx, err) } ofc, err := optionsForCalendars([]string{"name"}) if err != nil { - return clues.Wrap(err, "setting calendar options").WithClues(ctx).With(graph.ErrData(err)...) + return graph.Wrap(ctx, err, "setting calendar options") } el := errs.Local() @@ -162,7 +162,7 @@ func (c Events) EnumerateContainers( resp, err := builder.Get(ctx, ofc) if err != nil { - return clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return graph.Stack(ctx, err) } for _, cal := range resp.GetValue() { @@ -172,11 +172,7 @@ func (c Events) EnumerateContainers( cd := CalendarDisplayable{Calendarable: cal} if err := checkIDAndName(cd); err != nil { - el.AddRecoverable(clues.Stack(err). - WithClues(ctx). - With(graph.ErrData(err)...). - Label(fault.LabelForceNoBackupCreation)) - + errs.AddRecoverable(graph.Stack(ctx, err).Label(fault.LabelForceNoBackupCreation)) continue } @@ -190,11 +186,7 @@ func (c Events) EnumerateContainers( path.Builder{}.Append(ptr.Val(cd.GetId())), // storage path path.Builder{}.Append(ptr.Val(cd.GetDisplayName()))) // display location if err := fn(temp); err != nil { - el.AddRecoverable(clues.Stack(err). - WithClues(fctx). - With(graph.ErrData(err)...). - Label(fault.LabelForceNoBackupCreation)) - + errs.AddRecoverable(graph.Stack(fctx, err).Label(fault.LabelForceNoBackupCreation)) continue } } @@ -229,7 +221,7 @@ type eventPager struct { func (p *eventPager) getPage(ctx context.Context) (api.DeltaPageLinker, error) { resp, err := p.builder.Get(ctx, p.options) if err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err) } return resp, nil @@ -272,7 +264,7 @@ func (c Events) GetAddedAndRemovedItemIDs( // only return on error if it is NOT a delta issue. // on bad deltas we retry the call with the regular builder if !graph.IsErrInvalidDelta(err) { - return nil, nil, DeltaUpdate{}, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, nil, DeltaUpdate{}, graph.Stack(ctx, err) } resetDelta = true @@ -335,12 +327,12 @@ func (c Events) Serialize( defer writer.Close() if err = writer.WriteObjectValue("", event); err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err) } bs, err := writer.GetSerializedContent() if err != nil { - return nil, clues.Wrap(err, "serializing event").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "serializing event") } return bs, nil diff --git a/src/internal/connector/exchange/api/mail.go b/src/internal/connector/exchange/api/mail.go index ce5549404..b03fff837 100644 --- a/src/internal/connector/exchange/api/mail.go +++ b/src/internal/connector/exchange/api/mail.go @@ -50,7 +50,7 @@ func (c Mail) CreateMailFolder( mdl, err := c.stable.Client().UsersById(user).MailFolders().Post(ctx, requestBody, nil) if err != nil { - return nil, clues.Wrap(err, "creating mail folder").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "creating mail folder") } return mdl, nil @@ -62,7 +62,7 @@ func (c Mail) CreateMailFolderWithParent( ) (models.MailFolderable, error) { service, err := c.service() if err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err) } isHidden := false @@ -77,7 +77,7 @@ func (c Mail) CreateMailFolderWithParent( ChildFolders(). Post(ctx, requestBody, nil) if err != nil { - return nil, clues.Wrap(err, "creating nested mail folder").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "creating nested mail folder") } return mdl, nil @@ -91,7 +91,7 @@ func (c Mail) DeleteContainer( ) error { err := c.stable.Client().UsersById(user).MailFoldersById(folderID).Delete(ctx, nil) if err != nil { - return clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return graph.Stack(ctx, err) } return nil @@ -103,17 +103,17 @@ func (c Mail) GetContainerByID( ) (graph.Container, error) { service, err := c.service() if err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err) } ofmf, err := optionsForMailFoldersItem([]string{"displayName", "parentFolderId"}) if err != nil { - return nil, clues.Wrap(err, "setting mail folder options").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "setting mail folder options") } resp, err := service.Client().UsersById(userID).MailFoldersById(dirID).Get(ctx, ofmf) if err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err) } return resp, nil @@ -128,7 +128,7 @@ func (c Mail) GetItem( ) (serialization.Parsable, *details.ExchangeInfo, error) { mail, err := c.stable.Client().UsersById(user).MessagesById(itemID).Get(ctx, nil) if err != nil { - return nil, nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, nil, graph.Stack(ctx, err) } if *mail.GetHasAttachments() || HasAttachments(mail.GetBody()) { @@ -145,7 +145,7 @@ func (c Mail) GetItem( Attachments(). Get(ctx, options) if err != nil { - return nil, nil, clues.Wrap(err, "mail attachment download").WithClues(ctx).With(graph.ErrData(err)...) + return nil, nil, graph.Wrap(ctx, err, "mail attachment download") } mail.SetAttachments(attached.GetValue()) @@ -167,7 +167,7 @@ func (c Mail) EnumerateContainers( ) error { service, err := c.service() if err != nil { - return clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return graph.Stack(ctx, err) } el := errs.Local() @@ -183,7 +183,7 @@ func (c Mail) EnumerateContainers( resp, err := builder.Get(ctx, nil) if err != nil { - return clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return graph.Stack(ctx, err) } for _, v := range resp.GetValue() { @@ -198,11 +198,7 @@ func (c Mail) EnumerateContainers( temp := graph.NewCacheFolder(v, nil, nil) if err := fn(temp); err != nil { - el.AddRecoverable(clues.Stack(err). - WithClues(fctx). - With(graph.ErrData(err)...). - Label(fault.LabelForceNoBackupCreation)) - + errs.AddRecoverable(graph.Stack(fctx, err).Label(fault.LabelForceNoBackupCreation)) continue } } @@ -233,7 +229,7 @@ type mailPager struct { func (p *mailPager) getPage(ctx context.Context) (api.DeltaPageLinker, error) { page, err := p.builder.Get(ctx, p.options) if err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err) } return page, nil @@ -271,7 +267,7 @@ func (c Mail) GetAddedAndRemovedItemIDs( return nil, nil, DeltaUpdate{}, - clues.Wrap(err, "setting contact folder options").WithClues(ctx).With(graph.ErrData(err)...) + graph.Wrap(ctx, err, "setting contact folder options") } if len(oldDelta) > 0 { @@ -341,12 +337,12 @@ func (c Mail) Serialize( defer writer.Close() if err = writer.WriteObjectValue("", msg); err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err) } bs, err := writer.GetSerializedContent() if err != nil { - return nil, clues.Wrap(err, "serializing email").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "serializing email") } return bs, nil diff --git a/src/internal/connector/exchange/api/shared.go b/src/internal/connector/exchange/api/shared.go index b5f9a7466..8431f58c5 100644 --- a/src/internal/connector/exchange/api/shared.go +++ b/src/internal/connector/exchange/api/shared.go @@ -74,14 +74,14 @@ func getItemsAddedAndRemovedFromContainer( // get the next page of data, check for standard errors resp, err := pager.getPage(ctx) if err != nil { - return nil, nil, deltaURL, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, nil, deltaURL, graph.Stack(ctx, err) } // each category type responds with a different interface, but all // of them comply with GetValue, which is where we'll get our item data. items, err := pager.valuesIn(resp) if err != nil { - return nil, nil, "", clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, nil, "", graph.Stack(ctx, err) } itemCount += len(items) diff --git a/src/internal/connector/exchange/attachment_uploadable.go b/src/internal/connector/exchange/attachment_uploadable.go index cd7d2710d..fa03fa214 100644 --- a/src/internal/connector/exchange/attachment_uploadable.go +++ b/src/internal/connector/exchange/attachment_uploadable.go @@ -3,7 +3,6 @@ package exchange import ( "context" - "github.com/alcionai/clues" "github.com/microsoftgraph/msgraph-sdk-go/models" msusers "github.com/microsoftgraph/msgraph-sdk-go/users" @@ -44,7 +43,7 @@ func (mau *mailAttachmentUploader) uploadSmallAttachment(ctx context.Context, at Attachments(). Post(ctx, attach, nil) if err != nil { - return clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return graph.Stack(ctx, err) } return nil @@ -68,7 +67,7 @@ func (mau *mailAttachmentUploader) uploadSession( CreateUploadSession(). Post(ctx, session, nil) if err != nil { - return nil, clues.Wrap(err, "uploading mail attachment").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "uploading mail attachment") } return r, nil @@ -94,7 +93,7 @@ func (eau *eventAttachmentUploader) uploadSmallAttachment(ctx context.Context, a Attachments(). Post(ctx, attach, nil) if err != nil { - return clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return graph.Stack(ctx, err) } return nil @@ -116,7 +115,7 @@ func (eau *eventAttachmentUploader) uploadSession( CreateUploadSession(). Post(ctx, session, nil) if err != nil { - return nil, clues.Wrap(err, "uploading event attachment").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "uploading event attachment") } return r, nil diff --git a/src/internal/connector/exchange/restore_test.go b/src/internal/connector/exchange/restore_test.go index 8b123c09e..0591bb870 100644 --- a/src/internal/connector/exchange/restore_test.go +++ b/src/internal/connector/exchange/restore_test.go @@ -13,7 +13,6 @@ import ( "github.com/alcionai/corso/src/internal/connector/exchange/api" "github.com/alcionai/corso/src/internal/connector/graph" "github.com/alcionai/corso/src/internal/connector/mockconnector" - "github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/internal/tester" "github.com/alcionai/corso/src/pkg/account" "github.com/alcionai/corso/src/pkg/control" @@ -89,7 +88,7 @@ func (suite *ExchangeRestoreSuite) TestRestoreContact() { control.Copy, folderID, userID) - assert.NoError(t, err, support.ConnectorStackErrorTrace(err)) + assert.NoError(t, err) assert.NotNil(t, info, "contact item info") } @@ -123,7 +122,7 @@ func (suite *ExchangeRestoreSuite) TestRestoreEvent() { calendarID, userID, fault.New(true)) - assert.NoError(t, err, support.ConnectorStackErrorTrace(err)) + assert.NoError(t, err) assert.NotNil(t, info, "event item info") } @@ -352,7 +351,7 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() { destination, userID, fault.New(true)) - assert.NoError(t, err, support.ConnectorStackErrorTrace(err)) + assert.NoError(t, err) assert.NotNil(t, info, "item info was not populated") assert.NotNil(t, deleters) assert.NoError(t, deleters[test.category].DeleteContainer(ctx, userID, destination)) diff --git a/src/internal/connector/exchange/service_restore.go b/src/internal/connector/exchange/service_restore.go index 3abff9e4b..294be3ec6 100644 --- a/src/internal/connector/exchange/service_restore.go +++ b/src/internal/connector/exchange/service_restore.go @@ -70,14 +70,14 @@ func RestoreExchangeContact( ) (*details.ExchangeInfo, error) { contact, err := support.CreateContactFromBytes(bits) if err != nil { - return nil, clues.Wrap(err, "creating contact from bytes").WithClues(ctx) + return nil, graph.Wrap(ctx, err, "creating contact from bytes") } ctx = clues.Add(ctx, "item_id", ptr.Val(contact.GetId())) response, err := service.Client().UsersById(user).ContactFoldersById(destination).Contacts().Post(ctx, contact, nil) if err != nil { - return nil, clues.Wrap(err, "uploading Contact").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "uploading Contact") } if response == nil { @@ -125,7 +125,7 @@ func RestoreExchangeEvent( response, err := service.Client().UsersById(user).CalendarsById(destination).Events().Post(ctx, transformedEvent, nil) if err != nil { - return nil, clues.Wrap(err, "uploading event").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "uploading event") } if response == nil { @@ -249,7 +249,7 @@ func SendMailToBackStore( response, err := service.Client().UsersById(user).MailFoldersById(destination).Messages().Post(ctx, message, nil) if err != nil { - return clues.Wrap(err, "restoring mail").WithClues(ctx).With(graph.ErrData(err)...) + return graph.Wrap(ctx, err, "restoring mail") } if response == nil { @@ -609,7 +609,7 @@ func establishMailRestoreLocation( temp, err := ac.Mail().CreateMailFolderWithParent(ctx, user, folder, folderID) if err != nil { // Should only error if cache malfunctions or incorrect parameters - return "", errors.Wrap(err, support.ConnectorStackErrorTrace(err)) + return "", err } folderID = *temp.GetId() @@ -658,7 +658,7 @@ func establishContactsRestoreLocation( temp, err := ac.Contacts().CreateContactFolder(ctx, user, folders[0]) if err != nil { - return "", errors.Wrap(err, support.ConnectorStackErrorTrace(err)) + return "", err } folderID := *temp.GetId() @@ -695,7 +695,7 @@ func establishEventsRestoreLocation( temp, err := ac.Events().CreateCalendar(ctx, user, folders[0]) if err != nil { - return "", errors.Wrap(err, support.ConnectorStackErrorTrace(err)) + return "", err } folderID := *temp.GetId() diff --git a/src/internal/connector/graph/betasdk/beta_client_test.go b/src/internal/connector/graph/betasdk/beta_client_test.go index d90361399..88f2d83b9 100644 --- a/src/internal/connector/graph/betasdk/beta_client_test.go +++ b/src/internal/connector/graph/betasdk/beta_client_test.go @@ -56,18 +56,20 @@ func (suite *BetaClientSuite) TestCreateBetaClient() { func (suite *BetaClientSuite) TestBasicClientGetFunctionality() { ctx, flush := tester.NewContext() defer flush() + t := suite.T() + adpt, err := graph.CreateAdapter( suite.credentials.AzureTenantID, suite.credentials.AzureClientID, - suite.credentials.AzureClientSecret, - ) - + suite.credentials.AzureClientSecret) require.NoError(t, err) + client := NewBetaClient(adpt) require.NotNil(t, client) siteID := tester.M365SiteID(t) + // TODO(dadams39) document allowable calls in main collection, err := client.SitesById(siteID).Pages().Get(ctx, nil) // Ensures that the client is able to receive data from beta diff --git a/src/internal/connector/graph/errors.go b/src/internal/connector/graph/errors.go index 850e3fe64..a4910e975 100644 --- a/src/internal/connector/graph/errors.go +++ b/src/internal/connector/graph/errors.go @@ -12,7 +12,9 @@ import ( "github.com/pkg/errors" "golang.org/x/exp/slices" + "github.com/alcionai/clues" "github.com/alcionai/corso/src/internal/common" + "github.com/alcionai/corso/src/internal/common/ptr" ) // --------------------------------------------------------------------------- @@ -43,6 +45,17 @@ var ( Err500InternalServerError = errors.New("500 Internal Server Error") ) +var ( + mysiteURLNotFound = "unable to retrieve user's mysite url" + mysiteNotFound = "user's mysite not found" +) + +var Labels = struct { + MysiteNotFound string +}{ + MysiteNotFound: "mysite_not_found", +} + // The folder or item was deleted between the time we identified // it and when we tried to fetch data for it. type ErrDeletedInFlight struct { @@ -196,43 +209,74 @@ func hasErrorCode(err error, codes ...string) bool { return slices.Contains(lcodes, strings.ToLower(*oDataError.GetError().GetCode())) } -// ErrData is a helper function that extracts ODataError metadata from -// the error. If the error is not an ODataError type, returns an empty -// slice. The returned value is guaranteed to be an even-length pairing -// of key, value tuples. -func ErrData(e error) []any { - result := make([]any, 0) - +// Wrap is a helper function that extracts ODataError metadata from +// the error. If the error is not an ODataError type, returns the error. +func Wrap(ctx context.Context, e error, msg string) *clues.Err { if e == nil { - return result + return nil } odErr, ok := e.(odataerrors.ODataErrorable) if !ok { - return result + return clues.Wrap(e, msg).WithClues(ctx) } - // Get MainError - mainErr := odErr.GetError() + data, innerMsg := errData(odErr) - result = appendIf(result, "odataerror_code", mainErr.GetCode()) - result = appendIf(result, "odataerror_message", mainErr.GetMessage()) - result = appendIf(result, "odataerror_target", mainErr.GetTarget()) + return setLabels(clues.Wrap(e, msg).WithClues(ctx).With(data...), innerMsg) +} + +// Stack is a helper function that extracts ODataError metadata from +// the error. If the error is not an ODataError type, returns the error. +func Stack(ctx context.Context, e error) *clues.Err { + if e == nil { + return nil + } + + odErr, ok := e.(odataerrors.ODataErrorable) + if !ok { + return clues.Stack(e).WithClues(ctx) + } + + data, innerMsg := errData(odErr) + + return setLabels(clues.Stack(e).WithClues(ctx).With(data...), innerMsg) +} + +func setLabels(err *clues.Err, msg string) *clues.Err { + if strings.Contains(msg, mysiteNotFound) || strings.Contains(msg, mysiteURLNotFound) { + err = err.Label(Labels.MysiteNotFound) + } + + return err +} + +func errData(err odataerrors.ODataErrorable) ([]any, string) { + data := make([]any, 0) + + // Get MainError + mainErr := err.GetError() + + data = appendIf(data, "odataerror_code", mainErr.GetCode()) + data = appendIf(data, "odataerror_message", mainErr.GetMessage()) + data = appendIf(data, "odataerror_target", mainErr.GetTarget()) + msgConcat := ptr.Val(mainErr.GetMessage()) + ptr.Val(mainErr.GetCode()) for i, d := range mainErr.GetDetails() { pfx := fmt.Sprintf("odataerror_details_%d_", i) - result = appendIf(result, pfx+"code", d.GetCode()) - result = appendIf(result, pfx+"message", d.GetMessage()) - result = appendIf(result, pfx+"target", d.GetTarget()) + data = appendIf(data, pfx+"code", d.GetCode()) + data = appendIf(data, pfx+"message", d.GetMessage()) + data = appendIf(data, pfx+"target", d.GetTarget()) + msgConcat += ptr.Val(d.GetMessage()) } inner := mainErr.GetInnererror() if inner != nil { - result = appendIf(result, "odataerror_inner_cli_req_id", inner.GetClientRequestId()) - result = appendIf(result, "odataerror_inner_req_id", inner.GetRequestId()) + data = appendIf(data, "odataerror_inner_cli_req_id", inner.GetClientRequestId()) + data = appendIf(data, "odataerror_inner_req_id", inner.GetRequestId()) } - return result + return data, strings.ToLower(msgConcat) } func appendIf(a []any, k string, v *string) []any { diff --git a/src/internal/connector/graph/retry_middleware.go b/src/internal/connector/graph/retry_middleware.go index 371502a59..c836a251b 100644 --- a/src/internal/connector/graph/retry_middleware.go +++ b/src/internal/connector/graph/retry_middleware.go @@ -6,7 +6,6 @@ import ( "strconv" "time" - "github.com/alcionai/clues" backoff "github.com/cenkalti/backoff/v4" khttp "github.com/microsoft/kiota-http-go" ) @@ -50,10 +49,7 @@ func (middleware RetryHandler) retryRequest( response, err := pipeline.Next(req, middlewareIndex) if err != nil && !IsErrTimeout(err) { - return response, clues.Stack(err). - WithClues(ctx). - With("retry_count", executionCount). - With(ErrData(err)...) + return response, Stack(ctx, err).With("retry_count", executionCount) } return middleware.retryRequest(ctx, @@ -68,10 +64,7 @@ func (middleware RetryHandler) retryRequest( } if respErr != nil { - return nil, clues.Stack(respErr). - WithClues(ctx). - With("retry_count", executionCount). - With(ErrData(respErr)...) + return nil, Stack(ctx, respErr).With("retry_count", executionCount) } return resp, nil diff --git a/src/internal/connector/graph/service.go b/src/internal/connector/graph/service.go index 58cfab18e..1c189a6b3 100644 --- a/src/internal/connector/graph/service.go +++ b/src/internal/connector/graph/service.go @@ -8,7 +8,6 @@ import ( "time" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" - "github.com/alcionai/clues" backoff "github.com/cenkalti/backoff/v4" "github.com/microsoft/kiota-abstractions-go/serialization" ka "github.com/microsoft/kiota-authentication-azure-go" @@ -343,7 +342,7 @@ func (middleware RetryHandler) Intercept( response, err := pipeline.Next(req, middlewareIndex) if err != nil && !IsErrTimeout(err) { - return response, clues.Stack(err).WithClues(ctx).With(ErrData(err)...) + return response, Stack(ctx, err) } exponentialBackOff := backoff.NewExponentialBackOff() @@ -361,7 +360,7 @@ func (middleware RetryHandler) Intercept( exponentialBackOff, err) if err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(ErrData(err)...) + return nil, Stack(ctx, err) } return response, nil diff --git a/src/internal/connector/graph_connector.go b/src/internal/connector/graph_connector.go index 410e4b858..02475e5a2 100644 --- a/src/internal/connector/graph_connector.go +++ b/src/internal/connector/graph_connector.go @@ -280,14 +280,12 @@ func getResources( response, err := query(ctx, gs) if err != nil { - return nil, clues.Wrap(err, "retrieving tenant's resources"). - WithClues(ctx). - With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "retrieving tenant's resources") } iter, err := msgraphgocore.NewPageIterator(response, gs.Adapter(), parser) if err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err) } el := errs.Local() @@ -314,7 +312,7 @@ func getResources( } if err := iter.Iterate(ctx, callbackFunc); err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err) } return resources, el.Failure() diff --git a/src/internal/connector/graph_connector_test.go b/src/internal/connector/graph_connector_test.go index 3eddb9238..f419504d1 100644 --- a/src/internal/connector/graph_connector_test.go +++ b/src/internal/connector/graph_connector_test.go @@ -5,15 +5,14 @@ import ( "testing" "time" - "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "golang.org/x/exp/maps" + "github.com/alcionai/corso/src/internal/common/ptr" "github.com/alcionai/corso/src/internal/connector/graph" "github.com/alcionai/corso/src/internal/connector/mockconnector" - "github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/internal/data" "github.com/alcionai/corso/src/internal/tester" "github.com/alcionai/corso/src/internal/version" @@ -325,19 +324,15 @@ func mustGetDefaultDriveID( //revive:enable:context-as-argument d, err := service.Client().UsersById(userID).Drive().Get(ctx, nil) if err != nil { - err = errors.Wrapf( - err, - "failed to retrieve default user drive. user: %s, details: %s", - userID, - support.ConnectorStackErrorTrace(err), - ) + err = graph.Wrap(ctx, err, "retrieving drive") } require.NoError(t, err) - require.NotNil(t, d.GetId()) - require.NotEmpty(t, *d.GetId()) - return *d.GetId() + id := ptr.Val(d.GetId()) + require.NotEmpty(t, id) + + return id } func getCollectionsAndExpected( diff --git a/src/internal/connector/onedrive/api/drive.go b/src/internal/connector/onedrive/api/drive.go index 3e65e502b..0982664a8 100644 --- a/src/internal/connector/onedrive/api/drive.go +++ b/src/internal/connector/onedrive/api/drive.go @@ -69,7 +69,7 @@ func (p *driveItemPager) GetPage(ctx context.Context) (api.DeltaPageLinker, erro resp, err = p.builder.Get(ctx, p.options) if err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err) } return resp, nil @@ -120,8 +120,11 @@ func (p *userDrivePager) GetPage(ctx context.Context) (api.PageLinker, error) { ) resp, err = p.builder.Get(ctx, p.options) + if err != nil { + return nil, graph.Stack(ctx, err) + } - return resp, err + return resp, nil } func (p *userDrivePager) SetNext(link string) { @@ -171,7 +174,7 @@ func (p *siteDrivePager) GetPage(ctx context.Context) (api.PageLinker, error) { resp, err = p.builder.Get(ctx, p.options) if err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err) } return resp, nil @@ -194,7 +197,7 @@ func (p *siteDrivePager) GetDriveIDByName(ctx context.Context, driveName string) for { resp, err := p.builder.Get(ctx, p.options) if err != nil { - return empty, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return empty, graph.Stack(ctx, err) } for _, entry := range resp.GetValue() { @@ -230,7 +233,7 @@ func (p *siteDrivePager) GetFolderIDByName(ctx context.Context, driveID, folderN for { resp, err := builder.Get(ctx, option) if err != nil { - return empty, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return empty, graph.Stack(ctx, err) } for _, entry := range resp.GetValue() { diff --git a/src/internal/connector/onedrive/collection.go b/src/internal/connector/onedrive/collection.go index bf50e3f3f..8c05dc2e7 100644 --- a/src/internal/connector/onedrive/collection.go +++ b/src/internal/connector/onedrive/collection.go @@ -88,6 +88,7 @@ type Collection struct { // itemReadFunc returns a reader for the specified item type itemReaderFunc func( + ctx context.Context, hc *http.Client, item models.DriveItemable, ) (details.ItemInfo, io.ReadCloser, error) @@ -395,7 +396,7 @@ func (oc *Collection) populateItems(ctx context.Context, errs *fault.Bus) { err error ) - _, itemData, err = oc.itemReader(oc.itemClient, item) + _, itemData, err = oc.itemReader(ctx, oc.itemClient, item) if err != nil && graph.IsErrUnauthorized(err) { // assume unauthorized requests are a sign of an expired diff --git a/src/internal/connector/onedrive/collection_test.go b/src/internal/connector/onedrive/collection_test.go index da2c67b0c..4cb13e8dd 100644 --- a/src/internal/connector/onedrive/collection_test.go +++ b/src/internal/connector/onedrive/collection_test.go @@ -94,7 +94,7 @@ func (suite *CollectionUnitTestSuite) TestCollection() { numInstances: 1, source: OneDriveSource, itemDeets: nst{testItemName, 42, now}, - itemReader: func(*http.Client, models.DriveItemable) (details.ItemInfo, io.ReadCloser, error) { + itemReader: func(context.Context, *http.Client, models.DriveItemable) (details.ItemInfo, io.ReadCloser, error) { return details.ItemInfo{OneDrive: &details.OneDriveInfo{ItemName: testItemName, Modified: now}}, io.NopCloser(bytes.NewReader(testItemData)), nil @@ -109,7 +109,7 @@ func (suite *CollectionUnitTestSuite) TestCollection() { numInstances: 3, source: OneDriveSource, itemDeets: nst{testItemName, 42, now}, - itemReader: func(*http.Client, models.DriveItemable) (details.ItemInfo, io.ReadCloser, error) { + itemReader: func(context.Context, *http.Client, models.DriveItemable) (details.ItemInfo, io.ReadCloser, error) { return details.ItemInfo{OneDrive: &details.OneDriveInfo{ItemName: testItemName, Modified: now}}, io.NopCloser(bytes.NewReader(testItemData)), nil @@ -124,7 +124,7 @@ func (suite *CollectionUnitTestSuite) TestCollection() { numInstances: 1, source: SharePointSource, itemDeets: nst{testItemName, 42, now}, - itemReader: func(*http.Client, models.DriveItemable) (details.ItemInfo, io.ReadCloser, error) { + itemReader: func(context.Context, *http.Client, models.DriveItemable) (details.ItemInfo, io.ReadCloser, error) { return details.ItemInfo{SharePoint: &details.SharePointInfo{ItemName: testItemName, Modified: now}}, io.NopCloser(bytes.NewReader(testItemData)), nil @@ -139,7 +139,7 @@ func (suite *CollectionUnitTestSuite) TestCollection() { numInstances: 3, source: SharePointSource, itemDeets: nst{testItemName, 42, now}, - itemReader: func(*http.Client, models.DriveItemable) (details.ItemInfo, io.ReadCloser, error) { + itemReader: func(context.Context, *http.Client, models.DriveItemable) (details.ItemInfo, io.ReadCloser, error) { return details.ItemInfo{SharePoint: &details.SharePointInfo{ItemName: testItemName, Modified: now}}, io.NopCloser(bytes.NewReader(testItemData)), nil @@ -326,7 +326,11 @@ func (suite *CollectionUnitTestSuite) TestCollectionReadError() { mockItem.SetLastModifiedDateTime(&now) coll.Add(mockItem) - coll.itemReader = func(*http.Client, models.DriveItemable) (details.ItemInfo, io.ReadCloser, error) { + coll.itemReader = func( + context.Context, + *http.Client, + models.DriveItemable, + ) (details.ItemInfo, io.ReadCloser, error) { return details.ItemInfo{}, nil, assert.AnError } @@ -407,6 +411,7 @@ func (suite *CollectionUnitTestSuite) TestCollectionPermissionBackupLatestModTim coll.Add(mockItem) coll.itemReader = func( + context.Context, *http.Client, models.DriveItemable, ) (details.ItemInfo, io.ReadCloser, error) { diff --git a/src/internal/connector/onedrive/collections.go b/src/internal/connector/onedrive/collections.go index c9bb5c407..9952b6f25 100644 --- a/src/internal/connector/onedrive/collections.go +++ b/src/internal/connector/onedrive/collections.go @@ -267,7 +267,7 @@ func (c *Collections) Get( // Enumerate drives for the specified resourceOwner pager, err := c.drivePagerFunc(c.source, c.service, c.resourceOwner, nil) if err != nil { - return nil, nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, nil, graph.Stack(ctx, err) } retry := c.source == OneDriveSource diff --git a/src/internal/connector/onedrive/drive.go b/src/internal/connector/onedrive/drive.go index e6cab77fd..e3c985fbf 100644 --- a/src/internal/connector/onedrive/drive.go +++ b/src/internal/connector/onedrive/drive.go @@ -16,7 +16,6 @@ import ( "github.com/alcionai/corso/src/internal/connector/graph" gapi "github.com/alcionai/corso/src/internal/connector/graph/api" "github.com/alcionai/corso/src/internal/connector/onedrive/api" - "github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/pkg/fault" "github.com/alcionai/corso/src/pkg/logger" ) @@ -28,15 +27,10 @@ const ( // nextLinkKey is used to find the next link in a paged // graph response - nextLinkKey = "@odata.nextLink" - itemChildrenRawURLFmt = "https://graph.microsoft.com/v1.0/drives/%s/items/%s/children" - itemByPathRawURLFmt = "https://graph.microsoft.com/v1.0/drives/%s/items/%s:/%s" - itemNotFoundErrorCode = "itemNotFound" - userMysiteURLNotFound = "BadRequest Unable to retrieve user's mysite URL" - userMysiteURLNotFoundMsg = "Unable to retrieve user's mysite URL" - userMysiteNotFound = "ResourceNotFound User's mysite not found" - userMysiteNotFoundMsg = "User's mysite not found" - contextDeadlineExceeded = "context deadline exceeded" + nextLinkKey = "@odata.nextLink" + itemChildrenRawURLFmt = "https://graph.microsoft.com/v1.0/drives/%s/items/%s/children" + itemByPathRawURLFmt = "https://graph.microsoft.com/v1.0/drives/%s/items/%s:/%s" + itemNotFoundErrorCode = "itemNotFound" ) // DeltaUpdate holds the results of a current delta token. It normally @@ -97,22 +91,17 @@ func drives( for i := 0; i <= numberOfRetries; i++ { page, err = pager.GetPage(ctx) if err != nil { - // Various error handling. May return an error or perform a retry. - errMsg := support.ConnectorStackErrorTraceWrap(err, "").Error() - if strings.Contains(errMsg, userMysiteURLNotFound) || - strings.Contains(errMsg, userMysiteURLNotFoundMsg) || - strings.Contains(errMsg, userMysiteNotFound) || - strings.Contains(errMsg, userMysiteNotFoundMsg) { + if clues.HasLabel(err, graph.Labels.MysiteNotFound) { logger.Ctx(ctx).Infof("resource owner does not have a drive") return make([]models.Driveable, 0), nil // no license or drives. } - if strings.Contains(errMsg, contextDeadlineExceeded) && i < numberOfRetries { + if graph.IsErrTimeout(err) && i < numberOfRetries { time.Sleep(time.Duration(3*(i+1)) * time.Second) continue } - return nil, clues.Wrap(err, "retrieving drives").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "retrieving drives") } // No error encountered, break the retry loop so we can extract results @@ -122,7 +111,7 @@ func drives( tmp, err := pager.ValuesIn(page) if err != nil { - return nil, clues.Wrap(err, "extracting drives from response").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "extracting drives from response") } drives = append(drives, tmp...) @@ -232,14 +221,12 @@ func collectItems( } if err != nil { - return DeltaUpdate{}, nil, nil, clues.Wrap(err, "getting page").WithClues(ctx).With(graph.ErrData(err)...) + return DeltaUpdate{}, nil, nil, graph.Wrap(ctx, err, "getting page") } vals, err := pager.ValuesIn(page) if err != nil { - return DeltaUpdate{}, nil, nil, clues.Wrap(err, "extracting items from response"). - WithClues(ctx). - With(graph.ErrData(err)...) + return DeltaUpdate{}, nil, nil, graph.Wrap(ctx, err, "extracting items from response") } err = collector( @@ -297,15 +284,15 @@ func getFolder( foundItem, err = builder.Get(ctx, nil) if err != nil { if graph.IsErrDeletedInFlight(err) { - return nil, clues.Stack(errFolderNotFound, err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, clues.Stack(errFolderNotFound, err)) } - return nil, clues.Wrap(err, "getting folder").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "getting folder") } // Check if the item found is a folder, fail the call if not if foundItem.GetFolder() == nil { - return nil, clues.Stack(errFolderNotFound).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, errFolderNotFound) } return foundItem, nil @@ -325,7 +312,7 @@ func createItem( newItem, err := builder.Post(ctx, newItem, nil) if err != nil { - return nil, clues.Wrap(err, "creating item").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "creating item") } return newItem, nil @@ -447,10 +434,7 @@ func DeleteItem( ) error { err := gs.Client().DrivesById(driveID).ItemsById(itemID).Delete(ctx, nil) if err != nil { - return clues.Wrap(err, "deleting item"). - WithClues(ctx). - With("item_id", itemID). - With(graph.ErrData(err)...) + return graph.Wrap(ctx, err, "deleting item").With("item_id", itemID) } return nil diff --git a/src/internal/connector/onedrive/drive_test.go b/src/internal/connector/onedrive/drive_test.go index f72514baf..226fee577 100644 --- a/src/internal/connector/onedrive/drive_test.go +++ b/src/internal/connector/onedrive/drive_test.go @@ -12,10 +12,10 @@ import ( "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" + "github.com/alcionai/clues" "github.com/alcionai/corso/src/internal/common" "github.com/alcionai/corso/src/internal/connector/graph" "github.com/alcionai/corso/src/internal/connector/graph/api" - "github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/internal/tester" "github.com/alcionai/corso/src/pkg/control" "github.com/alcionai/corso/src/pkg/fault" @@ -78,6 +78,11 @@ func TestOneDriveUnitSuite(t *testing.T) { suite.Run(t, &OneDriveUnitSuite{Suite: tester.NewUnitSuite(t)}) } +const ( + userMysiteURLNotFound = "BadRequest Unable to retrieve user's mysite URL" + userMysiteNotFound = "ResourceNotFound User's mysite not found" +) + func odErr(code string) *odataerrors.ODataError { odErr := &odataerrors.ODataError{} merr := odataerrors.MainError{} @@ -88,6 +93,9 @@ func odErr(code string) *odataerrors.ODataError { } func (suite *OneDriveUnitSuite) TestDrives() { + ctx, flush := tester.NewContext() + defer flush() + numDriveResults := 4 emptyLink := "" link := "foo" @@ -95,18 +103,8 @@ func (suite *OneDriveUnitSuite) TestDrives() { // These errors won't be the "correct" format when compared to what graph // returns, but they're close enough to have the same info when the inner // details are extracted via support package. - mySiteURLNotFound := support.ConnectorStackErrorTraceWrap( - odErr(userMysiteURLNotFound), - "maximum retries or unretryable", - ) - mySiteNotFound := support.ConnectorStackErrorTraceWrap( - odErr(userMysiteNotFound), - "maximum retries or unretryable", - ) - deadlineExceeded := support.ConnectorStackErrorTraceWrap( - odErr(contextDeadlineExceeded), - "maximum retries or unretryable", - ) + mySiteURLNotFound := odErr(userMysiteURLNotFound) + mySiteNotFound := odErr(userMysiteNotFound) resultDrives := make([]models.Driveable, 0, numDriveResults) @@ -122,7 +120,7 @@ func (suite *OneDriveUnitSuite) TestDrives() { for i := 0; i < getDrivesRetries+1; i++ { tooManyRetries = append(tooManyRetries, pagerResult{ - err: deadlineExceeded, + err: context.DeadlineExceeded, }) } @@ -219,7 +217,7 @@ func (suite *OneDriveUnitSuite) TestDrives() { { drives: nil, nextLink: nil, - err: mySiteURLNotFound, + err: graph.Stack(ctx, mySiteURLNotFound), }, }, retry: true, @@ -232,7 +230,7 @@ func (suite *OneDriveUnitSuite) TestDrives() { { drives: nil, nextLink: nil, - err: mySiteNotFound, + err: graph.Stack(ctx, mySiteNotFound), }, }, retry: true, @@ -250,7 +248,7 @@ func (suite *OneDriveUnitSuite) TestDrives() { { drives: nil, nextLink: nil, - err: deadlineExceeded, + err: context.DeadlineExceeded, }, { drives: resultDrives[numDriveResults/2:], @@ -273,7 +271,7 @@ func (suite *OneDriveUnitSuite) TestDrives() { { drives: nil, nextLink: nil, - err: deadlineExceeded, + err: context.DeadlineExceeded, }, { drives: resultDrives[numDriveResults/2:], @@ -437,9 +435,6 @@ func (fm testFolderMatcher) Matches(path string) bool { } func (suite *OneDriveSuite) TestOneDriveNewCollections() { - ctx, flush := tester.NewContext() - defer flush() - creds, err := tester.NewM365Account(suite.T()).M365Config() require.NoError(suite.T(), err) @@ -458,13 +453,18 @@ func (suite *OneDriveSuite) TestOneDriveNewCollections() { for _, test := range tests { suite.Run(test.name, func() { - t := suite.T() + ctx, flush := tester.NewContext() + defer flush() - service := loadTestService(t) - scope := selectors. - NewOneDriveBackup([]string{test.user}). - AllData()[0] - odcs, excludes, err := NewCollections( + var ( + t = suite.T() + service = loadTestService(t) + scope = selectors. + NewOneDriveBackup([]string{test.user}). + AllData()[0] + ) + + colls := NewCollections( graph.HTTPClient(graph.NoTimeout()), creds.AzureTenantID, test.user, @@ -472,9 +472,12 @@ func (suite *OneDriveSuite) TestOneDriveNewCollections() { testFolderMatcher{scope}, service, service.updateStatus, - control.Options{ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}}, - ).Get(ctx, nil, fault.New(true)) - assert.NoError(t, err) + control.Options{ + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }) + + odcs, excludes, err := colls.Get(ctx, nil, fault.New(true)) + assert.NoError(t, err, clues.InErr(err)) // Don't expect excludes as this isn't an incremental backup. assert.Empty(t, excludes) diff --git a/src/internal/connector/onedrive/item.go b/src/internal/connector/onedrive/item.go index 0c33c0111..59ce4849b 100644 --- a/src/internal/connector/onedrive/item.go +++ b/src/internal/connector/onedrive/item.go @@ -35,7 +35,7 @@ func getDriveItem( ) (models.DriveItemable, error) { di, err := srv.Client().DrivesById(driveID).ItemsById(itemID).Get(ctx, nil) if err != nil { - return nil, clues.Wrap(err, "getting item").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "getting item") } return di, nil @@ -46,10 +46,11 @@ func getDriveItem( // and using a http client to initialize a reader // TODO: Add metadata fetching to SharePoint func sharePointItemReader( + ctx context.Context, hc *http.Client, item models.DriveItemable, ) (details.ItemInfo, io.ReadCloser, error) { - resp, err := downloadItem(hc, item) + resp, err := downloadItem(ctx, hc, item) if err != nil { return details.ItemInfo{}, nil, errors.Wrap(err, "downloading item") } @@ -106,6 +107,7 @@ func oneDriveItemMetaReader( // It crafts this by querying M365 for a download URL for the item // and using a http client to initialize a reader func oneDriveItemReader( + ctx context.Context, hc *http.Client, item models.DriveItemable, ) (details.ItemInfo, io.ReadCloser, error) { @@ -115,7 +117,7 @@ func oneDriveItemReader( ) if isFile { - resp, err := downloadItem(hc, item) + resp, err := downloadItem(ctx, hc, item) if err != nil { return details.ItemInfo{}, nil, errors.Wrap(err, "downloading item") } @@ -130,7 +132,7 @@ func oneDriveItemReader( return dii, rc, nil } -func downloadItem(hc *http.Client, item models.DriveItemable) (*http.Response, error) { +func downloadItem(ctx context.Context, hc *http.Client, item models.DriveItemable) (*http.Response, error) { url, ok := item.GetAdditionalData()[downloadURLKey].(*string) if !ok { return nil, clues.New("extracting file url").With("item_id", ptr.Val(item.GetId())) @@ -138,7 +140,7 @@ func downloadItem(hc *http.Client, item models.DriveItemable) (*http.Response, e req, err := http.NewRequest(http.MethodGet, *url, nil) if err != nil { - return nil, clues.Wrap(err, "new request").With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "new request") } //nolint:lll @@ -229,12 +231,7 @@ func oneDriveItemPermissionInfo( Permissions(). Get(ctx, nil) if err != nil { - err = clues.Wrap(err, "fetching item permissions"). - WithClues(ctx). - With("item_id", id). - With(graph.ErrData(err)...) - - return nil, err + return nil, graph.Wrap(ctx, err, "getting item metadata").With("item_id", id) } uperms := filterUserPermissions(ctx, perm.GetValue()) @@ -360,9 +357,7 @@ func driveItemWriter( r, err := service.Client().DrivesById(driveID).ItemsById(itemID).CreateUploadSession().Post(ctx, session, nil) if err != nil { - return nil, clues.Wrap(err, "creating item upload session"). - WithClues(ctx). - With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "creating item upload session") } logger.Ctx(ctx).Debug("created an upload session") @@ -428,7 +423,7 @@ func fetchParentReference( drive, err := service.Client().DrivesById(driveID).Get(ctx, options) if err != nil { - return nil, clues.Stack(err).WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Stack(ctx, err) } orig.SetName(drive.GetName()) diff --git a/src/internal/connector/onedrive/item_test.go b/src/internal/connector/onedrive/item_test.go index ef6954c40..9297373de 100644 --- a/src/internal/connector/onedrive/item_test.go +++ b/src/internal/connector/onedrive/item_test.go @@ -111,7 +111,7 @@ func (suite *ItemIntegrationSuite) TestItemReader_oneDrive() { ) // Read data for the file - itemInfo, itemData, err := oneDriveItemReader(graph.HTTPClient(graph.NoTimeout()), driveItem) + itemInfo, itemData, err := oneDriveItemReader(ctx, graph.HTTPClient(graph.NoTimeout()), driveItem) require.NoError(suite.T(), err) require.NotNil(suite.T(), itemInfo.OneDrive) diff --git a/src/internal/connector/onedrive/permission.go b/src/internal/connector/onedrive/permission.go index 78c15df58..f1dd982d7 100644 --- a/src/internal/connector/onedrive/permission.go +++ b/src/internal/connector/onedrive/permission.go @@ -190,7 +190,7 @@ func restorePermissions( PermissionsById(permissionIDMappings[p.ID]). Delete(ctx, nil) if err != nil { - return clues.Wrap(err, "removing permissions").WithClues(ctx).With(graph.ErrData(err)...) + return graph.Wrap(ctx, err, "removing permissions") } } @@ -222,7 +222,7 @@ func restorePermissions( np, err := service.Client().DrivesById(driveID).ItemsById(itemID).Invite().Post(ctx, pbody, nil) if err != nil { - return clues.Wrap(err, "setting permissions").WithClues(ctx).With(graph.ErrData(err)...) + return graph.Wrap(ctx, err, "setting permissions") } permissionIDMappings[p.ID] = *np.GetValue()[0].GetId() diff --git a/src/internal/connector/onedrive/restore.go b/src/internal/connector/onedrive/restore.go index caa3dc85a..4c5615c06 100644 --- a/src/internal/connector/onedrive/restore.go +++ b/src/internal/connector/onedrive/restore.go @@ -474,7 +474,7 @@ func CreateRestoreFolders( ) (string, error) { driveRoot, err := service.Client().DrivesById(driveID).Root().Get(ctx, nil) if err != nil { - return "", clues.Wrap(err, "getting drive root").WithClues(ctx).With(graph.ErrData(err)...) + return "", graph.Wrap(ctx, err, "getting drive root") } parentFolderID := ptr.Val(driveRoot.GetId()) @@ -550,7 +550,7 @@ func restoreData( // Upload the stream data written, err := io.CopyBuffer(w, progReader, copyBuffer) if err != nil { - return "", details.ItemInfo{}, clues.Wrap(err, "writing item bytes").WithClues(ctx).With(graph.ErrData(err)...) + return "", details.ItemInfo{}, graph.Wrap(ctx, err, "writing item bytes") } dii := details.ItemInfo{} diff --git a/src/internal/connector/sharepoint/api/pages.go b/src/internal/connector/sharepoint/api/pages.go index 168202533..00bd87a26 100644 --- a/src/internal/connector/sharepoint/api/pages.go +++ b/src/internal/connector/sharepoint/api/pages.go @@ -70,7 +70,7 @@ func GetSitePages( page, err = serv.Client().SitesById(siteID).PagesById(pageID).Get(ctx, opts) if err != nil { - el.AddRecoverable(clues.Wrap(err, "fetching page").WithClues(ctx).With(graph.ErrData(err)...)) + el.AddRecoverable(graph.Wrap(ctx, err, "fetching page")) return } @@ -113,7 +113,7 @@ func FetchPages(ctx context.Context, bs *discover.BetaService, siteID string) ([ for { resp, err = builder.Get(ctx, opts) if err != nil { - return nil, clues.Wrap(err, "fetching site page").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "fetching site page") } for _, entry := range resp.GetValue() { @@ -162,7 +162,7 @@ func DeleteSitePage( ) error { err := serv.Client().SitesById(siteID).PagesById(pageID).Delete(ctx, nil) if err != nil { - return clues.Wrap(err, "deleting page").WithClues(ctx).With(graph.ErrData(err)...) + return graph.Wrap(ctx, err, "deleting page") } return nil @@ -222,7 +222,7 @@ func RestoreSitePage( // See: https://learn.microsoft.com/en-us/graph/api/sitepage-create?view=graph-rest-beta restoredPage, err := service.Client().SitesById(siteID).Pages().Post(ctx, page, nil) if err != nil { - return dii, clues.Wrap(err, "creating page").WithClues(ctx).With(graph.ErrData(err)...) + return dii, graph.Wrap(ctx, err, "creating page") } pageID = ptr.Val(restoredPage.GetId()) @@ -240,7 +240,7 @@ func RestoreSitePage( Publish(). Post(ctx, nil) if err != nil { - return dii, clues.Wrap(err, "publishing page").WithClues(ctx).With(graph.ErrData(err)...) + return dii, graph.Wrap(ctx, err, "publishing page") } dii.SharePoint = PageInfo(restoredPage, int64(len(byteArray))) diff --git a/src/internal/connector/sharepoint/collection.go b/src/internal/connector/sharepoint/collection.go index 05ab52145..3c9401341 100644 --- a/src/internal/connector/sharepoint/collection.go +++ b/src/internal/connector/sharepoint/collection.go @@ -231,7 +231,7 @@ func (sc *Collection) retrieveLists( break } - byteArray, err := serializeContent(wtr, lst) + byteArray, err := serializeContent(ctx, wtr, lst) if err != nil { el.AddRecoverable(clues.Wrap(err, "serializing list").WithClues(ctx).Label(fault.LabelForceNoBackupCreation)) continue @@ -299,7 +299,7 @@ func (sc *Collection) retrievePages( break } - byteArray, err := serializeContent(wtr, pg) + byteArray, err := serializeContent(ctx, wtr, pg) if err != nil { el.AddRecoverable(clues.Wrap(err, "serializing page").WithClues(ctx).Label(fault.LabelForceNoBackupCreation)) continue @@ -324,17 +324,21 @@ func (sc *Collection) retrievePages( return metrics, el.Failure() } -func serializeContent(writer *kw.JsonSerializationWriter, obj absser.Parsable) ([]byte, error) { +func serializeContent( + ctx context.Context, + writer *kw.JsonSerializationWriter, + obj absser.Parsable, +) ([]byte, error) { defer writer.Close() err := writer.WriteObjectValue("", obj) if err != nil { - return nil, clues.Wrap(err, "writing object").With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "writing object") } byteArray, err := writer.GetSerializedContent() if err != nil { - return nil, clues.Wrap(err, "getting content from writer").With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "getting content from writer") } return byteArray, nil diff --git a/src/internal/connector/sharepoint/collection_test.go b/src/internal/connector/sharepoint/collection_test.go index 18e25de66..3d59512bc 100644 --- a/src/internal/connector/sharepoint/collection_test.go +++ b/src/internal/connector/sharepoint/collection_test.go @@ -206,7 +206,7 @@ func (suite *SharePointCollectionSuite) TestListCollection_Restore() { for { resp, err := builder.Get(ctx, nil) - assert.NoError(t, err, "experienced query error during clean up. Details: "+support.ConnectorStackErrorTrace(err)) + assert.NoError(t, err, "getting site lists") for _, temp := range resp.GetValue() { if *temp.GetDisplayName() == deets.SharePoint.ItemName { diff --git a/src/internal/connector/sharepoint/data_collections.go b/src/internal/connector/sharepoint/data_collections.go index 469822eea..6752fa71c 100644 --- a/src/internal/connector/sharepoint/data_collections.go +++ b/src/internal/connector/sharepoint/data_collections.go @@ -191,7 +191,7 @@ func collectLibraries( // token-based incrementals. odcs, excludes, err := colls.Get(ctx, nil, errs) if err != nil { - return nil, nil, clues.Wrap(err, "getting library").WithClues(ctx).With(graph.ErrData(err)...) + return nil, nil, graph.Wrap(ctx, err, "getting library") } return append(collections, odcs...), excludes, nil diff --git a/src/internal/connector/sharepoint/list.go b/src/internal/connector/sharepoint/list.go index 79989983c..41316f140 100644 --- a/src/internal/connector/sharepoint/list.go +++ b/src/internal/connector/sharepoint/list.go @@ -7,11 +7,9 @@ import ( "github.com/alcionai/clues" "github.com/microsoftgraph/msgraph-sdk-go/models" mssite "github.com/microsoftgraph/msgraph-sdk-go/sites" - "github.com/pkg/errors" "github.com/alcionai/corso/src/internal/common/ptr" "github.com/alcionai/corso/src/internal/connector/graph" - "github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/pkg/fault" ) @@ -46,7 +44,7 @@ func preFetchLists( for { resp, err := builder.Get(ctx, options) if err != nil { - return nil, clues.Wrap(err, "getting lists").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "getting lists") } for _, entry := range resp.GetValue() { @@ -131,7 +129,7 @@ func loadSiteLists( entry, err = gs.Client().SitesById(siteID).ListsById(id).Get(ctx, nil) if err != nil { - el.AddRecoverable(clues.Wrap(err, "getting site list").WithClues(ctx).With(graph.ErrData(err)...)) + el.AddRecoverable(graph.Wrap(ctx, err, "getting site list")) return } @@ -209,7 +207,7 @@ func fetchListItems( resp, err := builder.Get(ctx, nil) if err != nil { - return nil, errors.Wrap(err, support.ConnectorStackErrorTrace(err)) + return nil, err } for _, itm := range resp.GetValue() { @@ -221,7 +219,7 @@ func fetchListItems( fields, err := newPrefix.Fields().Get(ctx, nil) if err != nil { - el.AddRecoverable(clues.Wrap(err, "getting list fields").WithClues(ctx).With(graph.ErrData(err)...)) + el.AddRecoverable(graph.Wrap(ctx, err, "getting list fields")) continue } @@ -257,7 +255,7 @@ func fetchColumns( for { resp, err := builder.Get(ctx, nil) if err != nil { - return nil, clues.Wrap(err, "getting list columns").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "getting list columns") } cs = append(cs, resp.GetValue()...) @@ -274,7 +272,7 @@ func fetchColumns( for { resp, err := builder.Get(ctx, nil) if err != nil { - return nil, clues.Wrap(err, "getting content columns").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "getting content columns") } cs = append(cs, resp.GetValue()...) @@ -315,7 +313,7 @@ func fetchContentTypes( resp, err := builder.Get(ctx, nil) if err != nil { - return nil, errors.Wrap(err, support.ConnectorStackErrorTrace(err)) + return nil, err } for _, cont := range resp.GetValue() { @@ -367,7 +365,7 @@ func fetchColumnLinks( for { resp, err := builder.Get(ctx, nil) if err != nil { - return nil, clues.Wrap(err, "getting column links").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "getting column links") } links = append(links, resp.GetValue()...) @@ -394,7 +392,7 @@ func DeleteList( ) error { err := gs.Client().SitesById(siteID).ListsById(listID).Delete(ctx, nil) if err != nil { - return clues.Wrap(err, "deleting list").WithClues(ctx).With(graph.ErrData(err)...) + return graph.Wrap(ctx, err, "deleting list") } return nil diff --git a/src/internal/connector/sharepoint/queries.go b/src/internal/connector/sharepoint/queries.go index 236f90085..4f9010ae5 100644 --- a/src/internal/connector/sharepoint/queries.go +++ b/src/internal/connector/sharepoint/queries.go @@ -6,7 +6,6 @@ import ( absser "github.com/microsoft/kiota-abstractions-go/serialization" mssite "github.com/microsoftgraph/msgraph-sdk-go/sites" - "github.com/alcionai/clues" "github.com/alcionai/corso/src/internal/connector/graph" ) @@ -22,7 +21,7 @@ func GetAllSitesForTenant(ctx context.Context, gs graph.Servicer) (absser.Parsab sites, err := gs.Client().Sites().Get(ctx, options) if err != nil { - return nil, clues.Wrap(err, "getting sites").WithClues(ctx).With(graph.ErrData(err)...) + return nil, graph.Wrap(ctx, err, "getting sites") } return sites, nil diff --git a/src/internal/connector/sharepoint/restore.go b/src/internal/connector/sharepoint/restore.go index 0c77bde18..fa8a7e269 100644 --- a/src/internal/connector/sharepoint/restore.go +++ b/src/internal/connector/sharepoint/restore.go @@ -126,7 +126,7 @@ func createRestoreFolders( // Get Main Drive for Site, Documents mainDrive, err := service.Client().SitesById(siteID).Drive().Get(ctx, nil) if err != nil { - return "", clues.Wrap(err, "getting site drive root").WithClues(ctx).With(graph.ErrData(err)...) + return "", graph.Wrap(ctx, err, "getting site drive root") } return onedrive.CreateRestoreFolders(ctx, service, *mainDrive.GetId(), restoreFolders) @@ -182,7 +182,7 @@ func restoreListItem( // Restore to List base to M365 back store restoredList, err := service.Client().SitesById(siteID).Lists().Post(ctx, newList, nil) if err != nil { - return dii, clues.Wrap(err, "restoring list").WithClues(ctx).With(graph.ErrData(err)...) + return dii, graph.Wrap(ctx, err, "restoring list") } // Uploading of ListItems is conducted after the List is restored @@ -195,10 +195,8 @@ func restoreListItem( Items(). Post(ctx, lItem, nil) if err != nil { - return dii, clues.Wrap(err, "restoring list items"). - With("restored_list_id", ptr.Val(restoredList.GetId())). - WithClues(ctx). - With(graph.ErrData(err)...) + return dii, graph.Wrap(ctx, err, "restoring list items"). + With("restored_list_id", ptr.Val(restoredList.GetId())) } } } diff --git a/src/internal/connector/support/errors.go b/src/internal/connector/support/errors.go deleted file mode 100644 index 26c2e9aca..000000000 --- a/src/internal/connector/support/errors.go +++ /dev/null @@ -1,130 +0,0 @@ -package support - -import ( - "fmt" - "strconv" - "strings" - - multierror "github.com/hashicorp/go-multierror" - msgraph_errors "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" - "github.com/pkg/errors" -) - -// WrapErrorAndAppend helper function used to attach identifying information to an error -// and return it as a mulitierror -func WrapAndAppend(identifier string, e, previous error) error { - return multierror.Append(previous, errors.Wrap(e, identifier)) -} - -// WrapErrorAndAppendf format version of WrapErrorAndAppend -func WrapAndAppendf(identifier interface{}, e, previous error) error { - return multierror.Append(previous, errors.Wrapf(e, "%v", identifier)) -} - -// GetErrors Helper method to return the integer amount of errors in multi error -func GetNumberOfErrors(err error) int { - if err == nil { - return 0 - } - - result, _, wasFound := strings.Cut(err.Error(), " ") - if wasFound { - aNum, err := strconv.Atoi(result) - if err == nil { - return aNum - } - } - - return 1 -} - -// ListErrors is a helper method used to return the string of errors when -// the multiError library is used. -// depends on ConnectorStackErrorTrace -func ListErrors(multi multierror.Error) string { - aString := "" - - for idx, err := range multi.Errors { - detail := ConnectorStackErrorTrace(err) - if detail == "" { - detail = fmt.Sprintf("%v", err) - } - - aString = aString + fmt.Sprintf("\n\tErr: %d %v", idx+1, detail) - } - - return aString -} - -// concatenateStringFromPointers is a helper function that adds -// strings to the originalMessage iff the pointer is not nil -func concatenateStringFromPointers(orig string, pointers []*string) string { - for _, pointer := range pointers { - if pointer != nil { - orig = strings.Join([]string{orig, *pointer}, " ") - } - } - - return orig -} - -// ConnectorStackErrorTraceWrap is a helper function that wraps the -// stack trace for oDataErrors (if the error has one) onto the prefix. -// If no stack trace is found, wraps the error with only the prefix. -func ConnectorStackErrorTraceWrap(e error, prefix string) error { - cset := ConnectorStackErrorTrace(e) - if len(cset) > 0 { - return errors.Wrap(e, prefix+": "+cset) - } - - return errors.Wrap(e, prefix) -} - -// ConnectorStackErrorTrace is a helper function that extracts -// the stack trace for oDataErrors, if the error has one. -func ConnectorStackErrorTrace(e error) string { - eMessage := "" - - if oDataError, ok := e.(msgraph_errors.ODataErrorable); ok { - // Get MainError - mainErr := oDataError.GetError() - // message *string - // target *string - // code *string - // details ErrorDetailsable - // Ignoring Additional Detail - code := mainErr.GetCode() - subject := mainErr.GetMessage() - target := mainErr.GetTarget() - details := mainErr.GetDetails() - inners := mainErr.GetInnererror() - eMessage = concatenateStringFromPointers(eMessage, - []*string{code, subject, target}) - - // Get Error Details - // code, message, target - if details != nil { - eMessage = eMessage + "\nDetails Section:" - - for idx, detail := range details { - dMessage := fmt.Sprintf("Detail %d:", idx) - c := detail.GetCode() - m := detail.GetMessage() - t := detail.GetTarget() - dMessage = concatenateStringFromPointers(dMessage, - []*string{c, m, t}) - eMessage = eMessage + dMessage - } - } - - if inners != nil { - eMessage = eMessage + "\nConnector Section:" - client := inners.GetClientRequestId() - rID := inners.GetRequestId() - eMessage = concatenateStringFromPointers(eMessage, - []*string{client, rID}) - } - } - - return eMessage -} diff --git a/src/internal/connector/support/errors_test.go b/src/internal/connector/support/errors_test.go deleted file mode 100644 index 4df8cac0b..000000000 --- a/src/internal/connector/support/errors_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package support - -import ( - "errors" - "fmt" - "strings" - "testing" - - multierror "github.com/hashicorp/go-multierror" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/suite" - - "github.com/alcionai/corso/src/internal/tester" -) - -type GraphConnectorErrorSuite struct { - tester.Suite -} - -func TestGraphConnectorErrorSuite(t *testing.T) { - suite.Run(t, &GraphConnectorErrorSuite{Suite: tester.NewUnitSuite(t)}) -} - -func (suite *GraphConnectorErrorSuite) TestWrapAndAppend() { - t := suite.T() - - err1 := fmt.Errorf("New Error") - err2 := errors.New("I have two") - returnErr := WrapAndAppend("arc376", err2, err1) - assert.True(t, strings.Contains(returnErr.Error(), "arc376")) - assert.Error(t, returnErr) - - multi := &multierror.Error{Errors: []error{err1, err2}} - assert.True(t, strings.Contains(ListErrors(*multi), "two")) // Does not contain the wrapped information - t.Log(ListErrors(*multi)) -} - -func (suite *GraphConnectorErrorSuite) TestWrapAndAppend_OnVar() { - var ( - err1 error - id = "xi2058" - ) - - received := WrapAndAppend(id, errors.New("network error"), err1) - assert.True(suite.T(), strings.Contains(received.Error(), id)) -} - -func (suite *GraphConnectorErrorSuite) TestWrapAndAppend_Add3() { - t := suite.T() - - errOneTwo := WrapAndAppend("user1", assert.AnError, assert.AnError) - combined := WrapAndAppend("unix36", assert.AnError, errOneTwo) - allErrors := WrapAndAppend("fxi92874", assert.AnError, combined) - assert.True(t, strings.Contains(combined.Error(), "unix36")) - assert.True(t, strings.Contains(combined.Error(), "user1")) - assert.True(t, strings.Contains(allErrors.Error(), "fxi92874")) -} - -func (suite *GraphConnectorErrorSuite) TestWrapAndAppendf() { - err1 := assert.AnError - err2 := assert.AnError - combined := WrapAndAppendf(134323, err2, err1) - assert.True(suite.T(), strings.Contains(combined.Error(), "134323")) -} - -func (suite *GraphConnectorErrorSuite) TestConcatenateStringFromPointers() { - var ( - outString string - v1 = "Corso" - v3 = "remains" - s1 = &v1 - s2 *string - s3 = &v3 - t = suite.T() - ) - - outString = concatenateStringFromPointers(outString, []*string{s1, s2, s3}) - assert.True(t, strings.Contains(outString, v1)) - assert.True(t, strings.Contains(outString, v3)) -} - -func (suite *GraphConnectorErrorSuite) TestGetNumberOfErrors() { - table := []struct { - name string - errs error - expected int - }{ - { - name: "No error", - errs: nil, - expected: 0, - }, - { - name: "Not an ErrorList", - errs: errors.New("network error"), - expected: 1, - }, - { - name: "Three Errors", - errs: WrapAndAppend("tres", errors.New("three"), WrapAndAppend("arc376", errors.New("one"), errors.New("two"))), - expected: 3, - }, - } - for _, test := range table { - suite.Run(test.name, func() { - result := GetNumberOfErrors(test.errs) - assert.Equal(suite.T(), result, test.expected) - }) - } -} diff --git a/src/internal/operations/backup_integration_test.go b/src/internal/operations/backup_integration_test.go index 3c3d3e84c..411649e1f 100644 --- a/src/internal/operations/backup_integration_test.go +++ b/src/internal/operations/backup_integration_test.go @@ -1006,7 +1006,7 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_exchangeIncrementals() { require.NotEmpty(t, ids, "message ids in folder") err = cli.MessagesById(ids[0]).Delete(ctx, nil) - require.NoError(t, err, "deleting email item: %s", support.ConnectorStackErrorTrace(err)) + require.NoError(t, err, "deleting email item") case path.ContactsCategory: ids, _, _, err := ac.Contacts().GetAddedAndRemovedItemIDs(ctx, suite.user, containerID, "") @@ -1014,7 +1014,7 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_exchangeIncrementals() { require.NotEmpty(t, ids, "contact ids in folder") err = cli.ContactsById(ids[0]).Delete(ctx, nil) - require.NoError(t, err, "deleting contact item: %s", support.ConnectorStackErrorTrace(err)) + require.NoError(t, err, "deleting contact item") case path.EventsCategory: ids, _, _, err := ac.Events().GetAddedAndRemovedItemIDs(ctx, suite.user, containerID, "") @@ -1022,7 +1022,7 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_exchangeIncrementals() { require.NotEmpty(t, ids, "event ids in folder") err = cli.CalendarsById(ids[0]).Delete(ctx, nil) - require.NoError(t, err, "deleting calendar: %s", support.ConnectorStackErrorTrace(err)) + require.NoError(t, err, "deleting calendar") } } }, diff --git a/src/pkg/backup/backup.go b/src/pkg/backup/backup.go index ae61a8e24..61a8344c2 100644 --- a/src/pkg/backup/backup.go +++ b/src/pkg/backup/backup.go @@ -7,7 +7,6 @@ import ( "github.com/alcionai/corso/src/cli/print" "github.com/alcionai/corso/src/internal/common" - "github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/internal/model" "github.com/alcionai/corso/src/internal/stats" "github.com/alcionai/corso/src/internal/version" @@ -158,23 +157,13 @@ func (b Backup) Values() []string { } func (b Backup) countErrors() int { - errCount := b.ErrorCount - if errCount > 0 { - return errCount + if b.ErrorCount > 0 { + return b.ErrorCount } - // current tracking - if b.ReadErrors != nil || b.WriteErrors != nil { - return support.GetNumberOfErrors(b.ReadErrors) + support.GetNumberOfErrors(b.WriteErrors) - } - - // future tracking - if b.Errors.Failure != nil || len(b.Errors.Recovered) > 0 { - if b.Errors.Failure != nil { - errCount++ - } - - errCount += len(b.Errors.Recovered) + errCount := len(b.Errors.Recovered) + if b.Errors.Failure != nil { + errCount++ } return errCount