open-cluster-management.io/governance-policy-propagator@v0.13.0/controllers/propagator/replicatepolicy_pr_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  	appsv1 "open-cluster-management.io/multicloud-operators-subscription/pkg/apis/apps/placementrule/v1"
     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  // HandlerForRule maps a PlacementRule to all replicated policies which are in the namespace as
    18  // PlacementRule status.decisions. This finds placementBindings, of which placementRef is the placementRule,
    19  // then collects all rootPolicies in placementBindings. Replicated policies are determined
    20  // from decisions in the placementRule and a rootPolicy name
    21  func HandlerForRule(c client.Client) handler.EventHandler {
    22  	return &handlerForRule{
    23  		c,
    24  	}
    25  }
    26  
    27  type handlerForRule struct {
    28  	c client.Client
    29  }
    30  
    31  // Create implements EventHandler.
    32  func (e *handlerForRule) Create(ctx context.Context,
    33  	evt event.CreateEvent, q workqueue.RateLimitingInterface,
    34  ) {
    35  	e.mapAndEnqueue(ctx, q, evt.Object)
    36  }
    37  
    38  // Update implements EventHandler. Update only targeted(modified) objects
    39  func (e *handlerForRule) Update(ctx context.Context,
    40  	evt event.UpdateEvent, q workqueue.RateLimitingInterface,
    41  ) {
    42  	log.Info("Detect placementDecision and update targeted replicated-policies")
    43  	//nolint:forcetypeassert
    44  	newObj := evt.ObjectNew.(*appsv1.PlacementRule)
    45  	//nolint:forcetypeassert
    46  	oldObj := evt.ObjectOld.(*appsv1.PlacementRule)
    47  
    48  	newOjbDecisions := newObj.Status.Decisions
    49  	oldObjDecisions := oldObj.Status.Decisions
    50  
    51  	// Select only affected(Deleted in old or Created in new) objs
    52  	affectedDecisions := common.GetAffectedObjs(newOjbDecisions, oldObjDecisions)
    53  
    54  	// These is no status.decision change. Nothing to reconcile
    55  	if len(affectedDecisions) == 0 {
    56  		return
    57  	}
    58  
    59  	rootPolicyResults, err := common.GetRootPolicyRequests(ctx, e.c,
    60  		newObj.GetNamespace(), newObj.GetName(), common.PlacementRule)
    61  	if err != nil {
    62  		log.Error(err, "Failed to get RootPolicyResults to update by Rule event")
    63  
    64  		return
    65  	}
    66  
    67  	for _, pr := range rootPolicyResults {
    68  		for _, decision := range affectedDecisions {
    69  			q.Add(reconcile.Request{NamespacedName: types.NamespacedName{
    70  				Namespace: decision.ClusterNamespace,
    71  				Name:      pr.Namespace + "." + pr.Name,
    72  			}})
    73  		}
    74  	}
    75  }
    76  
    77  // Delete implements EventHandler.
    78  func (e *handlerForRule) Delete(ctx context.Context,
    79  	evt event.DeleteEvent, q workqueue.RateLimitingInterface,
    80  ) {
    81  	e.mapAndEnqueue(ctx, q, evt.Object)
    82  }
    83  
    84  // Generic implements EventHandler.
    85  func (e *handlerForRule) Generic(ctx context.Context,
    86  	evt event.GenericEvent, q workqueue.RateLimitingInterface,
    87  ) {
    88  	e.mapAndEnqueue(ctx, q, evt.Object)
    89  }
    90  
    91  func (e *handlerForRule) mapAndEnqueue(ctx context.Context,
    92  	q workqueue.RateLimitingInterface, obj client.Object,
    93  ) {
    94  	pRule := obj.(*appsv1.PlacementRule)
    95  	reqs := e.getMappedReplicatedPolicy(ctx, pRule)
    96  
    97  	for _, req := range reqs {
    98  		q.Add(req)
    99  	}
   100  }
   101  
   102  func (e *handlerForRule) getMappedReplicatedPolicy(ctx context.Context,
   103  	pRule *appsv1.PlacementRule,
   104  ) []reconcile.Request {
   105  	if len(pRule.Status.Decisions) == 0 {
   106  		return nil
   107  	}
   108  
   109  	rootPolicyResults, err := common.GetRootPolicyRequests(ctx, e.c,
   110  		pRule.GetNamespace(), pRule.GetName(), common.PlacementRule)
   111  	if err != nil {
   112  		log.Error(err, "Failed to get RootPolicyResults By Rule event")
   113  
   114  		return nil
   115  	}
   116  
   117  	var result []reconcile.Request
   118  
   119  	for _, pr := range rootPolicyResults {
   120  		for _, decision := range pRule.Status.Decisions {
   121  			result = append(result, reconcile.Request{NamespacedName: types.NamespacedName{
   122  				Namespace: decision.ClusterNamespace,
   123  				Name:      pr.Namespace + "." + pr.Name,
   124  			}})
   125  		}
   126  	}
   127  
   128  	return result
   129  }