Kopia Pod Volume Backup/Restore (#5259)

* kopia pvbr

Signed-off-by: Lyndon-Li <lyonghui@vmware.com>
This commit is contained in:
lyndon
2022-09-05 10:29:30 +08:00
committed by GitHub
parent a5a3df193d
commit 0282e65221
19 changed files with 441 additions and 95 deletions
+3 -13
View File
@@ -45,6 +45,8 @@ import (
"github.com/vmware-tanzu/velero/pkg/util/kube"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/vmware-tanzu/velero/pkg/podvolume"
)
const (
@@ -506,17 +508,5 @@ func getSnapshotsInBackup(ctx context.Context, backup *velerov1api.Backup, kbCli
return nil, errors.WithStack(err)
}
var res []repository.SnapshotIdentifier
for _, item := range podVolumeBackups.Items {
if item.Status.SnapshotID == "" {
continue
}
res = append(res, repository.SnapshotIdentifier{
VolumeNamespace: item.Spec.Pod.Namespace,
BackupStorageLocation: backup.Spec.StorageLocation,
SnapshotID: item.Status.SnapshotID,
})
}
return res, nil
return podvolume.GetSnapshotIdentifier(podVolumeBackups), nil
}
@@ -771,10 +771,12 @@ func TestGetSnapshotsInBackup(t *testing.T) {
{
VolumeNamespace: "ns-1",
SnapshotID: "snap-3",
RepositoryType: "restic",
},
{
VolumeNamespace: "ns-1",
SnapshotID: "snap-4",
RepositoryType: "restic",
},
},
},
@@ -822,6 +824,7 @@ func TestGetSnapshotsInBackup(t *testing.T) {
{
VolumeNamespace: "ns-1",
SnapshotID: "snap-3",
RepositoryType: "restic",
},
},
},
+28 -16
View File
@@ -32,39 +32,34 @@ import (
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/repository"
repoconfig "github.com/vmware-tanzu/velero/pkg/repository/config"
"github.com/vmware-tanzu/velero/pkg/restic"
"github.com/vmware-tanzu/velero/pkg/util/kube"
)
const (
repoSyncPeriod = 5 * time.Minute
repoSyncPeriod = 5 * time.Minute
defaultMaintainFrequency = 7 * 24 * time.Hour
)
type ResticRepoReconciler struct {
client.Client
namespace string
logger logrus.FieldLogger
clock clock.Clock
defaultMaintenanceFrequency time.Duration
repositoryManager repository.Manager
namespace string
logger logrus.FieldLogger
clock clock.Clock
maintenanceFrequency time.Duration
repositoryManager repository.Manager
}
func NewResticRepoReconciler(namespace string, logger logrus.FieldLogger, client client.Client,
defaultMaintenanceFrequency time.Duration, repositoryManager repository.Manager) *ResticRepoReconciler {
maintenanceFrequency time.Duration, repositoryManager repository.Manager) *ResticRepoReconciler {
c := &ResticRepoReconciler{
client,
namespace,
logger,
clock.RealClock{},
defaultMaintenanceFrequency,
maintenanceFrequency,
repositoryManager,
}
if c.defaultMaintenanceFrequency <= 0 {
logger.Infof("Invalid default restic maintenance frequency, setting to %v", restic.DefaultMaintenanceFrequency)
c.defaultMaintenanceFrequency = restic.DefaultMaintenanceFrequency
}
return c
}
@@ -135,7 +130,7 @@ func (r *ResticRepoReconciler) initializeRepo(ctx context.Context, req *velerov1
rr.Status.Phase = velerov1api.BackupRepositoryPhaseNotReady
if rr.Spec.MaintenanceFrequency.Duration <= 0 {
rr.Spec.MaintenanceFrequency = metav1.Duration{Duration: r.defaultMaintenanceFrequency}
rr.Spec.MaintenanceFrequency = metav1.Duration{Duration: r.getRepositoryMaintenanceFrequency(req)}
}
})
}
@@ -145,7 +140,7 @@ func (r *ResticRepoReconciler) initializeRepo(ctx context.Context, req *velerov1
rr.Spec.ResticIdentifier = repoIdentifier
if rr.Spec.MaintenanceFrequency.Duration <= 0 {
rr.Spec.MaintenanceFrequency = metav1.Duration{Duration: r.defaultMaintenanceFrequency}
rr.Spec.MaintenanceFrequency = metav1.Duration{Duration: r.getRepositoryMaintenanceFrequency(req)}
}
}); err != nil {
return err
@@ -161,6 +156,23 @@ func (r *ResticRepoReconciler) initializeRepo(ctx context.Context, req *velerov1
})
}
func (r *ResticRepoReconciler) getRepositoryMaintenanceFrequency(req *velerov1api.BackupRepository) time.Duration {
if r.maintenanceFrequency > 0 {
r.logger.WithField("frequency", r.maintenanceFrequency).Info("Set user defined maintenance frequency")
return r.maintenanceFrequency
} else {
frequency, err := r.repositoryManager.DefaultMaintenanceFrequency(req)
if err != nil || frequency <= 0 {
r.logger.WithError(err).WithField("returned frequency", frequency).Warn("Failed to get maitanance frequency, use the default one")
frequency = defaultMaintainFrequency
} else {
r.logger.WithField("frequency", frequency).Info("Set matainenance according to repository suggestion")
}
return frequency
}
}
// ensureRepo checks to see if a repository exists, and attempts to initialize it if
// it does not exist. An error is returned if the repository can't be connected to
// or initialized.
@@ -15,20 +15,23 @@ package controller
import (
"context"
"errors"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/repository"
repomokes "github.com/vmware-tanzu/velero/pkg/repository/mocks"
velerotest "github.com/vmware-tanzu/velero/pkg/test"
)
const defaultMaintenanceFrequency = 10 * time.Minute
const testMaintenanceFrequency = 10 * time.Minute
func mockResticRepoReconciler(t *testing.T, rr *velerov1api.BackupRepository, mockOn string, arg interface{}, ret interface{}) *ResticRepoReconciler {
mgr := &repomokes.RepositoryManager{}
@@ -39,7 +42,7 @@ func mockResticRepoReconciler(t *testing.T, rr *velerov1api.BackupRepository, mo
velerov1api.DefaultNamespace,
velerotest.NewLogger(),
velerotest.NewFakeControllerRuntimeClient(t),
defaultMaintenanceFrequency,
testMaintenanceFrequency,
mgr,
)
}
@@ -51,7 +54,7 @@ func mockResticRepositoryCR() *velerov1api.BackupRepository {
Name: "repo",
},
Spec: velerov1api.BackupRepositorySpec{
MaintenanceFrequency: metav1.Duration{defaultMaintenanceFrequency},
MaintenanceFrequency: metav1.Duration{testMaintenanceFrequency},
},
}
@@ -138,7 +141,7 @@ func TestResticRepoReconcile(t *testing.T) {
Name: "unknown",
},
Spec: velerov1api.BackupRepositorySpec{
MaintenanceFrequency: metav1.Duration{defaultMaintenanceFrequency},
MaintenanceFrequency: metav1.Duration{testMaintenanceFrequency},
},
},
expectNil: true,
@@ -151,7 +154,7 @@ func TestResticRepoReconcile(t *testing.T) {
Name: "repo",
},
Spec: velerov1api.BackupRepositorySpec{
MaintenanceFrequency: metav1.Duration{defaultMaintenanceFrequency},
MaintenanceFrequency: metav1.Duration{testMaintenanceFrequency},
},
},
expectNil: true,
@@ -164,7 +167,7 @@ func TestResticRepoReconcile(t *testing.T) {
Name: "repo",
},
Spec: velerov1api.BackupRepositorySpec{
MaintenanceFrequency: metav1.Duration{defaultMaintenanceFrequency},
MaintenanceFrequency: metav1.Duration{testMaintenanceFrequency},
},
Status: velerov1api.BackupRepositoryStatus{
Phase: velerov1api.BackupRepositoryPhaseNew,
@@ -187,3 +190,53 @@ func TestResticRepoReconcile(t *testing.T) {
})
}
}
func TestGetRepositoryMaintenanceFrequency(t *testing.T) {
tests := []struct {
name string
mgr repository.Manager
repo *velerov1api.BackupRepository
freqReturn time.Duration
freqError error
userDefinedFreq time.Duration
expectFreq time.Duration
}{
{
name: "user defined valid",
userDefinedFreq: time.Duration(time.Hour),
expectFreq: time.Duration(time.Hour),
},
{
name: "repo return valid",
freqReturn: time.Duration(time.Hour * 2),
expectFreq: time.Duration(time.Hour * 2),
},
{
name: "fall to default",
userDefinedFreq: -1,
freqError: errors.New("fake-error"),
expectFreq: defaultMaintainFrequency,
},
{
name: "fall to default, no freq error",
freqReturn: -1,
expectFreq: defaultMaintainFrequency,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
mgr := repomokes.RepositoryManager{}
mgr.On("DefaultMaintenanceFrequency", mock.Anything).Return(test.freqReturn, test.freqError)
reconciler := NewResticRepoReconciler(
velerov1api.DefaultNamespace,
velerotest.NewLogger(),
velerotest.NewFakeControllerRuntimeClient(t),
test.userDefinedFreq,
&mgr,
)
freq := reconciler.getRepositoryMaintenanceFrequency(test.repo)
assert.Equal(t, test.expectFreq, freq)
})
}
}