Skip to content

Commit 34ae2c0

Browse files
authored
GT-350 Backup lifetime - remove Backup once its lifetime has been reached (#1262)
1 parent 87f558f commit 34ae2c0

File tree

11 files changed

+139
-9
lines changed

11 files changed

+139
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Change Log
22

33
## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A)
4+
- (Feature) Backup lifetime - remove Backup once its lifetime has been reached
45

56
## [1.2.31](https://github.com/arangodb/kube-arangodb/tree/1.2.31) (2023-07-14)
67
- (Improvement) Block traffic on the services if there is more than 1 active leader in ActiveFailover mode

docs/design/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@
1818
- [Operator API](./api.md)
1919
- [Logging](./logging.md)
2020
- [Manual Recovery](./recovery.md)
21+
- [Backup](./backup.md)
2122

2223
## Features
2324
- [Force rebuild out-synced Shards with broken Merkle Tree](./features/rebuild_out_synced_shards.md)
2425
- [Failover Leader service](./features/failover_leader_service.md)
25-
- [Restore defaults from last accepted state of deployment](./features/deployment_spec_defaults.md)
26+
- [Restore defaults from last accepted state of deployment](./features/deployment_spec_defaults.md)

docs/design/backup.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# ArangoBackup
2+
3+
## Lifetime
4+
5+
The Lifetime of an ArangoBackup let us define the time an ArangoBackup is available in the system.
6+
E.g.: if we want to keep the ArangoBackup for 1 day, we can set the Lifetime to 1 day. After 1 day the ArangoBackup will be deleted automatically.
7+
8+
```yaml
9+
apiVersion: "backup.arangodb.com/v1alpha"
10+
kind: "ArangoBackup"
11+
metadata:
12+
name: backup-with-one-day-lifetime
13+
spec:
14+
deployment:
15+
name: deployment
16+
lifetime: 1d
17+
```
18+
19+
## Upload
20+
21+
You can upload the backup to a remote storage.
22+
Here is an example for uploading the backup to AWS S3.
23+
24+
```yaml
25+
apiVersion: "backup.arangodb.com/v1alpha"
26+
kind: "ArangoBackup"
27+
metadata:
28+
name: backup-and-upload
29+
spec:
30+
deployment:
31+
name: deployment
32+
upload:
33+
repositoryURL: "s3:BUCKET_NAME"
34+
credentialsSecretName: upload-credentials
35+
```
36+
37+
To make this work, you need to create a `upload-credentials` Secret with the credentials for the remote storage:
38+
39+
```yaml
40+
apiVersion: v1
41+
kind: Secret
42+
metadata:
43+
name: upload-credentials
44+
type: Opaque
45+
stringData:
46+
token: |
47+
{
48+
"s3": {
49+
"type": "s3",
50+
"provider": "AWS",
51+
"env_auth": "false",
52+
"region": "eu-central-1",
53+
"access_key_id": "ACCESS_KEY_ID",
54+
"secret_access_key": "SECRECT_ACCESS_KEY",
55+
"acl": "private",
56+
"no_check_bucket": "true"
57+
}
58+
}
59+
```

docs/design/logging.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ By default, operator logs in `pretty` format.
2020
To switch logging format to the JSON, you can use `operator.args` in chart template value:
2121
```yaml
2222
operator:
23-
args: ["--log.format=pretty"]
23+
args: ["--log.format=json"]
2424
```
2525

2626
## ArangoDeployment logging

pkg/apis/backup/v1/backup_spec.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -20,6 +20,8 @@
2020

2121
package v1
2222

23+
import meta "k8s.io/apimachinery/pkg/apis/meta/v1"
24+
2325
type ArangoBackupSpec struct {
2426
// Deployment
2527
Deployment ArangoBackupSpecDeployment `json:"deployment,omitempty"`
@@ -35,6 +37,9 @@ type ArangoBackupSpec struct {
3537
PolicyName *string `json:"policyName,omitempty"`
3638

3739
Backoff *ArangoBackupSpecBackOff `json:"backoff,omitempty"`
40+
41+
// Lifetime is the time after which the backup will be deleted. Format: "1.5h" or "2h45m".
42+
Lifetime *meta.Duration `json:"lifetime,omitempty"`
3843
}
3944

4045
type ArangoBackupSpecDeployment struct {

pkg/apis/backup/v1/backup_state.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const (
4545
)
4646

4747
var ArangoBackupStateMap = state.Map{
48-
ArangoBackupStateNone: {ArangoBackupStatePending},
48+
ArangoBackupStateNone: {ArangoBackupStatePending, ArangoBackupStateFailed},
4949
ArangoBackupStatePending: {ArangoBackupStateScheduled, ArangoBackupStateFailed},
5050
ArangoBackupStateScheduled: {ArangoBackupStateDownload, ArangoBackupStateCreate, ArangoBackupStateFailed},
5151
ArangoBackupStateDownload: {ArangoBackupStateDownloading, ArangoBackupStateFailed, ArangoBackupStateDownloadError},

pkg/apis/backup/v1/backup_validate.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -20,7 +20,9 @@
2020

2121
package v1
2222

23-
import "github.com/arangodb/kube-arangodb/pkg/util/errors"
23+
import (
24+
"github.com/arangodb/kube-arangodb/pkg/util/errors"
25+
)
2426

2527
func (a *ArangoBackup) Validate() error {
2628
if err := a.Spec.Validate(); err != nil {

pkg/apis/backup/v1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/handlers/backup/state_ready.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -21,6 +21,8 @@
2121
package backup
2222

2323
import (
24+
"time"
25+
2426
"github.com/arangodb/go-driver"
2527

2628
backupApi "github.com/arangodb/kube-arangodb/pkg/apis/backup/v1"
@@ -56,6 +58,20 @@ func stateReadyHandler(h *handler, backup *backupApi.ArangoBackup) (*backupApi.A
5658
)
5759
}
5860

61+
if backup.Spec.Lifetime != nil {
62+
if backupMeta.DateTime.Add(backup.Spec.Lifetime.Duration).Before(time.Now()) {
63+
err = client.Delete(driver.BackupID(backup.Status.Backup.ID))
64+
if err != nil {
65+
return nil, err
66+
}
67+
68+
return wrapUpdateStatus(backup,
69+
updateStatusState(backupApi.ArangoBackupStateDeleted, "Backup expired by lifetime"),
70+
updateStatusAvailable(false),
71+
)
72+
}
73+
}
74+
5975
var available = backupMeta.Available
6076

6177
// Temporally check if number of db servers match number of pieces

pkg/handlers/backup/state_ready_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ package backup
2323
import (
2424
"sync"
2525
"testing"
26+
"time"
2627

2728
"github.com/stretchr/testify/require"
29+
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
2830
"k8s.io/apimachinery/pkg/util/uuid"
2931

3032
"github.com/arangodb/go-driver"
@@ -66,6 +68,45 @@ func Test_State_Ready_Success(t *testing.T) {
6668
compareBackupMeta(t, backupMeta, newObj)
6769
}
6870

71+
func Test_State_Ready_With_Lifetime(t *testing.T) {
72+
// Arrange
73+
handler, mock := newErrorsFakeHandler(mockErrorsArangoClientBackup{})
74+
75+
obj, deployment := newObjectSet(backupApi.ArangoBackupStateReady)
76+
obj.Spec.Lifetime = &meta.Duration{Duration: 5 * time.Second}
77+
78+
createResponse, err := mock.Create()
79+
require.NoError(t, err)
80+
81+
backupMeta, err := mock.Get(createResponse.ID)
82+
require.NoError(t, err)
83+
84+
obj.Status.Backup = createBackupFromMeta(backupMeta, nil)
85+
86+
// Act
87+
createArangoDeployment(t, handler, deployment)
88+
createArangoBackup(t, handler, obj)
89+
90+
t.Run("First iteration", func(t *testing.T) {
91+
require.NoError(t, handler.Handle(newItemFromBackup(operation.Update, obj)))
92+
93+
// Assert
94+
newObj := refreshArangoBackup(t, handler, obj)
95+
checkBackup(t, newObj, backupApi.ArangoBackupStateReady, true)
96+
compareBackupMeta(t, backupMeta, newObj)
97+
})
98+
99+
t.Run("Second iteration once Lifetime is expired", func(t *testing.T) {
100+
time.Sleep(10 * time.Second)
101+
require.NoError(t, handler.Handle(newItemFromBackup(operation.Update, obj)))
102+
103+
// Assert
104+
newObj := refreshArangoBackup(t, handler, obj)
105+
checkBackup(t, newObj, backupApi.ArangoBackupStateDeleted, false)
106+
compareBackupMeta(t, backupMeta, newObj)
107+
})
108+
}
109+
69110
func Test_State_Ready_Unavailable(t *testing.T) {
70111
// Arrange
71112
handler, mock := newErrorsFakeHandler(mockErrorsArangoClientBackup{})

0 commit comments

Comments
 (0)