diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e18ae527..f4686c82c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - (Feature) JobScheduler Coverage - (Feature) JobScheduler Volumes, Probes, Lifecycle and Ports integration - (Feature) Merge ArangoDB Usage Metrics +- (Bugfix) Check Connection to the ArangoDB before creating Backup ## [1.2.38](https://github.com/arangodb/kube-arangodb/tree/1.2.38) (2024-02-22) - (Feature) Extract GRPC Server diff --git a/pkg/handlers/backup/arango_client.go b/pkg/handlers/backup/arango_client.go index a99bee6ed..177e4ae9d 100644 --- a/pkg/handlers/backup/arango_client.go +++ b/pkg/handlers/backup/arango_client.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany +// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -75,5 +75,7 @@ type ArangoBackupClient interface { Exists(driver.BackupID) (bool, error) Delete(driver.BackupID) error + HealthCheck() error + List() (map[driver.BackupID]driver.BackupMeta, error) } diff --git a/pkg/handlers/backup/arango_client_impl.go b/pkg/handlers/backup/arango_client_impl.go index c4bfe2d59..0792e547c 100644 --- a/pkg/handlers/backup/arango_client_impl.go +++ b/pkg/handlers/backup/arango_client_impl.go @@ -292,3 +292,11 @@ func (ac *arangoClientBackupImpl) Abort(jobID driver.BackupTransferJobID) error return ac.driver.Backup().Abort(ctx, jobID) } + +func (ac *arangoClientBackupImpl) HealthCheck() error { + ctx, cancel := globals.GetGlobalTimeouts().BackupArangoClientTimeout().WithTimeout(context.Background()) + defer cancel() + + _, err := ac.driver.Version(ctx) + return err +} diff --git a/pkg/handlers/backup/arango_client_mock_test.go b/pkg/handlers/backup/arango_client_mock_test.go index 8ada1a85e..69388c047 100644 --- a/pkg/handlers/backup/arango_client_mock_test.go +++ b/pkg/handlers/backup/arango_client_mock_test.go @@ -64,7 +64,7 @@ func newMockArangoClientBackup(errors mockErrorsArangoClientBackup) *mockArangoC } type mockErrorsArangoClientBackup struct { - createError, listError, getError, uploadError, downloadError, progressError, existsError, deleteError, abortError error + createError, listError, getError, uploadError, downloadError, progressError, existsError, deleteError, abortError, healthCheckError error } type mockArangoClientBackupState struct { @@ -245,6 +245,10 @@ func (m *mockArangoClientBackup) CreateAsync(jobID string) (ArangoBackupCreateRe return ArangoBackupCreateResponse{}, async.NewErrorAsyncJobInProgress(jobID) } +func (m *mockArangoClientBackup) HealthCheck() error { + return m.state.errors.healthCheckError +} + func (m *mockArangoClientBackup) getIDs() []string { ret := make([]string, 0, len(m.state.backups)) diff --git a/pkg/handlers/backup/state_create.go b/pkg/handlers/backup/state_create.go index 9c11288aa..78b4debfa 100644 --- a/pkg/handlers/backup/state_create.go +++ b/pkg/handlers/backup/state_create.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany +// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -39,6 +39,15 @@ func stateCreateHandler(h *handler, backup *backupApi.ArangoBackup) (*backupApi. return nil, newTemporaryError(err) } + if err := client.HealthCheck(); err != nil { + return wrapUpdateStatus(backup, + updateStatusState(backupApi.ArangoBackupStateCreateError, "Create failed on HealthCheck with error: %s", err.Error()), + cleanStatusJob(), + updateStatusAvailable(false), + addBackOff(backup.Spec), + ) + } + if features.AsyncBackupCreation().Enabled() { return asyncBackup(client, backup) } else { diff --git a/pkg/handlers/backup/state_create_test.go b/pkg/handlers/backup/state_create_test.go index b9fa893ce..f3538dbff 100644 --- a/pkg/handlers/backup/state_create_test.go +++ b/pkg/handlers/backup/state_create_test.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany +// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -153,6 +153,30 @@ func Test_State_Create_Upload(t *testing.T) { compareBackupMeta(t, backupMeta, newObj) } +func Test_State_Create_CreateError_Health(t *testing.T) { + *features.AsyncBackupCreation().EnabledPointer() = false + + // Arrange + handler, _ := newErrorsFakeHandler(mockErrorsArangoClientBackup{ + healthCheckError: newFatalErrorf("error"), + }) + + obj, deployment := newObjectSet(t, backupApi.ArangoBackupStateCreate) + + // Act + createArangoDeployment(t, handler, deployment) + createArangoBackup(t, handler, obj) + + require.NoError(t, handler.Handle(context.Background(), tests.NewItem(t, operation.Update, obj))) + + // Assert + newObj := refreshArangoBackup(t, handler, obj) + require.Equal(t, newObj.Status.State, backupApi.ArangoBackupStateCreateError) + require.Equal(t, newObj.Status.Message, "Create failed on HealthCheck with error: error") + require.Nil(t, newObj.Status.Backup) + require.False(t, newObj.Status.Available) +} + func Test_State_Create_CreateError(t *testing.T) { *features.AsyncBackupCreation().EnabledPointer() = false