diff --git a/cmd/controller-manager/app/controllermanager.go b/cmd/controller-manager/app/controllermanager.go index 3429981480b4..05d3fae8c9e8 100644 --- a/cmd/controller-manager/app/controllermanager.go +++ b/cmd/controller-manager/app/controllermanager.go @@ -741,6 +741,10 @@ func setupControllers(mgr controllerruntime.Manager, opts *options.Options, stop sharedFactory.Start(stopChan) sharedFactory.WaitForCacheSync(stopChan) + if err := helper.IndexWork(context.TODO(), mgr); err != nil { + klog.Fatalf("Failed to index Work: %v", err) + } + resourceInterpreter := resourceinterpreter.NewResourceInterpreter(controlPlaneInformerManager, serviceLister) if err := mgr.Add(resourceInterpreter); err != nil { klog.Fatalf("Failed to setup custom resource interpreter: %v", err) diff --git a/pkg/controllers/binding/binding_controller_test.go b/pkg/controllers/binding/binding_controller_test.go index 70d813d98d17..87eec36f53da 100644 --- a/pkg/controllers/binding/binding_controller_test.go +++ b/pkg/controllers/binding/binding_controller_test.go @@ -37,11 +37,13 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1" + workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1" workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2" testing2 "github.com/karmada-io/karmada/pkg/search/proxy/testing" "github.com/karmada-io/karmada/pkg/util" "github.com/karmada-io/karmada/pkg/util/fedinformer/genericmanager" "github.com/karmada-io/karmada/pkg/util/gclient" + utilhelper "github.com/karmada-io/karmada/pkg/util/helper" testing3 "github.com/karmada-io/karmada/pkg/util/testing" "github.com/karmada-io/karmada/test/helper" ) @@ -50,10 +52,16 @@ import ( // Currently support kind: Pod,Node. If you want support more kind, pls add it. // rs is nil means use default RestMapper, see: github.com/karmada-io/karmada/pkg/search/proxy/testing/constant.go func makeFakeRBCByResource(rs *workv1alpha2.ObjectReference) (*ResourceBindingController, error) { + c := fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithIndex( + &workv1alpha1.Work{}, + workv1alpha2.ResourceBindingPermanentIDLabel, + utilhelper.GenOneLabelEqualIndexerFunc(workv1alpha2.ResourceBindingPermanentIDLabel), + ).Build() + tempDyClient := fakedynamic.NewSimpleDynamicClient(scheme.Scheme) if rs == nil { return &ResourceBindingController{ - Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(), + Client: c, RESTMapper: testing2.RestMapper, InformerManager: genericmanager.NewSingleClusterInformerManager(tempDyClient, 0, nil), DynamicClient: tempDyClient, @@ -83,7 +91,7 @@ func makeFakeRBCByResource(rs *workv1alpha2.ObjectReference) (*ResourceBindingCo } return &ResourceBindingController{ - Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(), + Client: c, RESTMapper: helper.NewGroupRESTMapper(rs.Kind, meta.RESTScopeNamespace), InformerManager: testing3.NewSingleClusterInformerManagerByRS(src, obj), DynamicClient: tempDyClient, diff --git a/pkg/controllers/binding/cluster_resource_binding_controller_test.go b/pkg/controllers/binding/cluster_resource_binding_controller_test.go index 22572b4935d4..c033f870a0b0 100644 --- a/pkg/controllers/binding/cluster_resource_binding_controller_test.go +++ b/pkg/controllers/binding/cluster_resource_binding_controller_test.go @@ -37,20 +37,27 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1" + workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1" workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2" testing2 "github.com/karmada-io/karmada/pkg/search/proxy/testing" "github.com/karmada-io/karmada/pkg/util" "github.com/karmada-io/karmada/pkg/util/fedinformer/genericmanager" "github.com/karmada-io/karmada/pkg/util/gclient" + utilhelper "github.com/karmada-io/karmada/pkg/util/helper" testing3 "github.com/karmada-io/karmada/pkg/util/testing" "github.com/karmada-io/karmada/test/helper" ) func makeFakeCRBCByResource(rs *workv1alpha2.ObjectReference) (*ClusterResourceBindingController, error) { + c := fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithIndex( + &workv1alpha1.Work{}, + workv1alpha2.ClusterResourceBindingPermanentIDLabel, + utilhelper.GenOneLabelEqualIndexerFunc(workv1alpha2.ClusterResourceBindingPermanentIDLabel), + ).Build() tempDyClient := fakedynamic.NewSimpleDynamicClient(scheme.Scheme) if rs == nil { return &ClusterResourceBindingController{ - Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(), + Client: c, RESTMapper: testing2.RestMapper, InformerManager: genericmanager.NewSingleClusterInformerManager(tempDyClient, 0, nil), DynamicClient: tempDyClient, @@ -77,7 +84,7 @@ func makeFakeCRBCByResource(rs *workv1alpha2.ObjectReference) (*ClusterResourceB } return &ClusterResourceBindingController{ - Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(), + Client: c, RESTMapper: helper.NewGroupRESTMapper(rs.Kind, meta.RESTScopeNamespace), InformerManager: testing3.NewSingleClusterInformerManagerByRS(src, obj), DynamicClient: tempDyClient, diff --git a/pkg/controllers/status/crb_status_controller_test.go b/pkg/controllers/status/crb_status_controller_test.go index 1bf0b33dfa4e..d11bb3221f3a 100644 --- a/pkg/controllers/status/crb_status_controller_test.go +++ b/pkg/controllers/status/crb_status_controller_test.go @@ -33,10 +33,12 @@ import ( controllerruntime "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client/fake" + workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1" workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2" "github.com/karmada-io/karmada/pkg/resourceinterpreter/default/native" "github.com/karmada-io/karmada/pkg/util/fedinformer/genericmanager" "github.com/karmada-io/karmada/pkg/util/gclient" + utilhelper "github.com/karmada-io/karmada/pkg/util/helper" ) func generateCRBStatusController() *CRBStatusController { @@ -50,7 +52,11 @@ func generateCRBStatusController() *CRBStatusController { m.WaitForCacheSync() c := &CRBStatusController{ - Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(), + Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithIndex( + &workv1alpha1.Work{}, + workv1alpha2.ClusterResourceBindingPermanentIDLabel, + utilhelper.GenOneLabelEqualIndexerFunc(workv1alpha2.ClusterResourceBindingPermanentIDLabel), + ).Build(), DynamicClient: dynamicClient, InformerManager: m, RESTMapper: func() meta.RESTMapper { @@ -130,7 +136,9 @@ func TestCRBStatusController_Reconcile(t *testing.T) { // Prepare binding and create it in client if tt.binding != nil { - c.Client = fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(tt.binding).WithStatusSubresource(tt.binding).Build() + c.Client = fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(tt.binding).WithStatusSubresource(tt.binding). + WithIndex(&workv1alpha1.Work{}, workv1alpha2.ClusterResourceBindingPermanentIDLabel, utilhelper.GenOneLabelEqualIndexerFunc(workv1alpha2.ClusterResourceBindingPermanentIDLabel)). + Build() } res, err := c.Reconcile(context.Background(), req) @@ -200,7 +208,9 @@ func TestCRBStatusController_syncBindingStatus(t *testing.T) { } if tt.resourceExistInClient { - c.Client = fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(binding).WithStatusSubresource(binding).Build() + c.Client = fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(binding).WithStatusSubresource(binding). + WithIndex(&workv1alpha1.Work{}, workv1alpha2.ClusterResourceBindingPermanentIDLabel, utilhelper.GenOneLabelEqualIndexerFunc(workv1alpha2.ClusterResourceBindingPermanentIDLabel)). + Build() } err := c.syncBindingStatus(context.Background(), binding) diff --git a/pkg/controllers/status/rb_status_controller_test.go b/pkg/controllers/status/rb_status_controller_test.go index 537a07e8560e..63df9464b3a5 100644 --- a/pkg/controllers/status/rb_status_controller_test.go +++ b/pkg/controllers/status/rb_status_controller_test.go @@ -33,11 +33,13 @@ import ( controllerruntime "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client/fake" + workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1" workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2" "github.com/karmada-io/karmada/pkg/resourceinterpreter" "github.com/karmada-io/karmada/pkg/resourceinterpreter/default/native" "github.com/karmada-io/karmada/pkg/util/fedinformer/genericmanager" "github.com/karmada-io/karmada/pkg/util/gclient" + utilhelper "github.com/karmada-io/karmada/pkg/util/helper" ) func generateRBStatusController() *RBStatusController { @@ -51,7 +53,11 @@ func generateRBStatusController() *RBStatusController { m.WaitForCacheSync() c := &RBStatusController{ - Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(), + Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithIndex( + &workv1alpha1.Work{}, + workv1alpha2.ClusterResourceBindingPermanentIDLabel, + utilhelper.GenOneLabelEqualIndexerFunc(workv1alpha2.ClusterResourceBindingPermanentIDLabel), + ).Build(), DynamicClient: dynamicClient, InformerManager: m, RESTMapper: func() meta.RESTMapper { @@ -136,7 +142,9 @@ func TestRBStatusController_Reconcile(t *testing.T) { // Prepare binding and create it in client if tt.binding != nil { - c.Client = fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(tt.binding).WithStatusSubresource(tt.binding).Build() + c.Client = fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(tt.binding).WithStatusSubresource(tt.binding). + WithIndex(&workv1alpha1.Work{}, workv1alpha2.ResourceBindingPermanentIDLabel, utilhelper.GenOneLabelEqualIndexerFunc(workv1alpha2.ResourceBindingPermanentIDLabel)). + Build() } res, err := c.Reconcile(context.Background(), req) @@ -209,7 +217,9 @@ func TestRBStatusController_syncBindingStatus(t *testing.T) { } if tt.resourceExistInClient { - c.Client = fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(binding).WithStatusSubresource(binding).Build() + c.Client = fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(binding).WithStatusSubresource(binding). + WithIndex(&workv1alpha1.Work{}, workv1alpha2.ResourceBindingPermanentIDLabel, utilhelper.GenOneLabelEqualIndexerFunc(workv1alpha2.ResourceBindingPermanentIDLabel)). + Build() } err := c.syncBindingStatus(context.Background(), binding) diff --git a/pkg/util/helper/binding_test.go b/pkg/util/helper/binding_test.go index 4114aa9eff3c..986163a45528 100644 --- a/pkg/util/helper/binding_test.go +++ b/pkg/util/helper/binding_test.go @@ -433,6 +433,10 @@ func TestFindOrphanWorks(t *testing.T) { }, }, }, + ).WithIndex( + &workv1alpha1.Work{}, + workv1alpha2.ResourceBindingPermanentIDLabel, + GenOneLabelEqualIndexerFunc(workv1alpha2.ResourceBindingPermanentIDLabel), ).Build(), bindingNamespace: "default", bindingName: "binding", @@ -478,6 +482,10 @@ func TestFindOrphanWorks(t *testing.T) { }, }, }, + ).WithIndex( + &workv1alpha1.Work{}, + workv1alpha2.ResourceBindingPermanentIDLabel, + GenOneLabelEqualIndexerFunc(workv1alpha2.ResourceBindingPermanentIDLabel), ).Build(), bindingNamespace: "default", bindingName: "binding", @@ -530,6 +538,10 @@ func TestFindOrphanWorks(t *testing.T) { }, }, }, + ).WithIndex( + &workv1alpha1.Work{}, + workv1alpha2.ClusterResourceBindingPermanentIDLabel, + GenOneLabelEqualIndexerFunc(workv1alpha2.ClusterResourceBindingPermanentIDLabel), ).Build(), bindingNamespace: "", bindingName: "binding", @@ -987,7 +999,11 @@ func TestDeleteWorkByRBNamespaceAndName(t *testing.T) { { name: "work is not found", args: args{ - c: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(), + c: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).WithIndex( + &workv1alpha1.Work{}, + workv1alpha2.ResourceBindingPermanentIDLabel, + GenOneLabelEqualIndexerFunc(workv1alpha2.ResourceBindingPermanentIDLabel), + ).Build(), namespace: "default", name: "foo", bindingID: "3617252f-b1bb-43b0-98a1-c7de833c472c", @@ -1011,6 +1027,10 @@ func TestDeleteWorkByRBNamespaceAndName(t *testing.T) { }, }, }, + ).WithIndex( + &workv1alpha1.Work{}, + workv1alpha2.ResourceBindingPermanentIDLabel, + GenOneLabelEqualIndexerFunc(workv1alpha2.ResourceBindingPermanentIDLabel), ).Build(), namespace: "default", name: "foo", @@ -1034,6 +1054,10 @@ func TestDeleteWorkByRBNamespaceAndName(t *testing.T) { }, }, }, + ).WithIndex( + &workv1alpha1.Work{}, + workv1alpha2.ClusterResourceBindingPermanentIDLabel, + GenOneLabelEqualIndexerFunc(workv1alpha2.ClusterResourceBindingPermanentIDLabel), ).Build(), name: "foo", bindingID: "3617252f-b1bb-43b0-98a1-c7de833c472c", diff --git a/pkg/util/helper/index.go b/pkg/util/helper/index.go new file mode 100644 index 000000000000..cf018c62503c --- /dev/null +++ b/pkg/util/helper/index.go @@ -0,0 +1,40 @@ +package helper + +import ( + "context" + + "k8s.io/klog/v2" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1" + workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2" +) + +// IndexWork creates index for Work. +func IndexWork(ctx context.Context, mgr ctrl.Manager) error { + err := mgr.GetFieldIndexer().IndexField(ctx, &workv1alpha1.Work{}, workv1alpha2.ResourceBindingPermanentIDLabel, + GenOneLabelEqualIndexerFunc(workv1alpha2.ResourceBindingPermanentIDLabel)) + if err != nil { + klog.Errorf("failed to create index for work, err: %v", err) + return err + } + err = mgr.GetFieldIndexer().IndexField(ctx, &workv1alpha1.Work{}, workv1alpha2.ClusterResourceBindingPermanentIDLabel, + GenOneLabelEqualIndexerFunc(workv1alpha2.ClusterResourceBindingPermanentIDLabel)) + if err != nil { + klog.Errorf("failed to create index for work, err: %v", err) + return err + } + return nil +} + +// GenOneLabelEqualIndexerFunc returns an IndexerFunc used to index resource with the given key as label key. +func GenOneLabelEqualIndexerFunc(key string) client.IndexerFunc { + return func(obj client.Object) []string { + refKey := obj.GetLabels()[key] + if refKey == "" { + return nil + } + return []string{refKey} + } +} diff --git a/pkg/util/helper/index_test.go b/pkg/util/helper/index_test.go new file mode 100644 index 000000000000..20a777245fbe --- /dev/null +++ b/pkg/util/helper/index_test.go @@ -0,0 +1,58 @@ +package helper + +import ( + "testing" + + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func TestGenOneLabelEqualIndexerFunc(t *testing.T) { + type args struct { + key string + obj client.Object + } + tests := []struct { + name string + args args + want []string + }{ + { + name: "cache hit", + args: args{ + key: "a", + obj: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "a": "a", + }, + }, + }, + }, + want: []string{"a"}, + }, + { + name: "cache missed", + args: args{ + key: "b", + obj: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "a": "a", + }, + }, + }, + }, + want: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fn := GenOneLabelEqualIndexerFunc(tt.args.key) + assert.NotNil(t, fn) + assert.Equalf(t, tt.want, fn(tt.args.obj), "GenOneLabelEqualIndexerFunc(%v)", tt.args.key) + }) + } +} diff --git a/pkg/util/helper/work.go b/pkg/util/helper/work.go index 438a7309e8eb..987a3dc8e709 100644 --- a/pkg/util/helper/work.go +++ b/pkg/util/helper/work.go @@ -23,6 +23,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -117,15 +118,19 @@ func GetWorksByLabelsSet(ctx context.Context, c client.Client, ls labels.Set) (* } // GetWorksByBindingID gets WorkList by matching same binding's permanent id. +// Caller should ensure Work is indexed by binding's permanent id. func GetWorksByBindingID(ctx context.Context, c client.Client, bindingID string, namespaced bool) (*workv1alpha1.WorkList, error) { - var ls labels.Set + var key string if namespaced { - ls = labels.Set{workv1alpha2.ResourceBindingPermanentIDLabel: bindingID} + key = workv1alpha2.ResourceBindingPermanentIDLabel } else { - ls = labels.Set{workv1alpha2.ClusterResourceBindingPermanentIDLabel: bindingID} + key = workv1alpha2.ClusterResourceBindingPermanentIDLabel } - - return GetWorksByLabelsSet(ctx, c, ls) + workList := &workv1alpha1.WorkList{} + listOpt := &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(key, bindingID), + } + return workList, c.List(ctx, workList, listOpt) } // GenEventRef returns the event reference. sets the UID(.spec.uid) that might be missing for fire events. diff --git a/test/e2e/clusterresourcebinding_test.go b/test/e2e/clusterresourcebinding_test.go index 13885ff2cbaa..44a9b7fe6841 100644 --- a/test/e2e/clusterresourcebinding_test.go +++ b/test/e2e/clusterresourcebinding_test.go @@ -80,7 +80,7 @@ var _ = ginkgo.Describe("ClusterResourceBinding test", func() { ginkgo.It("creates work with permanent ID label", func() { framework.WaitClusterResourceBindingFitWith(karmadaClient, bindingName, func(clusterResourceBinding *workv1alpha2.ClusterResourceBinding) bool { - workList, err := helper.GetWorksByBindingID(context.Background(), controlPlaneClient, clusterResourceBinding.Labels[workv1alpha2.ClusterResourceBindingPermanentIDLabel], false) + workList, err := helper.GetWorksByBindingID(context.Background(), controllerManager.GetClient(), clusterResourceBinding.Labels[workv1alpha2.ClusterResourceBindingPermanentIDLabel], false) if err != nil { return false } diff --git a/test/e2e/framework/controllerruntime.go b/test/e2e/framework/controllerruntime.go new file mode 100644 index 000000000000..8e9fc37f6319 --- /dev/null +++ b/test/e2e/framework/controllerruntime.go @@ -0,0 +1,37 @@ +package framework + +import ( + "context" + + "github.com/onsi/gomega" + "k8s.io/client-go/rest" + "k8s.io/klog/v2" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" + + "github.com/karmada-io/karmada/pkg/util/fedinformer" + "github.com/karmada-io/karmada/pkg/util/gclient" + "github.com/karmada-io/karmada/pkg/util/restmapper" +) + +// InitControllerManagerAndStartCache initializes the controller manager and starts the cache. +func InitControllerManagerAndStartCache(restConfig *rest.Config) ctrl.Manager { + manager, err := ctrl.NewManager(restConfig, ctrl.Options{ + Logger: klog.Background(), + Scheme: gclient.NewSchema(), + MapperProvider: restmapper.MapperProvider, + NewCache: func(config *rest.Config, opts cache.Options) (cache.Cache, error) { + opts.DefaultTransform = fedinformer.StripUnusedFields + return cache.New(config, opts) + }, + }) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + + go func() { + _ = manager.GetCache().Start(context.TODO()) + }() + synced := manager.GetCache().WaitForCacheSync(context.TODO()) + gomega.Expect(synced).Should(gomega.BeTrue()) + + return manager +} diff --git a/test/e2e/suite_test.go b/test/e2e/suite_test.go index f82dd72e6599..a2c5c42bf6c1 100644 --- a/test/e2e/suite_test.go +++ b/test/e2e/suite_test.go @@ -40,6 +40,7 @@ import ( "k8s.io/client-go/rest" mapper "k8s.io/client-go/restmapper" "k8s.io/client-go/tools/clientcmd" + ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/kind/pkg/cluster" kindexec "sigs.k8s.io/kind/pkg/exec" @@ -48,6 +49,7 @@ import ( karmada "github.com/karmada-io/karmada/pkg/generated/clientset/versioned" "github.com/karmada-io/karmada/pkg/util" "github.com/karmada-io/karmada/pkg/util/gclient" + utilhelper "github.com/karmada-io/karmada/pkg/util/helper" "github.com/karmada-io/karmada/test/e2e/framework" "github.com/karmada-io/karmada/test/helper" ) @@ -114,6 +116,7 @@ var ( discoveryClient *discovery.DiscoveryClient restMapper meta.RESTMapper controlPlaneClient client.Client + controllerManager ctrl.Manager testNamespace string clusterProvider *cluster.Provider clusterLabels = map[string]string{"location": "CHN"} @@ -173,6 +176,11 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { framework.InitClusterInformation(karmadaClient, controlPlaneClient) + controllerManager = framework.InitControllerManagerAndStartCache(restConfig) + + err = utilhelper.IndexWork(context.TODO(), controllerManager) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + testNamespace = fmt.Sprintf("karmadatest-%s", rand.String(RandomStrLength)) err = setupTestNamespace(testNamespace, kubeClient) gomega.Expect(err).ShouldNot(gomega.HaveOccurred())