Skip to content

Commit 2b9b8c9

Browse files
committed
fix one case of from cache is not set correctly
Signed-off-by: Ryan Zhang <[email protected]>
1 parent f81a13d commit 2b9b8c9

File tree

7 files changed

+43
-23
lines changed

7 files changed

+43
-23
lines changed

pkg/controllers/placement/placement_status.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ func setPlacementConditions(
265265
func (r *Reconciler) buildClusterToBindingMap(ctx context.Context, placementObj fleetv1beta1.PlacementObj, latestSchedulingPolicySnapshot fleetv1beta1.PolicySnapshotObj) (map[string]fleetv1beta1.BindingObj, error) {
266266
placementKObj := klog.KObj(placementObj)
267267
// List all bindings for the placement object.
268-
bindings, err := controller.ListBindingsFromKey(ctx, r.Client, types.NamespacedName{Namespace: placementObj.GetNamespace(), Name: placementObj.GetName()})
268+
bindings, err := controller.ListBindingsFromKey(ctx, r.Client, types.NamespacedName{Namespace: placementObj.GetNamespace(), Name: placementObj.GetName()}, true)
269269
if err != nil {
270270
klog.ErrorS(err, "Failed to list bindings for placement", "placement", placementKObj)
271271
return nil, controller.NewAPIServerError(true, err)

pkg/controllers/rollout/controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req runtime.Request) (runtim
101101

102102
// list all the bindings associated with the placement
103103
// we read from the API server directly to avoid the repeated reconcile loop due to cache inconsistency
104-
allBindings, err := controller.ListBindingsFromKey(ctx, r.UncachedReader, placementKey)
104+
allBindings, err := controller.ListBindingsFromKey(ctx, r.UncachedReader, placementKey, false)
105105
if err != nil {
106106
klog.ErrorS(err, "Failed to list all the bindings associated with the placement",
107107
"placement", placementObjRef)

pkg/controllers/updaterun/initialization.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ func (r *Reconciler) collectScheduledClusters(
201201
updateRunRef := klog.KObj(updateRun)
202202
policySnapshotRef := klog.KObj(latestPolicySnapshot)
203203

204-
bindingObjs, err := controller.ListBindingsFromKey(ctx, r.Client, placementKey)
204+
bindingObjs, err := controller.ListBindingsFromKey(ctx, r.Client, placementKey, true)
205205
if err != nil {
206206
klog.ErrorS(err, "Failed to list bindings", "placement", placementKey, "policySnapshot", policySnapshotRef, "updateRun", updateRunRef)
207207
// list err can be retried.

pkg/scheduler/framework/framework.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ func (f *framework) RunSchedulingCycleFor(ctx context.Context, placementKey queu
289289
// overloading). In the long run we might still want to resort to a cached situation.
290290
//
291291
// TO-DO (chenyu1): explore the possibilities of using a mutation cache for better performance.
292-
bindings, err := controller.ListBindingsFromKey(ctx, f.uncachedReader, types.NamespacedName{Namespace: namespace, Name: name})
292+
bindings, err := controller.ListBindingsFromKey(ctx, f.uncachedReader, types.NamespacedName{Namespace: namespace, Name: name}, false)
293293
if err != nil {
294294
klog.ErrorS(err, "Failed to collect bindings", "policySnapshot", policyRef)
295295
return ctrl.Result{}, err

pkg/scheduler/scheduler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ func (s *Scheduler) cleanUpAllBindingsFor(ctx context.Context, placement fleetv1
305305
// Note that the listing is performed using the uncached client; this is to ensure that all related
306306
// bindings can be found, even if they have not been synced to the cache yet.
307307
// TO-DO (chenyu1): this is a very expensive op; explore options for optimization.
308-
bindings, err := controller.ListBindingsFromKey(ctx, s.uncachedReader, types.NamespacedName{Namespace: placement.GetNamespace(), Name: placement.GetName()})
308+
bindings, err := controller.ListBindingsFromKey(ctx, s.uncachedReader, types.NamespacedName{Namespace: placement.GetNamespace(), Name: placement.GetName()}, false)
309309
if err != nil {
310310
klog.ErrorS(err, "Failed to list all bindings", "placement", placementRef)
311311
return err

pkg/utils/controller/binding_resolver.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ func FetchBindingFromKey(ctx context.Context, c client.Reader, bindingKey types.
4747
// that belong to the specified binding key.
4848
// The binding key format determines whether to list ClusterResourceBindings (cluster-scoped)
4949
// or ResourceBindings (namespaced). For namespaced resources, the key format has a namespace.
50-
func ListBindingsFromKey(ctx context.Context, c client.Reader, placementKey types.NamespacedName) ([]placementv1beta1.BindingObj, error) {
50+
// The fromCache parameter indicates whether the client is a cached client (true) or an uncached client (false).
51+
func ListBindingsFromKey(ctx context.Context, c client.Reader, placementKey types.NamespacedName, fromCache bool) ([]placementv1beta1.BindingObj, error) {
5152
// Extract namespace and name from the binding key
5253
namespace := placementKey.Namespace
5354
name := placementKey.Name
@@ -65,7 +66,7 @@ func ListBindingsFromKey(ctx context.Context, c client.Reader, placementKey type
6566
bindingList = &placementv1beta1.ClusterResourceBindingList{}
6667
}
6768
if err := c.List(ctx, bindingList, listOptions...); err != nil {
68-
return nil, NewAPIServerError(false, err)
69+
return nil, NewAPIServerError(fromCache, err)
6970
}
7071

7172
bindingObjs := bindingList.GetBindingObjs()

pkg/utils/controller/binding_resolver_test.go

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ func TestListBindingsFromKey(t *testing.T) {
408408
WithObjects(tt.objects...).
409409
Build()
410410

411-
got, err := ListBindingsFromKey(ctx, fakeClient, tt.placementKey)
411+
got, err := ListBindingsFromKey(ctx, fakeClient, tt.placementKey, true)
412412

413413
if tt.wantErr {
414414
if err == nil {
@@ -498,13 +498,13 @@ func TestListBindingsFromKey_Sorted(t *testing.T) {
498498
},
499499
}
500500

501-
bindingsInMode0, err := ListBindingsFromKey(ctx, &mockClient, types.NamespacedName{Name: "placeholder"})
501+
bindingsInMode0, err := ListBindingsFromKey(ctx, &mockClient, types.NamespacedName{Name: "placeholder"}, true)
502502
if err != nil {
503503
t.Fatalf("ListBindingsFromKey() in mode 0 returned error: %v", err)
504504
}
505505

506506
mockMode.Store(1)
507-
bindingsInMode1, err := ListBindingsFromKey(ctx, &mockClient, types.NamespacedName{Name: "placeholder"})
507+
bindingsInMode1, err := ListBindingsFromKey(ctx, &mockClient, types.NamespacedName{Name: "placeholder"}, true)
508508
if err != nil {
509509
t.Fatalf("ListBindingsFromKey() in mode 1 returned error: %v", err)
510510
}
@@ -517,23 +517,42 @@ func TestListBindingsFromKey_Sorted(t *testing.T) {
517517
func TestListBindingsFromKey_ClientError(t *testing.T) {
518518
ctx := context.Background()
519519

520-
// Create a client that will return an error
521-
scheme := runtime.NewScheme()
522-
_ = placementv1beta1.AddToScheme(scheme)
523-
524-
// Use a fake client but override List to return error
525-
fakeClient := &failingListClient{
526-
Client: fake.NewClientBuilder().WithScheme(scheme).Build(),
520+
tests := []struct {
521+
name string
522+
fromCache bool
523+
wantErr error
524+
}{
525+
{
526+
name: "uncached client returns ErrAPIServerError",
527+
fromCache: false,
528+
wantErr: ErrAPIServerError,
529+
},
530+
{
531+
name: "cached client returns ErrUnexpectedBehavior as cached List should not fail",
532+
fromCache: true,
533+
wantErr: ErrUnexpectedBehavior,
534+
},
527535
}
528536

529-
_, err := ListBindingsFromKey(ctx, fakeClient, types.NamespacedName{Name: "test-placement"})
537+
for _, tt := range tests {
538+
t.Run(tt.name, func(t *testing.T) {
539+
// Create a client that will return an error
540+
scheme := runtime.NewScheme()
541+
_ = placementv1beta1.AddToScheme(scheme)
530542

531-
if err == nil {
532-
t.Fatalf("Expected error but got nil")
533-
}
543+
// Use a fake client but override List to return error
544+
fakeClient := &failingListClient{
545+
Client: fake.NewClientBuilder().WithScheme(scheme).Build(),
546+
}
534547

535-
if !errors.Is(err, ErrAPIServerError) {
536-
t.Errorf("Expected ErrAPIServerError but got: %v", err)
548+
_, err := ListBindingsFromKey(ctx, fakeClient, types.NamespacedName{Name: "test-placement"}, tt.fromCache)
549+
if err == nil {
550+
t.Fatalf("Expected error but got nil")
551+
}
552+
if !errors.Is(err, tt.wantErr) {
553+
t.Errorf("Expected %v but got: %v", tt.wantErr, err)
554+
}
555+
})
537556
}
538557
}
539558

0 commit comments

Comments
 (0)