mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-01-03 11:45:20 +00:00
@@ -304,6 +304,10 @@ func (r *RestoreMicroService) cancelPodVolumeRestore(pvr *velerov1api.PodVolumeR
|
||||
}
|
||||
}
|
||||
|
||||
var funcRemoveAll = os.RemoveAll
|
||||
var funcMkdirAll = os.MkdirAll
|
||||
var funcWriteFile = os.WriteFile
|
||||
|
||||
func writeCompletionMark(pvr *velerov1api.PodVolumeRestore, result datapath.RestoreResult, log logrus.FieldLogger) error {
|
||||
volumePath := result.Target.ByPath
|
||||
if volumePath == "" {
|
||||
@@ -314,7 +318,7 @@ func writeCompletionMark(pvr *velerov1api.PodVolumeRestore, result datapath.Rest
|
||||
// of this volume, which we don't want to carry over). If this fails for any reason, log and continue, since
|
||||
// this is non-essential cleanup (the done files are named based on restore UID and the init container looks
|
||||
// for the one specific to the restore being executed).
|
||||
if err := os.RemoveAll(filepath.Join(volumePath, ".velero")); err != nil {
|
||||
if err := funcRemoveAll(filepath.Join(volumePath, ".velero")); err != nil {
|
||||
log.WithError(err).Warnf("Failed to remove .velero directory from directory %s", volumePath)
|
||||
}
|
||||
|
||||
@@ -326,14 +330,14 @@ func writeCompletionMark(pvr *velerov1api.PodVolumeRestore, result datapath.Rest
|
||||
|
||||
// Create the .velero directory within the volume dir so we can write a done file
|
||||
// for this restore.
|
||||
if err := os.MkdirAll(filepath.Join(volumePath, ".velero"), 0755); err != nil {
|
||||
if err := funcMkdirAll(filepath.Join(volumePath, ".velero"), 0755); err != nil {
|
||||
return errors.Wrapf(err, "error creating .velero directory for done file")
|
||||
}
|
||||
|
||||
// Write a done file with name=<restore-uid> into the just-created .velero dir
|
||||
// within the volume. The velero init container on the pod is waiting
|
||||
// for this file to exist in each restored volume before completing.
|
||||
if err := os.WriteFile(filepath.Join(volumePath, ".velero", string(restoreUID)), nil, 0644); err != nil { //nolint:gosec // Internal usage. No need to check.
|
||||
if err := funcWriteFile(filepath.Join(volumePath, ".velero", string(restoreUID)), nil, 0644); err != nil {
|
||||
return errors.Wrapf(err, "error writing done file")
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package podvolume
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -42,6 +43,8 @@ import (
|
||||
kbclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
datapathmockes "github.com/vmware-tanzu/velero/pkg/datapath/mocks"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type restoreMsTestHelper struct {
|
||||
@@ -468,3 +471,152 @@ func TestRunCancelableDataPathRestore(t *testing.T) {
|
||||
|
||||
cancel()
|
||||
}
|
||||
|
||||
func TestWriteCompletionMark(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
pvr *velerov1api.PodVolumeRestore
|
||||
result datapath.RestoreResult
|
||||
funcRemoveAll func(string) error
|
||||
funcMkdirAll func(string, os.FileMode) error
|
||||
funcWriteFile func(string, []byte, os.FileMode) error
|
||||
expectedErr string
|
||||
expectedLog string
|
||||
}{
|
||||
{
|
||||
name: "no volume path",
|
||||
result: datapath.RestoreResult{},
|
||||
expectedErr: "target volume is empty in restore result",
|
||||
},
|
||||
{
|
||||
name: "no owner reference",
|
||||
result: datapath.RestoreResult{
|
||||
Target: datapath.AccessPoint{
|
||||
ByPath: "fake-volume-path",
|
||||
},
|
||||
},
|
||||
pvr: builder.ForPodVolumeRestore(velerov1api.DefaultNamespace, "fake-pvr").Result(),
|
||||
funcRemoveAll: func(string) error {
|
||||
return nil
|
||||
},
|
||||
expectedErr: "error finding restore UID",
|
||||
},
|
||||
{
|
||||
name: "mkdir fail",
|
||||
result: datapath.RestoreResult{
|
||||
Target: datapath.AccessPoint{
|
||||
ByPath: "fake-volume-path",
|
||||
},
|
||||
},
|
||||
pvr: builder.ForPodVolumeRestore(velerov1api.DefaultNamespace, "fake-pvr").OwnerReference([]metav1.OwnerReference{
|
||||
{
|
||||
UID: "fake-uid",
|
||||
},
|
||||
}).Result(),
|
||||
funcRemoveAll: func(string) error {
|
||||
return nil
|
||||
},
|
||||
funcMkdirAll: func(string, os.FileMode) error {
|
||||
return errors.New("fake-mk-dir-error")
|
||||
},
|
||||
expectedErr: "error creating .velero directory for done file: fake-mk-dir-error",
|
||||
},
|
||||
{
|
||||
name: "write file fail",
|
||||
result: datapath.RestoreResult{
|
||||
Target: datapath.AccessPoint{
|
||||
ByPath: "fake-volume-path",
|
||||
},
|
||||
},
|
||||
pvr: builder.ForPodVolumeRestore(velerov1api.DefaultNamespace, "fake-pvr").OwnerReference([]metav1.OwnerReference{
|
||||
{
|
||||
UID: "fake-uid",
|
||||
},
|
||||
}).Result(),
|
||||
funcRemoveAll: func(string) error {
|
||||
return nil
|
||||
},
|
||||
funcMkdirAll: func(string, os.FileMode) error {
|
||||
return nil
|
||||
},
|
||||
funcWriteFile: func(string, []byte, os.FileMode) error {
|
||||
return errors.New("fake-write-file-error")
|
||||
},
|
||||
expectedErr: "error writing done file: fake-write-file-error",
|
||||
},
|
||||
{
|
||||
name: "succeed",
|
||||
result: datapath.RestoreResult{
|
||||
Target: datapath.AccessPoint{
|
||||
ByPath: "fake-volume-path",
|
||||
},
|
||||
},
|
||||
pvr: builder.ForPodVolumeRestore(velerov1api.DefaultNamespace, "fake-pvr").OwnerReference([]metav1.OwnerReference{
|
||||
{
|
||||
UID: "fake-uid",
|
||||
},
|
||||
}).Result(),
|
||||
funcRemoveAll: func(string) error {
|
||||
return nil
|
||||
},
|
||||
funcMkdirAll: func(string, os.FileMode) error {
|
||||
return nil
|
||||
},
|
||||
funcWriteFile: func(string, []byte, os.FileMode) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "succeed but previous dir is not removed",
|
||||
result: datapath.RestoreResult{
|
||||
Target: datapath.AccessPoint{
|
||||
ByPath: "fake-volume-path",
|
||||
},
|
||||
},
|
||||
pvr: builder.ForPodVolumeRestore(velerov1api.DefaultNamespace, "fake-pvr").OwnerReference([]metav1.OwnerReference{
|
||||
{
|
||||
UID: "fake-uid",
|
||||
},
|
||||
}).Result(),
|
||||
funcRemoveAll: func(string) error {
|
||||
return errors.New("fake-remove-dir-error")
|
||||
},
|
||||
funcMkdirAll: func(string, os.FileMode) error {
|
||||
return nil
|
||||
},
|
||||
funcWriteFile: func(string, []byte, os.FileMode) error {
|
||||
return nil
|
||||
},
|
||||
expectedLog: "Failed to remove .velero directory from directory fake-volume-path",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
if test.funcRemoveAll != nil {
|
||||
funcRemoveAll = test.funcRemoveAll
|
||||
}
|
||||
|
||||
if test.funcMkdirAll != nil {
|
||||
funcMkdirAll = test.funcMkdirAll
|
||||
}
|
||||
|
||||
if test.funcWriteFile != nil {
|
||||
funcWriteFile = test.funcWriteFile
|
||||
}
|
||||
|
||||
logBuffer := ""
|
||||
err := writeCompletionMark(test.pvr, test.result, velerotest.NewSingleLogger(&logBuffer))
|
||||
|
||||
if test.expectedErr == "" {
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
assert.EqualError(t, err, test.expectedErr)
|
||||
}
|
||||
|
||||
if test.expectedLog != "" {
|
||||
assert.Contains(t, logBuffer, test.expectedLog)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user