@@ -22,7 +22,6 @@ import (
2222 "maps"
2323 "slices"
2424 "strings"
25- "sync"
2625 "time"
2726
2827 corev1 "k8s.io/api/core/v1"
@@ -41,6 +40,7 @@ import (
4140 "github.com/kube-bind/kube-bind/pkg/konnector/controllers/cluster/serviceexport/multinsinformer"
4241 "github.com/kube-bind/kube-bind/pkg/konnector/controllers/cluster/serviceexport/spec"
4342 "github.com/kube-bind/kube-bind/pkg/konnector/controllers/cluster/serviceexport/status"
43+ "github.com/kube-bind/kube-bind/pkg/konnector/controllers/contextstore"
4444 "github.com/kube-bind/kube-bind/pkg/konnector/controllers/dynamic"
4545 kubebindv1alpha2 "github.com/kube-bind/kube-bind/sdk/apis/kubebind/v1alpha2"
4646 conditionsapi "github.com/kube-bind/kube-bind/sdk/apis/third_party/conditions/apis/conditions/v1alpha1"
@@ -56,8 +56,7 @@ type reconciler struct {
5656
5757 consumerConfig , providerConfig * rest.Config
5858
59- lock sync.Mutex
60- syncContext map [string ]syncContext // by CRD name
59+ syncStore contextstore.Store // by APIServiceExport name. This includes same ctx for resourc claims and crds.
6160
6261 getCRD func (name string ) (* apiextensionsv1.CustomResourceDefinition , error )
6362 getServiceBinding func (name string ) (* kubebindv1alpha2.APIServiceBinding , error )
@@ -66,15 +65,10 @@ type reconciler struct {
6665 updateRemoteBoundSchema func (ctx context.Context , boundSchema * kubebindv1alpha2.BoundSchema ) error
6766}
6867
69- type syncContext struct {
70- generation int64
71- cancel func ()
72- }
73-
74- func (r * reconciler ) reconcile (ctx context.Context , name string , export * kubebindv1alpha2.APIServiceExport ) error {
68+ func (r * reconciler ) reconcile (ctx context.Context , namespace , name string , export * kubebindv1alpha2.APIServiceExport ) error {
7569 errs := []error {}
7670
77- if err := r .ensureControllers (ctx , name , export ); err != nil {
71+ if err := r .ensureControllers (ctx , namespace , name , export ); err != nil {
7872 errs = append (errs , err )
7973 }
8074
@@ -90,22 +84,17 @@ func (r *reconciler) reconcile(ctx context.Context, name string, export *kubebin
9084 return utilerrors .NewAggregate (errs )
9185}
9286
93- func (r * reconciler ) ensureControllers (ctx context.Context , name string , export * kubebindv1alpha2.APIServiceExport ) error {
87+ func (r * reconciler ) ensureControllers (ctx context.Context , namespace , name string , export * kubebindv1alpha2.APIServiceExport ) error {
9488 logger := klog .FromContext (ctx )
89+ exportKey := contextstore .Key (namespace + "." + name ) // Key for the export
9590
9691 if export == nil {
97- // stop dangling syncers on delete
98- r .lock .Lock ()
99- defer r .lock .Unlock ()
100-
10192 // Clean up any controllers associated with this export
102- for key , c := range r .syncContext {
103- if strings .HasSuffix (key , "." + name ) {
104- logger .V (1 ).Info ("Stopping APIServiceExport sync" , "key" , key , "reason" , "APIServiceExport deleted" )
105- c .cancel ()
106- delete (r .syncContext , key )
107- }
93+ deleted := r .syncStore .BulkDeletePrefixed (exportKey )
94+ for _ , k := range deleted {
95+ logger .V (1 ).Info ("Stopping APIServiceExport sync" , "key" , k .Key (), "reason" , "NoAPIServiceExport" )
10896 }
97+
10998 return nil
11099 }
111100
@@ -116,14 +105,9 @@ func (r *reconciler) ensureControllers(ctx context.Context, name string, export
116105 }
117106 if binding == nil {
118107 // Stop all controllers for this export
119- r .lock .Lock ()
120- defer r .lock .Unlock ()
121- for key , c := range r .syncContext {
122- if strings .HasSuffix (key , "." + export .Name ) {
123- logger .V (1 ).Info ("Stopping APIServiceExport sync" , "key" , key , "reason" , "NoAPIServiceBinding" )
124- c .cancel ()
125- delete (r .syncContext , key )
126- }
108+ deleted := r .syncStore .BulkDeletePrefixed (exportKey )
109+ for _ , k := range deleted {
110+ logger .V (1 ).Info ("Stopping APIServiceExport sync" , "key" , k .Key (), "reason" , "NoAPIServiceBinding" )
127111 }
128112 return nil
129113 }
@@ -139,15 +123,12 @@ func (r *reconciler) ensureControllers(ctx context.Context, name string, export
139123 schema , err := r .getRemoteBoundSchema (ctx , name )
140124 if err != nil {
141125 if errors .IsNotFound (err ) {
142- // Stop the controller for this schema if it exists
143- r .lock .Lock ()
144- key := name + "." + export .Name
145- if c , found := r .syncContext [key ]; found {
146- logger .V (1 ).Info ("Stopping APIServiceExport resource sync" , "key" , key , "reason" , "BoundSchema not found" )
147- c .cancel ()
148- delete (r .syncContext , key )
126+ // Stop the controller for this schema if it does not exists.
127+ key := contextstore .NewKey (namespace , name , name )
128+ deleted := r .syncStore .BulkDeletePrefixed (key )
129+ for _ , k := range deleted {
130+ logger .V (1 ).Info ("Stopping APIServiceExport sync" , "key" , k .Key (), "reason" , "BoundSchema not found" )
149131 }
150- r .lock .Unlock ()
151132 continue
152133 }
153134 errs = append (errs , err )
@@ -159,50 +140,45 @@ func (r *reconciler) ensureControllers(ctx context.Context, name string, export
159140 errs = append (errs , err )
160141 }
161142
162- processedSchemas [name ] = true
143+ processedSchemas [name ] = true // This is only schemas names (suffix)
163144 isClusterScoped = schema .Spec .Scope == apiextensionsv1 .ClusterScoped || schema .Spec .InformerScope == kubebindv1alpha2 .ClusterScope
164145 }
165146
166147 // Ensure controller for permission claims
167- if err := r .ensureControllersForPermissionClaims (ctx , binding , isClusterScoped ); err != nil {
148+ if err := r .ensureControllersForPermissionClaims (ctx , export , binding , isClusterScoped ); err != nil {
168149 errs = append (errs , err )
169150 }
170151
171- // Stop controllers for schemas that are no longer referenced
172- r .lock .Lock ()
173- for key , c := range r .syncContext {
174- parts := strings .Split (key , "." )
175- if len (parts ) == 2 && parts [1 ] == export .Name {
176- schemaName := parts [0 ]
177- if ! processedSchemas [schemaName ] {
178- logger .V (1 ).Info ("Stopping APIServiceExport resource sync" , "key" , key , "reason" , "Schema no longer referenced" )
179- c .cancel ()
180- delete (r .syncContext , key )
181- }
152+ // Stop controllers for schemas that are no longer referenced.
153+ // This will be `exportNamespace.exportName.<schemaName>`
154+ contexts := r .syncStore .ListPrefixed (exportKey )
155+ for _ , c := range contexts {
156+ schemaName := strings .TrimPrefix (string (c .Key ()), string (exportKey )+ "." ) // schemaName will be processed schema names.
157+ if ! processedSchemas [schemaName ] {
158+ logger .V (1 ).Info ("Stopping APIServiceExport resource sync" , "key" , c .Key (), "reason" , "Schema no longer referenced" )
159+ r .syncStore .Delete (c .Key ())
182160 }
161+
183162 }
184- r .lock .Unlock ()
185163
186164 return utilerrors .NewAggregate (errs )
187165}
188166
189167func (r * reconciler ) ensureControllerForSchema (ctx context.Context , export * kubebindv1alpha2.APIServiceExport , schema * kubebindv1alpha2.BoundSchema ) error {
190168 logger := klog .FromContext (ctx )
191- key := schema . Name + "." + export .Name
169+ key := contextstore . NewKey ( export . Namespace , export .Name , schema . Name )
192170
193- r .lock .Lock ()
194- c , found := r .syncContext [key ]
171+ c , found := r .syncStore .Get (key )
195172 if found {
196- if c .generation == export .Generation {
197- r .lock .Unlock ()
173+ if c .Generation == export .Generation {
198174 return nil // all as expected
199175 }
200176
201177 logger .V (1 ).Info ("Stopping APIServiceExport resource sync" , "key" , key , "reason" , "GenerationChanged" , "generation" , schema .Generation )
202- c .cancel ()
203- delete (r .syncContext , key )
178+ r .syncStore .Delete (key )
204179 }
205- r .lock .Unlock ()
180+
181+ // At this point we dont have a controller for this schema.
206182
207183 // start a new syncer
208184 var syncVersion string
@@ -307,26 +283,24 @@ func (r *reconciler) ensureControllerForSchema(ctx context.Context, export *kube
307283 go statusCtrl .Start (ctxWithCancel , 1 )
308284 }()
309285
310- r .lock .Lock ()
311- defer r .lock .Unlock ()
312- if c , found := r .syncContext [key ]; found {
313- c .cancel ()
314- }
315- r .syncContext [key ] = syncContext {
316- generation : schema .Generation ,
317- cancel : cancel ,
318- }
286+ r .syncStore .Set (key , contextstore.SyncContext {
287+ Generation : schema .Generation ,
288+ Cancel : cancel ,
289+ })
319290
320291 return nil
321292}
322293
323294func (r * reconciler ) ensureControllersForPermissionClaims (
324295 ctx context.Context ,
296+ export * kubebindv1alpha2.APIServiceExport ,
325297 binding * kubebindv1alpha2.APIServiceBinding ,
326298 isClusterScoped bool , // schema.Spec.Scope == apiextensionsv1.ClusterScoped || schema.Spec.InformerScope == kubebindv1alpha2.ClusterScope
327299) error {
328300 logger := klog .FromContext (ctx )
329301
302+ //ctxWithCancel, cancel := context.WithCancel(ctx)
303+
330304 dynamicProviderClient := dynamicclient .NewForConfigOrDie (r .providerConfig )
331305 dynamicConsumerClient := dynamicclient .NewForConfigOrDie (r .consumerConfig )
332306
0 commit comments