Skip to content

Commit f4836f7

Browse files
authored
fix: release populated PVC before postReady restore (#10334)
1 parent a414e31 commit f4836f7

2 files changed

Lines changed: 77 additions & 0 deletions

File tree

controllers/dataprotection/volumepopulator_controller.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,12 @@ func (r *VolumePopulatorReconciler) completeBoundPVCIfNeeded(reqCtx intctrlutil.
10081008
}
10091009
break
10101010
}
1011+
// Release the target PVC after prepareData and PV rebind. PostReady actions
1012+
// may need the workload pod to start, which cannot happen while the populate
1013+
// PVC still owns the restored PV.
1014+
if err := r.Cleanup(reqCtx, pvc); err != nil {
1015+
return err
1016+
}
10111017
postReadyCompleted, err := r.ensurePostReadyRestoreCompleted(reqCtx, pvc, restoreCtx)
10121018
if err != nil {
10131019
return err

controllers/dataprotection/volumepopulator_controller_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,77 @@ func TestEnsurePostReadyRestoreCompletedUsesOneRestorePerComponent(t *testing.T)
12461246
require.Equal(t, backup.Name, restoreList.Items[0].Spec.Backup.Name)
12471247
}
12481248

1249+
func TestCompleteBoundPVCReleasesPopulatePVCBeforeWaitingForPostReady(t *testing.T) {
1250+
scheme := runtime.NewScheme()
1251+
require.NoError(t, corev1.AddToScheme(scheme))
1252+
require.NoError(t, batchv1.AddToScheme(scheme))
1253+
require.NoError(t, kbappsv1.AddToScheme(scheme))
1254+
require.NoError(t, dpv1alpha1.AddToScheme(scheme))
1255+
apiGroup := dptypes.DataprotectionAPIGroup
1256+
backup := newBackupForRestoreDecision([]string{"data"}, nil)
1257+
pvc := newPVCForRestoreDecision("data", "mysql", "")
1258+
pvc.UID = types.UID("target-pvc")
1259+
pvc.Finalizers = []string{dptypes.DataProtectionFinalizerName}
1260+
pvc.Spec.VolumeName = "data-pv"
1261+
pvc.Spec.DataSourceRef = &corev1.TypedObjectReference{
1262+
APIGroup: &apiGroup,
1263+
Kind: dptypes.BackupKind,
1264+
Name: backup.Name,
1265+
}
1266+
pvc.Annotations[constant.RestoreSourceKindAnnotationKey] = dptypes.BackupKind
1267+
pvc.Annotations[constant.RestoreSourceNamespaceAnnotationKey] = backup.Namespace
1268+
populatePVC := &corev1.PersistentVolumeClaim{
1269+
ObjectMeta: metav1.ObjectMeta{
1270+
Namespace: pvc.Namespace,
1271+
Name: getPopulatePVCName(pvc.UID),
1272+
},
1273+
Spec: corev1.PersistentVolumeClaimSpec{
1274+
VolumeName: "data-pv",
1275+
},
1276+
}
1277+
comp := &kbappsv1.Component{
1278+
ObjectMeta: metav1.ObjectMeta{
1279+
Namespace: "default",
1280+
Name: constant.GenerateClusterComponentName("cluster", "mysql"),
1281+
UID: "component-uid",
1282+
},
1283+
Status: kbappsv1.ComponentStatus{
1284+
Phase: kbappsv1.CreatingComponentPhase,
1285+
Conditions: []metav1.Condition{{
1286+
Type: kbappsv1.ComponentConditionProgressing,
1287+
Status: metav1.ConditionTrue,
1288+
Reason: "PostProvision",
1289+
}},
1290+
},
1291+
}
1292+
reconciler := &VolumePopulatorReconciler{
1293+
Client: fake.NewClientBuilder().WithScheme(scheme).
1294+
WithStatusSubresource(pvc).
1295+
WithObjects(backup, pvc, populatePVC, comp).
1296+
Build(),
1297+
Scheme: scheme,
1298+
Recorder: record.NewFakeRecorder(10),
1299+
}
1300+
restoreMgr := dprestore.NewRestoreManager(&dpv1alpha1.Restore{
1301+
Spec: dpv1alpha1.RestoreSpec{Backup: dpv1alpha1.BackupRef{Name: backup.Name, Namespace: backup.Namespace}},
1302+
}, nil, scheme, reconciler.Client)
1303+
restoreMgr.PostReadyBackupSets = []dprestore.BackupActionSet{{Backup: backup}}
1304+
1305+
err := reconciler.completeBoundPVCIfNeeded(
1306+
intctrlutil.RequestCtx{Ctx: context.Background()},
1307+
pvc,
1308+
&pvcRestoreContext{restoreMgr: restoreMgr, mode: pvcRestoreModeRestoreData},
1309+
)
1310+
1311+
require.Error(t, err)
1312+
require.True(t, intctrlutil.IsRequeueError(err), err)
1313+
currentPVC := &corev1.PersistentVolumeClaim{}
1314+
require.NoError(t, reconciler.Client.Get(context.Background(), client.ObjectKeyFromObject(pvc), currentPVC))
1315+
require.NotContains(t, currentPVC.Finalizers, dptypes.DataProtectionFinalizerName)
1316+
currentPopulatePVC := &corev1.PersistentVolumeClaim{}
1317+
require.Error(t, reconciler.Client.Get(context.Background(), client.ObjectKeyFromObject(populatePVC), currentPopulatePVC))
1318+
}
1319+
12491320
func TestEnsurePostReadyRestoreCompletedRejectsMismatchedExistingRestore(t *testing.T) {
12501321
scheme := runtime.NewScheme()
12511322
require.NoError(t, corev1.AddToScheme(scheme))

0 commit comments

Comments
 (0)