open-cluster-management.io/governance-policy-propagator@v0.13.0/controllers/propagator/replicatepolicy_pd_eventHandler.go (about)

     1  package propagator
     2  
     3  import (
     4  	"context"
     5  
     6  	"k8s.io/apimachinery/pkg/types"
     7  	"k8s.io/client-go/util/workqueue"
     8  	clusterv1beta1 "open-cluster-management.io/api/cluster/v1beta1"
     9  	"sigs.k8s.io/controller-runtime/pkg/client"
    10  	"sigs.k8s.io/controller-runtime/pkg/event"
    11  	"sigs.k8s.io/controller-runtime/pkg/handler"
    12  	"sigs.k8s.io/controller-runtime/pkg/reconcile"
    13  
    14  	"open-cluster-management.io/governance-policy-propagator/controllers/common"
    15  )
    16  
    17  // HandlerForDecision maps a PlacementDecision
    18  // to all replicated policies that are in namespace as a decision cluster name.
    19  // The name of replicated policy is rootpolicy name + namespace which is in Placementbinding subject
    20  func HandlerForDecision(c client.Client) handler.EventHandler {
    21  	return &handlerForDecision{
    22  		c,
    23  	}
    24  }
    25  
    26  type handlerForDecision struct {
    27  	c client.Client
    28  }
    29  
    30  // Create implements EventHandler.
    31  func (e *handlerForDecision) Create(ctx context.Context,
    32  	evt event.CreateEvent, q workqueue.RateLimitingInterface,
    33  ) {
    34  	e.mapAndEnqueue(ctx, q, evt.Object)
    35  }
    36  
    37  // Update implements EventHandler. Update only targeted(modified) objects
    38  func (e *handlerForDecision) Update(ctx context.Context,
    39  	evt event.UpdateEvent, q workqueue.RateLimitingInterface,
    40  ) {
    41  	log.V(1).Info("Detect placementDecision and update targeted replicated-policies")
    42  	//nolint:forcetypeassert
    43  	newObj := evt.ObjectNew.(*clusterv1beta1.PlacementDecision)
    44  	//nolint:forcetypeassert
    45  	oldObj := evt.ObjectOld.(*clusterv1beta1.PlacementDecision)
    46  
    47  	placementName := newObj.GetLabels()["cluster.open-cluster-management.io/placement"]
    48  	if placementName == "" {
    49  		return
    50  	}
    51  
    52  	newOjbDecisions := newObj.Status.Decisions
    53  	oldObjDecisions := oldObj.Status.Decisions
    54  
    55  	// Select only affected(Deleted in old or Created in new) objs
    56  	affectedDecisions := common.GetAffectedObjs(newOjbDecisions, oldObjDecisions)
    57  
    58  	// These is no change. Nothing to reconcile
    59  	if len(affectedDecisions) == 0 {
    60  		return
    61  	}
    62  
    63  	rootPolicyResults, err := common.GetRootPolicyRequests(ctx, e.c,
    64  		newObj.GetNamespace(), placementName, common.Placement)
    65  	if err != nil {
    66  		log.Error(err, "Failed to get RootPolicyResults to update by decision event")
    67  
    68  		return
    69  	}
    70  
    71  	for _, pr := range rootPolicyResults {
    72  		for _, decision := range affectedDecisions {
    73  			q.Add(reconcile.Request{NamespacedName: types.NamespacedName{
    74  				Namespace: decision.ClusterName,
    75  				Name:      pr.Namespace + "." + pr.Name,
    76  			}})
    77  		}
    78  	}
    79  }
    80  
    81  // Delete implements EventHandler.
    82  func (e *handlerForDecision) Delete(ctx context.Context,
    83  	evt event.DeleteEvent, q workqueue.RateLimitingInterface,
    84  ) {
    85  	e.mapAndEnqueue(ctx, q, evt.Object)
    86  }
    87  
    88  // Generic implements EventHandler.
    89  func (e *handlerForDecision) Generic(ctx context.Context,
    90  	evt event.GenericEvent, q workqueue.RateLimitingInterface,
    91  ) {
    92  	e.mapAndEnqueue(ctx, q, evt.Object)
    93  }
    94  
    95  func (e *handlerForDecision) mapAndEnqueue(ctx context.Context,
    96  	q workqueue.RateLimitingInterface, obj client.Object,
    97  ) {
    98  	pDecision := obj.(*clusterv1beta1.PlacementDecision)
    99  	reqs := e.getMappedReplicatedPolicy(ctx, pDecision)
   100  
   101  	for _, req := range reqs {
   102  		q.Add(req)
   103  	}
   104  }
   105  
   106  func (e *handlerForDecision) getMappedReplicatedPolicy(ctx context.Context,
   107  	pDecision *clusterv1beta1.PlacementDecision,
   108  ) []reconcile.Request {
   109  	if len(pDecision.Status.Decisions) == 0 {
   110  		return nil
   111  	}
   112  
   113  	placementName := pDecision.GetLabels()["cluster.open-cluster-management.io/placement"]
   114  	if placementName == "" {
   115  		return nil
   116  	}
   117  
   118  	rootPolicyResults, err := common.GetRootPolicyRequests(ctx, e.c,
   119  		pDecision.GetNamespace(), placementName, common.Placement)
   120  	if err != nil {
   121  		log.Error(err, "Failed to get RootPolicyResults by decision events")
   122  
   123  		return nil
   124  	}
   125  
   126  	var result []reconcile.Request
   127  
   128  	for _, pr := range rootPolicyResults {
   129  		for _, decision := range pDecision.Status.Decisions {
   130  			result = append(result, reconcile.Request{NamespacedName: types.NamespacedName{
   131  				Namespace: decision.ClusterName,
   132  				Name:      pr.Namespace + "." + pr.Name,
   133  			}})
   134  		}
   135  	}
   136  
   137  	return result
   138  }