@@ -30,6 +30,7 @@ import (
30
30
"github.com/go-openapi/validate"
31
31
"github.com/golang/glog"
32
32
33
+ apiequality "k8s.io/apimachinery/pkg/api/equality"
33
34
apierrors "k8s.io/apimachinery/pkg/api/errors"
34
35
"k8s.io/apimachinery/pkg/api/meta"
35
36
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -79,6 +80,11 @@ type crdHandler struct {
79
80
80
81
// crdInfo stores enough information to serve the storage for the custom resource
81
82
type crdInfo struct {
83
+ // spec and acceptedNames are used to compare against if a change is made on a CRD. We only update
84
+ // the storage if one of these changes.
85
+ spec * apiextensions.CustomResourceDefinitionSpec
86
+ acceptedNames * apiextensions.CustomResourceDefinitionNames
87
+
82
88
storage * customresource.REST
83
89
requestScope handlers.RequestScope
84
90
}
@@ -108,6 +114,9 @@ func NewCustomResourceDefinitionHandler(
108
114
109
115
crdInformer .Informer ().AddEventHandler (cache.ResourceEventHandlerFuncs {
110
116
UpdateFunc : ret .updateCustomResourceDefinition ,
117
+ DeleteFunc : func (obj interface {}) {
118
+ ret .removeDeadStorage ()
119
+ },
111
120
})
112
121
113
122
ret .customStorage .Store (crdStorageMap {})
@@ -245,7 +254,7 @@ func (r *crdHandler) removeDeadStorage() {
245
254
return
246
255
}
247
256
248
- for uid := range storageMap {
257
+ for uid , s := range storageMap {
249
258
found := false
250
259
for _ , crd := range allCustomResourceDefinitions {
251
260
if crd .UID == uid {
@@ -254,6 +263,8 @@ func (r *crdHandler) removeDeadStorage() {
254
263
}
255
264
}
256
265
if ! found {
266
+ glog .V (4 ).Infof ("Removing dead CRD storage for %v" , s .requestScope .Resource )
267
+ s .storage .DestroyFunc ()
257
268
delete (storageMap , uid )
258
269
}
259
270
}
@@ -301,7 +312,7 @@ func (r *crdHandler) getServingInfoFor(crd *apiextensions.CustomResourceDefiniti
301
312
parameterScheme .AddGeneratedDeepCopyFuncs (metav1 .GetGeneratedDeepCopyFuncs ()... )
302
313
parameterCodec := runtime .NewParameterCodec (parameterScheme )
303
314
304
- kind := schema.GroupVersionKind {Group : crd .Spec .Group , Version : crd .Spec .Version , Kind : crd .Spec . Names .Kind }
315
+ kind := schema.GroupVersionKind {Group : crd .Spec .Group , Version : crd .Spec .Version , Kind : crd .Status . AcceptedNames .Kind }
305
316
typer := unstructuredObjectTyper {
306
317
delegate : parameterScheme ,
307
318
unstructuredTyper : discovery .NewUnstructuredObjectTyper (nil ),
@@ -319,8 +330,8 @@ func (r *crdHandler) getServingInfoFor(crd *apiextensions.CustomResourceDefiniti
319
330
validator := validate .NewSchemaValidator (openapiSchema , nil , "" , strfmt .Default )
320
331
321
332
storage := customresource .NewREST (
322
- schema.GroupResource {Group : crd .Spec .Group , Resource : crd .Spec . Names .Plural },
323
- schema.GroupVersionKind {Group : crd .Spec .Group , Version : crd .Spec .Version , Kind : crd .Spec . Names .ListKind },
333
+ schema.GroupResource {Group : crd .Spec .Group , Resource : crd .Status . AcceptedNames .Plural },
334
+ schema.GroupVersionKind {Group : crd .Spec .Group , Version : crd .Spec .Version , Kind : crd .Status . AcceptedNames .ListKind },
324
335
customresource .NewStrategy (
325
336
typer ,
326
337
crd .Spec .Scope == apiextensions .NamespaceScoped ,
@@ -367,14 +378,17 @@ func (r *crdHandler) getServingInfoFor(crd *apiextensions.CustomResourceDefiniti
367
378
Typer : typer ,
368
379
UnsafeConvertor : unstructured.UnstructuredObjectConverter {},
369
380
370
- Resource : schema.GroupVersionResource {Group : crd .Spec .Group , Version : crd .Spec .Version , Resource : crd .Spec . Names .Plural },
381
+ Resource : schema.GroupVersionResource {Group : crd .Spec .Group , Version : crd .Spec .Version , Resource : crd .Status . AcceptedNames .Plural },
371
382
Kind : kind ,
372
383
Subresource : "" ,
373
384
374
385
MetaGroupVersion : metav1 .SchemeGroupVersion ,
375
386
}
376
387
377
388
ret = & crdInfo {
389
+ spec : & crd .Spec ,
390
+ acceptedNames : & crd .Status .AcceptedNames ,
391
+
378
392
storage : storage ,
379
393
requestScope : requestScope ,
380
394
}
@@ -410,23 +424,36 @@ func (c crdObjectConverter) ConvertFieldLabel(version, kind, label, value string
410
424
}
411
425
}
412
426
413
- func (c * crdHandler ) updateCustomResourceDefinition (oldObj , _ interface {}) {
427
+ func (c * crdHandler ) updateCustomResourceDefinition (oldObj , newObj interface {}) {
414
428
oldCRD := oldObj .(* apiextensions.CustomResourceDefinition )
415
- glog . V ( 4 ). Infof ( "Updating customresourcedefinition %s" , oldCRD . Name )
429
+ newCRD := newObj .( * apiextensions. CustomResourceDefinition )
416
430
417
431
c .customStorageLock .Lock ()
418
432
defer c .customStorageLock .Unlock ()
419
-
420
433
storageMap := c .customStorage .Load ().(crdStorageMap )
434
+
435
+ oldInfo , found := storageMap [newCRD .UID ]
436
+ if ! found {
437
+ return
438
+ }
439
+ if apiequality .Semantic .DeepEqual (& newCRD .Spec , oldInfo .spec ) && apiequality .Semantic .DeepEqual (& newCRD .Status .AcceptedNames , oldInfo .acceptedNames ) {
440
+ glog .V (6 ).Infof ("Ignoring customresourcedefinition %s update because neither spec, nor accepted names changed" , oldCRD .Name )
441
+ return
442
+ }
443
+
444
+ glog .V (4 ).Infof ("Updating customresourcedefinition %s" , oldCRD .Name )
421
445
storageMap2 := make (crdStorageMap , len (storageMap ))
422
446
423
447
// Copy because we cannot write to storageMap without a race
424
448
// as it is used without locking elsewhere
425
449
for k , v := range storageMap {
450
+ if k == oldCRD .UID {
451
+ v .storage .DestroyFunc ()
452
+ continue
453
+ }
426
454
storageMap2 [k ] = v
427
455
}
428
456
429
- delete (storageMap2 , oldCRD .UID )
430
457
c .customStorage .Store (storageMap2 )
431
458
}
432
459
0 commit comments