diff --git a/CHANGELOG.md b/CHANGELOG.md index 179a39184..7ba6122fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Corso-generated .meta files and permissions no longer appear in the backup details. +- Panic and recovery if a user didn't exist in the tenant. ### Known Issues - Folders and Calendars containing zero items or subfolders are not included in the backup. diff --git a/src/cli/backup/exchange_e2e_test.go b/src/cli/backup/exchange_e2e_test.go index fccecbbad..642e351cb 100644 --- a/src/cli/backup/exchange_e2e_test.go +++ b/src/cli/backup/exchange_e2e_test.go @@ -203,6 +203,47 @@ func (suite *BackupExchangeE2ESuite) TestExchangeBackupCmd() { } } +func (suite *BackupExchangeE2ESuite) TestExchangeBackupCmd_UserNotInTenant() { + recorder := strings.Builder{} + + for _, set := range backupDataSets { + recorder.Reset() + + suite.Run(set.String(), func() { + t := suite.T() + + ctx, flush := tester.NewContext() + ctx = config.SetViper(ctx, suite.vpr) + defer flush() + + cmd := tester.StubRootCmd( + "backup", "create", "exchange", + "--config-file", suite.cfgFP, + "--"+utils.UserFN, "foo@nothere.com", + "--"+utils.DataFN, set.String()) + cli.BuildCommandTree(cmd) + + cmd.SetOut(&recorder) + + ctx = print.SetRootCmd(ctx, cmd) + + // run the command + err := cmd.ExecuteContext(ctx) + require.Error(t, err) + assert.Contains( + t, + err.Error(), + "not found within tenant", "error missing user not found") + assert.NotContains(t, err.Error(), "runtime error", "panic happened") + + t.Logf("backup error message: %s", err.Error()) + + result := recorder.String() + t.Log("backup results", result) + }) + } +} + // --------------------------------------------------------------------------- // tests prepared with a previous backup // --------------------------------------------------------------------------- diff --git a/src/cli/backup/onedrive_e2e_test.go b/src/cli/backup/onedrive_e2e_test.go index 46a12cdf9..13afa9ffa 100644 --- a/src/cli/backup/onedrive_e2e_test.go +++ b/src/cli/backup/onedrive_e2e_test.go @@ -113,6 +113,41 @@ func (suite *NoBackupOneDriveE2ESuite) TestOneDriveBackupListCmd_empty() { assert.Equal(t, "No backups available\n", result) } +func (suite *NoBackupOneDriveE2ESuite) TestOneDriveBackupCmd_UserNotInTenant() { + recorder := strings.Builder{} + + t := suite.T() + + ctx, flush := tester.NewContext() + defer flush() + + ctx = config.SetViper(ctx, suite.vpr) + + cmd := tester.StubRootCmd( + "backup", "create", "onedrive", + "--config-file", suite.cfgFP, + "--"+utils.UserFN, "foo@nothere.com") + cli.BuildCommandTree(cmd) + + cmd.SetOut(&recorder) + + ctx = print.SetRootCmd(ctx, cmd) + + // run the command + err := cmd.ExecuteContext(ctx) + require.Error(t, err) + assert.Contains( + t, + err.Error(), + "not found within tenant", "error missing user not found") + assert.NotContains(t, err.Error(), "runtime error", "panic happened") + + t.Logf("backup error message: %s", err.Error()) + + result := recorder.String() + t.Log("backup results", result) +} + // --------------------------------------------------------------------------- // tests for deleting backups // --------------------------------------------------------------------------- diff --git a/src/internal/operations/backup.go b/src/internal/operations/backup.go index d1b75b603..152b29e20 100644 --- a/src/internal/operations/backup.go +++ b/src/internal/operations/backup.go @@ -627,6 +627,11 @@ func (op *BackupOperation) persistResults( op.Status = Failed } + if opStats.k == nil { + op.Status = Failed + return errors.New("backup persistence never completed") + } + op.Results.BytesRead = opStats.k.TotalHashedBytes op.Results.BytesUploaded = opStats.k.TotalUploadedBytes op.Results.ItemsWritten = opStats.k.TotalFileCount