@@ -254,7 +254,40 @@ func (b *SchemaBuilder) buildKindRegistry() {
254
254
}
255
255
256
256
// Index by lowercase kind name for consistent lookup
257
- b .kindRegistry [strings .ToLower (gvk .Kind )] = append (b .kindRegistry [strings .ToLower (gvk .Kind )], resourceInfo )
257
+ key := strings .ToLower (gvk .Kind )
258
+ b .kindRegistry [key ] = append (b .kindRegistry [key ], resourceInfo )
259
+ }
260
+
261
+ // Ensure deterministic order for picks: sort each slice by Group, Version, Kind, SchemaKey
262
+ for kindKey , infos := range b .kindRegistry {
263
+ slices .SortFunc (infos , func (a , b ResourceInfo ) int {
264
+ if a .Group != b .Group {
265
+ if a .Group < b .Group {
266
+ return - 1
267
+ }
268
+ return 1
269
+ }
270
+ if a .Version != b .Version {
271
+ if a .Version < b .Version {
272
+ return - 1
273
+ }
274
+ return 1
275
+ }
276
+ if a .Kind != b .Kind {
277
+ if a .Kind < b .Kind {
278
+ return - 1
279
+ }
280
+ return 1
281
+ }
282
+ if a .SchemaKey < b .SchemaKey {
283
+ return - 1
284
+ }
285
+ if a .SchemaKey > b .SchemaKey {
286
+ return 1
287
+ }
288
+ return 0
289
+ })
290
+ b .kindRegistry [kindKey ] = infos
258
291
}
259
292
260
293
b .log .Debug ().Int ("kindCount" , len (b .kindRegistry )).Msg ("built kind registry for relationships" )
@@ -266,51 +299,34 @@ func (b *SchemaBuilder) expandRelationships(schema *spec.Schema) {
266
299
return
267
300
}
268
301
269
- // Create a copy of properties to avoid modifying while iterating
270
- originalProps := make (map [string ]spec.Schema )
271
- for k , v := range schema .Properties {
272
- originalProps [k ] = v
273
- }
302
+ for propName := range schema .Properties {
303
+ if ! isRefProperty (propName ) {
304
+ continue
305
+ }
274
306
275
- for propName := range originalProps {
276
- if strings .HasSuffix (propName , "Ref" ) && propName != "Ref" {
277
- // Extract the base kind (e.g., "role" from "roleRef")
278
- baseKind := strings .TrimSuffix (propName , "Ref" )
279
- b .log .Debug ().Str ("propName" , propName ).Str ("baseKind" , baseKind ).Msg ("Found Ref field" )
280
-
281
- // Find the first matching resource type for this kind
282
- lookupKey := strings .ToLower (baseKind )
283
- b .log .Debug ().Str ("lookupKey" , lookupKey ).Msg ("Looking up in kind registry" )
284
- if resourceTypes , exists := b .kindRegistry [lookupKey ]; exists && len (resourceTypes ) > 0 {
285
- b .log .Debug ().Str ("lookupKey" , lookupKey ).Int ("resourceCount" , len (resourceTypes )).Msg ("Found matching resources" )
286
- // Use the first matching resource type
287
- targetResource := resourceTypes [0 ]
288
-
289
- // Generate field name (e.g., "role" for "roleRef")
290
- fieldName := strings .ToLower (baseKind )
291
-
292
- // Add the relationship field
293
- if _ , exists := schema .Properties [fieldName ]; ! exists {
294
- // Create a reference to the target schema
295
- refSchema := spec.Schema {
296
- SchemaProps : spec.SchemaProps {
297
- Ref : spec .MustCreateRef (fmt .Sprintf ("#/definitions/%s.%s.%s" ,
298
- targetResource .Group , targetResource .Version , targetResource .Kind )),
299
- },
300
- }
301
- schema .Properties [fieldName ] = refSchema
302
-
303
- b .log .Info ().
304
- Str ("sourceField" , propName ).
305
- Str ("targetField" , fieldName ).
306
- Str ("targetKind" , targetResource .Kind ).
307
- Str ("targetGroup" , targetResource .Group ).
308
- Msg ("Added relationship field" )
309
- }
310
- } else {
311
- b .log .Debug ().Str ("lookupKey" , lookupKey ).Msg ("No matching resources found in kind registry" )
312
- }
307
+ baseKind := strings .TrimSuffix (propName , "Ref" )
308
+ lookupKey := strings .ToLower (baseKind )
309
+
310
+ resourceTypes , exists := b .kindRegistry [lookupKey ]
311
+ if ! exists || len (resourceTypes ) == 0 {
312
+ continue
313
+ }
314
+
315
+ fieldName := strings .ToLower (baseKind )
316
+ if _ , exists := schema .Properties [fieldName ]; exists {
317
+ continue
313
318
}
319
+
320
+ target := resourceTypes [0 ]
321
+ ref := spec .MustCreateRef (fmt .Sprintf ("#/definitions/%s.%s.%s" , target .Group , target .Version , target .Kind ))
322
+ schema .Properties [fieldName ] = spec.Schema {SchemaProps : spec.SchemaProps {Ref : ref }}
323
+
324
+ b .log .Info ().
325
+ Str ("sourceField" , propName ).
326
+ Str ("targetField" , fieldName ).
327
+ Str ("targetKind" , target .Kind ).
328
+ Str ("targetGroup" , target .Group ).
329
+ Msg ("Added relationship field" )
314
330
}
315
331
316
332
// Recursively process nested objects and write back modifications
@@ -322,6 +338,16 @@ func (b *SchemaBuilder) expandRelationships(schema *spec.Schema) {
322
338
}
323
339
}
324
340
341
+ func isRefProperty (name string ) bool {
342
+ if ! strings .HasSuffix (name , "Ref" ) {
343
+ return false
344
+ }
345
+ if name == "Ref" {
346
+ return false
347
+ }
348
+ return true
349
+ }
350
+
325
351
func (b * SchemaBuilder ) Complete () ([]byte , error ) {
326
352
v3JSON , err := json .Marshal (& schemaResponse {
327
353
Components : schemasComponentsWrapper {
0 commit comments