Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GT-350 Backup lifetime - remove Backup once its lifetime has been reached #1262

Merged
merged 6 commits into from
Jul 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Change Log

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

## [1.2.31](https://github.com/arangodb/kube-arangodb/tree/1.2.31) (2023-07-14)
- (Improvement) Block traffic on the services if there is more than 1 active leader in ActiveFailover mode
Expand Down
3 changes: 2 additions & 1 deletion docs/design/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
- [Operator API](./api.md)
- [Logging](./logging.md)
- [Manual Recovery](./recovery.md)
- [Backup](./backup.md)

## Features
- [Force rebuild out-synced Shards with broken Merkle Tree](./features/rebuild_out_synced_shards.md)
- [Failover Leader service](./features/failover_leader_service.md)
- [Restore defaults from last accepted state of deployment](./features/deployment_spec_defaults.md)
- [Restore defaults from last accepted state of deployment](./features/deployment_spec_defaults.md)
59 changes: 59 additions & 0 deletions docs/design/backup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# ArangoBackup

## Lifetime

The Lifetime of an ArangoBackup let us define the time an ArangoBackup is available in the system.
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.

```yaml
apiVersion: "backup.arangodb.com/v1alpha"
kind: "ArangoBackup"
metadata:
name: backup-with-one-day-lifetime
spec:
deployment:
name: deployment
lifetime: 1d
```

## Upload

You can upload the backup to a remote storage.
Here is an example for uploading the backup to AWS S3.

```yaml
apiVersion: "backup.arangodb.com/v1alpha"
kind: "ArangoBackup"
metadata:
name: backup-and-upload
spec:
deployment:
name: deployment
upload:
repositoryURL: "s3:BUCKET_NAME"
credentialsSecretName: upload-credentials
```

To make this work, you need to create a `upload-credentials` Secret with the credentials for the remote storage:

```yaml
apiVersion: v1
kind: Secret
metadata:
name: upload-credentials
type: Opaque
stringData:
token: |
{
"s3": {
"type": "s3",
"provider": "AWS",
"env_auth": "false",
"region": "eu-central-1",
"access_key_id": "ACCESS_KEY_ID",
"secret_access_key": "SECRECT_ACCESS_KEY",
"acl": "private",
"no_check_bucket": "true"
}
}
```
2 changes: 1 addition & 1 deletion docs/design/logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ By default, operator logs in `pretty` format.
To switch logging format to the JSON, you can use `operator.args` in chart template value:
```yaml
operator:
args: ["--log.format=pretty"]
args: ["--log.format=json"]
```

## ArangoDeployment logging
Expand Down
7 changes: 6 additions & 1 deletion pkg/apis/backup/v1/backup_spec.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// DISCLAIMER
//
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
// Copyright 2016-2023 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.
Expand All @@ -20,6 +20,8 @@

package v1

import meta "k8s.io/apimachinery/pkg/apis/meta/v1"

