fix(restore): guard against nil PVC in in-place restore preflight checks

Signed-off-by: Abhayraj Jaiswal <abhayraj916146@gmail.com>
This commit is contained in:
Abhayraj Jaiswal
2026-09-10 09:54:50 +00:00
parent 3df8ef0567
commit b51a2b20d3
2 changed files with 29 additions and 2 deletions
+7
View File
@@ -50,6 +50,10 @@ func CheckPVCNotInUse(
pvc *corev1api.PersistentVolumeClaim,
restoreUID types.UID,
) error {
if pvc == nil {
return errors.New("pvc cannot be nil")
}
podList := new(corev1api.PodList)
if err := cli.List(ctx, podList, &crclient.ListOptions{Namespace: pvc.Namespace}); err != nil {
return errors.Wrapf(err, "failed to check whether PVC %s/%s is in use: failed to list pods in namespace %s", pvc.Namespace, pvc.Name, pvc.Namespace)
@@ -139,6 +143,9 @@ func gatedByThisRestore(pod *corev1api.Pod, restoreUID types.UID) bool {
// bound to a different PV (the documented cross-namespace clone-and-restore
// workflow), and when the backed-up PV name is unknown.
func CheckPVCBoundToBackedUpPV(existingPVC *corev1api.PersistentVolumeClaim, backedUpPVName, sourceNamespace string) error {
if existingPVC == nil {
return errors.New("existing PVC cannot be nil")
}
if existingPVC.Status.Phase != corev1api.ClaimBound {
return errors.Errorf("in-place restore pre-flight check failed, skipping volume data restore: PVC %s/%s is not bound (phase %s)",
existingPVC.Namespace, existingPVC.Name, existingPVC.Status.Phase)
+22 -2
View File
@@ -82,10 +82,16 @@ func TestCheckPVCNotInUse(t *testing.T) {
tests := []struct {
name string
pods []*corev1api.Pod
pvc *corev1api.PersistentVolumeClaim
restoreUID types.UID
expectPass bool
expectMessage []string
expectError string
}{
{
name: "nil PVC returns error",
expectError: "pvc cannot be nil",
},
{
name: "no pods, check passes",
expectPass: true,
@@ -183,11 +189,19 @@ func TestCheckPVCNotInUse(t *testing.T) {
}
cli := velerotest.NewFakeControllerRuntimeClient(t, objs...)
pvc := &corev1api.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{Name: "pvc-1", Namespace: "default"},
pvc := tc.pvc
if pvc == nil && tc.name != "nil PVC returns error" {
pvc = &corev1api.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{Name: "pvc-1", Namespace: "default"},
}
}
err := CheckPVCNotInUse(t.Context(), cli, pvc, tc.restoreUID)
if tc.expectError != "" {
require.Error(t, err)
assert.EqualError(t, err, tc.expectError)
return
}
if tc.expectPass {
require.NoError(t, err)
return
@@ -216,6 +230,12 @@ func TestCheckPVCBoundToBackedUpPV(t *testing.T) {
backedUpPVName string
expectError string
}{
{
name: "nil existing PVC returns error",
existingPVC: nil,
backedUpPVName: "pv-1",
expectError: "existing PVC cannot be nil",
},
{
name: "bound to the backed-up PV, check passes",
existingPVC: pvc("default", "pv-1", corev1api.ClaimBound),