@@ -37,8 +37,8 @@ type SchemaBuilder struct {
37
37
schemas map [string ]* spec.Schema
38
38
err * multierror.Error
39
39
log * logger.Logger
40
- kindRegistry map [string ][] ResourceInfo
41
- preferredVersions map [string ]string // map[group/kind]preferredVersion
40
+ kindRegistry map [GroupVersionKind ] ResourceInfo // Changed: Use GVK as key for precise lookup
41
+ preferredVersions map [string ]string // map[group/kind]preferredVersion
42
42
}
43
43
44
44
// ResourceInfo holds information about a resource for relationship resolution
@@ -52,7 +52,7 @@ type ResourceInfo struct {
52
52
func NewSchemaBuilder (oc openapi.Client , preferredApiGroups []string , log * logger.Logger ) * SchemaBuilder {
53
53
b := & SchemaBuilder {
54
54
schemas : make (map [string ]* spec.Schema ),
55
- kindRegistry : make (map [string ][ ]ResourceInfo ),
55
+ kindRegistry : make (map [GroupVersionKind ]ResourceInfo ),
56
56
preferredVersions : make (map [string ]string ),
57
57
log : log ,
58
58
}
@@ -274,53 +274,78 @@ func (b *SchemaBuilder) buildKindRegistry() {
274
274
275
275
gvk := gvks [0 ]
276
276
277
- // Add to kind registry
277
+ // Add to kind registry with precise GVK key
278
278
resourceInfo := ResourceInfo {
279
279
Group : gvk .Group ,
280
280
Version : gvk .Version ,
281
281
Kind : gvk .Kind ,
282
282
SchemaKey : schemaKey ,
283
283
}
284
284
285
- // Index by lowercase kind name for consistent lookup
286
- key := strings .ToLower (gvk .Kind )
287
- b .kindRegistry [key ] = append (b .kindRegistry [key ], resourceInfo )
285
+ // Index by full GroupVersionKind for precise lookup (no collisions)
286
+ gvkKey := GroupVersionKind {
287
+ Group : gvk .Group ,
288
+ Version : gvk .Version ,
289
+ Kind : gvk .Kind ,
290
+ }
291
+ b .kindRegistry [gvkKey ] = resourceInfo
288
292
}
289
293
290
- // Sort by preferred version first, then by stability and group priority
291
- for kindKey , infos := range b .kindRegistry {
292
- slices .SortFunc (infos , func (a , bInfo ResourceInfo ) int {
293
- // 1. Prioritize resources with preferred versions
294
- aKey := fmt .Sprintf ("%s/%s" , a .Group , a .Kind )
295
- bKey := fmt .Sprintf ("%s/%s" , bInfo .Group , bInfo .Kind )
296
-
297
- aPreferred := b .preferredVersions [aKey ] == a .Version
298
- bPreferred := b .preferredVersions [bKey ] == bInfo .Version
294
+ // No sorting needed - each GVK is now uniquely indexed
295
+ b .log .Debug ().Int ("gvkCount" , len (b .kindRegistry )).Msg ("built kind registry for relationships" )
296
+ }
299
297
300
- if aPreferred && ! bPreferred {
301
- return - 1 // a is preferred, comes first
302
- }
303
- if ! aPreferred && bPreferred {
304
- return 1 // b is preferred, comes first
305
- }
298
+ // findBestResourceForKind finds the best matching resource for a given kind name
299
+ // using preferred version logic and group prioritization
300
+ func (b * SchemaBuilder ) findBestResourceForKind (kindName string ) * ResourceInfo {
301
+ // Collect all resources with matching kind name
302
+ candidates := make ([]ResourceInfo , 0 )
306
303
307
- // 2. If both or neither are preferred, prioritize by group (core comes first)
308
- if cmp := b .compareGroups (a .Group , bInfo .Group ); cmp != 0 {
309
- return cmp
310
- }
304
+ for gvk , resourceInfo := range b .kindRegistry {
305
+ if strings .EqualFold (gvk .Kind , kindName ) {
306
+ candidates = append (candidates , resourceInfo )
307
+ }
308
+ }
311
309
312
- // 3. Then by version stability (v1 > v1beta1 > v1alpha1)
313
- if cmp := b .compareVersionStability (a .Version , bInfo .Version ); cmp != 0 {
314
- return cmp
315
- }
310
+ if len (candidates ) == 0 {
311
+ return nil
312
+ }
316
313
317
- // 4. Finally by schema key for deterministic ordering
318
- return strings .Compare (a .SchemaKey , bInfo .SchemaKey )
319
- })
320
- b .kindRegistry [kindKey ] = infos
314
+ if len (candidates ) == 1 {
315
+ return & candidates [0 ]
321
316
}
322
317
323
- b .log .Debug ().Int ("kindCount" , len (b .kindRegistry )).Msg ("built kind registry for relationships" )
318
+ // Sort candidates using preferred version logic
319
+ slices .SortFunc (candidates , func (a , bRes ResourceInfo ) int {
320
+ // 1. Prioritize resources with preferred versions
321
+ aKey := fmt .Sprintf ("%s/%s" , a .Group , a .Kind )
322
+ bKey := fmt .Sprintf ("%s/%s" , bRes .Group , bRes .Kind )
323
+
324
+ aPreferred := b .preferredVersions [aKey ] == a .Version
325
+ bPreferred := b .preferredVersions [bKey ] == bRes .Version
326
+
327
+ if aPreferred && ! bPreferred {
328
+ return - 1 // a is preferred, comes first
329
+ }
330
+ if ! aPreferred && bPreferred {
331
+ return 1 // b is preferred, comes first
332
+ }
333
+
334
+ // 2. If both or neither are preferred, prioritize by group (core comes first)
335
+ if cmp := b .compareGroups (a .Group , bRes .Group ); cmp != 0 {
336
+ return cmp
337
+ }
338
+
339
+ // 3. Then by version stability (v1 > v1beta1 > v1alpha1)
340
+ if cmp := b .compareVersionStability (a .Version , bRes .Version ); cmp != 0 {
341
+ return cmp
342
+ }
343
+
344
+ // 4. Finally by schema key for deterministic ordering
345
+ return strings .Compare (a .SchemaKey , bRes .SchemaKey )
346
+ })
347
+
348
+ return & candidates [0 ]
324
349
}
325
350
326
351
// compareGroups prioritizes core Kubernetes groups over custom groups
@@ -385,19 +410,17 @@ func (b *SchemaBuilder) expandRelationships(schema *spec.Schema) {
385
410
}
386
411
387
412
baseKind := strings .TrimSuffix (propName , "Ref" )
388
- lookupKey := strings .ToLower (baseKind )
389
413
390
- resourceTypes , exists := b .kindRegistry [lookupKey ]
391
- if ! exists || len (resourceTypes ) == 0 {
414
+ // Find the best resource for this kind name using preferred version logic
415
+ target := b .findBestResourceForKind (baseKind )
416
+ if target == nil {
392
417
continue
393
418
}
394
419
395
420
fieldName := strings .ToLower (baseKind )
396
421
if _ , exists := schema .Properties [fieldName ]; exists {
397
422
continue
398
423
}
399
-
400
- target := resourceTypes [0 ]
401
424
ref := spec .MustCreateRef (fmt .Sprintf ("#/definitions/%s.%s.%s" , target .Group , target .Version , target .Kind ))
402
425
schema .Properties [fieldName ] = spec.Schema {SchemaProps : spec.SchemaProps {Ref : ref }}
403
426
0 commit comments