@@ -39,6 +39,8 @@ type SchemaBuilder struct {
39
39
log * logger.Logger
40
40
kindRegistry map [GroupVersionKind ]ResourceInfo // Changed: Use GVK as key for precise lookup
41
41
preferredVersions map [string ]string // map[group/kind]preferredVersion
42
+ maxRelationDepth int // maximum allowed relationship nesting depth (1 = single level)
43
+ relationDepths map [string ]int // tracks the minimum depth at which each schema is referenced
42
44
}
43
45
44
46
// ResourceInfo holds information about a resource for relationship resolution
@@ -54,6 +56,8 @@ func NewSchemaBuilder(oc openapi.Client, preferredApiGroups []string, log *logge
54
56
schemas : make (map [string ]* spec.Schema ),
55
57
kindRegistry : make (map [GroupVersionKind ]ResourceInfo ),
56
58
preferredVersions : make (map [string ]string ),
59
+ maxRelationDepth : 1 , // Default to 1-level depth for now
60
+ relationDepths : make (map [string ]int ),
57
61
log : log ,
58
62
}
59
63
@@ -75,6 +79,19 @@ func NewSchemaBuilder(oc openapi.Client, preferredApiGroups []string, log *logge
75
79
return b
76
80
}
77
81
82
+ // WithMaxRelationDepth sets the maximum allowed relationship nesting depth
83
+ // depth=1: A->B (single level)
84
+ // depth=2: A->B->C (two levels)
85
+ // depth=3: A->B->C->D (three levels)
86
+ func (b * SchemaBuilder ) WithMaxRelationDepth (depth int ) * SchemaBuilder {
87
+ if depth < 1 {
88
+ depth = 1 // Minimum depth is 1
89
+ }
90
+ b .maxRelationDepth = depth
91
+ b .log .Info ().Int ("maxRelationDepth" , depth ).Msg ("Set maximum relationship nesting depth" )
92
+ return b
93
+ }
94
+
78
95
type GroupVersionKind struct {
79
96
Group string `json:"group"`
80
97
Version string `json:"version"`
@@ -221,16 +238,64 @@ func (b *SchemaBuilder) WithRelationships() *SchemaBuilder {
221
238
// Build kind registry first
222
239
b .buildKindRegistry ()
223
240
224
- // Expand relationships in all schemas
225
- b .log .Info ().Int ("kindRegistrySize" , len (b .kindRegistry )).Msg ("Starting relationship expansion" )
226
- for schemaKey , schema := range b .schemas {
227
- b .log .Debug ().Str ("schemaKey" , schemaKey ).Msg ("Processing schema for relationships" )
228
- b .expandRelationships (schema )
241
+ // For depth=1: use simple relation target tracking (working approach)
242
+ // For depth>1: use iterative expansion (scalable approach)
243
+ if b .maxRelationDepth == 1 {
244
+ b .expandWithSimpleDepthControl ()
245
+ } else {
246
+ b .expandWithConfigurableDepthControl ()
229
247
}
230
248
231
249
return b
232
250
}
233
251
252
+ // expandWithSimpleDepthControl implements the working 1-level depth control
253
+ func (b * SchemaBuilder ) expandWithSimpleDepthControl () {
254
+ // First pass: identify relation targets
255
+ relationTargets := make (map [string ]bool )
256
+ for _ , schema := range b .schemas {
257
+ if schema .Properties == nil {
258
+ continue
259
+ }
260
+ for propName := range schema .Properties {
261
+ if ! isRefProperty (propName ) {
262
+ continue
263
+ }
264
+ baseKind := strings .TrimSuffix (propName , "Ref" )
265
+ target := b .findBestResourceForKind (baseKind )
266
+ if target != nil {
267
+ relationTargets [target .SchemaKey ] = true
268
+ }
269
+ }
270
+ }
271
+
272
+ b .log .Info ().
273
+ Int ("kindRegistrySize" , len (b .kindRegistry )).
274
+ Int ("relationTargets" , len (relationTargets )).
275
+ Msg ("Starting 1-level relationship expansion" )
276
+
277
+ // Second pass: expand only non-targets
278
+ for schemaKey , schema := range b .schemas {
279
+ if relationTargets [schemaKey ] {
280
+ b .log .Debug ().Str ("schemaKey" , schemaKey ).Msg ("Skipping relation target (1-level depth control)" )
281
+ continue
282
+ }
283
+ b .expandRelationshipsSimple (schema , schemaKey )
284
+ }
285
+ }
286
+
287
+ // expandWithConfigurableDepthControl implements scalable depth control for depth > 1
288
+ func (b * SchemaBuilder ) expandWithConfigurableDepthControl () {
289
+ b .log .Info ().
290
+ Int ("kindRegistrySize" , len (b .kindRegistry )).
291
+ Int ("maxRelationDepth" , b .maxRelationDepth ).
292
+ Msg ("Starting configurable relationship expansion" )
293
+
294
+ // TODO: Implement proper multi-level depth control
295
+ // For now, fall back to simple approach
296
+ b .expandWithSimpleDepthControl ()
297
+ }
298
+
234
299
// buildKindRegistry builds a map of kind names to available resource types
235
300
func (b * SchemaBuilder ) buildKindRegistry () {
236
301
for schemaKey , schema := range b .schemas {
@@ -286,6 +351,9 @@ func (b *SchemaBuilder) buildKindRegistry() {
286
351
b .log .Debug ().Int ("gvkCount" , len (b .kindRegistry )).Msg ("built kind registry for relationships" )
287
352
}
288
353
354
+ // TODO: Implement proper multi-level depth calculation when needed
355
+ // For now, focusing on the working 1-level depth control
356
+
289
357
// warnAboutMissingPreferredVersions checks for kinds with multiple resources but no preferred versions
290
358
func (b * SchemaBuilder ) warnAboutMissingPreferredVersions () {
291
359
// Group resources by kind name to find potential conflicts
@@ -429,8 +497,8 @@ func (b *SchemaBuilder) getVersionStability(version string) int {
429
497
return 0 // most stable (v1, v2, etc.)
430
498
}
431
499
432
- // expandRelationships detects fields ending with 'Ref' and adds corresponding relationship fields
433
- func (b * SchemaBuilder ) expandRelationships (schema * spec.Schema ) {
500
+ // expandRelationshipsSimple adds relationship fields for the simple 1-level depth control
501
+ func (b * SchemaBuilder ) expandRelationshipsSimple (schema * spec.Schema , schemaKey string ) {
434
502
if schema .Properties == nil {
435
503
return
436
504
}
@@ -452,24 +520,26 @@ func (b *SchemaBuilder) expandRelationships(schema *spec.Schema) {
452
520
if _ , exists := schema .Properties [fieldName ]; exists {
453
521
continue
454
522
}
455
- ref := spec .MustCreateRef (fmt .Sprintf ("#/definitions/%s.%s.%s" , target .Group , target .Version , target .Kind ))
523
+
524
+ // Create proper reference - handle empty group (core) properly
525
+ var refPath string
526
+ if target .Group == "" {
527
+ refPath = fmt .Sprintf ("#/definitions/%s.%s" , target .Version , target .Kind )
528
+ } else {
529
+ refPath = fmt .Sprintf ("#/definitions/%s.%s.%s" , target .Group , target .Version , target .Kind )
530
+ }
531
+ ref := spec .MustCreateRef (refPath )
456
532
schema .Properties [fieldName ] = spec.Schema {SchemaProps : spec.SchemaProps {Ref : ref }}
457
533
458
534
b .log .Info ().
459
535
Str ("sourceField" , propName ).
460
536
Str ("targetField" , fieldName ).
461
537
Str ("targetKind" , target .Kind ).
462
538
Str ("targetGroup" , target .Group ).
539
+ Str ("refPath" , refPath ).
540
+ Str ("sourceSchema" , schemaKey ).
463
541
Msg ("Added relationship field" )
464
542
}
465
-
466
- // Recursively process nested objects and write back modifications
467
- for key , prop := range schema .Properties {
468
- if prop .Type .Contains ("object" ) && prop .Properties != nil {
469
- b .expandRelationships (& prop )
470
- schema .Properties [key ] = prop
471
- }
472
- }
473
543
}
474
544
475
545
func isRefProperty (name string ) bool {
0 commit comments