Skip to content

Commit a53c8bc

Browse files
authored
Merge pull request #5779 from ctripcloud/work-index
Add index for work
2 parents e0d77eb + e2827b1 commit a53c8bc

File tree

11 files changed

+200
-17
lines changed

11 files changed

+200
-17
lines changed

cmd/controller-manager/app/controllermanager.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,10 @@ func Run(ctx context.Context, opts *options.Options) error {
190190
crtlmetrics.Registry.MustRegister(metrics.ResourceCollectors()...)
191191
crtlmetrics.Registry.MustRegister(metrics.PoolCollectors()...)
192192

193+
if err := helper.IndexWork(ctx, controllerManager); err != nil {
194+
klog.Fatalf("Failed to index Work: %v", err)
195+
}
196+
193197
setupControllers(controllerManager, opts, ctx.Done())
194198

195199
// blocks until the context is done.

pkg/controllers/binding/binding_controller_test.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ import (
3737
"sigs.k8s.io/controller-runtime/pkg/reconcile"
3838

3939
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
40+
workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
4041
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
4142
testing2 "github.com/karmada-io/karmada/pkg/search/proxy/testing"
4243
"github.com/karmada-io/karmada/pkg/util"
4344
"github.com/karmada-io/karmada/pkg/util/fedinformer/genericmanager"
4445
"github.com/karmada-io/karmada/pkg/util/gclient"
46+
utilhelper "github.com/karmada-io/karmada/pkg/util/helper"
4547
testing3 "github.com/karmada-io/karmada/pkg/util/testing"
4648
"github.com/karmada-io/karmada/test/helper"
4749
)
@@ -50,10 +52,16 @@ import (
5052
// Currently support kind: Pod,Node. If you want support more kind, pls add it.
5153
// rs is nil means use default RestMapper, see: github.com/karmada-io/karmada/pkg/search/proxy/testing/constant.go
5254
func makeFakeRBCByResource(rs *workv1alpha2.ObjectReference) (*ResourceBindingController, error) {
55+
c := fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithIndex(
56+
&workv1alpha1.Work{},
57+
workv1alpha2.ResourceBindingPermanentIDLabel,
58+
utilhelper.IndexerFuncBasedOnLabel(workv1alpha2.ResourceBindingPermanentIDLabel),
59+
).Build()
60+
5361
tempDyClient := fakedynamic.NewSimpleDynamicClient(scheme.Scheme)
5462
if rs == nil {
5563
return &ResourceBindingController{
56-
Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(),
64+
Client: c,
5765
RESTMapper: testing2.RestMapper,
5866
InformerManager: genericmanager.NewSingleClusterInformerManager(tempDyClient, 0, nil),
5967
DynamicClient: tempDyClient,
@@ -83,7 +91,7 @@ func makeFakeRBCByResource(rs *workv1alpha2.ObjectReference) (*ResourceBindingCo
8391
}
8492

8593
return &ResourceBindingController{
86-
Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(),
94+
Client: c,
8795
RESTMapper: helper.NewGroupRESTMapper(rs.Kind, meta.RESTScopeNamespace),
8896
InformerManager: testing3.NewSingleClusterInformerManagerByRS(src, obj),
8997
DynamicClient: tempDyClient,

pkg/controllers/binding/cluster_resource_binding_controller_test.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,27 @@ import (
3737
"sigs.k8s.io/controller-runtime/pkg/reconcile"
3838

3939
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
40+
workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
4041
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
4142
testing2 "github.com/karmada-io/karmada/pkg/search/proxy/testing"
4243
"github.com/karmada-io/karmada/pkg/util"
4344
"github.com/karmada-io/karmada/pkg/util/fedinformer/genericmanager"
4445
"github.com/karmada-io/karmada/pkg/util/gclient"
46+
utilhelper "github.com/karmada-io/karmada/pkg/util/helper"
4547
testing3 "github.com/karmada-io/karmada/pkg/util/testing"
4648
"github.com/karmada-io/karmada/test/helper"
4749
)
4850

4951
func makeFakeCRBCByResource(rs *workv1alpha2.ObjectReference) (*ClusterResourceBindingController, error) {
52+
c := fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithIndex(
53+
&workv1alpha1.Work{},
54+
workv1alpha2.ClusterResourceBindingPermanentIDLabel,
55+
utilhelper.IndexerFuncBasedOnLabel(workv1alpha2.ClusterResourceBindingPermanentIDLabel),
56+
).Build()
5057
tempDyClient := fakedynamic.NewSimpleDynamicClient(scheme.Scheme)
5158
if rs == nil {
5259
return &ClusterResourceBindingController{
53-
Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(),
60+
Client: c,
5461
RESTMapper: testing2.RestMapper,
5562
InformerManager: genericmanager.NewSingleClusterInformerManager(tempDyClient, 0, nil),
5663
DynamicClient: tempDyClient,
@@ -77,7 +84,7 @@ func makeFakeCRBCByResource(rs *workv1alpha2.ObjectReference) (*ClusterResourceB
7784
}
7885

7986
return &ClusterResourceBindingController{
80-
Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(),
87+
Client: c,
8188
RESTMapper: helper.NewGroupRESTMapper(rs.Kind, meta.RESTScopeNamespace),
8289
InformerManager: testing3.NewSingleClusterInformerManagerByRS(src, obj),
8390
DynamicClient: tempDyClient,

pkg/controllers/status/crb_status_controller_test.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ import (
3333
controllerruntime "sigs.k8s.io/controller-runtime"
3434
"sigs.k8s.io/controller-runtime/pkg/client/fake"
3535

36+
workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
3637
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
3738
"github.com/karmada-io/karmada/pkg/resourceinterpreter/default/native"
3839
"github.com/karmada-io/karmada/pkg/util/fedinformer/genericmanager"
3940
"github.com/karmada-io/karmada/pkg/util/gclient"
41+
utilhelper "github.com/karmada-io/karmada/pkg/util/helper"
4042
)
4143

4244
func generateCRBStatusController() *CRBStatusController {
@@ -50,7 +52,11 @@ func generateCRBStatusController() *CRBStatusController {
5052
m.WaitForCacheSync()
5153

5254
c := &CRBStatusController{
53-
Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(),
55+
Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithIndex(
56+
&workv1alpha1.Work{},
57+
workv1alpha2.ClusterResourceBindingPermanentIDLabel,
58+
utilhelper.IndexerFuncBasedOnLabel(workv1alpha2.ClusterResourceBindingPermanentIDLabel),
59+
).Build(),
5460
DynamicClient: dynamicClient,
5561
InformerManager: m,
5662
RESTMapper: func() meta.RESTMapper {
@@ -130,7 +136,9 @@ func TestCRBStatusController_Reconcile(t *testing.T) {
130136

131137
// Prepare binding and create it in client
132138
if tt.binding != nil {
133-
c.Client = fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(tt.binding).WithStatusSubresource(tt.binding).Build()
139+
c.Client = fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(tt.binding).WithStatusSubresource(tt.binding).
140+
WithIndex(&workv1alpha1.Work{}, workv1alpha2.ClusterResourceBindingPermanentIDLabel, utilhelper.IndexerFuncBasedOnLabel(workv1alpha2.ClusterResourceBindingPermanentIDLabel)).
141+
Build()
134142
}
135143

136144
res, err := c.Reconcile(context.Background(), req)
@@ -200,7 +208,9 @@ func TestCRBStatusController_syncBindingStatus(t *testing.T) {
200208
}
201209

202210
if tt.resourceExistInClient {
203-
c.Client = fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(binding).WithStatusSubresource(binding).Build()
211+
c.Client = fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(binding).WithStatusSubresource(binding).
212+
WithIndex(&workv1alpha1.Work{}, workv1alpha2.ClusterResourceBindingPermanentIDLabel, utilhelper.IndexerFuncBasedOnLabel(workv1alpha2.ClusterResourceBindingPermanentIDLabel)).
213+
Build()
204214
}
205215

206216
err := c.syncBindingStatus(context.Background(), binding)

pkg/controllers/status/rb_status_controller_test.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@ import (
3333
controllerruntime "sigs.k8s.io/controller-runtime"
3434
"sigs.k8s.io/controller-runtime/pkg/client/fake"
3535

36+
workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
3637
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
3738
"github.com/karmada-io/karmada/pkg/resourceinterpreter"
3839
"github.com/karmada-io/karmada/pkg/resourceinterpreter/default/native"
3940
"github.com/karmada-io/karmada/pkg/util/fedinformer/genericmanager"
4041
"github.com/karmada-io/karmada/pkg/util/gclient"
42+
utilhelper "github.com/karmada-io/karmada/pkg/util/helper"
4143
)
4244

4345
func generateRBStatusController() *RBStatusController {
@@ -51,7 +53,11 @@ func generateRBStatusController() *RBStatusController {
5153
m.WaitForCacheSync()
5254

5355
c := &RBStatusController{
54-
Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(),
56+
Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithIndex(
57+
&workv1alpha1.Work{},
58+
workv1alpha2.ClusterResourceBindingPermanentIDLabel,
59+
utilhelper.IndexerFuncBasedOnLabel(workv1alpha2.ClusterResourceBindingPermanentIDLabel),
60+
).Build(),
5561
DynamicClient: dynamicClient,
5662
InformerManager: m,
5763
RESTMapper: func() meta.RESTMapper {
@@ -136,7 +142,9 @@ func TestRBStatusController_Reconcile(t *testing.T) {
136142

137143
// Prepare binding and create it in client
138144
if tt.binding != nil {
139-
c.Client = fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(tt.binding).WithStatusSubresource(tt.binding).Build()
145+
c.Client = fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(tt.binding).WithStatusSubresource(tt.binding).
146+
WithIndex(&workv1alpha1.Work{}, workv1alpha2.ResourceBindingPermanentIDLabel, utilhelper.IndexerFuncBasedOnLabel(workv1alpha2.ResourceBindingPermanentIDLabel)).
147+
Build()
140148
}
141149

142150
res, err := c.Reconcile(context.Background(), req)
@@ -209,7 +217,9 @@ func TestRBStatusController_syncBindingStatus(t *testing.T) {
209217
}
210218

211219
if tt.resourceExistInClient {
212-
c.Client = fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(binding).WithStatusSubresource(binding).Build()
220+
c.Client = fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(binding).WithStatusSubresource(binding).
221+
WithIndex(&workv1alpha1.Work{}, workv1alpha2.ResourceBindingPermanentIDLabel, utilhelper.IndexerFuncBasedOnLabel(workv1alpha2.ResourceBindingPermanentIDLabel)).
222+
Build()
213223
}
214224

215225
err := c.syncBindingStatus(context.Background(), binding)

pkg/util/helper/binding_test.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,10 @@ func TestFindOrphanWorks(t *testing.T) {
433433
},
434434
},
435435
},
436+
).WithIndex(
437+
&workv1alpha1.Work{},
438+
workv1alpha2.ResourceBindingPermanentIDLabel,
439+
IndexerFuncBasedOnLabel(workv1alpha2.ResourceBindingPermanentIDLabel),
436440
).Build(),
437441
bindingNamespace: "default",
438442
bindingName: "binding",
@@ -478,6 +482,10 @@ func TestFindOrphanWorks(t *testing.T) {
478482
},
479483
},
480484
},
485+
).WithIndex(
486+
&workv1alpha1.Work{},
487+
workv1alpha2.ResourceBindingPermanentIDLabel,
488+
IndexerFuncBasedOnLabel(workv1alpha2.ResourceBindingPermanentIDLabel),
481489
).Build(),
482490
bindingNamespace: "default",
483491
bindingName: "binding",
@@ -530,6 +538,10 @@ func TestFindOrphanWorks(t *testing.T) {
530538
},
531539
},
532540
},
541+
).WithIndex(
542+
&workv1alpha1.Work{},
543+
workv1alpha2.ClusterResourceBindingPermanentIDLabel,
544+
IndexerFuncBasedOnLabel(workv1alpha2.ClusterResourceBindingPermanentIDLabel),
533545
).Build(),
534546
bindingNamespace: "",
535547
bindingName: "binding",
@@ -987,7 +999,11 @@ func TestDeleteWorkByRBNamespaceAndName(t *testing.T) {
987999
{
9881000
name: "work is not found",
9891001
args: args{
990-
c: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(),
1002+
c: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithIndex(
1003+
&workv1alpha1.Work{},
1004+
workv1alpha2.ResourceBindingPermanentIDLabel,
1005+
IndexerFuncBasedOnLabel(workv1alpha2.ResourceBindingPermanentIDLabel),
1006+
).Build(),
9911007
namespace: "default",
9921008
name: "foo",
9931009
bindingID: "3617252f-b1bb-43b0-98a1-c7de833c472c",
@@ -1011,6 +1027,10 @@ func TestDeleteWorkByRBNamespaceAndName(t *testing.T) {
10111027
},
10121028
},
10131029
},
1030+
).WithIndex(
1031+
&workv1alpha1.Work{},
1032+
workv1alpha2.ResourceBindingPermanentIDLabel,
1033+
IndexerFuncBasedOnLabel(workv1alpha2.ResourceBindingPermanentIDLabel),
10141034
).Build(),
10151035
namespace: "default",
10161036
name: "foo",
@@ -1034,6 +1054,10 @@ func TestDeleteWorkByRBNamespaceAndName(t *testing.T) {
10341054
},
10351055
},
10361056
},
1057+
).WithIndex(
1058+
&workv1alpha1.Work{},
1059+
workv1alpha2.ClusterResourceBindingPermanentIDLabel,
1060+
IndexerFuncBasedOnLabel(workv1alpha2.ClusterResourceBindingPermanentIDLabel),
10371061
).Build(),
10381062
name: "foo",
10391063
bindingID: "3617252f-b1bb-43b0-98a1-c7de833c472c",

pkg/util/helper/index.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package helper
2+
3+
import (
4+
"context"
5+
6+
"k8s.io/klog/v2"
7+
ctrl "sigs.k8s.io/controller-runtime"
8+
"sigs.k8s.io/controller-runtime/pkg/client"
9+
10+
workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
11+
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
12+
)
13+
14+
// IndexWork creates index for Work.
15+
func IndexWork(ctx context.Context, mgr ctrl.Manager) error {
16+
err := mgr.GetFieldIndexer().IndexField(ctx, &workv1alpha1.Work{}, workv1alpha2.ResourceBindingPermanentIDLabel,
17+
IndexerFuncBasedOnLabel(workv1alpha2.ResourceBindingPermanentIDLabel))
18+
if err != nil {
19+
klog.Errorf("failed to create index for work, err: %v", err)
20+
return err
21+
}
22+
err = mgr.GetFieldIndexer().IndexField(ctx, &workv1alpha1.Work{}, workv1alpha2.ClusterResourceBindingPermanentIDLabel,
23+
IndexerFuncBasedOnLabel(workv1alpha2.ClusterResourceBindingPermanentIDLabel))
24+
if err != nil {
25+
klog.Errorf("failed to create index for work, err: %v", err)
26+
return err
27+
}
28+
return nil
29+
}
30+
31+
// IndexerFuncBasedOnLabel returns an IndexerFunc used to index resource with the given key as label key.
32+
func IndexerFuncBasedOnLabel(key string) client.IndexerFunc {
33+
return func(obj client.Object) []string {
34+
val, ok := obj.GetLabels()[key]
35+
if !ok {
36+
return nil
37+
}
38+
return []string{val}
39+
}
40+
}

pkg/util/helper/index_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package helper
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
corev1 "k8s.io/api/core/v1"
8+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+
"sigs.k8s.io/controller-runtime/pkg/client"
10+
)
11+
12+
func TestIndexerFuncBasedOnLabel(t *testing.T) {
13+
type args struct {
14+
key string
15+
obj client.Object
16+
}
17+
tests := []struct {
18+
name string
19+
args args
20+
want []string
21+
}{
22+
{
23+
name: "cache hit",
24+
args: args{
25+
key: "a",
26+
obj: &corev1.Pod{
27+
ObjectMeta: metav1.ObjectMeta{
28+
Labels: map[string]string{
29+
"a": "a",
30+
},
31+
},
32+
},
33+
},
34+
want: []string{"a"},
35+
},
36+
{
37+
name: "cache missed",
38+
args: args{
39+
key: "b",
40+
obj: &corev1.Pod{
41+
ObjectMeta: metav1.ObjectMeta{
42+
Labels: map[string]string{
43+
"a": "a",
44+
},
45+
},
46+
},
47+
},
48+
want: nil,
49+
},
50+
}
51+
for _, tt := range tests {
52+
t.Run(tt.name, func(t *testing.T) {
53+
fn := IndexerFuncBasedOnLabel(tt.args.key)
54+
if !assert.NotNil(t, fn) {
55+
t.FailNow()
56+
}
57+
assert.Equalf(t, tt.want, fn(tt.args.obj), "IndexerFuncBasedOnLabel(%v)", tt.args.key)
58+
})
59+
}
60+
}

pkg/util/helper/work.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
corev1 "k8s.io/api/core/v1"
2424
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2525
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
26+
"k8s.io/apimachinery/pkg/fields"
2627
"k8s.io/apimachinery/pkg/labels"
2728
"k8s.io/apimachinery/pkg/runtime"
2829
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -117,15 +118,19 @@ func GetWorksByLabelsSet(ctx context.Context, c client.Client, ls labels.Set) (*
117118
}
118119

119120
// GetWorksByBindingID gets WorkList by matching same binding's permanent id.
121+
// Caller should ensure Work is indexed by binding's permanent id.
120122
func GetWorksByBindingID(ctx context.Context, c client.Client, bindingID string, namespaced bool) (*workv1alpha1.WorkList, error) {
121-
var ls labels.Set
123+
var key string
122124
if namespaced {
123-
ls = labels.Set{workv1alpha2.ResourceBindingPermanentIDLabel: bindingID}
125+
key = workv1alpha2.ResourceBindingPermanentIDLabel
124126
} else {
125-
ls = labels.Set{workv1alpha2.ClusterResourceBindingPermanentIDLabel: bindingID}
127+
key = workv1alpha2.ClusterResourceBindingPermanentIDLabel
126128
}
127-
128-
return GetWorksByLabelsSet(ctx, c, ls)
129+
workList := &workv1alpha1.WorkList{}
130+
listOpt := &client.ListOptions{
131+
FieldSelector: fields.OneTermEqualSelector(key, bindingID),
132+
}
133+
return workList, c.List(ctx, workList, listOpt)
129134
}
130135

131136
// GenEventRef returns the event reference. sets the UID(.spec.uid) that might be missing for fire events.

0 commit comments

Comments
 (0)