Skip to content

Commit

Permalink
Reconcile related drpcs when drcluster is deleted
Browse files Browse the repository at this point in the history
- When filtering update events, consider also the update when the new
  object is marked for deletion.
- When filtering drpcs consider all drpcs referencing a deleted
  drcluster.

With this change, when a drcluster is deleted, the drpc controller
updates the VRG ManifestWork on the remaining cluster. Previously this
happened minutes after a drcluster was deleted.

Notes:

- We don't get a delete event when the drcluster is deleted, but an
  update event. I don't know if this is a bug in controller runtime or
  expected behavior.

Signed-off-by: Nir Soffer <[email protected]>
  • Loading branch information
nirs authored and ShyamsundarR committed Jan 12, 2024
1 parent bfe93e7 commit 2b66f98
Showing 1 changed file with 83 additions and 3 deletions.
86 changes: 83 additions & 3 deletions controllers/drplacementcontrol_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ func DRClusterPredicateFunc() predicate.Funcs {
// DRClusterUpdateOfInterest checks if the new DRCluster resource as compared to the older version
// requires any attention, it checks for the following updates:
// - If any maintenance mode is reported as activated
// - If drcluster was marked for deletion
//
// TODO: Needs some logs for easier troubleshooting
func DRClusterUpdateOfInterest(oldDRCluster, newDRCluster *rmn.DRCluster) bool {
Expand All @@ -303,8 +304,8 @@ func DRClusterUpdateOfInterest(oldDRCluster, newDRCluster *rmn.DRCluster) bool {
}
}

// Exhausted all failover activation checks, this update is NOT of interest
return false
// Exhausted all failover activation checks, the only interesting update is deleting a drcluster.
return drClusterIsDeleted(newDRCluster)
}

// checkFailoverActivation checks if provided provisioner and storage instance is activated as per the
Expand Down Expand Up @@ -347,7 +348,16 @@ func getFailoverActivatedCondition(mMode rmn.ClusterMaintenanceMode) *metav1.Con
func (r *DRPlacementControlReconciler) FilterDRCluster(drcluster *rmn.DRCluster) []ctrl.Request {
log := ctrl.Log.WithName("DRPCFilter").WithName("DRCluster").WithValues("cluster", drcluster)

drpcCollections, err := DRPCsFailingOverToCluster(r.Client, log, drcluster.GetName())
var drpcCollections []DRPCAndPolicy

var err error

if drClusterIsDeleted(drcluster) {
drpcCollections, err = DRPCsUsingDRCluster(r.Client, log, drcluster)
} else {
drpcCollections, err = DRPCsFailingOverToCluster(r.Client, log, drcluster.GetName())
}

if err != nil {
log.Info("Failed to process filter")

Expand All @@ -373,6 +383,76 @@ type DRPCAndPolicy struct {
drPolicy *rmn.DRPolicy
}

// DRPCsUsingDRCluster finds DRPC resources using the DRcluster.
func DRPCsUsingDRCluster(k8sclient client.Client, log logr.Logger, drcluster *rmn.DRCluster) ([]DRPCAndPolicy, error) {
drpolicies := &rmn.DRPolicyList{}
if err := k8sclient.List(context.TODO(), drpolicies); err != nil {
log.Error(err, "Failed to list DRPolicies", "drcluster", drcluster.GetName())

return nil, err
}

found := []DRPCAndPolicy{}

for i := range drpolicies.Items {
drpolicy := &drpolicies.Items[i]

for _, clusterName := range drpolicy.Spec.DRClusters {
if clusterName != drcluster.GetName() {
continue
}

log.Info("Found DRPolicy referencing DRCluster", "drpolicy", drpolicy.GetName())

drpcs, err := DRPCsUsingDRPolicy(k8sclient, log, drpolicy)
if err != nil {
return nil, err
}

for _, drpc := range drpcs {
found = append(found, DRPCAndPolicy{drpc: drpc, drPolicy: drpolicy})
}

break
}
}

return found, nil
}

// DRPCsUsingDRPolicy finds DRPC resources that reference the DRPolicy.
func DRPCsUsingDRPolicy(
k8sclient client.Client,
log logr.Logger,
drpolicy *rmn.DRPolicy,
) ([]*rmn.DRPlacementControl, error) {
drpcs := &rmn.DRPlacementControlList{}
if err := k8sclient.List(context.TODO(), drpcs); err != nil {
log.Error(err, "Failed to list DRPCs", "drpolicy", drpolicy.GetName())

return nil, err
}

found := []*rmn.DRPlacementControl{}

for i := range drpcs.Items {
drpc := &drpcs.Items[i]

if drpc.Spec.DRPolicyRef.Name != drpolicy.GetName() {
continue
}

log.Info("Found DRPC referencing drpolicy",
"name", drpc.GetName(),
"namespace", drpc.GetNamespace(),
"drpolicy", drpolicy.GetName())

found = append(found, drpc)
}

return found, nil
}

// DRPCsFailingOverToCluster lists DRPC resources that are failing over to the passed in drcluster
//
//nolint:gocognit
Expand Down

0 comments on commit 2b66f98

Please sign in to comment.