Skip to content

Commit f7ea25d

Browse files
authored
fix: requeue the request when the override has been changed (#1097)
1 parent eee5143 commit f7ea25d

3 files changed

Lines changed: 101 additions & 8 deletions

File tree

pkg/controllers/workgenerator/controller.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,16 +1530,31 @@ func (r *Reconciler) SetupWithManager(mgr controllerruntime.Manager) error {
15301530
newResourceSnapshot := newWork.Labels[fleetv1beta1.ParentResourceSnapshotIndexLabel]
15311531
if oldResourceSnapshot == "" || newResourceSnapshot == "" {
15321532
klog.ErrorS(controller.NewUnexpectedBehaviorError(errors.New("found an invalid work without parent-resource-snapshot-index")),
1533-
"Could not find the parent resource snapshot index label", "oldWork", klog.KObj(oldWork), "oldResourceSnapshotLabelValue", oldResourceSnapshot,
1534-
"newWork", klog.KObj(newWork), "newResourceSnapshotLabelValue", newResourceSnapshot)
1533+
"Could not find the parent resource snapshot index label", "oldWork", klog.KObj(oldWork), "oldWorkLabels", oldWork.Labels,
1534+
"newWork", klog.KObj(newWork), "newWorkLabels", newWork.Labels)
15351535
return
15361536
}
1537-
// There is an edge case that, the work spec is the same but from different resourceSnapshots.
1538-
// WorkGenerator will update the work because of the label changes, but the generation is the same.
1539-
// When the normal update happens, the controller will set the applied condition as false and wait
1540-
// until the work condition has been changed.
1537+
oldClusterResourceOverrideSnapshotHash := oldWork.Annotations[fleetv1beta1.ParentClusterResourceOverrideSnapshotHashAnnotation]
1538+
newClusterResourceOverrideSnapshotHash := newWork.Annotations[fleetv1beta1.ParentClusterResourceOverrideSnapshotHashAnnotation]
1539+
oldResourceOverrideSnapshotHash := oldWork.Annotations[fleetv1beta1.ParentResourceOverrideSnapshotHashAnnotation]
1540+
newResourceOverrideSnapshotHash := newWork.Annotations[fleetv1beta1.ParentResourceOverrideSnapshotHashAnnotation]
1541+
if oldClusterResourceOverrideSnapshotHash == "" || newClusterResourceOverrideSnapshotHash == "" ||
1542+
oldResourceOverrideSnapshotHash == "" || newResourceOverrideSnapshotHash == "" {
1543+
klog.ErrorS(controller.NewUnexpectedBehaviorError(errors.New("found an invalid work without override-snapshot-hash")),
1544+
"Could not find the override-snapshot-hash annotation", "oldWork", klog.KObj(oldWork), "oldWorkAnnotations", oldWork.Annotations,
1545+
"newWork", klog.KObj(newWork), "newWorkAnnotations", newWork.Annotations)
1546+
return
1547+
}
1548+
1549+
// There is an edge case that, the work spec is the same but from different resourceSnapshots or resourceOverrideSnapshots.
1550+
// WorkGenerator will update the work because of the label/annotation changes, but the generation is the same.
1551+
// When the override update happens, the rollout controller will set the applied condition as false
1552+
// and wait for the workGenerator to update it. The workGenerator will wait for the work status change,
1553+
// but here the status didn't change as the work's spec didn't change
15411554
// In this edge case, we need to requeue the binding to update the binding status.
1542-
if oldResourceSnapshot == newResourceSnapshot {
1555+
if oldResourceSnapshot == newResourceSnapshot &&
1556+
oldClusterResourceOverrideSnapshotHash == newClusterResourceOverrideSnapshotHash &&
1557+
oldResourceOverrideSnapshotHash == newResourceOverrideSnapshotHash {
15431558
klog.V(2).InfoS("The work applied or available condition stayed as true, no need to reconcile", "oldWork", klog.KObj(oldWork), "newWork", klog.KObj(newWork))
15441559
return
15451560
}

test/e2e/placement_cro_test.go

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ var _ = Context("creating clusterResourceOverride (selecting all clusters) to ov
130130
}, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update cro as expected", crpName)
131131
})
132132

