From b0d3d4f3ee66ed264669333af4dc3e8887674934 Mon Sep 17 00:00:00 2001 From: Abhishek Pandey Date: Wed, 5 Jul 2023 10:53:24 -0700 Subject: [PATCH] Expose corso extensions via options (#3746) Two changes: 1. Add a new field to `control.Options` to allow SDK users to supply item extension factories. 2. Move repository pkg tests from `repository_test.go` to `repository.go`. Reason is that having a separate test package prevents us from verifying state of underlying implementations (e.g. state of `repository.repository` struct). --- #### Does this PR need a docs update or release note? - [ ] :white_check_mark: Yes, it's included - [x] :clock1: Yes, but in a later PR - [ ] :no_entry: No #### Type of change - [x] :sunflower: Feature - [ ] :bug: Bugfix - [ ] :world_map: Documentation - [ ] :robot: Supportability/Tests - [ ] :computer: CI/Deployment - [ ] :broom: Tech Debt/Cleanup #### Issue(s) * internal #### Test Plan - [ ] :muscle: Manual - [x] :zap: Unit test - [ ] :green_heart: E2E --- src/pkg/control/options.go | 16 +++-- src/pkg/repository/repository_test.go | 98 +++++++++++++++++++++++---- 2 files changed, 92 insertions(+), 22 deletions(-) diff --git a/src/pkg/control/options.go b/src/pkg/control/options.go index d82907397..91fe33cbb 100644 --- a/src/pkg/control/options.go +++ b/src/pkg/control/options.go @@ -8,18 +8,20 @@ import ( "github.com/alcionai/corso/src/internal/common/dttm" "github.com/alcionai/corso/src/pkg/control/repository" + "github.com/alcionai/corso/src/pkg/extensions" "github.com/alcionai/corso/src/pkg/logger" ) // Options holds the optional configurations for a process type Options struct { - DisableMetrics bool `json:"disableMetrics"` - FailureHandling FailurePolicy `json:"failureHandling"` - RestorePermissions bool `json:"restorePermissions"` - SkipReduce bool `json:"skipReduce"` - ToggleFeatures Toggles `json:"toggleFeatures"` - Parallelism Parallelism `json:"parallelism"` - Repo repository.Options `json:"repo"` + DisableMetrics bool `json:"disableMetrics"` + FailureHandling FailurePolicy `json:"failureHandling"` + RestorePermissions bool `json:"restorePermissions"` + SkipReduce bool `json:"skipReduce"` + ToggleFeatures Toggles `json:"toggleFeatures"` + Parallelism Parallelism `json:"parallelism"` + Repo repository.Options `json:"repo"` + ItemExtensionFactory []extensions.CreateItemExtensioner `json:"-"` } type Parallelism struct { diff --git a/src/pkg/repository/repository_test.go b/src/pkg/repository/repository_test.go index 84b876d9d..cc980434d 100644 --- a/src/pkg/repository/repository_test.go +++ b/src/pkg/repository/repository_test.go @@ -1,4 +1,4 @@ -package repository_test +package repository import ( "os" @@ -15,7 +15,7 @@ import ( "github.com/alcionai/corso/src/pkg/control" ctrlRepo "github.com/alcionai/corso/src/pkg/control/repository" "github.com/alcionai/corso/src/pkg/control/testdata" - "github.com/alcionai/corso/src/pkg/repository" + "github.com/alcionai/corso/src/pkg/extensions" "github.com/alcionai/corso/src/pkg/selectors" "github.com/alcionai/corso/src/pkg/storage" ) @@ -58,7 +58,7 @@ func (suite *RepositoryUnitSuite) TestInitialize() { st, err := test.storage() assert.NoError(t, err, clues.ToCore(err)) - _, err = repository.Initialize(ctx, test.account, st, control.Defaults()) + _, err = Initialize(ctx, test.account, st, control.Defaults()) test.errCheck(t, err, clues.ToCore(err)) }) } @@ -92,7 +92,7 @@ func (suite *RepositoryUnitSuite) TestConnect() { st, err := test.storage() assert.NoError(t, err, clues.ToCore(err)) - _, err = repository.Connect(ctx, test.account, st, "not_found", control.Defaults()) + _, err = Connect(ctx, test.account, st, "not_found", control.Defaults()) test.errCheck(t, err, clues.ToCore(err)) }) } @@ -135,7 +135,7 @@ func (suite *RepositoryIntegrationSuite) TestInitialize() { defer flush() st := test.storage(t) - r, err := repository.Initialize(ctx, test.account, st, control.Defaults()) + r, err := Initialize(ctx, test.account, st, control.Defaults()) if err == nil { defer func() { err := r.Close(ctx) @@ -167,7 +167,7 @@ func (suite *RepositoryIntegrationSuite) TestInitializeWithRole() { st.SessionName = "corso-repository-test" st.SessionDuration = roleDuration.String() - r, err := repository.Initialize(ctx, account.Account{}, st, control.Options{}) + r, err := Initialize(ctx, account.Account{}, st, control.Options{}) require.NoError(suite.T(), err) defer func() { @@ -184,11 +184,11 @@ func (suite *RepositoryIntegrationSuite) TestConnect() { // need to initialize the repository before we can test connecting to it. st := tester.NewPrefixedS3Storage(t) - repo, err := repository.Initialize(ctx, account.Account{}, st, control.Defaults()) + repo, err := Initialize(ctx, account.Account{}, st, control.Defaults()) require.NoError(t, err, clues.ToCore(err)) // now re-connect - _, err = repository.Connect(ctx, account.Account{}, st, repo.GetID(), control.Defaults()) + _, err = Connect(ctx, account.Account{}, st, repo.GetID(), control.Defaults()) assert.NoError(t, err, clues.ToCore(err)) } @@ -201,7 +201,7 @@ func (suite *RepositoryIntegrationSuite) TestConnect_sameID() { // need to initialize the repository before we can test connecting to it. st := tester.NewPrefixedS3Storage(t) - r, err := repository.Initialize(ctx, account.Account{}, st, control.Defaults()) + r, err := Initialize(ctx, account.Account{}, st, control.Defaults()) require.NoError(t, err, clues.ToCore(err)) oldID := r.GetID() @@ -210,7 +210,7 @@ func (suite *RepositoryIntegrationSuite) TestConnect_sameID() { require.NoError(t, err, clues.ToCore(err)) // now re-connect - r, err = repository.Connect(ctx, account.Account{}, st, oldID, control.Defaults()) + r, err = Connect(ctx, account.Account{}, st, oldID, control.Defaults()) require.NoError(t, err, clues.ToCore(err)) assert.Equal(t, oldID, r.GetID()) } @@ -226,7 +226,7 @@ func (suite *RepositoryIntegrationSuite) TestNewBackup() { // need to initialize the repository before we can test connecting to it. st := tester.NewPrefixedS3Storage(t) - r, err := repository.Initialize(ctx, acct, st, control.Defaults()) + r, err := Initialize(ctx, acct, st, control.Defaults()) require.NoError(t, err, clues.ToCore(err)) userID := tester.M365UserID(t) @@ -248,7 +248,7 @@ func (suite *RepositoryIntegrationSuite) TestNewRestore() { // need to initialize the repository before we can test connecting to it. st := tester.NewPrefixedS3Storage(t) - r, err := repository.Initialize(ctx, acct, st, control.Defaults()) + r, err := Initialize(ctx, acct, st, control.Defaults()) require.NoError(t, err, clues.ToCore(err)) ro, err := r.NewRestore(ctx, "backup-id", selectors.Selector{DiscreteOwner: "test"}, restoreCfg) @@ -267,7 +267,7 @@ func (suite *RepositoryIntegrationSuite) TestNewMaintenance() { // need to initialize the repository before we can test connecting to it. st := tester.NewPrefixedS3Storage(t) - r, err := repository.Initialize(ctx, acct, st, control.Defaults()) + r, err := Initialize(ctx, acct, st, control.Defaults()) require.NoError(t, err, clues.ToCore(err)) mo, err := r.NewMaintenance(ctx, ctrlRepo.Maintenance{}) @@ -284,13 +284,81 @@ func (suite *RepositoryIntegrationSuite) TestConnect_DisableMetrics() { // need to initialize the repository before we can test connecting to it. st := tester.NewPrefixedS3Storage(t) - repo, err := repository.Initialize(ctx, account.Account{}, st, control.Defaults()) + repo, err := Initialize(ctx, account.Account{}, st, control.Defaults()) require.NoError(t, err) // now re-connect - r, err := repository.Connect(ctx, account.Account{}, st, repo.GetID(), control.Options{DisableMetrics: true}) + r, err := Connect(ctx, account.Account{}, st, repo.GetID(), control.Options{DisableMetrics: true}) assert.NoError(t, err) // now we have repoID beforehand assert.Equal(t, r.GetID(), r.GetID()) } + +// Test_Options tests that the options are passed through to the repository +// correctly +func (suite *RepositoryIntegrationSuite) Test_Options() { + table := []struct { + name string + opts func() control.Options + expectedLen int + }{ + { + name: "default options", + opts: func() control.Options { + return control.Defaults() + }, + expectedLen: 0, + }, + { + name: "options with an extension factory", + opts: func() control.Options { + o := control.Defaults() + o.ItemExtensionFactory = append( + o.ItemExtensionFactory, + &extensions.MockItemExtensionFactory{}) + + return o + }, + expectedLen: 1, + }, + { + name: "options with multiple extension factories", + opts: func() control.Options { + o := control.Defaults() + f := []extensions.CreateItemExtensioner{ + &extensions.MockItemExtensionFactory{}, + &extensions.MockItemExtensionFactory{}, + } + + o.ItemExtensionFactory = f + + return o + }, + expectedLen: 2, + }, + } + + for _, test := range table { + suite.Run(test.name, func() { + t := suite.T() + acct := tester.NewM365Account(t) + st := tester.NewPrefixedS3Storage(t) + + ctx, flush := tester.NewContext(t) + defer flush() + + repo, err := Initialize(ctx, acct, st, test.opts()) + require.NoError(t, err) + + r := repo.(*repository) + assert.Equal(t, test.expectedLen, len(r.Opts.ItemExtensionFactory)) + + repo, err = Connect(ctx, acct, st, repo.GetID(), test.opts()) + assert.NoError(t, err) + + r = repo.(*repository) + assert.Equal(t, test.expectedLen, len(r.Opts.ItemExtensionFactory)) + }) + } +}