diff --git a/CHANGELOG.md b/CHANGELOG.md index b93597507..26296e27d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] (alpha) +### Added + +- Incremental backup support for exchange is now enabled by default. + ### Changed - The selectors Reduce() process will only include details that match the DiscreteOwner, if one is specified. diff --git a/src/cli/backup/exchange.go b/src/cli/backup/exchange.go index 6f068a8c3..1501ddcb8 100644 --- a/src/cli/backup/exchange.go +++ b/src/cli/backup/exchange.go @@ -105,7 +105,7 @@ func addExchangeCommands(cmd *cobra.Command) *cobra.Command { switch cmd.Use { case createCommand: c, fs = utils.AddCommand(cmd, exchangeCreateCmd()) - options.AddFeatureFlags(cmd, options.ExchangeIncrementals()) + options.AddFeatureToggle(cmd, options.DisableIncrementals()) c.Use = c.Use + " " + exchangeServiceCommandCreateUseSuffix c.Example = exchangeServiceCommandCreateExamples diff --git a/src/cli/options/options.go b/src/cli/options/options.go index 2d72f8d68..4988c29ca 100644 --- a/src/cli/options/options.go +++ b/src/cli/options/options.go @@ -19,8 +19,8 @@ func Control() control.Options { opt.DisableMetrics = true } - if exchangeIncrementals { - opt.EnabledFeatures.ExchangeIncrementals = true + if disableIncrementals { + opt.ToggleFeatures.DisableIncrementals = true } return opt @@ -53,28 +53,28 @@ func AddGlobalOperationFlags(cmd *cobra.Command) { // Feature Flags // --------------------------------------------------------------------------- -var exchangeIncrementals bool +var disableIncrementals bool type exposeFeatureFlag func(*pflag.FlagSet) -// AddFeatureFlags adds CLI flags for each exposed feature flags to the +// AddFeatureToggle adds CLI flags for each exposed feature toggle to the // persistent flag set within the command. -func AddFeatureFlags(cmd *cobra.Command, effs ...exposeFeatureFlag) { +func AddFeatureToggle(cmd *cobra.Command, effs ...exposeFeatureFlag) { fs := cmd.PersistentFlags() for _, fflag := range effs { fflag(fs) } } -// Adds the '--exchange-incrementals' cli flag which, when set, enables -// incrementals data retrieval for exchange backups. -func ExchangeIncrementals() func(*pflag.FlagSet) { +// Adds the hidden '--no-incrementals' cli flag which, when set, disables +// incremental backups. +func DisableIncrementals() func(*pflag.FlagSet) { return func(fs *pflag.FlagSet) { fs.BoolVar( - &exchangeIncrementals, - "exchange-incrementals", + &disableIncrementals, + "disable-incrementals", false, - "Enable incremental data retrieval in Exchange backups.") - cobra.CheckErr(fs.MarkHidden("exchange-incrementals")) + "Disable incremental data retrieval in backups.") + cobra.CheckErr(fs.MarkHidden("disable-incrementals")) } } diff --git a/src/internal/connector/exchange/service_iterators_test.go b/src/internal/connector/exchange/service_iterators_test.go index bce71b5e9..75a03c3d7 100644 --- a/src/internal/connector/exchange/service_iterators_test.go +++ b/src/internal/connector/exchange/service_iterators_test.go @@ -644,11 +644,7 @@ func (suite *ServiceIteratorsSuite) TestFilterContainersAndFillCollections_incre test.resolver, allScope, test.dps, - control.Options{ - EnabledFeatures: control.FeatureFlags{ - ExchangeIncrementals: true, - }, - }, + control.Options{}, ) assert.NoError(t, err) diff --git a/src/internal/operations/backup.go b/src/internal/operations/backup.go index 8ba5869f3..65e8bc037 100644 --- a/src/internal/operations/backup.go +++ b/src/internal/operations/backup.go @@ -212,7 +212,7 @@ func (op *BackupOperation) Run(ctx context.Context) (err error) { // checker to see if conditions are correct for incremental backup behavior such as // retrieving metadata like delta tokens and previous paths. func useIncrementalBackup(sel selectors.Selector, opts control.Options) bool { - return opts.EnabledFeatures.ExchangeIncrementals && sel.Service == selectors.ServiceExchange + return !opts.ToggleFeatures.DisableIncrementals } // --------------------------------------------------------------------------- diff --git a/src/internal/operations/backup_integration_test.go b/src/internal/operations/backup_integration_test.go index 0f7495b13..1b9e50c9d 100644 --- a/src/internal/operations/backup_integration_test.go +++ b/src/internal/operations/backup_integration_test.go @@ -52,7 +52,7 @@ func prepNewTestBackupOp( ctx context.Context, bus events.Eventer, sel selectors.Selector, - featureFlags control.FeatureFlags, + featureToggles control.Toggles, ) (BackupOperation, account.Account, *kopia.Wrapper, *kopia.ModelStore, func()) { //revive:enable:context-as-argument acct := tester.NewM365Account(t) @@ -90,7 +90,7 @@ func prepNewTestBackupOp( ms.Close(ctx) } - bo := newTestBackupOp(t, ctx, kw, ms, acct, sel, bus, featureFlags, closer) + bo := newTestBackupOp(t, ctx, kw, ms, acct, sel, bus, featureToggles, closer) return bo, acct, kw, ms, closer } @@ -109,7 +109,7 @@ func newTestBackupOp( acct account.Account, sel selectors.Selector, bus events.Eventer, - featureFlags control.FeatureFlags, + featureToggles control.Toggles, closer func(), ) BackupOperation { //revive:enable:context-as-argument @@ -118,7 +118,7 @@ func newTestBackupOp( opts = control.Options{} ) - opts.EnabledFeatures = featureFlags + opts.ToggleFeatures = featureToggles bo, err := NewBackupOperation(ctx, opts, kw, sw, acct, sel, bus) if !assert.NoError(t, err) { @@ -554,7 +554,7 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_exchange() { var ( mb = evmock.NewBus() sel = test.selector().Selector - ffs = control.FeatureFlags{ExchangeIncrementals: test.runIncremental} + ffs = control.Toggles{} ) bo, acct, kw, ms, closer := prepNewTestBackupOp(t, ctx, mb, sel, ffs) @@ -630,7 +630,7 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_exchangeIncrementals() { var ( t = suite.T() acct = tester.NewM365Account(t) - ffs = control.FeatureFlags{ExchangeIncrementals: true} + ffs = control.Toggles{} mb = evmock.NewBus() now = common.Now() users = []string{suite.user} @@ -1010,7 +1010,7 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_oneDrive() { sel.Include(sel.AllData()) - bo, _, _, _, closer := prepNewTestBackupOp(t, ctx, mb, sel.Selector, control.FeatureFlags{}) + bo, _, _, _, closer := prepNewTestBackupOp(t, ctx, mb, sel.Selector, control.Toggles{}) defer closer() runAndCheckBackup(t, ctx, &bo, mb) @@ -1032,7 +1032,7 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_sharePoint() { sel.Include(sel.AllData()) - bo, _, _, _, closer := prepNewTestBackupOp(t, ctx, mb, sel.Selector, control.FeatureFlags{}) + bo, _, _, _, closer := prepNewTestBackupOp(t, ctx, mb, sel.Selector, control.Toggles{}) defer closer() runAndCheckBackup(t, ctx, &bo, mb) diff --git a/src/pkg/control/options.go b/src/pkg/control/options.go index 47abe7111..9cc5a334a 100644 --- a/src/pkg/control/options.go +++ b/src/pkg/control/options.go @@ -6,17 +6,17 @@ import ( // Options holds the optional configurations for a process type Options struct { - Collision CollisionPolicy `json:"-"` - DisableMetrics bool `json:"disableMetrics"` - FailFast bool `json:"failFast"` - EnabledFeatures FeatureFlags `json:"enabledFeatures"` + Collision CollisionPolicy `json:"-"` + DisableMetrics bool `json:"disableMetrics"` + FailFast bool `json:"failFast"` + ToggleFeatures Toggles `json:"ToggleFeatures"` } // Defaults provides an Options with the default values set. func Defaults() Options { return Options{ - FailFast: true, - EnabledFeatures: FeatureFlags{}, + FailFast: true, + ToggleFeatures: Toggles{}, } } @@ -63,11 +63,15 @@ func DefaultRestoreDestination(timeFormat common.TimeFormat) RestoreDestination } // --------------------------------------------------------------------------- -// Feature Flags +// Feature Flags and Toggles // --------------------------------------------------------------------------- -type FeatureFlags struct { - // ExchangeIncrementals allow for re-use of delta links when backing up - // exchange data, reducing the amount of data pulled from graph. - ExchangeIncrementals bool `json:"incrementals,omitempty"` +// Toggles allows callers to force corso to behave in ways that deviate from +// the default expectations by turning on or shutting off certain features. +// The default state for every toggle is false; toggles are only turned on +// if specified by the caller. +type Toggles struct { + // DisableIncrementals prevents backups from using incremental lookups, + // forcing a new, complete backup of all data regardless of prior state. + DisableIncrementals bool `json:"exchangeIncrementals,omitempty"` }