add iteminfo to restore details (#1041)

## Description

Extends the restore details with itemInfo from restored items.

## Type of change

- [x] 🌻 Feature

## Issue(s)

* #977

## Test Plan

- [x] 💪 Manual
- [x] 💚 E2E
This commit is contained in:
Keepers 2022-10-05 15:19:21 -06:00 committed by GitHub
parent 010d8d5df1
commit f4556288a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 96 additions and 65 deletions

View File

@ -373,15 +373,24 @@ func (suite *ExchangeServiceSuite) TestGetContainerID() {
// is able to restore a several messageable item to a Mailbox.
// The result should be all successful items restored within the same folder.
func (suite *ExchangeServiceSuite) TestRestoreMessages() {
ctx := context.Background()
userID := tester.M365UserID(suite.T())
now := time.Now()
var (
ctx = context.Background()
userID = tester.M365UserID(suite.T())
now = time.Now()
folderName = "TestRestoreMessage: " + common.FormatSimpleDateTime(now)
)
folderName := "TestRestoreMessage: " + common.FormatSimpleDateTime(now)
folder, err := CreateMailFolder(ctx, suite.es, userID, folderName)
require.NoError(suite.T(), err)
folderID := *folder.GetId()
defer func() {
// Remove the folder containing message prior to exiting test
err = DeleteMailFolder(ctx, suite.es, userID, folderID)
assert.NoError(suite.T(), err, "Failure during folder clean-up")
}()
tests := []struct {
name string
bytes []byte
@ -402,67 +411,80 @@ func (suite *ExchangeServiceSuite) TestRestoreMessages() {
for _, test := range tests {
suite.T().Run(test.name, func(t *testing.T) {
err = RestoreMailMessage(context.Background(),
info, err := RestoreMailMessage(context.Background(),
test.bytes,
suite.es,
control.Copy,
folderID,
userID,
)
require.NoError(t, err, support.ConnectorStackErrorTrace(err))
assert.NoError(t, err, support.ConnectorStackErrorTrace(err))
assert.NotNil(t, info, "message item info")
})
}
err = DeleteMailFolder(ctx, suite.es, userID, folderID)
assert.NoError(suite.T(), err, "Failure during folder clean-up")
}
// TestRestoreContact ensures contact object can be created, placed into
// the Corso Folder. The function handles test clean-up.
func (suite *ExchangeServiceSuite) TestRestoreContact() {
t := suite.T()
ctx := context.Background()
userID := tester.M365UserID(t)
now := time.Now()
var (
t = suite.T()
ctx = context.Background()
userID = tester.M365UserID(t)
now = time.Now()
folderName = "TestRestoreContact: " + common.FormatSimpleDateTime(now)
)
folderName := "TestRestoreContact: " + common.FormatSimpleDateTime(now)
aFolder, err := CreateContactFolder(ctx, suite.es, userID, folderName)
require.NoError(t, err)
folderID := *aFolder.GetId()
err = RestoreExchangeContact(context.Background(),
defer func() {
// Remove the folder containing contact prior to exiting test
err = DeleteContactFolder(ctx, suite.es, userID, folderID)
assert.NoError(t, err)
}()
info, err := RestoreExchangeContact(context.Background(),
mockconnector.GetMockContactBytes("Corso TestContact"),
suite.es,
control.Copy,
folderID,
userID)
assert.NoError(t, err)
// Removes folder containing contact prior to exiting test
err = DeleteContactFolder(ctx, suite.es, userID, folderID)
assert.NoError(t, err)
assert.NoError(t, err, support.ConnectorStackErrorTrace(err))
assert.NotNil(t, info, "contact item info")
}
// TestRestoreEvent verifies that event object is able to created
// and sent into the test account of the Corso user in the newly created Corso Calendar
func (suite *ExchangeServiceSuite) TestRestoreEvent() {
t := suite.T()
ctx := context.Background()
userID := tester.M365UserID(t)
name := "TestRestoreEvent: " + common.FormatSimpleDateTime(time.Now())
var (
t = suite.T()
ctx = context.Background()
userID = tester.M365UserID(t)
name = "TestRestoreEvent: " + common.FormatSimpleDateTime(time.Now())
)
calendar, err := CreateCalendar(ctx, suite.es, userID, name)
require.NoError(t, err)
calendarID := *calendar.GetId()
err = RestoreExchangeEvent(context.Background(),
defer func() {
// Removes calendar containing events created during the test
err = DeleteCalendar(ctx, suite.es, userID, calendarID)
assert.NoError(t, err)
}()
info, err := RestoreExchangeEvent(context.Background(),
mockconnector.GetMockEventWithAttendeesBytes(name),
suite.es,
control.Copy,
calendarID,
userID)
assert.NoError(t, err)
// Removes calendar containing events created during the test
err = DeleteCalendar(ctx, suite.es, userID, *calendar.GetId())
assert.NoError(t, err)
assert.NoError(t, err, support.ConnectorStackErrorTrace(err))
assert.NotNil(t, info, "event item info")
}
// TestGetRestoreContainer checks the ability to Create a "container" for the
@ -585,7 +607,7 @@ func (suite *ExchangeServiceSuite) TestRestoreExchangeObject() {
for _, test := range tests {
suite.T().Run(test.name, func(t *testing.T) {
destination := test.destination()
err := RestoreExchangeObject(
info, err := RestoreExchangeObject(
ctx,
test.bytes,
test.category,
@ -594,7 +616,9 @@ func (suite *ExchangeServiceSuite) TestRestoreExchangeObject() {
destination,
userID,
)
assert.NoError(t, err)
assert.NoError(t, err, support.ConnectorStackErrorTrace(err))
assert.NotNil(t, info, "item info is populated")
cleanupError := test.cleanupFunc(ctx, service, userID, destination)
assert.NoError(t, cleanupError)
})

View File

@ -78,9 +78,9 @@ func RestoreExchangeObject(
policy control.CollisionPolicy,
service graph.Service,
destination, user string,
) error {
) (*details.ExchangeInfo, error) {
if policy != control.Copy {
return fmt.Errorf("restore policy: %s not supported for RestoreExchangeObject", policy)
return nil, fmt.Errorf("restore policy: %s not supported for RestoreExchangeObject", policy)
}
setting := categoryToOptionIdentifier(category)
@ -93,7 +93,7 @@ func RestoreExchangeObject(
case events:
return RestoreExchangeEvent(ctx, bits, service, control.Copy, destination, user)
default:
return fmt.Errorf("type: %s not supported for RestoreExchangeObject", category)
return nil, fmt.Errorf("type: %s not supported for RestoreExchangeObject", category)
}
}
@ -109,17 +109,17 @@ func RestoreExchangeContact(
service graph.Service,
cp control.CollisionPolicy,
destination, user string,
) error {
) (*details.ExchangeInfo, error) {
contact, err := support.CreateContactFromBytes(bits)
if err != nil {
return errors.Wrap(err, "failure to create contact from bytes: RestoreExchangeContact")
return nil, errors.Wrap(err, "failure to create contact from bytes: RestoreExchangeContact")
}
response, err := service.Client().UsersById(user).ContactFoldersById(destination).Contacts().Post(ctx, contact, nil)
if err != nil {
name := *contact.GetGivenName()
return errors.Wrap(
return nil, errors.Wrap(
err,
"failure to create Contact during RestoreExchangeContact: "+name+" "+
support.ConnectorStackErrorTrace(err),
@ -127,10 +127,10 @@ func RestoreExchangeContact(
}
if response == nil {
return errors.New("msgraph contact post fail: REST response not received")
return nil, errors.New("msgraph contact post fail: REST response not received")
}
return nil
return ContactInfo(contact), nil
}
// RestoreExchangeEvent restores a contact to the @bits byte
@ -145,17 +145,17 @@ func RestoreExchangeEvent(
service graph.Service,
cp control.CollisionPolicy,
destination, user string,
) error {
) (*details.ExchangeInfo, error) {
event, err := support.CreateEventFromBytes(bits)
if err != nil {
return err
return nil, err
}
transformedEvent := support.ToEventSimplified(event)
response, err := service.Client().UsersById(user).CalendarsById(destination).Events().Post(ctx, transformedEvent, nil)
if err != nil {
return errors.Wrap(err,
return nil, errors.Wrap(err,
fmt.Sprintf(
"failure to event creation failure during RestoreExchangeEvent: %s",
support.ConnectorStackErrorTrace(err)),
@ -163,10 +163,10 @@ func RestoreExchangeEvent(
}
if response == nil {
return errors.New("msgraph event post fail: REST response not received")
return nil, errors.New("msgraph event post fail: REST response not received")
}
return nil
return EventInfo(event), nil
}
// RestoreMailMessage utility function to place an exchange.Mail
@ -182,11 +182,11 @@ func RestoreMailMessage(
cp control.CollisionPolicy,
destination,
user string,
) error {
) (*details.ExchangeInfo, error) {
// Creates messageable object from original bytes
originalMessage, err := support.CreateMessageFromBytes(bits)
if err != nil {
return err
return nil, err
}
// Sets fields from original message from storage
clone := support.ToMessage(originalMessage)
@ -223,7 +223,7 @@ func RestoreMailMessage(
"policy", cp)
fallthrough
case control.Copy:
return SendMailToBackStore(ctx, service, user, destination, clone)
return MessageInfo(clone), SendMailToBackStore(ctx, service, user, destination, clone)
}
}
@ -383,7 +383,7 @@ func restoreCollection(
byteArray := buf.Bytes()
err = RestoreExchangeObject(ctx, byteArray, category, policy, gs, folderID, user)
info, err := RestoreExchangeObject(ctx, byteArray, category, policy, gs, folderID, user)
if err != nil {
// More information to be here
errUpdater(
@ -406,7 +406,9 @@ func restoreCollection(
itemPath.String(),
itemPath.ShortRef(),
"",
details.ItemInfo{})
details.ItemInfo{
Exchange: info,
})
}
}
}

View File

@ -47,10 +47,6 @@ func TestGraphConnectorIntegrationSuite(t *testing.T) {
}
func (suite *GraphConnectorIntegrationSuite) SetupSuite() {
if err := tester.RunOnAny(tester.CorsoCITests); err != nil {
suite.T().Skip(err)
}
ctx := context.Background()
_, err := tester.GetRequiredEnvVars(tester.M365AcctCredEnvs...)
require.NoError(suite.T(), err)

View File

@ -9,6 +9,7 @@ import (
"time"
msup "github.com/microsoftgraph/msgraph-sdk-go/drives/item/items/item/createuploadsession"
"github.com/microsoftgraph/msgraph-sdk-go/models"
"github.com/pkg/errors"
"gopkg.in/resty.v1"
@ -56,13 +57,19 @@ func driveItemReader(
return nil, nil, errors.Wrapf(err, "failed to download file from %s", *downloadURL)
}
return driveItemInfo(item), resp.Body, nil
}
// driveItemInfo will populate a details.OneDriveInfo struct
// with properties from the drive item.
func driveItemInfo(di models.DriveItemable) *details.OneDriveInfo {
return &details.OneDriveInfo{
ItemType: details.OneDriveItem,
ItemName: *item.GetName(),
Created: *item.GetCreatedDateTime(),
Modified: *item.GetLastModifiedDateTime(),
Size: *item.GetSize(),
}, resp.Body, nil
ItemName: *di.GetName(),
Created: *di.GetCreatedDateTime(),
Modified: *di.GetLastModifiedDateTime(),
Size: *di.GetSize(),
}
}
// driveItemWriter is used to initialize and return an io.Writer to upload data for the specified item

View File

@ -142,7 +142,7 @@ func restoreCollection(
metrics.TotalBytes += int64(len(copyBuffer))
err := restoreItem(ctx,
itemInfo, err := restoreItem(ctx,
service,
itemData,
drivePath.driveID,
@ -165,7 +165,9 @@ func restoreCollection(
itemPath.String(),
itemPath.ShortRef(),
"",
details.ItemInfo{})
details.ItemInfo{
OneDrive: itemInfo,
})
metrics.Successes++
}
@ -224,7 +226,7 @@ func restoreItem(
itemData data.Stream,
driveID, parentFolderID string,
copyBuffer []byte,
) error {
) (*details.OneDriveInfo, error) {
defer trace.StartRegion(ctx, "gc:oneDrive:restoreItem").End()
itemName := itemData.UUID()
@ -233,26 +235,26 @@ func restoreItem(
// Get the stream size (needed to create the upload session)
ss, ok := itemData.(data.StreamSize)
if !ok {
return errors.Errorf("item %q does not implement DataStreamInfo", itemName)
return nil, errors.Errorf("item %q does not implement DataStreamInfo", itemName)
}
// Create Item
newItem, err := createItem(ctx, service, driveID, parentFolderID, newItem(itemData.UUID(), false))
if err != nil {
return errors.Wrapf(err, "failed to create item %s", itemName)
return nil, errors.Wrapf(err, "failed to create item %s", itemName)
}
// Get a drive item writer
w, err := driveItemWriter(ctx, service, driveID, *newItem.GetId(), ss.Size())
if err != nil {
return errors.Wrapf(err, "failed to create item upload session %s", itemName)
return nil, errors.Wrapf(err, "failed to create item upload session %s", itemName)
}
// Upload the stream data
_, err = io.CopyBuffer(w, itemData.ToReader(), copyBuffer)
if err != nil {
return errors.Wrapf(err, "failed to upload data: item %s", itemName)
return nil, errors.Wrapf(err, "failed to upload data: item %s", itemName)
}
return nil
return driveItemInfo(newItem), nil
}