@@ -55,6 +55,10 @@ import (
5555var (
5656 // maxFailedResourcePlacementLimit indicates the max number of failed resource placements to include in the status.
5757 maxFailedResourcePlacementLimit = 100
58+ // maxDriftedResourcePlacementLimit indicates the max number of drifted resource placements to include in the status.
59+ maxDriftedResourcePlacementLimit = 100
60+ // maxDiffedResourcePlacementLimit indicates the max number of diffed resource placements to include in the status.
61+ maxDiffedResourcePlacementLimit = 100
5862
5963 errResourceSnapshotNotFound = fmt .Errorf ("the master resource snapshot is not found" )
6064)
@@ -775,6 +779,46 @@ func setBindingStatus(works map[string]*fleetv1beta1.Work, resourceBinding *flee
775779 klog .V (2 ).InfoS ("Populated failed manifests" , "clusterResourceBinding" , bindingRef , "numberOfFailedPlacements" , len (failedResourcePlacements ))
776780 }
777781 }
782+
783+ resourceBinding .Status .DriftedPlacements = nil
784+ // collect and set the drifted resource placements to the binding
785+ driftedResourcePlacements := make ([]fleetv1beta1.DriftedResourcePlacement , 0 , maxDriftedResourcePlacementLimit ) // preallocate the memory
786+ for _ , w := range works {
787+ if w .DeletionTimestamp != nil {
788+ klog .V (2 ).InfoS ("Ignoring the deleting work" , "clusterResourceBinding" , bindingRef , "work" , klog .KObj (w ))
789+ continue // ignore the deleting work
790+ }
791+ driftedManifests := extractDriftedResourcePlacementsFromWork (w )
792+ driftedResourcePlacements = append (driftedResourcePlacements , driftedManifests ... )
793+ }
794+ // cut the list to keep only the max limit
795+ if len (driftedResourcePlacements ) > maxDriftedResourcePlacementLimit {
796+ driftedResourcePlacements = driftedResourcePlacements [0 :maxDriftedResourcePlacementLimit ]
797+ }
798+ resourceBinding .Status .DriftedPlacements = driftedResourcePlacements
799+ if len (driftedResourcePlacements ) > 0 {
800+ klog .V (2 ).InfoS ("Populated drifted manifests" , "clusterResourceBinding" , bindingRef , "numberOfDriftedPlacements" , len (driftedResourcePlacements ))
801+ }
802+
803+ resourceBinding .Status .DiffedPlacements = nil
804+ // collect and set the diffed resource placements to the binding
805+ diffedResourcePlacements := make ([]fleetv1beta1.DiffedResourcePlacement , 0 , maxDiffedResourcePlacementLimit ) // preallocate the memory
806+ for _ , w := range works {
807+ if w .DeletionTimestamp != nil {
808+ klog .V (2 ).InfoS ("Ignoring the deleting work" , "clusterResourceBinding" , bindingRef , "work" , klog .KObj (w ))
809+ continue // ignore the deleting work
810+ }
811+ diffedManifests := extractDiffedResourcePlacementsFromWork (w )
812+ diffedResourcePlacements = append (diffedResourcePlacements , diffedManifests ... )
813+ }
814+ // cut the list to keep only the max limit
815+ if len (diffedResourcePlacements ) > maxDiffedResourcePlacementLimit {
816+ diffedResourcePlacements = diffedResourcePlacements [0 :maxDiffedResourcePlacementLimit ]
817+ }
818+ resourceBinding .Status .DiffedPlacements = diffedResourcePlacements
819+ if len (diffedResourcePlacements ) > 0 {
820+ klog .V (2 ).InfoS ("Populated diffed manifests" , "clusterResourceBinding" , bindingRef , "numberOfDiffedPlacements" , len (diffedResourcePlacements ))
821+ }
778822}
779823
780824func buildAllWorkAppliedCondition (works map [string ]* fleetv1beta1.Work , binding * fleetv1beta1.ClusterResourceBinding ) metav1.Condition {
@@ -955,6 +999,92 @@ func extractFailedResourcePlacementsFromWork(work *fleetv1beta1.Work) []fleetv1b
955999 return res
9561000}
9571001
1002+ // extractDriftedResourcePlacementsFromWork extracts the drifted placements from work
1003+ func extractDriftedResourcePlacementsFromWork (work * fleetv1beta1.Work ) []fleetv1beta1.DriftedResourcePlacement {
1004+ // check if the work is generated by an enveloped object
1005+ envelopeType , isEnveloped := work .GetLabels ()[fleetv1beta1 .EnvelopeTypeLabel ]
1006+ var envelopObjName , envelopObjNamespace string
1007+ if isEnveloped {
1008+ // If the work generated by an enveloped object, it must contain those labels.
1009+ envelopObjName = work .GetLabels ()[fleetv1beta1 .EnvelopeNameLabel ]
1010+ envelopObjNamespace = work .GetLabels ()[fleetv1beta1 .EnvelopeNamespaceLabel ]
1011+ }
1012+ res := make ([]fleetv1beta1.DriftedResourcePlacement , 0 , len (work .Status .ManifestConditions ))
1013+ for _ , manifestCondition := range work .Status .ManifestConditions {
1014+ driftedManifest := fleetv1beta1.DriftedResourcePlacement {
1015+ ResourceIdentifier : fleetv1beta1.ResourceIdentifier {
1016+ Group : manifestCondition .Identifier .Group ,
1017+ Version : manifestCondition .Identifier .Version ,
1018+ Kind : manifestCondition .Identifier .Kind ,
1019+ Name : manifestCondition .Identifier .Name ,
1020+ Namespace : manifestCondition .Identifier .Namespace ,
1021+ },
1022+ ObservationTime : manifestCondition .DriftDetails .ObservationTime ,
1023+ TargetClusterObservedGeneration : manifestCondition .DriftDetails .ObservedInMemberClusterGeneration ,
1024+ FirstDriftedObservedTime : manifestCondition .DriftDetails .FirstDriftedObservedTime ,
1025+ ObservedDrifts : manifestCondition .DriftDetails .ObservedDrifts ,
1026+ }
1027+
1028+ if isEnveloped {
1029+ klog .V (2 ).InfoS ("Found a drifted enveloped manifest" ,
1030+ "manifestName" , manifestCondition .Identifier .Name ,
1031+ "group" , manifestCondition .Identifier .Group ,
1032+ "version" , manifestCondition .Identifier .Version , "kind" , manifestCondition .Identifier .Kind ,
1033+ "envelopeType" , envelopeType , "envelopObjName" , envelopObjName , "envelopObjNamespace" , envelopObjNamespace )
1034+ } else {
1035+ klog .V (2 ).InfoS ("Found a drifted manifest" ,
1036+ "manifestName" , manifestCondition .Identifier .Name , "group" , manifestCondition .Identifier .Group ,
1037+ "version" , manifestCondition .Identifier .Version , "kind" , manifestCondition .Identifier .Kind )
1038+ }
1039+ res = append (res , driftedManifest )
1040+ continue //jump to the next manifest
1041+ }
1042+ return res
1043+ }
1044+
1045+ // extractDiffedResourcePlacementsFromWork extracts the diffed placements from work
1046+ func extractDiffedResourcePlacementsFromWork (work * fleetv1beta1.Work ) []fleetv1beta1.DiffedResourcePlacement {
1047+ // check if the work is generated by an enveloped object
1048+ envelopeType , isEnveloped := work .GetLabels ()[fleetv1beta1 .EnvelopeTypeLabel ]
1049+ var envelopObjName , envelopObjNamespace string
1050+ if isEnveloped {
1051+ // If the work generated by an enveloped object, it must contain those labels.
1052+ envelopObjName = work .GetLabels ()[fleetv1beta1 .EnvelopeNameLabel ]
1053+ envelopObjNamespace = work .GetLabels ()[fleetv1beta1 .EnvelopeNamespaceLabel ]
1054+ }
1055+ res := make ([]fleetv1beta1.DiffedResourcePlacement , 0 , len (work .Status .ManifestConditions ))
1056+ for _ , manifestCondition := range work .Status .ManifestConditions {
1057+ diffedManifest := fleetv1beta1.DiffedResourcePlacement {
1058+ ResourceIdentifier : fleetv1beta1.ResourceIdentifier {
1059+ Group : manifestCondition .Identifier .Group ,
1060+ Version : manifestCondition .Identifier .Version ,
1061+ Kind : manifestCondition .Identifier .Kind ,
1062+ Name : manifestCondition .Identifier .Name ,
1063+ Namespace : manifestCondition .Identifier .Namespace ,
1064+ },
1065+ ObservationTime : manifestCondition .DiffDetails .ObservationTime ,
1066+ TargetClusterObservedGeneration : manifestCondition .DiffDetails .ObservedInMemberClusterGeneration ,
1067+ FirstDiffedObservedTime : manifestCondition .DiffDetails .FirstDiffedObservedTime ,
1068+ ObservedDiffs : manifestCondition .DiffDetails .ObservedDiffs ,
1069+ }
1070+
1071+ if isEnveloped {
1072+ klog .V (2 ).InfoS ("Found a diffed enveloped manifest" ,
1073+ "manifestName" , manifestCondition .Identifier .Name ,
1074+ "group" , manifestCondition .Identifier .Group ,
1075+ "version" , manifestCondition .Identifier .Version , "kind" , manifestCondition .Identifier .Kind ,
1076+ "envelopeType" , envelopeType , "envelopObjName" , envelopObjName , "envelopObjNamespace" , envelopObjNamespace )
1077+ } else {
1078+ klog .V (2 ).InfoS ("Found a diffed manifest" ,
1079+ "manifestName" , manifestCondition .Identifier .Name , "group" , manifestCondition .Identifier .Group ,
1080+ "version" , manifestCondition .Identifier .Version , "kind" , manifestCondition .Identifier .Kind )
1081+ }
1082+ res = append (res , diffedManifest )
1083+ continue //jump to the next manifest
1084+ }
1085+ return res
1086+ }
1087+
9581088// SetupWithManager sets up the controller with the Manager.
9591089// It watches binding events and also update/delete events for work.
9601090func (r * Reconciler ) SetupWithManager (mgr controllerruntime.Manager ) error {
@@ -1045,6 +1175,21 @@ func (r *Reconciler) SetupWithManager(mgr controllerruntime.Manager) error {
10451175 }
10461176 }
10471177 }
1178+ // we need to compare the drift placement
1179+ oldDriftedPlacements := extractDriftedResourcePlacementsFromWork (oldWork )
1180+ newDriftedPlacements := extractDriftedResourcePlacementsFromWork (newWork )
1181+ if utils .IsDriftedResourcePlacementsEqual (oldDriftedPlacements , newDriftedPlacements ) {
1182+ klog .V (2 ).InfoS ("The drifted placement list didn't change, no need to reconcile" , "oldWork" , klog .KObj (oldWork ), "newWork" , klog .KObj (newWork ))
1183+ return
1184+ }
1185+
1186+ // we need to compare the diffed placement
1187+ oldDiffedPlacements := extractDiffedResourcePlacementsFromWork (oldWork )
1188+ newDiffedPlacements := extractDiffedResourcePlacementsFromWork (newWork )
1189+ if utils .IsDiffedResourcePlacementsEqual (oldDiffedPlacements , newDiffedPlacements ) {
1190+ klog .V (2 ).InfoS ("The diffed placement list didn't change, no need to reconcile" , "oldWork" , klog .KObj (oldWork ), "newWork" , klog .KObj (newWork ))
1191+ return
1192+ }
10481193 // We need to update the binding status in this case
10491194 klog .V (2 ).InfoS ("Received a work update event that we need to handle" , "work" , klog .KObj (newWork ), "parentBindingName" , parentBindingName )
10501195 queue .Add (reconcile.Request {NamespacedName : types.NamespacedName {
0 commit comments