Ignore permissions restore failure with a log (#4220)
<!-- 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: ---> - [ ] 🌻 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.--> - [x] 💪 Manual - [ ] ⚡ Unit test - [ ] 💚 E2E
This commit is contained in:
parent
f335f6de6f
commit
b9c8bcbd30
@ -12,7 +12,9 @@ import (
|
|||||||
"github.com/alcionai/corso/src/internal/common/ptr"
|
"github.com/alcionai/corso/src/internal/common/ptr"
|
||||||
"github.com/alcionai/corso/src/internal/data"
|
"github.com/alcionai/corso/src/internal/data"
|
||||||
"github.com/alcionai/corso/src/internal/m365/collection/drive/metadata"
|
"github.com/alcionai/corso/src/internal/m365/collection/drive/metadata"
|
||||||
|
"github.com/alcionai/corso/src/internal/m365/graph"
|
||||||
"github.com/alcionai/corso/src/internal/version"
|
"github.com/alcionai/corso/src/internal/version"
|
||||||
|
"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"
|
||||||
)
|
)
|
||||||
@ -193,7 +195,10 @@ func UpdatePermissions(
|
|||||||
itemID string,
|
itemID string,
|
||||||
permAdded, permRemoved []metadata.Permission,
|
permAdded, permRemoved []metadata.Permission,
|
||||||
oldPermIDToNewID *xsync.MapOf[string, string],
|
oldPermIDToNewID *xsync.MapOf[string, string],
|
||||||
|
errs *fault.Bus,
|
||||||
) error {
|
) error {
|
||||||
|
el := errs.Local()
|
||||||
|
|
||||||
// The ordering of the operations is important here. We first
|
// The ordering of the operations is important here. We first
|
||||||
// remove all the removed permissions and then add the added ones.
|
// remove all the removed permissions and then add the added ones.
|
||||||
for _, p := range permRemoved {
|
for _, p := range permRemoved {
|
||||||
@ -223,6 +228,10 @@ func UpdatePermissions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range permAdded {
|
for _, p := range permAdded {
|
||||||
|
if el.Failure() != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
ictx := clues.Add(
|
ictx := clues.Add(
|
||||||
ctx,
|
ctx,
|
||||||
"permission_entity_type", p.EntityType,
|
"permission_entity_type", p.EntityType,
|
||||||
@ -267,14 +276,20 @@ func UpdatePermissions(
|
|||||||
pbody.SetRecipients([]models.DriveRecipientable{rec})
|
pbody.SetRecipients([]models.DriveRecipientable{rec})
|
||||||
|
|
||||||
newPerm, err := udip.PostItemPermissionUpdate(ictx, driveID, itemID, pbody)
|
newPerm, err := udip.PostItemPermissionUpdate(ictx, driveID, itemID, pbody)
|
||||||
|
if graph.IsErrUsersCannotBeResolved(err) {
|
||||||
|
logger.CtxErr(ictx, err).Info("Unable to restore link share")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return clues.Stack(err)
|
el.AddRecoverable(ictx, clues.Stack(err))
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
oldPermIDToNewID.Store(p.ID, ptr.Val(newPerm.GetValue()[0].GetId()))
|
oldPermIDToNewID.Store(p.ID, ptr.Val(newPerm.GetValue()[0].GetId()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return el.Failure()
|
||||||
}
|
}
|
||||||
|
|
||||||
type updateDeleteItemLinkSharer interface {
|
type updateDeleteItemLinkSharer interface {
|
||||||
@ -289,14 +304,20 @@ func UpdateLinkShares(
|
|||||||
itemID string,
|
itemID string,
|
||||||
lsAdded, lsRemoved []metadata.LinkShare,
|
lsAdded, lsRemoved []metadata.LinkShare,
|
||||||
oldLinkShareIDToNewID *xsync.MapOf[string, string],
|
oldLinkShareIDToNewID *xsync.MapOf[string, string],
|
||||||
|
errs *fault.Bus,
|
||||||
) (bool, error) {
|
) (bool, error) {
|
||||||
// You can only delete inherited sharing links the first time you
|
// You can only delete inherited sharing links the first time you
|
||||||
// create a sharing link which is done using
|
// create a sharing link which is done using
|
||||||
// `retainInheritedPermissions`. We cannot separately delete any
|
// `retainInheritedPermissions`. We cannot separately delete any
|
||||||
// inherited link shares via DELETE API call like for permissions.
|
// inherited link shares via DELETE API call like for permissions.
|
||||||
alreadyDeleted := false
|
alreadyDeleted := false
|
||||||
|
el := errs.Local()
|
||||||
|
|
||||||
for _, ls := range lsAdded {
|
for _, ls := range lsAdded {
|
||||||
|
if el.Failure() != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
ictx := clues.Add(ctx, "link_share_id", ls.ID)
|
ictx := clues.Add(ctx, "link_share_id", ls.ID)
|
||||||
|
|
||||||
// Links with password are not shared with a specific user
|
// Links with password are not shared with a specific user
|
||||||
@ -363,13 +384,23 @@ func UpdateLinkShares(
|
|||||||
}
|
}
|
||||||
|
|
||||||
newLS, err := upils.PostItemLinkShareUpdate(ictx, driveID, itemID, lsbody)
|
newLS, err := upils.PostItemLinkShareUpdate(ictx, driveID, itemID, lsbody)
|
||||||
|
if graph.IsErrUsersCannotBeResolved(err) {
|
||||||
|
logger.CtxErr(ictx, err).Info("Unable to restore link share")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return alreadyDeleted, clues.Stack(err)
|
el.AddRecoverable(ctx, clues.Stack(err))
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
oldLinkShareIDToNewID.Store(ls.ID, ptr.Val(newLS.GetId()))
|
oldLinkShareIDToNewID.Store(ls.ID, ptr.Val(newLS.GetId()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if el.Failure() != nil {
|
||||||
|
return alreadyDeleted, el.Failure()
|
||||||
|
}
|
||||||
|
|
||||||
// It is possible to have empty link shares even though we should
|
// It is possible to have empty link shares even though we should
|
||||||
// have inherited one if the user creates a link using
|
// have inherited one if the user creates a link using
|
||||||
// `retainInheritedPermissions` as false, but then deleted it. We
|
// `retainInheritedPermissions` as false, but then deleted it. We
|
||||||
@ -411,6 +442,7 @@ func RestorePermissions(
|
|||||||
itemPath path.Path,
|
itemPath path.Path,
|
||||||
current metadata.Metadata,
|
current metadata.Metadata,
|
||||||
caches *restoreCaches,
|
caches *restoreCaches,
|
||||||
|
errs *fault.Bus,
|
||||||
) error {
|
) error {
|
||||||
if current.SharingMode == metadata.SharingModeInherited {
|
if current.SharingMode == metadata.SharingModeInherited {
|
||||||
return nil
|
return nil
|
||||||
@ -435,7 +467,8 @@ func RestorePermissions(
|
|||||||
itemID,
|
itemID,
|
||||||
lsAdded,
|
lsAdded,
|
||||||
lsRemoved,
|
lsRemoved,
|
||||||
caches.OldLinkShareIDToNewID)
|
caches.OldLinkShareIDToNewID,
|
||||||
|
errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return clues.Wrap(err, "updating link shares")
|
return clues.Wrap(err, "updating link shares")
|
||||||
}
|
}
|
||||||
@ -464,7 +497,8 @@ func RestorePermissions(
|
|||||||
itemID,
|
itemID,
|
||||||
permAdded,
|
permAdded,
|
||||||
permRemoved,
|
permRemoved,
|
||||||
caches.OldPermIDToNewID)
|
caches.OldPermIDToNewID,
|
||||||
|
errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return clues.Wrap(err, "updating permissions")
|
return clues.Wrap(err, "updating permissions")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -130,7 +130,8 @@ func RestoreCollection(
|
|||||||
dc.FullPath(),
|
dc.FullPath(),
|
||||||
colMeta,
|
colMeta,
|
||||||
caches,
|
caches,
|
||||||
rcc.RestoreConfig.IncludePermissions)
|
rcc.RestoreConfig.IncludePermissions,
|
||||||
|
errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return metrics, clues.Wrap(err, "creating folders for restore")
|
return metrics, clues.Wrap(err, "creating folders for restore")
|
||||||
}
|
}
|
||||||
@ -211,7 +212,8 @@ func RestoreCollection(
|
|||||||
caches,
|
caches,
|
||||||
itemData,
|
itemData,
|
||||||
itemPath,
|
itemPath,
|
||||||
ctr)
|
ctr,
|
||||||
|
errs)
|
||||||
|
|
||||||
// skipped items don't get counted, but they can error
|
// skipped items don't get counted, but they can error
|
||||||
if !skipped {
|
if !skipped {
|
||||||
@ -260,6 +262,7 @@ func restoreItem(
|
|||||||
itemData data.Item,
|
itemData data.Item,
|
||||||
itemPath path.Path,
|
itemPath path.Path,
|
||||||
ctr *count.Bus,
|
ctr *count.Bus,
|
||||||
|
errs *fault.Bus,
|
||||||
) (details.ItemInfo, bool, error) {
|
) (details.ItemInfo, bool, error) {
|
||||||
itemUUID := itemData.ID()
|
itemUUID := itemData.ID()
|
||||||
ctx = clues.Add(ctx, "item_id", itemUUID)
|
ctx = clues.Add(ctx, "item_id", itemUUID)
|
||||||
@ -332,7 +335,8 @@ func restoreItem(
|
|||||||
caches,
|
caches,
|
||||||
itemPath,
|
itemPath,
|
||||||
itemData,
|
itemData,
|
||||||
ctr)
|
ctr,
|
||||||
|
errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, graph.ErrItemAlreadyExistsConflict) && rcc.RestoreConfig.OnCollision == control.Skip {
|
if errors.Is(err, graph.ErrItemAlreadyExistsConflict) && rcc.RestoreConfig.OnCollision == control.Skip {
|
||||||
return details.ItemInfo{}, true, nil
|
return details.ItemInfo{}, true, nil
|
||||||
@ -357,7 +361,8 @@ func restoreItem(
|
|||||||
caches,
|
caches,
|
||||||
itemPath,
|
itemPath,
|
||||||
itemData,
|
itemData,
|
||||||
ctr)
|
ctr,
|
||||||
|
errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, graph.ErrItemAlreadyExistsConflict) && rcc.RestoreConfig.OnCollision == control.Skip {
|
if errors.Is(err, graph.ErrItemAlreadyExistsConflict) && rcc.RestoreConfig.OnCollision == control.Skip {
|
||||||
return details.ItemInfo{}, true, nil
|
return details.ItemInfo{}, true, nil
|
||||||
@ -412,6 +417,7 @@ func restoreV1File(
|
|||||||
itemPath path.Path,
|
itemPath path.Path,
|
||||||
itemData data.Item,
|
itemData data.Item,
|
||||||
ctr *count.Bus,
|
ctr *count.Bus,
|
||||||
|
errs *fault.Bus,
|
||||||
) (details.ItemInfo, error) {
|
) (details.ItemInfo, error) {
|
||||||
trimmedName := strings.TrimSuffix(itemData.ID(), metadata.DataFileSuffix)
|
trimmedName := strings.TrimSuffix(itemData.ID(), metadata.DataFileSuffix)
|
||||||
|
|
||||||
@ -452,7 +458,8 @@ func restoreV1File(
|
|||||||
itemID,
|
itemID,
|
||||||
itemPath,
|
itemPath,
|
||||||
meta,
|
meta,
|
||||||
caches)
|
caches,
|
||||||
|
errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return details.ItemInfo{}, clues.Wrap(err, "restoring item permissions")
|
return details.ItemInfo{}, clues.Wrap(err, "restoring item permissions")
|
||||||
}
|
}
|
||||||
@ -472,6 +479,7 @@ func restoreV6File(
|
|||||||
itemPath path.Path,
|
itemPath path.Path,
|
||||||
itemData data.Item,
|
itemData data.Item,
|
||||||
ctr *count.Bus,
|
ctr *count.Bus,
|
||||||
|
errs *fault.Bus,
|
||||||
) (details.ItemInfo, error) {
|
) (details.ItemInfo, error) {
|
||||||
trimmedName := strings.TrimSuffix(itemData.ID(), metadata.DataFileSuffix)
|
trimmedName := strings.TrimSuffix(itemData.ID(), metadata.DataFileSuffix)
|
||||||
|
|
||||||
@ -528,7 +536,8 @@ func restoreV6File(
|
|||||||
itemID,
|
itemID,
|
||||||
itemPath,
|
itemPath,
|
||||||
meta,
|
meta,
|
||||||
caches)
|
caches,
|
||||||
|
errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return details.ItemInfo{}, clues.Wrap(err, "restoring item permissions")
|
return details.ItemInfo{}, clues.Wrap(err, "restoring item permissions")
|
||||||
}
|
}
|
||||||
@ -550,6 +559,7 @@ func CreateRestoreFolders(
|
|||||||
folderMetadata metadata.Metadata,
|
folderMetadata metadata.Metadata,
|
||||||
caches *restoreCaches,
|
caches *restoreCaches,
|
||||||
restorePerms bool,
|
restorePerms bool,
|
||||||
|
errs *fault.Bus,
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
id, err := createRestoreFolders(
|
id, err := createRestoreFolders(
|
||||||
ctx,
|
ctx,
|
||||||
@ -577,7 +587,8 @@ func CreateRestoreFolders(
|
|||||||
id,
|
id,
|
||||||
folderPath,
|
folderPath,
|
||||||
folderMetadata,
|
folderMetadata,
|
||||||
caches)
|
caches,
|
||||||
|
errs)
|
||||||
|
|
||||||
return id, err
|
return id, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/alcionai/corso/src/internal/version"
|
"github.com/alcionai/corso/src/internal/version"
|
||||||
"github.com/alcionai/corso/src/pkg/control"
|
"github.com/alcionai/corso/src/pkg/control"
|
||||||
"github.com/alcionai/corso/src/pkg/count"
|
"github.com/alcionai/corso/src/pkg/count"
|
||||||
|
"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/services/m365/api"
|
"github.com/alcionai/corso/src/pkg/services/m365/api"
|
||||||
apiMock "github.com/alcionai/corso/src/pkg/services/m365/api/mock"
|
apiMock "github.com/alcionai/corso/src/pkg/services/m365/api/mock"
|
||||||
@ -246,7 +247,8 @@ func (suite *RestoreUnitSuite) TestRestoreItem_collisionHandling() {
|
|||||||
ItemInfo: odStub.DriveItemInfo(),
|
ItemInfo: odStub.DriveItemInfo(),
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
ctr)
|
ctr,
|
||||||
|
fault.New(true))
|
||||||
|
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
test.expectSkipped(t, skip)
|
test.expectSkipped(t, skip)
|
||||||
|
|||||||
@ -49,6 +49,7 @@ const (
|
|||||||
// nameAlreadyExists occurs when a request with
|
// nameAlreadyExists occurs when a request with
|
||||||
// @microsoft.graph.conflictBehavior=fail finds a conflicting file.
|
// @microsoft.graph.conflictBehavior=fail finds a conflicting file.
|
||||||
nameAlreadyExists errorCode = "nameAlreadyExists"
|
nameAlreadyExists errorCode = "nameAlreadyExists"
|
||||||
|
noResolvedUsers errorCode = "noResolvedUsers"
|
||||||
QuotaExceeded errorCode = "ErrorQuotaExceeded"
|
QuotaExceeded errorCode = "ErrorQuotaExceeded"
|
||||||
RequestResourceNotFound errorCode = "Request_ResourceNotFound"
|
RequestResourceNotFound errorCode = "Request_ResourceNotFound"
|
||||||
// Returned when we try to get the inbox of a user that doesn't exist.
|
// Returned when we try to get the inbox of a user that doesn't exist.
|
||||||
@ -66,6 +67,7 @@ const (
|
|||||||
MysiteURLNotFound errorMessage = "unable to retrieve user's mysite url"
|
MysiteURLNotFound errorMessage = "unable to retrieve user's mysite url"
|
||||||
MysiteNotFound errorMessage = "user's mysite not found"
|
MysiteNotFound errorMessage = "user's mysite not found"
|
||||||
NoSPLicense errorMessage = "Tenant does not have a SPO license"
|
NoSPLicense errorMessage = "Tenant does not have a SPO license"
|
||||||
|
usersCannotBeResolved errorMessage = "One or more users could not be resolved"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -225,6 +227,10 @@ func IsErrFolderExists(err error) bool {
|
|||||||
return hasErrorCode(err, folderExists)
|
return hasErrorCode(err, folderExists)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsErrUsersCannotBeResolved(err error) bool {
|
||||||
|
return hasErrorCode(err, noResolvedUsers) || hasErrorMessage(err, usersCannotBeResolved)
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// error parsers
|
// error parsers
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@ -252,6 +258,30 @@ func hasErrorCode(err error, codes ...errorCode) bool {
|
|||||||
return filters.Equal(cs).Compare(code)
|
return filters.Equal(cs).Compare(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only use this as a last resort. Prefer the code or statuscode if possible.
|
||||||
|
func hasErrorMessage(err error, msgs ...errorMessage) bool {
|
||||||
|
if err == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var oDataError odataerrors.ODataErrorable
|
||||||
|
if !errors.As(err, &oDataError) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, ok := ptr.ValOK(oDataError.GetErrorEscaped().GetMessage())
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
cs := make([]string, len(msgs))
|
||||||
|
for i, c := range msgs {
|
||||||
|
cs[i] = string(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return filters.Equal(cs).Compare(msg)
|
||||||
|
}
|
||||||
|
|
||||||
// Wrap is a helper function that extracts ODataError metadata from
|
// Wrap is a helper function that extracts ODataError metadata from
|
||||||
// the error. If the error is not an ODataError type, returns the error.
|
// the error. If the error is not an ODataError type, returns the error.
|
||||||
func Wrap(ctx context.Context, e error, msg string) *clues.Err {
|
func Wrap(ctx context.Context, e error, msg string) *clues.Err {
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -466,7 +467,7 @@ func (suite *GraphErrorsUnitSuite) TestIsErrFolderExists() {
|
|||||||
expect: assert.False,
|
expect: assert.False,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "matching oDataErr",
|
name: "matching oDataErr msg",
|
||||||
err: odErr(string(folderExists)),
|
err: odErr(string(folderExists)),
|
||||||
expect: assert.True,
|
expect: assert.True,
|
||||||
},
|
},
|
||||||
@ -489,6 +490,56 @@ func (suite *GraphErrorsUnitSuite) TestIsErrFolderExists() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *GraphErrorsUnitSuite) TestIsErrUsersCannotBeResolved() {
|
||||||
|
table := []struct {
|
||||||
|
name string
|
||||||
|
err error
|
||||||
|
expect assert.BoolAssertionFunc
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "nil",
|
||||||
|
err: nil,
|
||||||
|
expect: assert.False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-matching",
|
||||||
|
err: assert.AnError,
|
||||||
|
expect: assert.False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-matching oDataErr",
|
||||||
|
err: odErrMsg("InvalidRequest", "cant resolve users"),
|
||||||
|
expect: assert.False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "matching oDataErr code",
|
||||||
|
err: odErrMsg(string(noResolvedUsers), "usersCannotBeResolved"),
|
||||||
|
expect: assert.True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "matching oDataErr msg",
|
||||||
|
err: odErrMsg("InvalidRequest", string(usersCannotBeResolved)),
|
||||||
|
expect: assert.True,
|
||||||
|
},
|
||||||
|
// next two tests are to make sure the checks are case insensitive
|
||||||
|
{
|
||||||
|
name: "oDataErr uppercase",
|
||||||
|
err: odErrMsg("InvalidRequest", strings.ToUpper(string(usersCannotBeResolved))),
|
||||||
|
expect: assert.True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "oDataErr lowercase",
|
||||||
|
err: odErrMsg("InvalidRequest", strings.ToLower(string(usersCannotBeResolved))),
|
||||||
|
expect: assert.True,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range table {
|
||||||
|
suite.Run(test.name, func() {
|
||||||
|
test.expect(suite.T(), IsErrUsersCannotBeResolved(test.err))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (suite *GraphErrorsUnitSuite) TestIsErrCannotOpenFileAttachment() {
|
func (suite *GraphErrorsUnitSuite) TestIsErrCannotOpenFileAttachment() {
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
@ -393,7 +393,8 @@ func runDriveIncrementalTest(
|
|||||||
ptr.Val(newFile.GetId()),
|
ptr.Val(newFile.GetId()),
|
||||||
[]metadata.Permission{writePerm},
|
[]metadata.Permission{writePerm},
|
||||||
[]metadata.Permission{},
|
[]metadata.Permission{},
|
||||||
permissionIDMappings)
|
permissionIDMappings,
|
||||||
|
fault.New(true))
|
||||||
require.NoErrorf(t, err, "adding permission to file %v", clues.ToCore(err))
|
require.NoErrorf(t, err, "adding permission to file %v", clues.ToCore(err))
|
||||||
// no expectedDeets: metadata isn't tracked
|
// no expectedDeets: metadata isn't tracked
|
||||||
},
|
},
|
||||||
@ -411,7 +412,8 @@ func runDriveIncrementalTest(
|
|||||||
*newFile.GetId(),
|
*newFile.GetId(),
|
||||||
[]metadata.Permission{},
|
[]metadata.Permission{},
|
||||||
[]metadata.Permission{writePerm},
|
[]metadata.Permission{writePerm},
|
||||||
permissionIDMappings)
|
permissionIDMappings,
|
||||||
|
fault.New(true))
|
||||||
require.NoErrorf(t, err, "removing permission from file %v", clues.ToCore(err))
|
require.NoErrorf(t, err, "removing permission from file %v", clues.ToCore(err))
|
||||||
// no expectedDeets: metadata isn't tracked
|
// no expectedDeets: metadata isn't tracked
|
||||||
},
|
},
|
||||||
@ -430,7 +432,8 @@ func runDriveIncrementalTest(
|
|||||||
targetContainer,
|
targetContainer,
|
||||||
[]metadata.Permission{writePerm},
|
[]metadata.Permission{writePerm},
|
||||||
[]metadata.Permission{},
|
[]metadata.Permission{},
|
||||||
permissionIDMappings)
|
permissionIDMappings,
|
||||||
|
fault.New(true))
|
||||||
require.NoErrorf(t, err, "adding permission to container %v", clues.ToCore(err))
|
require.NoErrorf(t, err, "adding permission to container %v", clues.ToCore(err))
|
||||||
// no expectedDeets: metadata isn't tracked
|
// no expectedDeets: metadata isn't tracked
|
||||||
},
|
},
|
||||||
@ -449,7 +452,8 @@ func runDriveIncrementalTest(
|
|||||||
targetContainer,
|
targetContainer,
|
||||||
[]metadata.Permission{},
|
[]metadata.Permission{},
|
||||||
[]metadata.Permission{writePerm},
|
[]metadata.Permission{writePerm},
|
||||||
permissionIDMappings)
|
permissionIDMappings,
|
||||||
|
fault.New(true))
|
||||||
require.NoErrorf(t, err, "removing permission from container %v", clues.ToCore(err))
|
require.NoErrorf(t, err, "removing permission from container %v", clues.ToCore(err))
|
||||||
// no expectedDeets: metadata isn't tracked
|
// no expectedDeets: metadata isn't tracked
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user