type ArangoBackupSpec struct {
// Deployment
Deployment ArangoBackupSpecDeployment `json:"deployment,omitempty"`
Expand All @@ -35,6 +37,9 @@ type ArangoBackupSpec struct {
PolicyName *string `json:"policyName,omitempty"`

Backoff *ArangoBackupSpecBackOff `json:"backoff,omitempty"`

jwierzbo marked this conversation as resolved.
Show resolved Hide resolved
// Lifetime is the time after which the backup will be deleted. Format: "1.5h" or "2h45m".
Lifetime *meta.Duration `json:"lifetime,omitempty"`
}

type ArangoBackupSpecDeployment struct {
Expand Down
2 changes: 1 addition & 1 deletion pkg/apis/backup/v1/backup_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const (
)

var ArangoBackupStateMap = state.Map{
ArangoBackupStateNone: {ArangoBackupStatePending},
ArangoBackupStateNone: {ArangoBackupStatePending, ArangoBackupStateFailed},
ArangoBackupStatePending: {ArangoBackupStateScheduled, ArangoBackupStateFailed},
ArangoBackupStateScheduled: {ArangoBackupStateDownload, ArangoBackupStateCreate, ArangoBackupStateFailed},
ArangoBackupStateDownload: {ArangoBackupStateDownloading, ArangoBackupStateFailed, ArangoBackupStateDownloadError},
Expand Down
6 changes: 4 additions & 2 deletions pkg/apis/backup/v1/backup_validate.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// DISCLAIMER
//
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
// Copyright 2016-2023 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.
Expand All @@ -20,7 +20,9 @@

package v1

import "github.com/arangodb/kube-arangodb/pkg/util/errors"
import (
"github.com/arangodb/kube-arangodb/pkg/util/errors"
)

func (a *ArangoBackup) Validate() error {
if err := a.Spec.Validate(); err != nil {
Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/backup/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 17 additions & 1 deletion pkg/handlers/backup/state_ready.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// DISCLAIMER
//
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
// Copyright 2016-2023 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.
Expand All @@ -21,6 +21,8 @@
package backup

import (
"time"

"github.com/arangodb/go-driver"

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

if backup.Spec.Lifetime != nil {
if backupMeta.DateTime.Add(backup.Spec.Lifetime.Duration).Before(time.Now()) {
err = client.Delete(driver.BackupID(backup.Status.Backup.ID))
if err != nil {
return nil, err
}

return wrapUpdateStatus(backup,
updateStatusState(backupApi.ArangoBackupStateDeleted, "Backup expired by lifetime"),
updateStatusAvailable(false),
)
}
}

var available = backupMeta.Available

// Temporally check if number of db servers match number of pieces
Expand Down
41 changes: 41 additions & 0 deletions pkg/handlers/backup/state_ready_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ package backup
import (
"sync"
"testing"
"time"

"github.com/stretchr/testify/require"
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/uuid"

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

func Test_State_Ready_With_Lifetime(t *testing.T) {
// Arrange
handler, mock := newErrorsFakeHandler(mockErrorsArangoClientBackup{})

obj, deployment := newObjectSet(backupApi.ArangoBackupStateReady)
obj.Spec.Lifetime = &meta.Duration{Duration: 5 * time.Second}

createResponse, err := mock.Create()
require.NoError(t, err)

backupMeta, err := mock.Get(createResponse.ID)
require.NoError(t, err)

obj.Status.Backup = createBackupFromMeta(backupMeta, nil)

// Act
createArangoDeployment(t, handler, deployment)
createArangoBackup(t, handler, obj)

t.Run("First iteration", func(t *testing.T) {
require.NoError(t, handler.Handle(newItemFromBackup(operation.Update, obj)))

// Assert
newObj := refreshArangoBackup(t, handler, obj)
checkBackup(t, newObj, backupApi.ArangoBackupStateReady, true)
compareBackupMeta(t, backupMeta, newObj)
})

t.Run("Second iteration once Lifetime is expired", func(t *testing.T) {
time.Sleep(10 * time.Second)
require.NoError(t, handler.Handle(newItemFromBackup(operation.Update, obj)))

// Assert
newObj := refreshArangoBackup(t, handler, obj)
checkBackup(t, newObj, backupApi.ArangoBackupStateDeleted, false)
compareBackupMeta(t, backupMeta, newObj)
})
}

func Test_State_Ready_Unavailable(t *testing.T) {
// Arrange
handler, mock := newErrorsFakeHandler(mockErrorsArangoClientBackup{})
Expand Down
4 changes: 2 additions & 2 deletions pkg/operatorV2/operator_worker.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// DISCLAIMER
//
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
// Copyright 2016-2023 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.
Expand Down Expand Up @@ -61,7 +61,7 @@ func (o *operator) processNextItem() bool {
err := o.processObject(obj)

if err != nil {
loggerWorker.Interface("object", obj).Error("Error during object handling")
loggerWorker.Interface("object", obj).Error("Error during object handling: %v", err)
return true
}

Expand Down