@@ -63,9 +63,8 @@ import (
6363// VolumePopulatorReconciler reconciles Backup dataSource PVCs.
6464type VolumePopulatorReconciler struct {
6565 client.Client
66- APIReader client.Reader
67- Scheme * runtime.Scheme
68- Recorder record.EventRecorder
66+ Scheme * runtime.Scheme
67+ Recorder record.EventRecorder
6968}
7069
7170type pvcRestoreMode string
@@ -139,9 +138,6 @@ func (r *VolumePopulatorReconciler) handleSyncPVCError(reqCtx intctrlutil.Reques
139138
140139// SetupWithManager sets up the controller with the Manager.
141140func (r * VolumePopulatorReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
142- if r .APIReader == nil {
143- r .APIReader = mgr .GetAPIReader ()
144- }
145141 return intctrlutil .NewControllerManagedBy (mgr ).
146142 For (& corev1.PersistentVolumeClaim {}).
147143 Watches (& dpv1alpha1.Restore {}, handler .EnqueueRequestsFromMapFunc (r .mapRestoreToPVCs ),
@@ -1244,97 +1240,36 @@ func (r *VolumePopulatorReconciler) completeBoundPVCIfNeeded(reqCtx intctrlutil.
12441240}
12451241
12461242// validateBoundTargetPV verifies that an already-bound target PVC points to
1247- // the PV rebound by this populator. Use the direct API reader when available so
1248- // informer ordering between the PV and PVC updates cannot create a permanent
1249- // false failure.
1243+ // the PV rebound by this populator.
12501244func (r * VolumePopulatorReconciler ) validateBoundTargetPV (reqCtx intctrlutil.RequestCtx ,
12511245 pvc * corev1.PersistentVolumeClaim ) error {
12521246 if pvc .Spec .VolumeName == "" {
12531247 return intctrlutil .NewRequeueError (reconcileInterval , "waiting for target PVC to bind" )
12541248 }
1255- reader := client .Reader (r .Client )
1256- if r .APIReader != nil {
1257- reader = r .APIReader
1258- }
12591249 pv := & corev1.PersistentVolume {}
1260- if err := reader .Get (reqCtx .Ctx , types.NamespacedName {Name : pvc .Spec .VolumeName }, pv ); err != nil {
1250+ if err := r . Client .Get (reqCtx .Ctx , types.NamespacedName {Name : pvc .Spec .VolumeName }, pv ); err != nil {
12611251 if apierrors .IsNotFound (err ) {
12621252 return intctrlutil .NewRequeueError (reconcileInterval ,
12631253 fmt .Sprintf ("waiting for target PV %s for PVC %s/%s" , pvc .Spec .VolumeName , pvc .Namespace , pvc .Name ))
12641254 }
12651255 return err
12661256 }
1267- claimRef := pv .Spec .ClaimRef
1268- claimMatches := claimRef != nil && claimRef .Namespace == pvc .Namespace && claimRef .Name == pvc .Name
1269- if claimMatches && pvc .UID != "" {
1270- claimMatches = claimRef .UID == pvc .UID
1271- }
1272- if ! claimMatches {
1257+ if ! pvClaimRefMatchesPVC (pv .Spec .ClaimRef , pvc ) {
12731258 return intctrlutil .NewFatalError (fmt .Sprintf (
12741259 "target PVC %s/%s is bound to PV %s whose claimRef does not identify the restore target" ,
12751260 pvc .Namespace , pvc .Name , pv .Name ))
12761261 }
1277- expectedAttempt , err := populationAttemptIdentity (pvc )
1278- if err != nil {
1279- return intctrlutil .NewFatalError (err .Error ())
1280- }
1281- if actualAttempt := pv .Annotations [AnnPopulationAttempt ]; actualAttempt != "" {
1282- if actualAttempt == expectedAttempt {
1283- return nil
1284- }
1262+ if pvc .Spec .DataSourceRef == nil || pvc .Spec .DataSourceRef .Name == "" {
12851263 return intctrlutil .NewFatalError (fmt .Sprintf (
1286- "target PVC %s/%s is bound to PV %s from population attempt %q, expected %q" ,
1287- pvc .Namespace , pvc .Name , pv .Name , actualAttempt , expectedAttempt ))
1264+ "target PVC %s/%s has no dataSourceRef" , pvc .Namespace , pvc .Name ))
12881265 }
1289-
1290- // Compatibility for an in-flight rebind started by an older controller:
1291- // the old marker recorded only the source name. Accept it only while the
1292- // exact helper PVC still points at this PV. A provisioner-bound empty PV
1293- // cannot satisfy this relationship.
12941266 expectedSource := pvc .Spec .DataSourceRef .Name
1295- if expectedSource != "" && pv .Annotations [AnnPopulateFrom ] == expectedSource {
1296- helper := & corev1.PersistentVolumeClaim {}
1297- helperKey := types.NamespacedName {Namespace : pvc .Namespace , Name : getPopulatePVCName (pvc .UID )}
1298- if err := reader .Get (reqCtx .Ctx , helperKey , helper ); err == nil && helper .Spec .VolumeName == pv .Name {
1299- return nil
1300- } else if err != nil && apierrors .IsNotFound (err ) && pvcBindingCompleted (pvc ) {
1301- // An older controller wrote AnnPopulateFrom before deleting the helper
1302- // and before recording population success. If Kubernetes has already
1303- // completed the target binding, the exact target ClaimRef validated
1304- // above plus the legacy marker is sufficient to resume after an upgrade.
1305- return nil
1306- } else if err != nil && ! apierrors .IsNotFound (err ) {
1307- return err
1308- }
1309- }
1310- return intctrlutil .NewFatalError (fmt .Sprintf (
1311- "target PVC %s/%s is bound to PV %s without expected population provenance %s=%q" ,
1312- pvc .Namespace , pvc .Name , pv .Name , AnnPopulationAttempt , expectedAttempt ))
1313- }
1314-
1315- func populationAttemptIdentity (pvc * corev1.PersistentVolumeClaim ) (string , error ) {
1316- if pvc .UID == "" {
1317- return "" , fmt .Errorf ("target PVC %s/%s has no UID" , pvc .Namespace , pvc .Name )
1318- }
1319- if pvc .Spec .DataSourceRef == nil || pvc .Spec .DataSourceRef .Name == "" {
1320- return "" , fmt .Errorf ("target PVC %s/%s has no dataSourceRef identity" , pvc .Namespace , pvc .Name )
1321- }
1322- apiGroup := ""
1323- if pvc .Spec .DataSourceRef .APIGroup != nil {
1324- apiGroup = * pvc .Spec .DataSourceRef .APIGroup
1325- }
1326- sourceNamespace := pvc .Namespace
1327- if pvc .Spec .DataSourceRef .Kind == dptypes .BackupKind {
1328- var err error
1329- sourceNamespace , err = backupNamespaceFromPVC (pvc )
1330- if err != nil {
1331- return "" , err
1332- }
1333- } else if pvc .Spec .DataSourceRef .Namespace != nil && * pvc .Spec .DataSourceRef .Namespace != "" {
1334- sourceNamespace = * pvc .Spec .DataSourceRef .Namespace
1267+ if pv .Annotations [AnnPopulateFrom ] != expectedSource {
1268+ return intctrlutil .NewFatalError (fmt .Sprintf (
1269+ "target PVC %s/%s is bound to PV %s without expected population provenance %s=%q" ,
1270+ pvc .Namespace , pvc .Name , pv .Name , AnnPopulateFrom , expectedSource ))
13351271 }
1336- return fmt .Sprintf ("v1|%s|%s|%s|%s|%s" , pvc .UID , apiGroup , pvc .Spec .DataSourceRef .Kind ,
1337- sourceNamespace , pvc .Spec .DataSourceRef .Name ), nil
1272+ return nil
13381273}
13391274
13401275func (r * VolumePopulatorReconciler ) waitForSerialPredecessors (reqCtx intctrlutil.RequestCtx ,
@@ -2089,16 +2024,12 @@ func (r *VolumePopulatorReconciler) rebindPVCAndPV(reqCtx intctrlutil.RequestCtx
20892024 if populatePVC .Spec .VolumeName == "" {
20902025 return false , nil
20912026 }
2092- attempt , err := populationAttemptIdentity (pvc )
2093- if err != nil {
2094- return false , intctrlutil .NewFatalError (err .Error ())
2095- }
2096- reader := client .Reader (r .Client )
2097- if r .APIReader != nil {
2098- reader = r .APIReader
2027+ if pvc .Spec .DataSourceRef == nil || pvc .Spec .DataSourceRef .Name == "" {
2028+ return false , intctrlutil .NewFatalError (fmt .Sprintf (
2029+ "target PVC %s/%s has no dataSourceRef" , pvc .Namespace , pvc .Name ))
20992030 }
21002031 pv := & corev1.PersistentVolume {}
2101- if err := reader .Get (reqCtx .Ctx , types.NamespacedName {Name : populatePVC .Spec .VolumeName }, pv ); err != nil {
2032+ if err := r . Client .Get (reqCtx .Ctx , types.NamespacedName {Name : populatePVC .Spec .VolumeName }, pv ); err != nil {
21022033 if ! apierrors .IsNotFound (err ) {
21032034 return false , err
21042035 }
@@ -2108,28 +2039,10 @@ func (r *VolumePopulatorReconciler) rebindPVCAndPV(reqCtx intctrlutil.RequestCtx
21082039 // Examine the claimref for the PV and see if it's bound to the correct PVC
21092040 claimRef := pv .Spec .ClaimRef
21102041 if pvClaimRefMatchesPVC (claimRef , pvc ) {
2111- actualAttempt := pv .Annotations [AnnPopulationAttempt ]
2112- if actualAttempt != attempt {
2113- legacyRebind := actualAttempt == "" &&
2114- pv .Annotations [AnnPopulateFrom ] == pvc .Spec .DataSourceRef .Name &&
2115- populatePVC .Namespace == pvc .Namespace &&
2116- populatePVC .Name == getPopulatePVCName (pvc .UID ) &&
2117- populatePVC .Spec .VolumeName == pv .Name
2118- if ! legacyRebind {
2119- return false , intctrlutil .NewFatalError (fmt .Sprintf (
2120- "PV %s already identifies target PVC %s/%s but does not carry population attempt %q" ,
2121- pv .Name , pvc .Namespace , pvc .Name , attempt ))
2122- }
2123- // Resume an old controller that patched the PV ClaimRef and legacy
2124- // marker, then crashed before writing targetPVC.spec.volumeName.
2125- patchPV := client .MergeFromWithOptions (pv .DeepCopy (), client.MergeFromWithOptimisticLock {})
2126- if pv .Annotations == nil {
2127- pv .Annotations = map [string ]string {}
2128- }
2129- pv .Annotations [AnnPopulationAttempt ] = attempt
2130- if err := r .Client .Patch (reqCtx .Ctx , pv , patchPV ); err != nil {
2131- return false , requeuePVRebindConflict (err , pv , pvc )
2132- }
2042+ if pv .Annotations [AnnPopulateFrom ] != pvc .Spec .DataSourceRef .Name {
2043+ return false , intctrlutil .NewFatalError (fmt .Sprintf (
2044+ "PV %s already identifies target PVC %s/%s without expected population provenance %s=%q" ,
2045+ pv .Name , pvc .Namespace , pvc .Name , AnnPopulateFrom , pvc .Spec .DataSourceRef .Name ))
21332046 }
21342047 return true , r .bindTargetPVCToPV (reqCtx , pvc , pv .Name )
21352048 }
@@ -2150,7 +2063,6 @@ func (r *VolumePopulatorReconciler) rebindPVCAndPV(reqCtx intctrlutil.RequestCtx
21502063 pv .Annotations = map [string ]string {}
21512064 }
21522065 pv .Annotations [AnnPopulateFrom ] = pvc .Spec .DataSourceRef .Name
2153- pv .Annotations [AnnPopulationAttempt ] = attempt
21542066 if err := r .Client .Patch (reqCtx .Ctx , pv , patchPV ); err != nil {
21552067 return false , requeuePVRebindConflict (err , pv , pvc )
21562068 }
0 commit comments