From 625cf744a69b4f7c3342cc756ad34b125f3f9aec Mon Sep 17 00:00:00 2001 From: Keepers <104464746+ryanfkeepers@users.noreply.github.com> Date: Tue, 19 Jul 2022 14:20:12 -0600 Subject: [PATCH] adds the onError option to operations (#347) * adds the onError option to operations Adds the OnError option to operations.Options. OnError tells corso whether to continue despite concurrent processing errors, or to exit processing on any error. Also includes flag support for setting the option. Only adds the options, does not assert error handling behavior in corso. --- src/cli/backup/exchange.go | 4 +++- src/cli/cli.go | 2 +- src/cli/options/options.go | 23 +++++++++++++++++++++++ src/cli/restore/exchange.go | 4 +++- src/internal/operations/operation.go | 8 +++++++- src/pkg/repository/repository.go | 13 +++++++++---- src/pkg/repository/repository_test.go | 5 +++-- 7 files changed, 49 insertions(+), 10 deletions(-) create mode 100644 src/cli/options/options.go diff --git a/src/cli/backup/exchange.go b/src/cli/backup/exchange.go index 83b455117..6621c8464 100644 --- a/src/cli/backup/exchange.go +++ b/src/cli/backup/exchange.go @@ -6,6 +6,7 @@ import ( "github.com/spf13/pflag" "github.com/alcionai/corso/cli/config" + "github.com/alcionai/corso/cli/options" "github.com/alcionai/corso/cli/print" "github.com/alcionai/corso/cli/utils" "github.com/alcionai/corso/pkg/logger" @@ -43,6 +44,7 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command { "data", nil, "Select one or more types of data to backup: "+dataEmail+", "+dataContacts+", or "+dataEvents) + options.AddOperationFlags(c) case listCommand: c, _ = utils.AddCommand(parent, exchangeListCmd) case detailsCommand: @@ -98,7 +100,7 @@ func createExchangeCmd(cmd *cobra.Command, args []string) error { sel := exchangeBackupCreateSelectors(exchangeAll, user, exchangeData) - bo, err := r.NewBackup(ctx, sel) + bo, err := r.NewBackup(ctx, sel, options.OperationOptions()) if err != nil { return errors.Wrap(err, "Failed to initialize Exchange backup") } diff --git a/src/cli/cli.go b/src/cli/cli.go index b61f1a377..a7e43fcea 100644 --- a/src/cli/cli.go +++ b/src/cli/cli.go @@ -27,8 +27,8 @@ var corsoCmd = &cobra.Command{ // the root-level flags var ( - version bool cfgFile string + version bool ) func init() { diff --git a/src/cli/options/options.go b/src/cli/options/options.go new file mode 100644 index 000000000..c0cbf6ce4 --- /dev/null +++ b/src/cli/options/options.go @@ -0,0 +1,23 @@ +package options + +import ( + "github.com/alcionai/corso/internal/operations" + "github.com/spf13/cobra" +) + +var ( + fastFail bool +) + +// AddFlags adds the operation option flags +func AddOperationFlags(parent *cobra.Command) { + fs := parent.Flags() + fs.BoolVar(&fastFail, "fast-fail", false, "stop processing immediately if any error occurs") + // TODO: reveal this flag when fail-fast support is implemented + cobra.CheckErr(fs.MarkHidden("fast-fail")) +} + +// OperationOptions produces the operation options based on the user's flags. +func OperationOptions() operations.Options { + return operations.NewOptions(fastFail) +} diff --git a/src/cli/restore/exchange.go b/src/cli/restore/exchange.go index 3fea01832..b558cdd1d 100644 --- a/src/cli/restore/exchange.go +++ b/src/cli/restore/exchange.go @@ -8,6 +8,7 @@ import ( "github.com/spf13/pflag" "github.com/alcionai/corso/cli/config" + "github.com/alcionai/corso/cli/options" "github.com/alcionai/corso/cli/utils" "github.com/alcionai/corso/pkg/logger" "github.com/alcionai/corso/pkg/repository" @@ -37,6 +38,7 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command { fs.StringVar(&backupID, "backup", "", "ID of the backup to restore") cobra.CheckErr(c.MarkFlagRequired("backup")) fs.StringVar(&user, "user", "", "ID of the user whose exchange data will get restored") + options.AddOperationFlags(c) } return c } @@ -86,7 +88,7 @@ func restoreExchangeCmd(cmd *cobra.Command, args []string) error { } defer utils.CloseRepo(ctx, r) - ro, err := r.NewRestore(ctx, backupID, exchangeRestoreSelectors(user, emailFolder, email)) + ro, err := r.NewRestore(ctx, backupID, exchangeRestoreSelectors(user, emailFolder, email), options.OperationOptions()) if err != nil { return errors.Wrap(err, "Failed to initialize Exchange restore") } diff --git a/src/internal/operations/operation.go b/src/internal/operations/operation.go index 5165496ee..3153378ad 100644 --- a/src/internal/operations/operation.go +++ b/src/internal/operations/operation.go @@ -38,8 +38,14 @@ type operation struct { // Options configure some parameters of the operation type Options struct { + FailFast bool `json:"failFast"` // todo: collision handling - // todo: fast fail vs best attempt +} + +func NewOptions(failFast bool) Options { + return Options{ + FailFast: failFast, + } } func newOperation( diff --git a/src/pkg/repository/repository.go b/src/pkg/repository/repository.go index 53fdbc709..71fbab84a 100644 --- a/src/pkg/repository/repository.go +++ b/src/pkg/repository/repository.go @@ -128,10 +128,10 @@ func (r *Repository) Close(ctx context.Context) error { } // NewBackup generates a BackupOperation runner. -func (r Repository) NewBackup(ctx context.Context, selector selectors.Selector) (operations.BackupOperation, error) { +func (r Repository) NewBackup(ctx context.Context, selector selectors.Selector, opts operations.Options) (operations.BackupOperation, error) { return operations.NewBackupOperation( ctx, - operations.Options{}, + opts, r.dataLayer, store.NewKopiaStore(r.modelStore), r.Account, @@ -139,10 +139,15 @@ func (r Repository) NewBackup(ctx context.Context, selector selectors.Selector) } // NewRestore generates a restoreOperation runner. -func (r Repository) NewRestore(ctx context.Context, backupID string, sel selectors.Selector) (operations.RestoreOperation, error) { +func (r Repository) NewRestore( + ctx context.Context, + backupID string, + sel selectors.Selector, + opts operations.Options, +) (operations.RestoreOperation, error) { return operations.NewRestoreOperation( ctx, - operations.Options{}, + opts, r.dataLayer, store.NewKopiaStore(r.modelStore), r.Account, diff --git a/src/pkg/repository/repository_test.go b/src/pkg/repository/repository_test.go index 5525b6766..5b1809fea 100644 --- a/src/pkg/repository/repository_test.go +++ b/src/pkg/repository/repository_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" + "github.com/alcionai/corso/internal/operations" ctesting "github.com/alcionai/corso/internal/testing" "github.com/alcionai/corso/pkg/account" "github.com/alcionai/corso/pkg/repository" @@ -171,7 +172,7 @@ func (suite *RepositoryIntegrationSuite) TestNewBackup() { r, err := repository.Initialize(ctx, acct, st) require.NoError(t, err) - bo, err := r.NewBackup(ctx, selectors.Selector{}) + bo, err := r.NewBackup(ctx, selectors.Selector{}, operations.Options{}) require.NoError(t, err) require.NotNil(t, bo) } @@ -190,7 +191,7 @@ func (suite *RepositoryIntegrationSuite) TestNewRestore() { r, err := repository.Initialize(ctx, acct, st) require.NoError(t, err) - ro, err := r.NewRestore(ctx, "backup-id", selectors.Selector{}) + ro, err := r.NewRestore(ctx, "backup-id", selectors.Selector{}, operations.Options{}) require.NoError(t, err) require.NotNil(t, ro) }