Merge pull request #608 from skriss/no-pv-snapshot-if-restic-backup

don't snapshot volumes that have been backed up with restic
This commit is contained in:
Andy Goldstein
2018-06-28 13:27:30 -04:00
committed by GitHub
9 changed files with 223 additions and 61 deletions
+1
View File
@@ -286,6 +286,7 @@ func (kb *kubernetesBackupper) Backup(backup *api.Backup, backupFile, logFile io
resourceHooks,
kb.snapshotService,
resticBackupper,
newPVCSnapshotTracker(),
)
for _, group := range kb.discoveryHelper.Resources() {
+5
View File
@@ -542,6 +542,7 @@ func TestBackup(t *testing.T) {
test.expectedHooks,
mock.Anything,
mock.Anything, // restic backupper
mock.Anything, // pvc snapshot tracker
).Return(groupBackupper)
for group, err := range test.backupGroupErrors {
@@ -606,6 +607,7 @@ func TestBackupUsesNewCohabitatingResourcesForEachBackup(t *testing.T) {
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
).Return(&mockGroupBackupper{})
assert.NoError(t, b.Backup(&v1.Backup{}, &bytes.Buffer{}, &bytes.Buffer{}, nil))
@@ -637,6 +639,7 @@ func TestBackupUsesNewCohabitatingResourcesForEachBackup(t *testing.T) {
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
).Return(&mockGroupBackupper{})
assert.NoError(t, b.Backup(&v1.Backup{}, &bytes.Buffer{}, &bytes.Buffer{}, nil))
@@ -665,6 +668,7 @@ func (f *mockGroupBackupperFactory) newGroupBackupper(
resourceHooks []resourceHook,
snapshotService cloudprovider.SnapshotService,
resticBackupper restic.Backupper,
resticSnapshotTracker *pvcSnapshotTracker,
) groupBackupper {
args := f.Called(
log,
@@ -681,6 +685,7 @@ func (f *mockGroupBackupperFactory) newGroupBackupper(
resourceHooks,
snapshotService,
resticBackupper,
resticSnapshotTracker,
)
return args.Get(0).(groupBackupper)
}
+5
View File
@@ -51,6 +51,7 @@ type groupBackupperFactory interface {
resourceHooks []resourceHook,
snapshotService cloudprovider.SnapshotService,
resticBackupper restic.Backupper,
resticSnapshotTracker *pvcSnapshotTracker,
) groupBackupper
}
@@ -70,6 +71,7 @@ func (f *defaultGroupBackupperFactory) newGroupBackupper(
resourceHooks []resourceHook,
snapshotService cloudprovider.SnapshotService,
resticBackupper restic.Backupper,
resticSnapshotTracker *pvcSnapshotTracker,
) groupBackupper {
return &defaultGroupBackupper{
log: log,
@@ -86,6 +88,7 @@ func (f *defaultGroupBackupperFactory) newGroupBackupper(
resourceHooks: resourceHooks,
snapshotService: snapshotService,
resticBackupper: resticBackupper,
resticSnapshotTracker: resticSnapshotTracker,
resourceBackupperFactory: &defaultResourceBackupperFactory{},
}
}
@@ -108,6 +111,7 @@ type defaultGroupBackupper struct {
resourceHooks []resourceHook
snapshotService cloudprovider.SnapshotService
resticBackupper restic.Backupper
resticSnapshotTracker *pvcSnapshotTracker
resourceBackupperFactory resourceBackupperFactory
}
@@ -131,6 +135,7 @@ func (gb *defaultGroupBackupper) backupGroup(group *metav1.APIResourceList) erro
gb.resourceHooks,
gb.snapshotService,
gb.resticBackupper,
gb.resticSnapshotTracker,
)
)
+5
View File
@@ -89,6 +89,7 @@ func TestBackupGroup(t *testing.T) {
resourceHooks,
nil, // snapshot service
nil, // restic backupper
newPVCSnapshotTracker(),
).(*defaultGroupBackupper)
resourceBackupperFactory := &mockResourceBackupperFactory{}
@@ -113,6 +114,7 @@ func TestBackupGroup(t *testing.T) {
resourceHooks,
nil,
mock.Anything, // restic backupper
mock.Anything, // pvc snapshot tracker
).Return(resourceBackupper)
group := &metav1.APIResourceList{
@@ -161,6 +163,7 @@ func (rbf *mockResourceBackupperFactory) newResourceBackupper(
resourceHooks []resourceHook,
snapshotService cloudprovider.SnapshotService,
resticBackupper restic.Backupper,
resticSnapshotTracker *pvcSnapshotTracker,
) resourceBackupper {
args := rbf.Called(
log,
@@ -176,6 +179,8 @@ func (rbf *mockResourceBackupperFactory) newResourceBackupper(
tarWriter,
resourceHooks,
snapshotService,
resticBackupper,
resticSnapshotTracker,
)
return args.Get(0).(resourceBackupper)
}
+78 -60
View File
@@ -28,7 +28,6 @@ import (
corev1api "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -58,6 +57,7 @@ type itemBackupperFactory interface {
discoveryHelper discovery.Helper,
snapshotService cloudprovider.SnapshotService,
resticBackupper restic.Backupper,
resticSnapshotTracker *pvcSnapshotTracker,
) ItemBackupper
}
@@ -75,6 +75,7 @@ func (f *defaultItemBackupperFactory) newItemBackupper(
discoveryHelper discovery.Helper,
snapshotService cloudprovider.SnapshotService,
resticBackupper restic.Backupper,
resticSnapshotTracker *pvcSnapshotTracker,
) ItemBackupper {
ib := &defaultItemBackupper{
backup: backup,
@@ -90,7 +91,8 @@ func (f *defaultItemBackupperFactory) newItemBackupper(
itemHookHandler: &defaultItemHookHandler{
podCommandExecutor: podCommandExecutor,
},
resticBackupper: resticBackupper,
resticBackupper: resticBackupper,
resticSnapshotTracker: resticSnapshotTracker,
}
// this is for testing purposes
@@ -104,17 +106,18 @@ type ItemBackupper interface {
}
type defaultItemBackupper struct {
backup *api.Backup
namespaces *collections.IncludesExcludes
resources *collections.IncludesExcludes
backedUpItems map[itemKey]struct{}
actions []resolvedAction
tarWriter tarWriter
resourceHooks []resourceHook
dynamicFactory client.DynamicFactory
discoveryHelper discovery.Helper
snapshotService cloudprovider.SnapshotService
resticBackupper restic.Backupper
backup *api.Backup
namespaces *collections.IncludesExcludes
resources *collections.IncludesExcludes
backedUpItems map[itemKey]struct{}
actions []resolvedAction
tarWriter tarWriter
resourceHooks []resourceHook
dynamicFactory client.DynamicFactory
discoveryHelper discovery.Helper
snapshotService cloudprovider.SnapshotService
resticBackupper restic.Backupper
resticSnapshotTracker *pvcSnapshotTracker
itemHookHandler itemHookHandler
additionalItemBackupper ItemBackupper
@@ -178,9 +181,30 @@ func (ib *defaultItemBackupper) backupItem(logger logrus.FieldLogger, obj runtim
return err
}
backupErrs := make([]error, 0)
err = ib.executeActions(log, obj, groupResource, name, namespace, metadata)
if err != nil {
var (
backupErrs []error
pod *corev1api.Pod
resticVolumesToBackup []string
)
if groupResource == kuberesource.Pods {
// pod needs to be initialized for the unstructured converter
pod = new(corev1api.Pod)
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), pod); err != nil {
backupErrs = append(backupErrs, errors.WithStack(err))
// nil it on error since it's not valid
pod = nil
} else {
// get the volumes to backup using restic, and add any of them that are PVCs to the pvc snapshot
// tracker, so that when we backup PVCs/PVs via an item action in the next step, we don't snapshot
// PVs that will have their data backed up with restic.
resticVolumesToBackup = restic.GetVolumesToBackup(pod)
ib.resticSnapshotTracker.Track(pod, resticVolumesToBackup)
}
}
if err := ib.executeActions(log, obj, groupResource, name, namespace, metadata); err != nil {
log.WithError(err).Error("Error executing item actions")
backupErrs = append(backupErrs, err)
}
@@ -188,24 +212,22 @@ func (ib *defaultItemBackupper) backupItem(logger logrus.FieldLogger, obj runtim
if groupResource == kuberesource.PersistentVolumes {
if ib.snapshotService == nil {
log.Debug("Skipping Persistent Volume snapshot because they're not enabled.")
} else {
if err := ib.takePVSnapshot(obj, ib.backup, log); err != nil {
backupErrs = append(backupErrs, err)
}
} else if err := ib.takePVSnapshot(obj, ib.backup, log); err != nil {
backupErrs = append(backupErrs, err)
}
}
if groupResource == kuberesource.Pods && len(restic.GetVolumesToBackup(metadata)) > 0 {
var (
updatedObj runtime.Unstructured
errs []error
)
if groupResource == kuberesource.Pods && pod != nil {
// this function will return partial results, so process volumeSnapshots
// even if there are errors.
volumeSnapshots, errs := ib.backupPodVolumes(log, pod, resticVolumesToBackup)
if updatedObj, errs = backupPodVolumes(log, ib.backup, obj, ib.resticBackupper); len(errs) > 0 {
backupErrs = append(backupErrs, errs...)
} else {
obj = updatedObj
// annotate the pod with the successful volume snapshots
for volume, snapshot := range volumeSnapshots {
restic.SetPodSnapshotAnnotation(metadata, volume, snapshot)
}
backupErrs = append(backupErrs, errs...)
}
log.Debug("Executing post hooks")
@@ -248,37 +270,19 @@ func (ib *defaultItemBackupper) backupItem(logger logrus.FieldLogger, obj runtim
return nil
}
func backupPodVolumes(log logrus.FieldLogger, backup *api.Backup, obj runtime.Unstructured, backupper restic.Backupper) (runtime.Unstructured, []error) {
if backupper == nil {
// backupPodVolumes triggers restic backups of the specified pod volumes, and returns a map of volume name -> snapshot ID
// for volumes that were successfully backed up, and a slice of any errors that were encountered.
func (ib *defaultItemBackupper) backupPodVolumes(log logrus.FieldLogger, pod *corev1api.Pod, volumes []string) (map[string]string, []error) {
if len(volumes) == 0 {
return nil, nil
}
if ib.resticBackupper == nil {
log.Warn("No restic backupper, not backing up pod's volumes")
return obj, nil
return nil, nil
}
pod := new(corev1api.Pod)
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), pod); err != nil {
return nil, []error{errors.WithStack(err)}
}
volumeSnapshots, errs := backupper.BackupPodVolumes(backup, pod, log)
if len(errs) > 0 {
return nil, errs
}
if len(volumeSnapshots) == 0 {
return obj, nil
}
// annotate the pod with the successful volume snapshots
for volume, snapshot := range volumeSnapshots {
restic.SetPodSnapshotAnnotation(pod, volume, snapshot)
}
// convert annotated pod back to unstructured to return
unstructuredObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(pod)
if err != nil {
return nil, []error{errors.WithStack(err)}
}
return &unstructured.Unstructured{Object: unstructuredObj}, nil
return ib.resticBackupper.BackupPodVolumes(ib.backup, pod, log)
}
func (ib *defaultItemBackupper) executeActions(log logrus.FieldLogger, obj runtime.Unstructured, groupResource schema.GroupResource, name, namespace string, metadata metav1.Object) error {
@@ -347,7 +351,7 @@ const zoneLabel = "failure-domain.beta.kubernetes.io/zone"
// takePVSnapshot triggers a snapshot for the volume/disk underlying a PersistentVolume if the provided
// backup has volume snapshots enabled and the PV is of a compatible type. Also records cloud
// disk type and IOPS (if applicable) to be able to restore to current state later.
func (ib *defaultItemBackupper) takePVSnapshot(pv runtime.Unstructured, backup *api.Backup, log logrus.FieldLogger) error {
func (ib *defaultItemBackupper) takePVSnapshot(obj runtime.Unstructured, backup *api.Backup, log logrus.FieldLogger) error {
log.Info("Executing takePVSnapshot")
if backup.Spec.SnapshotVolumes != nil && !*backup.Spec.SnapshotVolumes {
@@ -355,7 +359,21 @@ func (ib *defaultItemBackupper) takePVSnapshot(pv runtime.Unstructured, backup *
return nil
}
metadata, err := meta.Accessor(pv)
pv := new(corev1api.PersistentVolume)
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), pv); err != nil {
return errors.WithStack(err)
}
// If this PV is claimed, see if we've already taken a (restic) snapshot of the contents
// of this PV. If so, don't take a snapshot.
if pv.Spec.ClaimRef != nil {
if ib.resticSnapshotTracker.Has(pv.Spec.ClaimRef.Namespace, pv.Spec.ClaimRef.Name) {
log.Info("Skipping Persistent Volume snapshot because volume has already been backed up.")
return nil
}
}
metadata, err := meta.Accessor(obj)
if err != nil {
return errors.WithStack(err)
}
@@ -370,7 +388,7 @@ func (ib *defaultItemBackupper) takePVSnapshot(pv runtime.Unstructured, backup *
log.Infof("label %q is not present on PersistentVolume", zoneLabel)
}
volumeID, err := ib.snapshotService.GetVolumeID(pv)
volumeID, err := ib.snapshotService.GetVolumeID(obj)
if err != nil {
return errors.Wrapf(err, "error getting volume ID for PersistentVolume")
}
+53 -1
View File
@@ -39,6 +39,7 @@ import (
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
)
func TestBackupItemSkips(t *testing.T) {
@@ -163,6 +164,8 @@ func TestBackupItemNoSkips(t *testing.T) {
snapshottableVolumes map[string]api.VolumeBackupInfo
snapshotError error
additionalItemError error
trackedPVCs sets.String
expectedTrackedPVCs sets.String
}{
{
name: "explicit namespace include",
@@ -293,6 +296,32 @@ func TestBackupItemNoSkips(t *testing.T) {
"vol-abc123": {SnapshotID: "snapshot-1", AvailabilityZone: "us-east-1c"},
},
},
{
name: "takePVSnapshot is not invoked for PVs when their claim is tracked in the restic PVC tracker",
namespaceIncludesExcludes: collections.NewIncludesExcludes().Includes("*"),
item: `{"apiVersion": "v1", "kind": "PersistentVolume", "metadata": {"name": "mypv", "labels": {"failure-domain.beta.kubernetes.io/zone": "us-east-1c"}}, "spec": {"claimRef": {"namespace": "pvc-ns", "name": "pvc"}, "awsElasticBlockStore": {"volumeID": "aws://us-east-1c/vol-abc123"}}}`,
expectError: false,
expectExcluded: false,
expectedTarHeaderName: "resources/persistentvolumes/cluster/mypv.json",
groupResource: "persistentvolumes",
// empty snapshottableVolumes causes a snapshotService to be created, but no
// snapshots are expected to be taken.
snapshottableVolumes: map[string]api.VolumeBackupInfo{},
trackedPVCs: sets.NewString(key("pvc-ns", "pvc"), key("another-pvc-ns", "another-pvc")),
},
{
name: "takePVSnapshot is invoked for PVs when their claim is not tracked in the restic PVC tracker",
namespaceIncludesExcludes: collections.NewIncludesExcludes().Includes("*"),
item: `{"apiVersion": "v1", "kind": "PersistentVolume", "metadata": {"name": "mypv", "labels": {"failure-domain.beta.kubernetes.io/zone": "us-east-1c"}}, "spec": {"claimRef": {"namespace": "pvc-ns", "name": "pvc"}, "awsElasticBlockStore": {"volumeID": "aws://us-east-1c/vol-abc123"}}}`,
expectError: false,
expectExcluded: false,
expectedTarHeaderName: "resources/persistentvolumes/cluster/mypv.json",
groupResource: "persistentvolumes",
snapshottableVolumes: map[string]api.VolumeBackupInfo{
"vol-abc123": {SnapshotID: "snapshot-1", AvailabilityZone: "us-east-1c"},
},
trackedPVCs: sets.NewString(key("another-pvc-ns", "another-pvc")),
},
{
name: "backup fails when takePVSnapshot fails",
namespaceIncludesExcludes: collections.NewIncludesExcludes().Includes("*"),
@@ -304,6 +333,16 @@ func TestBackupItemNoSkips(t *testing.T) {
},
snapshotError: fmt.Errorf("failure"),
},
{
name: "pod's restic PVC volume backups (only) are tracked",
item: `{"apiVersion": "v1", "kind": "Pod", "spec": {"volumes": [{"name": "volume-1", "persistentVolumeClaim": {"claimName": "bar"}},{"name": "volume-2", "persistentVolumeClaim": {"claimName": "baz"}},{"name": "volume-1", "emptyDir": {}}]}, "metadata":{"namespace":"foo","name":"bar", "annotations": {"backup.ark.heptio.com/backup-volumes": "volume-1,volume-2"}}}`,
namespaceIncludesExcludes: collections.NewIncludesExcludes().Includes("*"),
groupResource: "pods",
expectError: false,
expectExcluded: false,
expectedTarHeaderName: "resources/pods/namespaces/foo/bar.json",
expectedTrackedPVCs: sets.NewString(key("foo", "bar"), key("foo", "baz")),
},
}
for _, test := range tests {
@@ -376,6 +415,7 @@ func TestBackupItemNoSkips(t *testing.T) {
discoveryHelper,
nil, // snapshot service
nil, // restic backupper
newPVCSnapshotTracker(),
).(*defaultItemBackupper)
var snapshotService *arktest.FakeSnapshotService
@@ -388,6 +428,10 @@ func TestBackupItemNoSkips(t *testing.T) {
b.snapshotService = snapshotService
}
if test.trackedPVCs != nil {
b.resticSnapshotTracker.pvcs = test.trackedPVCs
}
// make sure the podCommandExecutor was set correctly in the real hook handler
assert.Equal(t, podCommandExecutor, b.itemHookHandler.(*defaultItemHookHandler).podCommandExecutor)
@@ -469,7 +513,7 @@ func TestBackupItemNoSkips(t *testing.T) {
}
if test.snapshottableVolumes != nil {
require.Equal(t, 1, len(snapshotService.SnapshotsTaken))
require.Equal(t, len(test.snapshottableVolumes), len(snapshotService.SnapshotsTaken))
var expectedBackups []api.VolumeBackupInfo
for _, vbi := range test.snapshottableVolumes {
@@ -483,6 +527,14 @@ func TestBackupItemNoSkips(t *testing.T) {
assert.Equal(t, expectedBackups, actualBackups)
}
if test.expectedTrackedPVCs != nil {
require.Equal(t, len(test.expectedTrackedPVCs), len(b.resticSnapshotTracker.pvcs))
for key := range test.expectedTrackedPVCs {
assert.True(t, b.resticSnapshotTracker.pvcs.Has(key))
}
}
})
}
}
+61
View File
@@ -0,0 +1,61 @@
/*
Copyright 2018 the Heptio Ark contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package backup
import (
"fmt"
corev1api "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/sets"
)
// pvcSnapshotTracker keeps track of persistent volume claims that have been snapshotted
// with restic.
type pvcSnapshotTracker struct {
pvcs sets.String
}
func newPVCSnapshotTracker() *pvcSnapshotTracker {
return &pvcSnapshotTracker{
pvcs: sets.NewString(),
}
}
// Track takes a pod and a list of volumes from that pod that were snapshotted, and
// tracks each snapshotted volume that's a PVC.
func (t *pvcSnapshotTracker) Track(pod *corev1api.Pod, snapshottedVolumes []string) {
for _, volumeName := range snapshottedVolumes {
// if the volume is a PVC, track it
for _, volume := range pod.Spec.Volumes {
if volume.Name == volumeName {
if volume.PersistentVolumeClaim != nil {
t.pvcs.Insert(key(pod.Namespace, volume.PersistentVolumeClaim.ClaimName))
}
break
}
}
}
}
// Has returns true if the PVC with the specified namespace and name has been tracked.
func (t *pvcSnapshotTracker) Has(namespace, name string) bool {
return t.pvcs.Has(key(namespace, name))
}
func key(namespace, name string) string {
return fmt.Sprintf("%s/%s", namespace, name)
}
+5
View File
@@ -53,6 +53,7 @@ type resourceBackupperFactory interface {
resourceHooks []resourceHook,
snapshotService cloudprovider.SnapshotService,
resticBackupper restic.Backupper,
resticSnapshotTracker *pvcSnapshotTracker,
) resourceBackupper
}
@@ -73,6 +74,7 @@ func (f *defaultResourceBackupperFactory) newResourceBackupper(
resourceHooks []resourceHook,
snapshotService cloudprovider.SnapshotService,
resticBackupper restic.Backupper,
resticSnapshotTracker *pvcSnapshotTracker,
) resourceBackupper {
return &defaultResourceBackupper{
log: log,
@@ -89,6 +91,7 @@ func (f *defaultResourceBackupperFactory) newResourceBackupper(
resourceHooks: resourceHooks,
snapshotService: snapshotService,
resticBackupper: resticBackupper,
resticSnapshotTracker: resticSnapshotTracker,
itemBackupperFactory: &defaultItemBackupperFactory{},
}
}
@@ -112,6 +115,7 @@ type defaultResourceBackupper struct {
resourceHooks []resourceHook
snapshotService cloudprovider.SnapshotService
resticBackupper restic.Backupper
resticSnapshotTracker *pvcSnapshotTracker
itemBackupperFactory itemBackupperFactory
}
@@ -187,6 +191,7 @@ func (rb *defaultResourceBackupper) backupResource(
rb.discoveryHelper,
rb.snapshotService,
rb.resticBackupper,
rb.resticSnapshotTracker,
)
namespacesToList := getNamespacesToList(rb.namespaces)
+10
View File
@@ -272,6 +272,7 @@ func TestBackupResource(t *testing.T) {
resourceHooks,
nil, // snapshot service
nil, // restic backupper
newPVCSnapshotTracker(),
).(*defaultResourceBackupper)
itemBackupperFactory := &mockItemBackupperFactory{}
@@ -295,6 +296,7 @@ func TestBackupResource(t *testing.T) {
discoveryHelper,
mock.Anything,
mock.Anything,
mock.Anything,
).Return(itemBackupper)
if len(test.listResponses) > 0 {
@@ -438,6 +440,7 @@ func TestBackupResourceCohabitation(t *testing.T) {
resourceHooks,
nil, // snapshot service
nil, // restic backupper
newPVCSnapshotTracker(),
).(*defaultResourceBackupper)
itemBackupperFactory := &mockItemBackupperFactory{}
@@ -460,6 +463,7 @@ func TestBackupResourceCohabitation(t *testing.T) {
discoveryHelper,
mock.Anything, // snapshot service
mock.Anything, // restic backupper
mock.Anything, // pvc snapshot tracker
).Return(itemBackupper)
client := &arktest.FakeDynamicClient{}
@@ -519,6 +523,7 @@ func TestBackupResourceOnlyIncludesSpecifiedNamespaces(t *testing.T) {
resourceHooks,
nil, // snapshot service
nil, // restic backupper
newPVCSnapshotTracker(),
).(*defaultResourceBackupper)
itemBackupperFactory := &mockItemBackupperFactory{}
@@ -555,6 +560,7 @@ func TestBackupResourceOnlyIncludesSpecifiedNamespaces(t *testing.T) {
discoveryHelper,
mock.Anything,
mock.Anything,
mock.Anything,
).Return(itemBackupper)
client := &arktest.FakeDynamicClient{}
@@ -622,6 +628,7 @@ func TestBackupResourceListAllNamespacesExcludesCorrectly(t *testing.T) {
resourceHooks,
nil, // snapshot service
nil, // restic backupper
newPVCSnapshotTracker(),
).(*defaultResourceBackupper)
itemBackupperFactory := &mockItemBackupperFactory{}
@@ -647,6 +654,7 @@ func TestBackupResourceListAllNamespacesExcludesCorrectly(t *testing.T) {
discoveryHelper,
mock.Anything,
mock.Anything,
mock.Anything,
).Return(itemBackupper)
client := &arktest.FakeDynamicClient{}
@@ -684,6 +692,7 @@ func (ibf *mockItemBackupperFactory) newItemBackupper(
discoveryHelper discovery.Helper,
snapshotService cloudprovider.SnapshotService,
resticBackupper restic.Backupper,
resticSnapshotTracker *pvcSnapshotTracker,
) ItemBackupper {
args := ibf.Called(
backup,
@@ -698,6 +707,7 @@ func (ibf *mockItemBackupperFactory) newItemBackupper(
discoveryHelper,
snapshotService,
resticBackupper,
resticSnapshotTracker,
)
return args.Get(0).(ItemBackupper)
}