133-
It("should update CRP status on demand as expected", func() {
133+
It("should refresh the CRP status even as there is no change on the resources", func() {
134134
wantCRONames := []string{fmt.Sprintf(placementv1alpha1.OverrideSnapshotNameFmt, croName, 1)}
135135
crpStatusUpdatedActual := crpStatusWithOverrideUpdatedActual(workResourceIdentifiers(), allMemberClusterNames, "0", wantCRONames, nil)
136136
Eventually(crpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update CRP %s status as expected", crpName)
@@ -144,6 +144,44 @@ var _ = Context("creating clusterResourceOverride (selecting all clusters) to ov
144144
checkIfOverrideAnnotationsOnAllMemberClusters(true, want)
145145
})
146146

147+
It("update cro attached to this CRP only and no updates on the namespace", func() {
148+
Eventually(func() error {
149+
cro := &placementv1alpha1.ClusterResourceOverride{}
150+
if err := hubClient.Get(ctx, types.NamespacedName{Name: croName}, cro); err != nil {
151+
return err
152+
}
153+
cro.Spec.Policy.OverrideRules = append(cro.Spec.Policy.OverrideRules, placementv1alpha1.OverrideRule{
154+
ClusterSelector: &placementv1beta1.ClusterSelector{
155+
ClusterSelectorTerms: []placementv1beta1.ClusterSelectorTerm{
156+
{
157+
LabelSelector: &metav1.LabelSelector{
158+
MatchLabels: map[string]string{
159+
"invalid-key": "invalid-value",
160+
},
161+
},
162+
},
163+
},
164+
},
165+
OverrideType: placementv1alpha1.DeleteOverrideType,
166+
})
167+
return hubClient.Update(ctx, cro)
168+
}, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update cro as expected", crpName)
169+
})
170+
171+
It("should update CRP status on demand as expected", func() {
172+
wantCRONames := []string{fmt.Sprintf(placementv1alpha1.OverrideSnapshotNameFmt, croName, 2)}
173+
crpStatusUpdatedActual := crpStatusWithOverrideUpdatedActual(workResourceIdentifiers(), allMemberClusterNames, "0", wantCRONames, nil)
174+
Eventually(crpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update CRP %s status as expected", crpName)
175+
})
176+
177+
// This check will ignore the annotation of resources.
178+
It("should place the selected resources on member clusters", checkIfPlacedWorkResourcesOnAllMemberClusters)
179+
180+
It("should have new override annotation value on the placed resources", func() {
181+
want := map[string]string{croTestAnnotationKey: croTestAnnotationValue1}
182+
checkIfOverrideAnnotationsOnAllMemberClusters(true, want)
183+
})
184+
147185
It("delete the cro attached to this CRP", func() {
148186
cleanupClusterResourceOverride(croName)
149187
})

test/e2e/placement_ro_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,46 @@ var _ = Context("creating resourceOverride (selecting all clusters) to override
143143
want := map[string]string{roTestAnnotationKey: roTestAnnotationValue1}
144144
checkIfOverrideAnnotationsOnAllMemberClusters(false, want)
145145
})
146+
147+
It("update ro attached to this CRP only and no update on the configmap itself", func() {
148+
Eventually(func() error {
149+
ro := &placementv1alpha1.ResourceOverride{}
150+
if err := hubClient.Get(ctx, types.NamespacedName{Name: roName, Namespace: roNamespace}, ro); err != nil {
151+
return err
152+
}
153+
ro.Spec.Policy.OverrideRules = append(ro.Spec.Policy.OverrideRules, placementv1alpha1.OverrideRule{
154+
ClusterSelector: &placementv1beta1.ClusterSelector{
155+
ClusterSelectorTerms: []placementv1beta1.ClusterSelectorTerm{
156+
{
157+
LabelSelector: &metav1.LabelSelector{
158+
MatchLabels: map[string]string{
159+
"invalid-key": "invalid-value",
160+
},
161+
},
162+
},
163+
},
164+
},
165+
OverrideType: placementv1alpha1.DeleteOverrideType,
166+
})
167+
return hubClient.Update(ctx, ro)
168+
}, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update ro as expected", crpName)
169+
})
170+
171+
It("should refresh the CRP status even as there is no change on the resources", func() {
172+
wantRONames := []placementv1beta1.NamespacedName{
173+
{Namespace: roNamespace, Name: fmt.Sprintf(placementv1alpha1.OverrideSnapshotNameFmt, roName, 2)},
174+
}
175+
crpStatusUpdatedActual := crpStatusWithOverrideUpdatedActual(workResourceIdentifiers(), allMemberClusterNames, "0", nil, wantRONames)
176+
Eventually(crpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update CRP %s status as expected", crpName)
177+
})
178+
179+
// This check will ignore the annotation of resources.
180+
It("should place the selected resources on member clusters", checkIfPlacedWorkResourcesOnAllMemberClusters)
181+
182+
It("should have override annotations on the configmap", func() {
183+
want := map[string]string{roTestAnnotationKey: roTestAnnotationValue1}
184+
checkIfOverrideAnnotationsOnAllMemberClusters(false, want)
185+
})
146186
})
147187

148188
var _ = Context("creating resourceOverride with multiple jsonPatchOverrides to override configMap", Ordered, func() {

0 commit comments

Comments
 (0)