From ac35757c35904ea5f8998a9cd54ece8e0570c62b Mon Sep 17 00:00:00 2001 From: Adam Janikowski <12255597+ajanikow@users.noreply.github.com> Date: Sat, 4 Dec 2021 01:13:11 +0100 Subject: [PATCH] [Feature] Allow to abort upload (#845) --- CHANGELOG.md | 1 + .../arango/backup/arango_client_impl.go | 7 ++ .../handlers/arango/backup/state_uploading.go | 14 +++ .../arango/backup/state_uploading_test.go | 97 +++++++++++++++---- 4 files changed, 101 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af765ddc1..3450493a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A) - Add ArangoBackup backoff functionality +- Allow to abort ArangoBackup uploads by removing spec.upload ## [1.2.5](https://github.com/arangodb/kube-arangodb/tree/1.2.5) (2021-10-25) - Split & Unify Lifecycle management functionality diff --git a/pkg/backup/handlers/arango/backup/arango_client_impl.go b/pkg/backup/handlers/arango/backup/arango_client_impl.go index 7a47f74a0..9e7d341d2 100644 --- a/pkg/backup/handlers/arango/backup/arango_client_impl.go +++ b/pkg/backup/handlers/arango/backup/arango_client_impl.go @@ -188,6 +188,13 @@ func (ac *arangoClientBackupImpl) Progress(jobID driver.BackupTransferJobID) (Ar return ArangoBackupProgress{}, err } + if report.Cancelled { + return ArangoBackupProgress{ + Failed: true, + FailMessage: "Upload cancelled", + }, nil + } + var ret ArangoBackupProgress var completedCount int var total int diff --git a/pkg/backup/handlers/arango/backup/state_uploading.go b/pkg/backup/handlers/arango/backup/state_uploading.go index 75c8cece5..3970669ea 100644 --- a/pkg/backup/handlers/arango/backup/state_uploading.go +++ b/pkg/backup/handlers/arango/backup/state_uploading.go @@ -83,6 +83,20 @@ func stateUploadingHandler(h *handler, backup *backupApi.ArangoBackup) (*backupA ) } + if backup.Spec.Upload == nil { + // Upload is canceled + + if err = client.Abort(driver.BackupTransferJobID(backup.Status.Progress.JobID)); err == nil { + return wrapUpdateStatus(backup, + updateStatusState(backupApi.ArangoBackupStateReady, ""), + cleanStatusJob(), + updateStatusBackupUpload(util.NewBool(false)), + updateStatusAvailable(true), + cleanBackOff(), + ) + } + } + return wrapUpdateStatus(backup, updateStatusState(backupApi.ArangoBackupStateUploading, ""), updateStatusAvailable(true), diff --git a/pkg/backup/handlers/arango/backup/state_uploading_test.go b/pkg/backup/handlers/arango/backup/state_uploading_test.go index 151f83809..600d82d71 100644 --- a/pkg/backup/handlers/arango/backup/state_uploading_test.go +++ b/pkg/backup/handlers/arango/backup/state_uploading_test.go @@ -57,6 +57,10 @@ func Test_State_Uploading_Success(t *testing.T) { obj.Status.Backup = createBackupFromMeta(backupMeta, nil) + obj.Spec.Upload = &backupApi.ArangoBackupSpecOperation{ + RepositoryURL: "S3 URL", + } + obj.Status.Progress = &backupApi.ArangoBackupProgress{ JobID: string(progress), } @@ -162,16 +166,13 @@ func Test_StateUploading_FailedProgress(t *testing.T) { backupMeta, err := mock.Get(createResponse.ID) require.NoError(t, err) - progress, err := mock.Download(backupMeta.ID) + progress, err := mock.Upload(backupMeta.ID) require.NoError(t, err) obj.Status.Backup = createBackupFromMeta(backupMeta, nil) - obj.Spec.Download = &backupApi.ArangoBackupSpecDownload{ - ArangoBackupSpecOperation: backupApi.ArangoBackupSpecOperation{ - RepositoryURL: "S3 URL", - }, - ID: string(backupMeta.ID), + obj.Spec.Upload = &backupApi.ArangoBackupSpecOperation{ + RepositoryURL: "S3 URL", } obj.Status.Progress = &backupApi.ArangoBackupProgress{ @@ -204,16 +205,13 @@ func Test_State_Uploading_TemporaryFailedProgress(t *testing.T) { backupMeta, err := mock.Get(createResponse.ID) require.NoError(t, err) - progress, err := mock.Download(backupMeta.ID) + progress, err := mock.Upload(backupMeta.ID) require.NoError(t, err) obj.Status.Backup = createBackupFromMeta(backupMeta, nil) - obj.Spec.Download = &backupApi.ArangoBackupSpecDownload{ - ArangoBackupSpecOperation: backupApi.ArangoBackupSpecOperation{ - RepositoryURL: "S3 URL", - }, - ID: string(backupMeta.ID), + obj.Spec.Upload = &backupApi.ArangoBackupSpecOperation{ + RepositoryURL: "S3 URL", } obj.Status.Progress = &backupApi.ArangoBackupProgress{ @@ -248,16 +246,13 @@ func Test_State_Uploading_NotFoundProgress(t *testing.T) { backupMeta, err := mock.Get(createResponse.ID) require.NoError(t, err) - progress, err := mock.Download(backupMeta.ID) + progress, err := mock.Upload(backupMeta.ID) require.NoError(t, err) obj.Status.Backup = createBackupFromMeta(backupMeta, nil) - obj.Spec.Download = &backupApi.ArangoBackupSpecDownload{ - ArangoBackupSpecOperation: backupApi.ArangoBackupSpecOperation{ - RepositoryURL: "S3 URL", - }, - ID: string(backupMeta.ID), + obj.Spec.Upload = &backupApi.ArangoBackupSpecOperation{ + RepositoryURL: "S3 URL", } obj.Status.Progress = &backupApi.ArangoBackupProgress{ @@ -276,3 +271,69 @@ func Test_State_Uploading_NotFoundProgress(t *testing.T) { require.Equal(t, fmt.Sprintf("job with id %s does not exist anymore", progress), newObj.Status.Message) require.Nil(t, newObj.Status.Progress) } + +func Test_StateUploading_Abort_Success(t *testing.T) { + // Arrange + handler, mock := newErrorsFakeHandler(mockErrorsArangoClientBackup{}) + + obj, deployment := newObjectSet(backupApi.ArangoBackupStateUploading) + + createResponse, err := mock.Create() + require.NoError(t, err) + + backupMeta, err := mock.Get(createResponse.ID) + require.NoError(t, err) + + progress, err := mock.Upload(backupMeta.ID) + require.NoError(t, err) + + obj.Status.Backup = createBackupFromMeta(backupMeta, nil) + + obj.Status.Progress = &backupApi.ArangoBackupProgress{ + JobID: string(progress), + } + + // Act + createArangoDeployment(t, handler, deployment) + createArangoBackup(t, handler, obj) + + require.NoError(t, handler.Handle(newItemFromBackup(operation.Update, obj))) + + // Assert + newObj := refreshArangoBackup(t, handler, obj) + checkBackup(t, newObj, backupApi.ArangoBackupStateReady, true) +} + +func Test_StateUploading_Abort_Fail(t *testing.T) { + // Arrange + handler, mock := newErrorsFakeHandler(mockErrorsArangoClientBackup{ + abortError: newTemporaryErrorf("error"), + }) + + obj, deployment := newObjectSet(backupApi.ArangoBackupStateUploading) + + createResponse, err := mock.Create() + require.NoError(t, err) + + backupMeta, err := mock.Get(createResponse.ID) + require.NoError(t, err) + + progress, err := mock.Upload(backupMeta.ID) + require.NoError(t, err) + + obj.Status.Backup = createBackupFromMeta(backupMeta, nil) + + obj.Status.Progress = &backupApi.ArangoBackupProgress{ + JobID: string(progress), + } + + // Act + createArangoDeployment(t, handler, deployment) + createArangoBackup(t, handler, obj) + + require.NoError(t, handler.Handle(newItemFromBackup(operation.Update, obj))) + + // Assert + newObj := refreshArangoBackup(t, handler, obj) + checkBackup(t, newObj, backupApi.ArangoBackupStateUploading, true) +}