@@ -361,3 +361,81 @@ func LoadFromCluster(ctx context.Context, client kubernetes.Interface, selectors
361361 RawSpecs : rawSpecs ,
362362 })
363363}
364+
365+ // LoadAdditionalSpecFromURIs loads additional specs from the URIs provided in the kinds.
366+ // This function will modify kinds in place.
367+ func LoadAdditionalSpecFromURIs (ctx context.Context , kinds * loader.TroubleshootKinds ) {
368+
369+ obj := reflect .ValueOf (* kinds )
370+
371+ // iterate over all fields of the TroubleshootKinds
372+ // e.g. SupportBundlesV1Beta2, PreflightsV1Beta2, etc.
373+ for i := 0 ; i < obj .NumField (); i ++ {
374+ field := obj .Field (i )
375+ if field .Kind () != reflect .Slice {
376+ continue
377+ }
378+
379+ // look at each spec in the slice
380+ // e.g. each spec in []PreflightsV1Beta2
381+ for count := 0 ; count < field .Len (); count ++ {
382+ currentSpec := field .Index (count )
383+ specName := currentSpec .Type ().Name ()
384+
385+ // check if .Spec.Uri exists
386+ specField := currentSpec .FieldByName ("Spec" )
387+ if ! specField .IsValid () {
388+ continue
389+ }
390+ uriField := specField .FieldByName ("Uri" )
391+ if uriField .Kind () != reflect .String {
392+ continue
393+ }
394+
395+ // download spec from URI
396+ uri := uriField .String ()
397+ if uri == "" {
398+ continue
399+ }
400+ rawSpec , err := downloadFromHttpURL (ctx , uri , nil )
401+ if err != nil {
402+ klog .Warningf ("failed to download spec from URI %q: %v" , uri , err )
403+ continue
404+ }
405+
406+ // load spec from raw spec
407+ uriKinds , err := loader .LoadSpecs (ctx , loader.LoadOptions {RawSpec : string (rawSpec )})
408+ if err != nil {
409+ klog .Warningf ("failed to load spec from URI %q: %v" , uri , err )
410+ continue
411+ }
412+
413+ // replace original spec with the loaded spec from URI
414+ newSpec := getFirstSpecOf (uriKinds , specName )
415+ if ! newSpec .IsValid () {
416+ klog .Warningf ("failed to read spec of type %s in URI %s" , specName , uri )
417+ continue
418+ }
419+ currentSpec .Set (newSpec )
420+ }
421+ }
422+ }
423+
424+ // dynamically get spec from kinds of given name
425+ // return first element of the spec slice
426+ func getFirstSpecOf (kinds * loader.TroubleshootKinds , name string ) reflect.Value {
427+ obj := reflect .ValueOf (* kinds )
428+ for i := 0 ; i < obj .NumField (); i ++ {
429+ field := obj .Field (i )
430+ if field .Kind () != reflect .Slice {
431+ continue
432+ }
433+ if field .Len () > 0 {
434+ if field .Index (0 ).Type ().Name () == name {
435+ // return first element
436+ return field .Index (0 )
437+ }
438+ }
439+ }
440+ return reflect.Value {}
441+ }
0 commit comments