cetnralize restoreConfig (#3563)

centralizes all restore configuration management within a restoreConfig struct.  This struct is owned by the control package, which allows it to be utilized by both CLI and SDK consumers.

---

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

- [x]  No

#### Type of change

- [x] 🧹 Tech Debt/Cleanup

#### Issue(s)

* #3562

#### Test Plan

- [x]  Unit test
- [x] 💚 E2E
This commit is contained in:
Keepers 2023-06-12 17:33:22 -06:00 committed by GitHub
parent de589a4571
commit 960e8b79a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 186 additions and 207 deletions

View File

@ -96,13 +96,13 @@ func restoreExchangeCmd(cmd *cobra.Command, args []string) error {
defer utils.CloseRepo(ctx, r) defer utils.CloseRepo(ctx, r)
dest := control.DefaultRestoreDestination(dttm.HumanReadable) restoreCfg := control.DefaultRestoreConfig(dttm.HumanReadable)
Infof(ctx, "Restoring to folder %s", dest.ContainerName) Infof(ctx, "Restoring to folder %s", restoreCfg.Location)
sel := utils.IncludeExchangeRestoreDataSelectors(opts) sel := utils.IncludeExchangeRestoreDataSelectors(opts)
utils.FilterExchangeRestoreInfoSelectors(sel, opts) utils.FilterExchangeRestoreInfoSelectors(sel, opts)
ro, err := r.NewRestore(ctx, utils.BackupIDFV, sel.Selector, dest) ro, err := r.NewRestore(ctx, utils.BackupIDFV, sel.Selector, restoreCfg)
if err != nil { if err != nil {
return Only(ctx, clues.Wrap(err, "Failed to initialize Exchange restore")) return Only(ctx, clues.Wrap(err, "Failed to initialize Exchange restore"))
} }

View File

@ -97,13 +97,13 @@ func restoreOneDriveCmd(cmd *cobra.Command, args []string) error {
defer utils.CloseRepo(ctx, r) defer utils.CloseRepo(ctx, r)
dest := control.DefaultRestoreDestination(dttm.HumanReadableDriveItem) restoreCfg := control.DefaultRestoreConfig(dttm.HumanReadableDriveItem)
Infof(ctx, "Restoring to folder %s", dest.ContainerName) Infof(ctx, "Restoring to folder %s", restoreCfg.Location)
sel := utils.IncludeOneDriveRestoreDataSelectors(opts) sel := utils.IncludeOneDriveRestoreDataSelectors(opts)
utils.FilterOneDriveRestoreInfoSelectors(sel, opts) utils.FilterOneDriveRestoreInfoSelectors(sel, opts)
ro, err := r.NewRestore(ctx, utils.BackupIDFV, sel.Selector, dest) ro, err := r.NewRestore(ctx, utils.BackupIDFV, sel.Selector, restoreCfg)
if err != nil { if err != nil {
return Only(ctx, clues.Wrap(err, "Failed to initialize OneDrive restore")) return Only(ctx, clues.Wrap(err, "Failed to initialize OneDrive restore"))
} }

View File

@ -102,13 +102,13 @@ func restoreSharePointCmd(cmd *cobra.Command, args []string) error {
defer utils.CloseRepo(ctx, r) defer utils.CloseRepo(ctx, r)
dest := control.DefaultRestoreDestination(dttm.HumanReadableDriveItem) restoreCfg := control.DefaultRestoreConfig(dttm.HumanReadableDriveItem)
Infof(ctx, "Restoring to folder %s", dest.ContainerName) Infof(ctx, "Restoring to folder %s", restoreCfg.Location)
sel := utils.IncludeSharePointRestoreDataSelectors(ctx, opts) sel := utils.IncludeSharePointRestoreDataSelectors(ctx, opts)
utils.FilterSharePointRestoreInfoSelectors(sel, opts) utils.FilterSharePointRestoreInfoSelectors(sel, opts)
ro, err := r.NewRestore(ctx, utils.BackupIDFV, sel.Selector, dest) ro, err := r.NewRestore(ctx, utils.BackupIDFV, sel.Selector, restoreCfg)
if err != nil { if err != nil {
return Only(ctx, clues.Wrap(err, "Failed to initialize SharePoint restore")) return Only(ctx, clues.Wrap(err, "Failed to initialize SharePoint restore"))
} }

View File

@ -83,9 +83,9 @@ func generateAndRestoreItems(
items: items, items: items,
}} }}
dest := control.DefaultRestoreDestination(dttm.SafeForTesting) dest := control.DefaultRestoreConfig(dttm.SafeForTesting)
dest.ContainerName = destFldr dest.Location = destFldr
print.Infof(ctx, "Restoring to folder %s", dest.ContainerName) print.Infof(ctx, "Restoring to folder %s", dest.Location)
dataColls, err := buildCollections( dataColls, err := buildCollections(
service, service,
@ -163,7 +163,7 @@ type collection struct {
func buildCollections( func buildCollections(
service path.ServiceType, service path.ServiceType,
tenant, user string, tenant, user string,
dest control.RestoreDestination, dest control.RestoreConfig,
colls []collection, colls []collection,
) ([]data.RestoreCollection, error) { ) ([]data.RestoreCollection, error) {
collections := make([]data.RestoreCollection, 0, len(colls)) collections := make([]data.RestoreCollection, 0, len(colls))
@ -224,9 +224,9 @@ func generateAndRestoreDriveItems(
ctx, flush := tester.NewContext(nil) ctx, flush := tester.NewContext(nil)
defer flush() defer flush()
dest := control.DefaultRestoreDestination(dttm.SafeForTesting) dest := control.DefaultRestoreConfig(dttm.SafeForTesting)
dest.ContainerName = destFldr dest.Location = destFldr
print.Infof(ctx, "Restoring to folder %s", dest.ContainerName) print.Infof(ctx, "Restoring to folder %s", dest.Location)
var driveID string var driveID string
@ -394,7 +394,7 @@ func generateAndRestoreDriveItems(
Service: service, Service: service,
Tenant: tenantID, Tenant: tenantID,
ResourceOwners: []string{resourceOwner}, ResourceOwners: []string{resourceOwner},
Dest: tester.DefaultTestRestoreDestination(""), RestoreCfg: tester.DefaultTestRestoreConfig(""),
} }
_, _, collections, _, err := connector.GetCollectionsAndExpected( _, _, collections, _, err := connector.GetCollectionsAndExpected(

View File

@ -233,7 +233,7 @@ func (gc *GraphConnector) ConsumeRestoreCollections(
ctx context.Context, ctx context.Context,
backupVersion int, backupVersion int,
sels selectors.Selector, sels selectors.Selector,
dest control.RestoreDestination, restoreCfg control.RestoreConfig,
opts control.Options, opts control.Options,
dcs []data.RestoreCollection, dcs []data.RestoreCollection,
errs *fault.Bus, errs *fault.Bus,
@ -251,13 +251,13 @@ func (gc *GraphConnector) ConsumeRestoreCollections(
switch sels.Service { switch sels.Service {
case selectors.ServiceExchange: case selectors.ServiceExchange:
status, err = exchange.RestoreCollections(ctx, gc.AC, dest, dcs, deets, errs) status, err = exchange.RestoreCollections(ctx, gc.AC, restoreCfg, dcs, deets, errs)
case selectors.ServiceOneDrive: case selectors.ServiceOneDrive:
status, err = onedrive.RestoreCollections( status, err = onedrive.RestoreCollections(
ctx, ctx,
onedrive.NewRestoreHandler(gc.AC), onedrive.NewRestoreHandler(gc.AC),
backupVersion, backupVersion,
dest, restoreCfg,
opts, opts,
dcs, dcs,
deets, deets,
@ -267,7 +267,7 @@ func (gc *GraphConnector) ConsumeRestoreCollections(
ctx, ctx,
backupVersion, backupVersion,
gc.AC, gc.AC,
dest, restoreCfg,
opts, opts,
dcs, dcs,
deets, deets,

View File

@ -51,7 +51,7 @@ func (suite *ContactsRestoreIntgSuite) TestCreateContainerDestination() {
path.EmailCategory, path.EmailCategory,
suite.creds.AzureTenantID, suite.creds.AzureTenantID,
suite.userID, suite.userID,
tester.DefaultTestRestoreDestination("").ContainerName, tester.DefaultTestRestoreConfig("").Location,
[]string{"Hufflepuff"}, []string{"Hufflepuff"},
[]string{"Ravenclaw"}) []string{"Ravenclaw"})
} }

View File

@ -51,7 +51,7 @@ func (suite *EventsRestoreIntgSuite) TestCreateContainerDestination() {
path.EmailCategory, path.EmailCategory,
suite.creds.AzureTenantID, suite.creds.AzureTenantID,
suite.userID, suite.userID,
tester.DefaultTestRestoreDestination("").ContainerName, tester.DefaultTestRestoreConfig("").Location,
[]string{"Durmstrang"}, []string{"Durmstrang"},
[]string{"Beauxbatons"}) []string{"Beauxbatons"})
} }

View File

@ -51,7 +51,7 @@ func (suite *MailRestoreIntgSuite) TestCreateContainerDestination() {
path.EmailCategory, path.EmailCategory,
suite.creds.AzureTenantID, suite.creds.AzureTenantID,
suite.userID, suite.userID,
tester.DefaultTestRestoreDestination("").ContainerName, tester.DefaultTestRestoreConfig("").Location,
[]string{"Griffindor", "Croix"}, []string{"Griffindor", "Croix"},
[]string{"Griffindor", "Felicius"}) []string{"Griffindor", "Felicius"})
} }

View File

@ -54,7 +54,7 @@ func (suite *RestoreIntgSuite) TestRestoreContact() {
var ( var (
userID = tester.M365UserID(t) userID = tester.M365UserID(t)
folderName = tester.DefaultTestRestoreDestination("contact").ContainerName folderName = tester.DefaultTestRestoreConfig("contact").Location
handler = newContactRestoreHandler(suite.ac) handler = newContactRestoreHandler(suite.ac)
) )
@ -88,7 +88,7 @@ func (suite *RestoreIntgSuite) TestRestoreEvent() {
var ( var (
userID = tester.M365UserID(t) userID = tester.M365UserID(t)
subject = tester.DefaultTestRestoreDestination("event").ContainerName subject = tester.DefaultTestRestoreConfig("event").Location
handler = newEventRestoreHandler(suite.ac) handler = newEventRestoreHandler(suite.ac)
) )
@ -154,7 +154,7 @@ func (suite *RestoreIntgSuite) TestRestoreExchangeObject() {
bytes: exchMock.MessageBytes("Restore Exchange Object"), bytes: exchMock.MessageBytes("Restore Exchange Object"),
category: path.EmailCategory, category: path.EmailCategory,
destination: func(t *testing.T, ctx context.Context) string { destination: func(t *testing.T, ctx context.Context) string {
folderName := tester.DefaultTestRestoreDestination("mailobj").ContainerName folderName := tester.DefaultTestRestoreConfig("mailobj").Location
folder, err := handlers[path.EmailCategory]. folder, err := handlers[path.EmailCategory].
CreateContainer(ctx, userID, folderName, "") CreateContainer(ctx, userID, folderName, "")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -167,7 +167,7 @@ func (suite *RestoreIntgSuite) TestRestoreExchangeObject() {
bytes: exchMock.MessageWithDirectAttachment("Restore 1 Attachment"), bytes: exchMock.MessageWithDirectAttachment("Restore 1 Attachment"),
category: path.EmailCategory, category: path.EmailCategory,
destination: func(t *testing.T, ctx context.Context) string { destination: func(t *testing.T, ctx context.Context) string {
folderName := tester.DefaultTestRestoreDestination("mailwattch").ContainerName folderName := tester.DefaultTestRestoreConfig("mailwattch").Location
folder, err := handlers[path.EmailCategory]. folder, err := handlers[path.EmailCategory].
CreateContainer(ctx, userID, folderName, "") CreateContainer(ctx, userID, folderName, "")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -180,7 +180,7 @@ func (suite *RestoreIntgSuite) TestRestoreExchangeObject() {
bytes: exchMock.MessageWithItemAttachmentEvent("Event Item Attachment"), bytes: exchMock.MessageWithItemAttachmentEvent("Event Item Attachment"),
category: path.EmailCategory, category: path.EmailCategory,
destination: func(t *testing.T, ctx context.Context) string { destination: func(t *testing.T, ctx context.Context) string {
folderName := tester.DefaultTestRestoreDestination("eventwattch").ContainerName folderName := tester.DefaultTestRestoreConfig("eventwattch").Location
folder, err := handlers[path.EmailCategory]. folder, err := handlers[path.EmailCategory].
CreateContainer(ctx, userID, folderName, "") CreateContainer(ctx, userID, folderName, "")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -193,7 +193,7 @@ func (suite *RestoreIntgSuite) TestRestoreExchangeObject() {
bytes: exchMock.MessageWithItemAttachmentMail("Mail Item Attachment"), bytes: exchMock.MessageWithItemAttachmentMail("Mail Item Attachment"),
category: path.EmailCategory, category: path.EmailCategory,
destination: func(t *testing.T, ctx context.Context) string { destination: func(t *testing.T, ctx context.Context) string {
folderName := tester.DefaultTestRestoreDestination("mailitemattch").ContainerName folderName := tester.DefaultTestRestoreConfig("mailitemattch").Location
folder, err := handlers[path.EmailCategory]. folder, err := handlers[path.EmailCategory].
CreateContainer(ctx, userID, folderName, "") CreateContainer(ctx, userID, folderName, "")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -209,7 +209,7 @@ func (suite *RestoreIntgSuite) TestRestoreExchangeObject() {
), ),
category: path.EmailCategory, category: path.EmailCategory,
destination: func(t *testing.T, ctx context.Context) string { destination: func(t *testing.T, ctx context.Context) string {
folderName := tester.DefaultTestRestoreDestination("mailbasicattch").ContainerName folderName := tester.DefaultTestRestoreConfig("mailbasicattch").Location
folder, err := handlers[path.EmailCategory]. folder, err := handlers[path.EmailCategory].
CreateContainer(ctx, userID, folderName, "") CreateContainer(ctx, userID, folderName, "")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -225,7 +225,7 @@ func (suite *RestoreIntgSuite) TestRestoreExchangeObject() {
), ),
category: path.EmailCategory, category: path.EmailCategory,
destination: func(t *testing.T, ctx context.Context) string { destination: func(t *testing.T, ctx context.Context) string {
folderName := tester.DefaultTestRestoreDestination("mailnestattch").ContainerName folderName := tester.DefaultTestRestoreConfig("mailnestattch").Location
folder, err := handlers[path.EmailCategory]. folder, err := handlers[path.EmailCategory].
CreateContainer(ctx, userID, folderName, "") CreateContainer(ctx, userID, folderName, "")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -241,7 +241,7 @@ func (suite *RestoreIntgSuite) TestRestoreExchangeObject() {
), ),
category: path.EmailCategory, category: path.EmailCategory,
destination: func(t *testing.T, ctx context.Context) string { destination: func(t *testing.T, ctx context.Context) string {
folderName := tester.DefaultTestRestoreDestination("mailcontactattch").ContainerName folderName := tester.DefaultTestRestoreConfig("mailcontactattch").Location
folder, err := handlers[path.EmailCategory]. folder, err := handlers[path.EmailCategory].
CreateContainer(ctx, userID, folderName, "") CreateContainer(ctx, userID, folderName, "")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -254,7 +254,7 @@ func (suite *RestoreIntgSuite) TestRestoreExchangeObject() {
bytes: exchMock.MessageWithNestedItemAttachmentEvent("Nested Item Attachment"), bytes: exchMock.MessageWithNestedItemAttachmentEvent("Nested Item Attachment"),
category: path.EmailCategory, category: path.EmailCategory,
destination: func(t *testing.T, ctx context.Context) string { destination: func(t *testing.T, ctx context.Context) string {
folderName := tester.DefaultTestRestoreDestination("nestedattch").ContainerName folderName := tester.DefaultTestRestoreConfig("nestedattch").Location
folder, err := handlers[path.EmailCategory]. folder, err := handlers[path.EmailCategory].
CreateContainer(ctx, userID, folderName, "") CreateContainer(ctx, userID, folderName, "")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -267,7 +267,7 @@ func (suite *RestoreIntgSuite) TestRestoreExchangeObject() {
bytes: exchMock.MessageWithLargeAttachment("Restore Large Attachment"), bytes: exchMock.MessageWithLargeAttachment("Restore Large Attachment"),
category: path.EmailCategory, category: path.EmailCategory,
destination: func(t *testing.T, ctx context.Context) string { destination: func(t *testing.T, ctx context.Context) string {
folderName := tester.DefaultTestRestoreDestination("maillargeattch").ContainerName folderName := tester.DefaultTestRestoreConfig("maillargeattch").Location
folder, err := handlers[path.EmailCategory]. folder, err := handlers[path.EmailCategory].
CreateContainer(ctx, userID, folderName, "") CreateContainer(ctx, userID, folderName, "")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -280,7 +280,7 @@ func (suite *RestoreIntgSuite) TestRestoreExchangeObject() {
bytes: exchMock.MessageWithTwoAttachments("Restore 2 Attachments"), bytes: exchMock.MessageWithTwoAttachments("Restore 2 Attachments"),
category: path.EmailCategory, category: path.EmailCategory,
destination: func(t *testing.T, ctx context.Context) string { destination: func(t *testing.T, ctx context.Context) string {
folderName := tester.DefaultTestRestoreDestination("mailtwoattch").ContainerName folderName := tester.DefaultTestRestoreConfig("mailtwoattch").Location
folder, err := handlers[path.EmailCategory]. folder, err := handlers[path.EmailCategory].
CreateContainer(ctx, userID, folderName, "") CreateContainer(ctx, userID, folderName, "")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -293,7 +293,7 @@ func (suite *RestoreIntgSuite) TestRestoreExchangeObject() {
bytes: exchMock.MessageWithOneDriveAttachment("Restore Reference(OneDrive) Attachment"), bytes: exchMock.MessageWithOneDriveAttachment("Restore Reference(OneDrive) Attachment"),
category: path.EmailCategory, category: path.EmailCategory,
destination: func(t *testing.T, ctx context.Context) string { destination: func(t *testing.T, ctx context.Context) string {
folderName := tester.DefaultTestRestoreDestination("mailrefattch").ContainerName folderName := tester.DefaultTestRestoreConfig("mailrefattch").Location
folder, err := handlers[path.EmailCategory]. folder, err := handlers[path.EmailCategory].
CreateContainer(ctx, userID, folderName, "") CreateContainer(ctx, userID, folderName, "")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -306,7 +306,7 @@ func (suite *RestoreIntgSuite) TestRestoreExchangeObject() {
bytes: exchMock.ContactBytes("Test_Omega"), bytes: exchMock.ContactBytes("Test_Omega"),
category: path.ContactsCategory, category: path.ContactsCategory,
destination: func(t *testing.T, ctx context.Context) string { destination: func(t *testing.T, ctx context.Context) string {
folderName := tester.DefaultTestRestoreDestination("contact").ContainerName folderName := tester.DefaultTestRestoreConfig("contact").Location
folder, err := handlers[path.ContactsCategory]. folder, err := handlers[path.ContactsCategory].
CreateContainer(ctx, userID, folderName, "") CreateContainer(ctx, userID, folderName, "")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -319,7 +319,7 @@ func (suite *RestoreIntgSuite) TestRestoreExchangeObject() {
bytes: exchMock.EventBytes("Restored Event Object"), bytes: exchMock.EventBytes("Restored Event Object"),
category: path.EventsCategory, category: path.EventsCategory,
destination: func(t *testing.T, ctx context.Context) string { destination: func(t *testing.T, ctx context.Context) string {
folderName := tester.DefaultTestRestoreDestination("event").ContainerName folderName := tester.DefaultTestRestoreConfig("event").Location
calendar, err := handlers[path.EventsCategory]. calendar, err := handlers[path.EventsCategory].
CreateContainer(ctx, userID, folderName, "") CreateContainer(ctx, userID, folderName, "")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -332,7 +332,7 @@ func (suite *RestoreIntgSuite) TestRestoreExchangeObject() {
bytes: exchMock.EventWithAttachment("Restored Event Attachment"), bytes: exchMock.EventWithAttachment("Restored Event Attachment"),
category: path.EventsCategory, category: path.EventsCategory,
destination: func(t *testing.T, ctx context.Context) string { destination: func(t *testing.T, ctx context.Context) string {
folderName := tester.DefaultTestRestoreDestination("eventobj").ContainerName folderName := tester.DefaultTestRestoreConfig("eventobj").Location
calendar, err := handlers[path.EventsCategory]. calendar, err := handlers[path.EventsCategory].
CreateContainer(ctx, userID, folderName, "") CreateContainer(ctx, userID, folderName, "")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))

View File

@ -190,7 +190,7 @@ func (suite *ServiceIteratorsSuite) TestFilterContainersAndFillCollections() {
getter mockGetter getter mockGetter
resolver graph.ContainerResolver resolver graph.ContainerResolver
scope selectors.ExchangeScope scope selectors.ExchangeScope
failFast control.FailureBehavior failFast control.FailurePolicy
expectErr assert.ErrorAssertionFunc expectErr assert.ErrorAssertionFunc
expectNewColls int expectNewColls int
expectMetadataColls int expectMetadataColls int

View File

@ -27,7 +27,7 @@ import (
func RestoreCollections( func RestoreCollections(
ctx context.Context, ctx context.Context,
ac api.Client, ac api.Client,
dest control.RestoreDestination, restoreCfg control.RestoreConfig,
dcs []data.RestoreCollection, dcs []data.RestoreCollection,
deets *details.Builder, deets *details.Builder,
errs *fault.Bus, errs *fault.Bus,
@ -76,7 +76,7 @@ func RestoreCollections(
containerID, gcr, err := createDestination( containerID, gcr, err := createDestination(
ictx, ictx,
handler, handler,
handler.formatRestoreDestination(dest.ContainerName, dc.FullPath()), handler.formatRestoreDestination(restoreCfg.Location, dc.FullPath()),
userID, userID,
directoryCache[category], directoryCache[category],
isNewCache, isNewCache,
@ -116,7 +116,7 @@ func RestoreCollections(
support.Restore, support.Restore,
len(dcs), len(dcs),
metrics, metrics,
dest.ContainerName) restoreCfg.Location)
return status, el.Failure() return status, el.Failure()
} }

View File

@ -936,7 +936,7 @@ func checkCollections(
category = returned.FullPath().Category() category = returned.FullPath().Category()
expectedColData = expected[returned.FullPath().String()] expectedColData = expected[returned.FullPath().String()]
folders = returned.FullPath().Elements() folders = returned.FullPath().Elements()
rootDir = folders[len(folders)-1] == config.Dest.ContainerName rootDir = folders[len(folders)-1] == config.RestoreCfg.Location
) )
// Need to iterate through all items even if we don't expect to find a match // Need to iterate through all items even if we don't expect to find a match

View File

@ -339,7 +339,7 @@ func GetCollectionsAndExpected(
config.Service, config.Service,
config.Tenant, config.Tenant,
owner, owner,
config.Dest, config.RestoreCfg,
testCollections, testCollections,
backupVersion, backupVersion,
) )

View File

@ -293,8 +293,8 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreFailsBadService() {
defer flush() defer flush()
var ( var (
dest = tester.DefaultTestRestoreDestination("") restoreCfg = tester.DefaultTestRestoreConfig("")
sel = selectors.Selector{ sel = selectors.Selector{
Service: selectors.ServiceUnknown, Service: selectors.ServiceUnknown,
} }
) )
@ -303,7 +303,7 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreFailsBadService() {
ctx, ctx,
version.Backup, version.Backup,
sel, sel,
dest, restoreCfg,
control.Options{ control.Options{
RestorePermissions: true, RestorePermissions: true,
ToggleFeatures: control.Toggles{}, ToggleFeatures: control.Toggles{},
@ -320,7 +320,7 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreFailsBadService() {
} }
func (suite *GraphConnectorIntegrationSuite) TestEmptyCollections() { func (suite *GraphConnectorIntegrationSuite) TestEmptyCollections() {
dest := tester.DefaultTestRestoreDestination("") restoreCfg := tester.DefaultTestRestoreConfig("")
table := []struct { table := []struct {
name string name string
col []data.RestoreCollection col []data.RestoreCollection
@ -381,7 +381,7 @@ func (suite *GraphConnectorIntegrationSuite) TestEmptyCollections() {
ctx, ctx,
version.Backup, version.Backup,
test.sel, test.sel,
dest, restoreCfg,
control.Options{ control.Options{
RestorePermissions: true, RestorePermissions: true,
ToggleFeatures: control.Toggles{}, ToggleFeatures: control.Toggles{},
@ -413,7 +413,7 @@ func runRestore(
) { ) {
t.Logf( t.Logf(
"Restoring collections to %s for resourceOwners(s) %v\n", "Restoring collections to %s for resourceOwners(s) %v\n",
config.Dest.ContainerName, config.RestoreCfg.Location,
config.ResourceOwners) config.ResourceOwners)
start := time.Now() start := time.Now()
@ -424,7 +424,7 @@ func runRestore(
ctx, ctx,
backupVersion, backupVersion,
restoreSel, restoreSel,
config.Dest, config.RestoreCfg,
config.Opts, config.Opts,
collections, collections,
fault.New(true)) fault.New(true))
@ -472,7 +472,7 @@ func runBackupAndCompare(
for _, ro := range config.ResourceOwners { for _, ro := range config.ResourceOwners {
expectedDests = append(expectedDests, destAndCats{ expectedDests = append(expectedDests, destAndCats{
resourceOwner: ro, resourceOwner: ro,
dest: config.Dest.ContainerName, dest: config.RestoreCfg.Location,
cats: cats, cats: cats,
}) })
@ -536,7 +536,7 @@ func runRestoreBackupTest(
Service: test.service, Service: test.service,
Tenant: tenant, Tenant: tenant,
ResourceOwners: resourceOwners, ResourceOwners: resourceOwners,
Dest: tester.DefaultTestRestoreDestination(""), RestoreCfg: tester.DefaultTestRestoreConfig(""),
} }
totalItems, totalKopiaItems, collections, expectedData, err := GetCollectionsAndExpected( totalItems, totalKopiaItems, collections, expectedData, err := GetCollectionsAndExpected(
@ -581,7 +581,7 @@ func runRestoreTestWithVersion(
Service: test.service, Service: test.service,
Tenant: tenant, Tenant: tenant,
ResourceOwners: resourceOwners, ResourceOwners: resourceOwners,
Dest: tester.DefaultTestRestoreDestination(""), RestoreCfg: tester.DefaultTestRestoreConfig(""),
} }
totalItems, _, collections, _, err := GetCollectionsAndExpected( totalItems, _, collections, _, err := GetCollectionsAndExpected(
@ -618,7 +618,7 @@ func runRestoreBackupTestVersions(
Service: test.service, Service: test.service,
Tenant: tenant, Tenant: tenant,
ResourceOwners: resourceOwners, ResourceOwners: resourceOwners,
Dest: tester.DefaultTestRestoreDestination(""), RestoreCfg: tester.DefaultTestRestoreConfig(""),
} }
totalItems, _, collections, _, err := GetCollectionsAndExpected( totalItems, _, collections, _, err := GetCollectionsAndExpected(
@ -993,11 +993,11 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames
allExpectedData := map[string]map[string][]byte{} allExpectedData := map[string]map[string][]byte{}
for i, collection := range test.collections { for i, collection := range test.collections {
// Get a dest per collection so they're independent. // Get a restoreCfg per collection so they're independent.
dest := tester.DefaultTestRestoreDestination("") restoreCfg := tester.DefaultTestRestoreConfig("")
expectedDests = append(expectedDests, destAndCats{ expectedDests = append(expectedDests, destAndCats{
resourceOwner: suite.user, resourceOwner: suite.user,
dest: dest.ContainerName, dest: restoreCfg.Location,
cats: map[path.CategoryType]struct{}{ cats: map[path.CategoryType]struct{}{
collection.Category: {}, collection.Category: {},
}, },
@ -1007,7 +1007,7 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames
test.service, test.service,
suite.connector.tenant, suite.connector.tenant,
suite.user, suite.user,
dest, restoreCfg,
[]ColInfo{collection}, []ColInfo{collection},
version.Backup, version.Backup,
) )
@ -1023,7 +1023,7 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames
"Restoring %v/%v collections to %s\n", "Restoring %v/%v collections to %s\n",
i+1, i+1,
len(test.collections), len(test.collections),
dest.ContainerName, restoreCfg.Location,
) )
restoreGC := loadConnector(ctx, t, test.resource) restoreGC := loadConnector(ctx, t, test.resource)
@ -1031,7 +1031,7 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames
ctx, ctx,
version.Backup, version.Backup,
restoreSel, restoreSel,
dest, restoreCfg,
control.Options{ control.Options{
RestorePermissions: true, RestorePermissions: true,
ToggleFeatures: control.Toggles{}, ToggleFeatures: control.Toggles{},
@ -1081,7 +1081,7 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames
ci := ConfigInfo{ ci := ConfigInfo{
Opts: control.Options{RestorePermissions: true}, Opts: control.Options{RestorePermissions: true},
// Alright to be empty, needed for OneDrive. // Alright to be empty, needed for OneDrive.
Dest: control.RestoreDestination{}, RestoreCfg: control.RestoreConfig{},
} }
// Pull the data prior to waiting for the status as otherwise it will // Pull the data prior to waiting for the status as otherwise it will

View File

@ -43,7 +43,7 @@ type ConfigInfo struct {
Service path.ServiceType Service path.ServiceType
Tenant string Tenant string
ResourceOwners []string ResourceOwners []string
Dest control.RestoreDestination RestoreCfg control.RestoreConfig
} }
func mustToDataLayerPath( func mustToDataLayerPath(
@ -66,15 +66,15 @@ func mustToDataLayerPath(
// combination of the location the data was recently restored to and where the // combination of the location the data was recently restored to and where the
// data was originally in the hierarchy. // data was originally in the hierarchy.
func backupOutputPathFromRestore( func backupOutputPathFromRestore(
restoreDest control.RestoreDestination, restoreCfg control.RestoreConfig,
inputPath path.Path, inputPath path.Path,
) (path.Path, error) { ) (path.Path, error) {
base := []string{restoreDest.ContainerName} base := []string{restoreCfg.Location}
// OneDrive has leading information like the drive ID. // OneDrive has leading information like the drive ID.
if inputPath.Service() == path.OneDriveService || inputPath.Service() == path.SharePointService { if inputPath.Service() == path.OneDriveService || inputPath.Service() == path.SharePointService {
folders := inputPath.Folders() folders := inputPath.Folders()
base = append(append([]string{}, folders[:3]...), restoreDest.ContainerName) base = append(append([]string{}, folders[:3]...), restoreCfg.Location)
if len(folders) > 3 { if len(folders) > 3 {
base = append(base, folders[3:]...) base = append(base, folders[3:]...)
@ -117,7 +117,7 @@ func (rc mockRestoreCollection) FetchItemByName(
func collectionsForInfo( func collectionsForInfo(
service path.ServiceType, service path.ServiceType,
tenant, user string, tenant, user string,
dest control.RestoreDestination, restoreCfg control.RestoreConfig,
allInfo []ColInfo, allInfo []ColInfo,
backupVersion int, backupVersion int,
) (int, int, []data.RestoreCollection, map[string]map[string][]byte, error) { ) (int, int, []data.RestoreCollection, map[string]map[string][]byte, error) {
@ -142,7 +142,7 @@ func collectionsForInfo(
mc := exchMock.NewCollection(pth, pth, len(info.Items)) mc := exchMock.NewCollection(pth, pth, len(info.Items))
baseDestPath, err := backupOutputPathFromRestore(dest, pth) baseDestPath, err := backupOutputPathFromRestore(restoreCfg, pth)
if err != nil { if err != nil {
return totalItems, kopiaEntries, collections, expectedData, err return totalItems, kopiaEntries, collections, expectedData, err
} }

View File

@ -60,7 +60,7 @@ func (gc GraphConnector) ConsumeRestoreCollections(
_ context.Context, _ context.Context,
_ int, _ int,
_ selectors.Selector, _ selectors.Selector,
_ control.RestoreDestination, _ control.RestoreConfig,
_ control.Options, _ control.Options,
_ []data.RestoreCollection, _ []data.RestoreCollection,
_ *fault.Bus, _ *fault.Bus,

View File

@ -155,7 +155,7 @@ func (suite *ItemIntegrationSuite) TestItemWriter() {
root, err := suite.service.ac.Drives().GetRootFolder(ctx, test.driveID) root, err := suite.service.ac.Drives().GetRootFolder(ctx, test.driveID)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
newFolderName := tester.DefaultTestRestoreDestination("folder").ContainerName newFolderName := tester.DefaultTestRestoreConfig("folder").Location
t.Logf("creating folder %s", newFolderName) t.Logf("creating folder %s", newFolderName)
newFolder, err := rh.PostItemInContainer( newFolder, err := rh.PostItemInContainer(

View File

@ -64,7 +64,7 @@ func RestoreCollections(
ctx context.Context, ctx context.Context,
rh RestoreHandler, rh RestoreHandler,
backupVersion int, backupVersion int,
dest control.RestoreDestination, restoreCfg control.RestoreConfig,
opts control.Options, opts control.Options,
dcs []data.RestoreCollection, dcs []data.RestoreCollection,
deets *details.Builder, deets *details.Builder,
@ -79,7 +79,7 @@ func RestoreCollections(
ctx = clues.Add( ctx = clues.Add(
ctx, ctx,
"backup_version", backupVersion, "backup_version", backupVersion,
"destination", dest.ContainerName) "restore_location", restoreCfg.Location)
// Reorder collections so that the parents directories are created // Reorder collections so that the parents directories are created
// before the child directories; a requirement for permissions. // before the child directories; a requirement for permissions.
@ -97,7 +97,7 @@ func RestoreCollections(
ictx = clues.Add( ictx = clues.Add(
ctx, ctx,
"category", dc.FullPath().Category(), "category", dc.FullPath().Category(),
"destination", clues.Hide(dest.ContainerName), "destination", clues.Hide(restoreCfg.Location),
"resource_owner", clues.Hide(dc.FullPath().ResourceOwner()), "resource_owner", clues.Hide(dc.FullPath().ResourceOwner()),
"full_path", dc.FullPath()) "full_path", dc.FullPath())
) )
@ -108,7 +108,7 @@ func RestoreCollections(
backupVersion, backupVersion,
dc, dc,
caches, caches,
dest.ContainerName, restoreCfg.Location,
deets, deets,
opts.RestorePermissions, opts.RestorePermissions,
errs) errs)
@ -128,7 +128,7 @@ func RestoreCollections(
support.Restore, support.Restore,
len(dcs), len(dcs),
restoreMetrics, restoreMetrics,
dest.ContainerName) restoreCfg.Location)
return status, el.Failure() return status, el.Failure()
} }

View File

@ -63,7 +63,7 @@ func (suite *URLCacheIntegrationSuite) TestURLCacheBasic() {
t = suite.T() t = suite.T()
ac = suite.ac.Drives() ac = suite.ac.Drives()
driveID = suite.driveID driveID = suite.driveID
newFolderName = tester.DefaultTestRestoreDestination("folder").ContainerName newFolderName = tester.DefaultTestRestoreConfig("folder").Location
driveItemPager = suite.ac.Drives().NewItemPager(driveID, "", api.DriveItemSelectDefault()) driveItemPager = suite.ac.Drives().NewItemPager(driveID, "", api.DriveItemSelectDefault())
) )

View File

@ -92,7 +92,7 @@ func (suite *SharePointPageSuite) TestRestoreSinglePage() {
ctx, flush := tester.NewContext(t) ctx, flush := tester.NewContext(t)
defer flush() defer flush()
destName := tester.DefaultTestRestoreDestination("").ContainerName destName := tester.DefaultTestRestoreConfig("").Location
testName := "MockPage" testName := "MockPage"
// Create Test Page // Create Test Page

View File

@ -208,7 +208,7 @@ func (suite *SharePointCollectionSuite) TestListCollection_Restore() {
info: sharePointListInfo(listing, int64(len(byteArray))), info: sharePointListInfo(listing, int64(len(byteArray))),
} }
destName := tester.DefaultTestRestoreDestination("").ContainerName destName := tester.DefaultTestRestoreConfig("").Location
deets, err := restoreListItem(ctx, service, listData, suite.siteID, destName) deets, err := restoreListItem(ctx, service, listData, suite.siteID, destName)
assert.NoError(t, err, clues.ToCore(err)) assert.NoError(t, err, clues.ToCore(err))

View File

@ -43,7 +43,7 @@ func RestoreCollections(
ctx context.Context, ctx context.Context,
backupVersion int, backupVersion int,
ac api.Client, ac api.Client,
dest control.RestoreDestination, restoreCfg control.RestoreConfig,
opts control.Options, opts control.Options,
dcs []data.RestoreCollection, dcs []data.RestoreCollection,
deets *details.Builder, deets *details.Builder,
@ -71,7 +71,7 @@ func RestoreCollections(
metrics support.CollectionMetrics metrics support.CollectionMetrics
ictx = clues.Add(ctx, ictx = clues.Add(ctx,
"category", category, "category", category,
"destination", clues.Hide(dest.ContainerName), "restore_location", restoreCfg.Location,
"resource_owner", clues.Hide(dc.FullPath().ResourceOwner()), "resource_owner", clues.Hide(dc.FullPath().ResourceOwner()),
"full_path", dc.FullPath()) "full_path", dc.FullPath())
) )
@ -84,7 +84,7 @@ func RestoreCollections(
backupVersion, backupVersion,
dc, dc,
caches, caches,
dest.ContainerName, restoreCfg.Location,
deets, deets,
opts.RestorePermissions, opts.RestorePermissions,
errs) errs)
@ -94,7 +94,7 @@ func RestoreCollections(
ictx, ictx,
ac.Stable, ac.Stable,
dc, dc,
dest.ContainerName, restoreCfg.Location,
deets, deets,
errs) errs)
@ -103,7 +103,7 @@ func RestoreCollections(
ictx, ictx,
ac.Stable, ac.Stable,
dc, dc,
dest.ContainerName, restoreCfg.Location,
deets, deets,
errs) errs)
@ -127,7 +127,7 @@ func RestoreCollections(
support.Restore, support.Restore,
len(dcs), len(dcs),
restoreMetrics, restoreMetrics,
dest.ContainerName) restoreCfg.Location)
return status, el.Failure() return status, el.Failure()
} }

View File

@ -381,14 +381,14 @@ func generateContainerOfItems(
items: items, items: items,
}} }}
dest := control.DefaultRestoreDestination(dttm.SafeForTesting) restoreCfg := control.DefaultRestoreConfig(dttm.SafeForTesting)
dest.ContainerName = destFldr restoreCfg.Location = destFldr
dataColls := buildCollections( dataColls := buildCollections(
t, t,
service, service,
tenantID, resourceOwner, tenantID, resourceOwner,
dest, restoreCfg,
collections) collections)
opts := control.Defaults() opts := control.Defaults()
@ -398,7 +398,7 @@ func generateContainerOfItems(
ctx, ctx,
backupVersion, backupVersion,
sel, sel,
dest, restoreCfg,
opts, opts,
dataColls, dataColls,
fault.New(true)) fault.New(true))
@ -443,7 +443,7 @@ func buildCollections(
t *testing.T, t *testing.T,
service path.ServiceType, service path.ServiceType,
tenant, user string, tenant, user string,
dest control.RestoreDestination, restoreCfg control.RestoreConfig,
colls []incrementalCollection, colls []incrementalCollection,
) []data.RestoreCollection { ) []data.RestoreCollection {
t.Helper() t.Helper()

View File

@ -37,7 +37,7 @@ type (
ctx context.Context, ctx context.Context,
backupVersion int, backupVersion int,
selector selectors.Selector, selector selectors.Selector,
dest control.RestoreDestination, restoreCfg control.RestoreConfig,
opts control.Options, opts control.Options,
dcs []data.RestoreCollection, dcs []data.RestoreCollection,
errs *fault.Bus, errs *fault.Bus,

View File

@ -35,11 +35,11 @@ import (
type RestoreOperation struct { type RestoreOperation struct {
operation operation
BackupID model.StableID `json:"backupID"` BackupID model.StableID
Destination control.RestoreDestination `json:"destination"` Results RestoreResults
Results RestoreResults `json:"results"` Selectors selectors.Selector
Selectors selectors.Selector `json:"selectors"` RestoreCfg control.RestoreConfig
Version string `json:"version"` Version string
acct account.Account acct account.Account
rc inject.RestoreConsumer rc inject.RestoreConsumer
@ -61,17 +61,17 @@ func NewRestoreOperation(
acct account.Account, acct account.Account,
backupID model.StableID, backupID model.StableID,
sel selectors.Selector, sel selectors.Selector,
dest control.RestoreDestination, restoreCfg control.RestoreConfig,
bus events.Eventer, bus events.Eventer,
) (RestoreOperation, error) { ) (RestoreOperation, error) {
op := RestoreOperation{ op := RestoreOperation{
operation: newOperation(opts, bus, kw, sw), operation: newOperation(opts, bus, kw, sw),
acct: acct, acct: acct,
BackupID: backupID, BackupID: backupID,
Destination: dest, RestoreCfg: restoreCfg,
Selectors: sel, Selectors: sel,
Version: "v0", Version: "v0",
rc: rc, rc: rc,
} }
if err := op.validate(); err != nil { if err := op.validate(); err != nil {
return RestoreOperation{}, err return RestoreOperation{}, err
@ -138,7 +138,7 @@ func (op *RestoreOperation) Run(ctx context.Context) (restoreDetails *details.De
"tenant_id", clues.Hide(op.acct.ID()), "tenant_id", clues.Hide(op.acct.ID()),
"backup_id", op.BackupID, "backup_id", op.BackupID,
"service", op.Selectors.Service, "service", op.Selectors.Service,
"destination_container", clues.Hide(op.Destination.ContainerName)) "destination_container", clues.Hide(op.RestoreCfg.Location))
defer func() { defer func() {
op.bus.Event( op.bus.Event(
@ -257,7 +257,7 @@ func (op *RestoreOperation) do(
op.rc, op.rc,
bup.Version, bup.Version,
op.Selectors, op.Selectors,
op.Destination, op.RestoreCfg,
op.Options, op.Options,
dcs, dcs,
op.Errors) op.Errors)
@ -314,7 +314,7 @@ func consumeRestoreCollections(
rc inject.RestoreConsumer, rc inject.RestoreConsumer,
backupVersion int, backupVersion int,
sel selectors.Selector, sel selectors.Selector,
dest control.RestoreDestination, restoreCfg control.RestoreConfig,
opts control.Options, opts control.Options,
dcs []data.RestoreCollection, dcs []data.RestoreCollection,
errs *fault.Bus, errs *fault.Bus,
@ -329,7 +329,7 @@ func consumeRestoreCollections(
ctx, ctx,
backupVersion, backupVersion,
sel, sel,
dest, restoreCfg,
opts, opts,
dcs, dcs,
errs) errs)

View File

@ -46,11 +46,11 @@ func TestRestoreOpSuite(t *testing.T) {
func (suite *RestoreOpSuite) TestRestoreOperation_PersistResults() { func (suite *RestoreOpSuite) TestRestoreOperation_PersistResults() {
var ( var (
kw = &kopia.Wrapper{} kw = &kopia.Wrapper{}
sw = &store.Wrapper{} sw = &store.Wrapper{}
gc = &mock.GraphConnector{} gc = &mock.GraphConnector{}
now = time.Now() now = time.Now()
dest = tester.DefaultTestRestoreDestination("") restoreCfg = tester.DefaultTestRestoreConfig("")
) )
table := []struct { table := []struct {
@ -113,7 +113,7 @@ func (suite *RestoreOpSuite) TestRestoreOperation_PersistResults() {
account.Account{}, account.Account{},
"foo", "foo",
selectors.Selector{DiscreteOwner: "test"}, selectors.Selector{DiscreteOwner: "test"},
dest, restoreCfg,
evmock.NewBus()) evmock.NewBus())
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -215,11 +215,11 @@ func (suite *RestoreOpIntegrationSuite) TearDownSuite() {
func (suite *RestoreOpIntegrationSuite) TestNewRestoreOperation() { func (suite *RestoreOpIntegrationSuite) TestNewRestoreOperation() {
var ( var (
kw = &kopia.Wrapper{} kw = &kopia.Wrapper{}
sw = &store.Wrapper{} sw = &store.Wrapper{}
gc = &mock.GraphConnector{} gc = &mock.GraphConnector{}
dest = tester.DefaultTestRestoreDestination("") restoreCfg = tester.DefaultTestRestoreConfig("")
opts = control.Defaults() opts = control.Defaults()
) )
table := []struct { table := []struct {
@ -251,7 +251,7 @@ func (suite *RestoreOpIntegrationSuite) TestNewRestoreOperation() {
tester.NewM365Account(t), tester.NewM365Account(t),
"backup-id", "backup-id",
selectors.Selector{DiscreteOwner: "test"}, selectors.Selector{DiscreteOwner: "test"},
dest, restoreCfg,
evmock.NewBus()) evmock.NewBus())
test.errCheck(t, err, clues.ToCore(err)) test.errCheck(t, err, clues.ToCore(err))
}) })
@ -370,14 +370,14 @@ func (suite *RestoreOpIntegrationSuite) TestRestore_Run() {
tables := []struct { tables := []struct {
name string name string
owner string owner string
dest control.RestoreDestination restoreCfg control.RestoreConfig
getSelector func(t *testing.T, owners []string) selectors.Selector getSelector func(t *testing.T, owners []string) selectors.Selector
setup func(t *testing.T, kw *kopia.Wrapper, sw *store.Wrapper, acct account.Account, owner string) bupResults setup func(t *testing.T, kw *kopia.Wrapper, sw *store.Wrapper, acct account.Account, owner string) bupResults
}{ }{
{ {
name: "Exchange_Restore", name: "Exchange_Restore",
owner: tester.M365UserID(suite.T()), owner: tester.M365UserID(suite.T()),
dest: tester.DefaultTestRestoreDestination(""), restoreCfg: tester.DefaultTestRestoreConfig(""),
getSelector: func(t *testing.T, owners []string) selectors.Selector { getSelector: func(t *testing.T, owners []string) selectors.Selector {
rsel := selectors.NewExchangeRestore(owners) rsel := selectors.NewExchangeRestore(owners)
rsel.Include(rsel.AllData()) rsel.Include(rsel.AllData())
@ -387,9 +387,9 @@ func (suite *RestoreOpIntegrationSuite) TestRestore_Run() {
setup: setupExchangeBackup, setup: setupExchangeBackup,
}, },
{ {
name: "SharePoint_Restore", name: "SharePoint_Restore",
owner: tester.M365SiteID(suite.T()), owner: tester.M365SiteID(suite.T()),
dest: control.DefaultRestoreDestination(dttm.SafeForTesting), restoreCfg: control.DefaultRestoreConfig(dttm.SafeForTesting),
getSelector: func(t *testing.T, owners []string) selectors.Selector { getSelector: func(t *testing.T, owners []string) selectors.Selector {
rsel := selectors.NewSharePointRestore(owners) rsel := selectors.NewSharePointRestore(owners)
rsel.Include(rsel.AllData()) rsel.Include(rsel.AllData())
@ -423,7 +423,7 @@ func (suite *RestoreOpIntegrationSuite) TestRestore_Run() {
tester.NewM365Account(t), tester.NewM365Account(t),
bup.backupID, bup.backupID,
test.getSelector(t, bup.selectorResourceOwners), test.getSelector(t, bup.selectorResourceOwners),
test.dest, test.restoreCfg,
mb) mb)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -453,8 +453,8 @@ func (suite *RestoreOpIntegrationSuite) TestRestore_Run_errorNoBackup() {
defer flush() defer flush()
var ( var (
dest = tester.DefaultTestRestoreDestination("") restoreCfg = tester.DefaultTestRestoreConfig("")
mb = evmock.NewBus() mb = evmock.NewBus()
) )
rsel := selectors.NewExchangeRestore(selectors.None()) rsel := selectors.NewExchangeRestore(selectors.None())
@ -475,7 +475,7 @@ func (suite *RestoreOpIntegrationSuite) TestRestore_Run_errorNoBackup() {
tester.NewM365Account(t), tester.NewM365Account(t),
"backupID", "backupID",
rsel.Selector, rsel.Selector,
dest, restoreCfg,
mb) mb)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))

View File

@ -9,10 +9,10 @@ import (
const RestoreFolderPrefix = "Corso_Test" const RestoreFolderPrefix = "Corso_Test"
func DefaultTestRestoreDestination(namespace string) control.RestoreDestination { func DefaultTestRestoreConfig(namespace string) control.RestoreConfig {
var ( var (
dest = control.DefaultRestoreDestination(dttm.SafeForTesting) restoreCfg = control.DefaultRestoreConfig(dttm.SafeForTesting)
sft = dttm.FormatNow(dttm.SafeForTesting) sft = dttm.FormatNow(dttm.SafeForTesting)
) )
parts := []string{RestoreFolderPrefix, namespace, sft} parts := []string{RestoreFolderPrefix, namespace, sft}
@ -20,7 +20,7 @@ func DefaultTestRestoreDestination(namespace string) control.RestoreDestination
parts = []string{RestoreFolderPrefix, sft} parts = []string{RestoreFolderPrefix, sft}
} }
dest.ContainerName = strings.Join(parts, "_") restoreCfg.Location = strings.Join(parts, "_")
return dest return restoreCfg
} }

View File

@ -1,26 +0,0 @@
// Code generated by "stringer -type=CollisionPolicy"; DO NOT EDIT.
package control
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[Unknown-0]
_ = x[Copy-1]
_ = x[Skip-2]
_ = x[Replace-3]
}
const _CollisionPolicy_name = "UnknownCopySkipReplace"
var _CollisionPolicy_index = [...]uint8{0, 7, 11, 15, 22}
func (i CollisionPolicy) String() string {
if i < 0 || i >= CollisionPolicy(len(_CollisionPolicy_index)-1) {
return "CollisionPolicy(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _CollisionPolicy_name[_CollisionPolicy_index[i]:_CollisionPolicy_index[i+1]]
}

View File

@ -7,9 +7,8 @@ import (
// Options holds the optional configurations for a process // Options holds the optional configurations for a process
type Options struct { type Options struct {
Collision CollisionPolicy `json:"-"`
DisableMetrics bool `json:"disableMetrics"` DisableMetrics bool `json:"disableMetrics"`
FailureHandling FailureBehavior `json:"failureHandling"` FailureHandling FailurePolicy `json:"failureHandling"`
RestorePermissions bool `json:"restorePermissions"` RestorePermissions bool `json:"restorePermissions"`
SkipReduce bool `json:"skipReduce"` SkipReduce bool `json:"skipReduce"`
ToggleFeatures Toggles `json:"toggleFeatures"` ToggleFeatures Toggles `json:"toggleFeatures"`
@ -17,8 +16,6 @@ type Options struct {
Repo repository.Options `json:"repo"` Repo repository.Options `json:"repo"`
} }
type FailureBehavior string
type Parallelism struct { type Parallelism struct {
// sets the collection buffer size before blocking. // sets the collection buffer size before blocking.
CollectionBuffer int CollectionBuffer int
@ -26,13 +23,15 @@ type Parallelism struct {
ItemFetch int ItemFetch int
} }
type FailurePolicy string
const ( const (
// fails and exits the run immediately // fails and exits the run immediately
FailFast FailureBehavior = "fail-fast" FailFast FailurePolicy = "fail-fast"
// recovers whenever possible, reports non-zero recoveries as a failure // recovers whenever possible, reports non-zero recoveries as a failure
FailAfterRecovery FailureBehavior = "fail-after-recovery" FailAfterRecovery FailurePolicy = "fail-after-recovery"
// recovers whenever possible, does not report recovery as failure // recovers whenever possible, does not report recovery as failure
BestEffort FailureBehavior = "best-effort" BestEffort FailurePolicy = "best-effort"
) )
// Defaults provides an Options with the default values set. // Defaults provides an Options with the default values set.
@ -48,44 +47,50 @@ func Defaults() Options {
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Restore Item Collision Policy // Restore Configuration
// ---------------------------------------------------------------------------
// CollisionPolicy describes how the datalayer behaves in case of a collision.
type CollisionPolicy int
//go:generate stringer -type=CollisionPolicy
const (
Unknown CollisionPolicy = iota
Copy
Skip
Replace
)
// ---------------------------------------------------------------------------
// Restore Destination
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
const ( const (
defaultRestoreLocation = "Corso_Restore_" defaultRestoreLocation = "Corso_Restore_"
) )
// RestoreDestination is a POD that contains an override of the resource owner // CollisionPolicy describes how the datalayer behaves in case of a collision.
// to restore data under and the name of the root of the restored container type CollisionPolicy string
// hierarchy.
type RestoreDestination struct { const (
// ResourceOwnerOverride overrides the default resource owner to restore to. Unknown CollisionPolicy = ""
// If it is not populated items should be restored under the previous resource Skip CollisionPolicy = "skip"
// owner of the item. Copy CollisionPolicy = "copy"
ResourceOwnerOverride string Replace CollisionPolicy = "replace"
// ContainerName is the name of the root of the restored container hierarchy. )
// This field must be populated for a restore.
ContainerName string // RestoreConfig contains
type RestoreConfig struct {
// Defines the per-item collision handling policy.
// Defaults to Skip.
OnCollision CollisionPolicy
// ProtectedResource specifies which resource the data will be restored to.
// If empty, restores to the same resource that was backed up.
// Defaults to empty.
ProtectedResource string
// Location specifies the container into which the data will be restored.
// Only accepts container names, does not accept IDs.
// If empty or "/", data will get restored in place, beginning at the root.
// Defaults to "Corso_Restore_<current_dttm>"
Location string
// Drive specifies the drive into which the data will be restored.
// If empty, data is restored to the same drive that was backed up.
// Defaults to empty.
Drive string
} }
func DefaultRestoreDestination(timeFormat dttm.TimeFormat) RestoreDestination { func DefaultRestoreConfig(timeFormat dttm.TimeFormat) RestoreConfig {
return RestoreDestination{ return RestoreConfig{
ContainerName: defaultRestoreLocation + dttm.FormatNow(timeFormat), OnCollision: Skip,
Location: defaultRestoreLocation + dttm.FormatNow(timeFormat),
} }
} }

View File

@ -151,9 +151,9 @@ func runRestoreLoadTest(
t.Skip("restore load test is toggled off") t.Skip("restore load test is toggled off")
} }
dest := tester.DefaultTestRestoreDestination("") restoreCfg := tester.DefaultTestRestoreConfig("")
rst, err := r.NewRestore(ctx, backupID, restSel, dest) rst, err := r.NewRestore(ctx, backupID, restSel, restoreCfg)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
doRestoreLoadTest(t, ctx, rst, service, bup.Results.ItemsWritten, usersUnderTest) doRestoreLoadTest(t, ctx, rst, service, bup.Results.ItemsWritten, usersUnderTest)

View File

@ -69,7 +69,7 @@ type Repository interface {
ctx context.Context, ctx context.Context,
backupID string, backupID string,
sel selectors.Selector, sel selectors.Selector,
dest control.RestoreDestination, restoreCfg control.RestoreConfig,
) (operations.RestoreOperation, error) ) (operations.RestoreOperation, error)
NewMaintenance( NewMaintenance(
ctx context.Context, ctx context.Context,
@ -336,7 +336,7 @@ func (r repository) NewRestore(
ctx context.Context, ctx context.Context,
backupID string, backupID string,
sel selectors.Selector, sel selectors.Selector,
dest control.RestoreDestination, restoreCfg control.RestoreConfig,
) (operations.RestoreOperation, error) { ) (operations.RestoreOperation, error) {
gc, err := connectToM365(ctx, sel, r.Account) gc, err := connectToM365(ctx, sel, r.Account)
if err != nil { if err != nil {
@ -352,7 +352,7 @@ func (r repository) NewRestore(
r.Account, r.Account,
model.StableID(backupID), model.StableID(backupID),
sel, sel,
dest, restoreCfg,
r.Bus) r.Bus)
} }

View File

@ -242,7 +242,7 @@ func (suite *RepositoryIntegrationSuite) TestNewRestore() {
defer flush() defer flush()
acct := tester.NewM365Account(t) acct := tester.NewM365Account(t)
dest := tester.DefaultTestRestoreDestination("") restoreCfg := tester.DefaultTestRestoreConfig("")
// need to initialize the repository before we can test connecting to it. // need to initialize the repository before we can test connecting to it.
st := tester.NewPrefixedS3Storage(t) st := tester.NewPrefixedS3Storage(t)
@ -250,7 +250,7 @@ func (suite *RepositoryIntegrationSuite) TestNewRestore() {
r, err := repository.Initialize(ctx, acct, st, control.Defaults()) r, err := repository.Initialize(ctx, acct, st, control.Defaults())
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
ro, err := r.NewRestore(ctx, "backup-id", selectors.Selector{DiscreteOwner: "test"}, dest) ro, err := r.NewRestore(ctx, "backup-id", selectors.Selector{DiscreteOwner: "test"}, restoreCfg)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
require.NotNil(t, ro) require.NotNil(t, ro)
} }