Skip to content

Commit be8ae25

Browse files
authored
[Bugfix] Allow ArangoBackup Creation during Upload state (#1009)
1 parent 1b6f047 commit be8ae25

File tree

5 files changed

+104
-53
lines changed

5 files changed

+104
-53
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
- (Feature) Set a leader in active fail-over mode
1313
- (Feature) Use policy/v1 instead policy/v1beta1
1414
- (Feature) OPS CLI with Arango Task
15+
- (Bugfix) Allow ArangoBackup Creation during Upload state
1516

1617
## [1.2.13](https://github.com/arangodb/kube-arangodb/tree/1.2.13) (2022-06-07)
1718
- (Bugfix) Fix arangosync members state inspection

pkg/handlers/backup/state_pending.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ func statePendingHandler(h *handler, backup *backupApi.ArangoBackup) (*backupApi
3030
return nil, err
3131
}
3232

33-
running, err := isBackupRunning(backup, h.client.BackupV1().ArangoBackups(backup.Namespace))
33+
states, err := countBackupStates(backup, h.client.BackupV1().ArangoBackups(backup.Namespace))
3434
if err != nil {
3535
return nil, err
3636
}
3737

38-
if running {
38+
if l := states.get(backupApi.ArangoBackupStateScheduled, backupApi.ArangoBackupStateCreate, backupApi.ArangoBackupStateDownload, backupApi.ArangoBackupStateDownloading); len(l) > 0 {
3939
return wrapUpdateStatus(backup,
4040
updateStatusState(backupApi.ArangoBackupStatePending, "backup already in process"))
4141
}

pkg/handlers/backup/state_pending_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,44 @@ func Test_State_Pending_OneBackupObject(t *testing.T) {
7878
checkBackup(t, newObj, backupApi.ArangoBackupStateScheduled, false)
7979
}
8080

81+
func Test_State_Pending_WithUploadRunning(t *testing.T) {
82+
// Arrange
83+
handler, _ := newErrorsFakeHandler(mockErrorsArangoClientBackup{})
84+
85+
obj, deployment := newObjectSet(backupApi.ArangoBackupStatePending)
86+
87+
uploading := newArangoBackup(deployment.GetName(), deployment.GetNamespace(), string(uuid.NewUUID()), backupApi.ArangoBackupStateUploading)
88+
89+
// Act
90+
createArangoDeployment(t, handler, deployment)
91+
createArangoBackup(t, handler, obj, uploading)
92+
93+
require.NoError(t, handler.Handle(newItemFromBackup(operation.Update, obj)))
94+
95+
// Assert
96+
newObj := refreshArangoBackup(t, handler, obj)
97+
checkBackup(t, newObj, backupApi.ArangoBackupStateScheduled, false)
98+
}
99+
100+
func Test_State_Pending_WithScheduled(t *testing.T) {
101+
// Arrange
102+
handler, _ := newErrorsFakeHandler(mockErrorsArangoClientBackup{})
103+
104+
obj, deployment := newObjectSet(backupApi.ArangoBackupStatePending)
105+
106+
uploading := newArangoBackup(deployment.GetName(), deployment.GetNamespace(), string(uuid.NewUUID()), backupApi.ArangoBackupStateScheduled)
107+
108+
// Act
109+
createArangoDeployment(t, handler, deployment)
110+
createArangoBackup(t, handler, obj, uploading)
111+
112+
require.NoError(t, handler.Handle(newItemFromBackup(operation.Update, obj)))
113+
114+
// Assert
115+
newObj := refreshArangoBackup(t, handler, obj)
116+
checkBackup(t, newObj, backupApi.ArangoBackupStatePending, false)
117+
}
118+
81119
func Test_State_Pending_MultipleBackupObjectWithLimitation(t *testing.T) {
82120
// Arrange
83121
handler, _ := newErrorsFakeHandler(mockErrorsArangoClientBackup{})

pkg/handlers/backup/state_ready.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ package backup
2323
import (
2424
"github.com/arangodb/go-driver"
2525
backupApi "github.com/arangodb/kube-arangodb/pkg/apis/backup/v1"
26+
"github.com/arangodb/kube-arangodb/pkg/util/globals"
2627
)
2728

2829
func stateReadyHandler(h *handler, backup *backupApi.ArangoBackup) (*backupApi.ArangoBackupStatus, error) {
@@ -71,21 +72,33 @@ func stateReadyHandler(h *handler, backup *backupApi.ArangoBackup) (*backupApi.A
7172
if backup.Spec.Upload != nil &&
7273
(backup.Status.Backup.Uploaded == nil || (backup.Status.Backup.Uploaded != nil && !*backup.Status.Backup.Uploaded)) {
7374
// Ensure that we can start upload process
74-
running, err := isBackupRunning(backup, h.client.BackupV1().ArangoBackups(backup.Namespace))
75+
states, err := countBackupStates(backup, h.client.BackupV1().ArangoBackups(backup.Namespace))
7576
if err != nil {
7677
return nil, err
7778
}
7879

79-
if running {
80-
return wrapUpdateStatus(backup,
81-
updateStatusState(backupApi.ArangoBackupStateReady, "Upload process queued"),
82-
updateStatusBackup(backupMeta),
83-
updateStatusAvailable(true),
84-
)
80+
if l := states.get(backupApi.ArangoBackupStateUpload, backupApi.ArangoBackupStateUploading); globals.GetGlobals().Backup().ConcurrentUploads().Get() > len(l) {
81+
// Check if there is no upload with same id
82+
if len(l.filter(func(b *backupApi.ArangoBackup) bool {
83+
if a1 := b.Status.Backup; a1 != nil {
84+
if a2 := backup.Status.Backup; a2 != nil {
85+
return a1.ID == a2.ID
86+
}
87+
}
88+
89+
return false
90+
})) == 0 {
91+
92+
return wrapUpdateStatus(backup,
93+
updateStatusState(backupApi.ArangoBackupStateUpload, ""),
94+
updateStatusBackup(backupMeta),
95+
updateStatusAvailable(true),
96+
)
97+
}
8598
}
8699

87100
return wrapUpdateStatus(backup,
88-
updateStatusState(backupApi.ArangoBackupStateUpload, ""),
101+
updateStatusState(backupApi.ArangoBackupStateReady, "Upload process queued"),
89102
updateStatusBackup(backupMeta),
90103
updateStatusAvailable(true),
91104
)

pkg/handlers/backup/util.go

Lines changed: 42 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ package backup
2222

2323
import (
2424
"context"
25-
"strings"
26-
27-
"github.com/arangodb/kube-arangodb/pkg/util/globals"
2825

2926
clientBackup "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/backup/v1"
3027

@@ -34,66 +31,68 @@ import (
3431
"github.com/arangodb/kube-arangodb/pkg/handlers/backup/state"
3532
)
3633

37-
var (
38-
progressStates = []state.State{
39-
backupApi.ArangoBackupStateScheduled,
40-
backupApi.ArangoBackupStateCreate,
41-
backupApi.ArangoBackupStateDownload,
42-
backupApi.ArangoBackupStateDownloading,
43-
backupApi.ArangoBackupStateUpload,
44-
backupApi.ArangoBackupStateUploading,
34+
type backupStates []*backupApi.ArangoBackup
35+
36+
func (b backupStates) filter(f func(b *backupApi.ArangoBackup) bool) backupStates {
37+
if f == nil {
38+
return nil
4539
}
46-
)
4740

48-
func inProgress(backup *backupApi.ArangoBackup) bool {
49-
for _, state := range progressStates {
50-
if state == backup.Status.State {
51-
return true
41+
r := make(backupStates, 0, len(b))
42+
43+
for id := range b {
44+
if f(b[id]) {
45+
r = append(r, b[id])
5246
}
5347
}
5448

55-
return false
49+
return r
5650
}
5751

58-
func isBackupRunning(backup *backupApi.ArangoBackup, client clientBackup.ArangoBackupInterface) (bool, error) {
52+
type backupStatesCount map[state.State]backupStates
53+
54+
func (b backupStatesCount) get(states ...state.State) backupStates {
55+
i := 0
56+
57+
for _, s := range states {
58+
i += len(b[s])
59+
}
60+
61+
if i == 0 {
62+
return nil
63+
}
64+
65+
r := make(backupStates, 0, i)
66+
67+
for _, s := range states {
68+
r = append(r, b[s]...)
69+
}
70+
71+
return r
72+
}
73+
74+
func countBackupStates(backup *backupApi.ArangoBackup, client clientBackup.ArangoBackupInterface) (backupStatesCount, error) {
5975
backups, err := client.List(context.Background(), meta.ListOptions{})
6076

6177
if err != nil {
62-
return false, newTemporaryError(err)
78+
return nil, newTemporaryError(err)
6379
}
6480

65-
currentUploads := 0
81+
ret := map[state.State]backupStates{}
6682

6783
for _, existingBackup := range backups.Items {
84+
// Skip same backup from count
6885
if existingBackup.Name == backup.Name {
6986
continue
7087
}
7188

72-
// We can upload multiple uploads from same deployment in same time
73-
if backup.Status.State == backupApi.ArangoBackupStateReady &&
74-
(existingBackup.Status.State == backupApi.ArangoBackupStateUpload || existingBackup.Status.State == backupApi.ArangoBackupStateUploading) {
75-
currentUploads++
76-
if backupUpload := backup.Status.Backup; backupUpload != nil {
77-
if existingBackupUpload := existingBackup.Status.Backup; existingBackupUpload != nil {
78-
if strings.EqualFold(backupUpload.ID, existingBackupUpload.ID) {
79-
return true, nil
80-
}
81-
}
82-
}
83-
} else {
84-
if existingBackup.Spec.Deployment.Name != backup.Spec.Deployment.Name {
85-
continue
86-
}
87-
88-
if inProgress(&existingBackup) {
89-
return true, nil
90-
}
89+
// Skip backups which are not on same deployment from count
90+
if existingBackup.Spec.Deployment.Name != backup.Spec.Deployment.Name {
91+
continue
9192
}
92-
}
9393

94-
if backup.Status.State == backupApi.ArangoBackupStateReady {
95-
return currentUploads >= globals.GetGlobals().Backup().ConcurrentUploads().Get(), nil
94+
ret[existingBackup.Status.State] = append(ret[existingBackup.Status.State], existingBackup.DeepCopy())
9695
}
9796

98-
return false, nil
97+
return ret, nil
9998
}

0 commit comments

Comments
 (0)