Skip to content

Commit 2d5687a

Browse files
committed
refactor(kubevirt): Extract helper functions from searchDataSources
Break down the searchDataSources function into smaller, focused helper functions: - getDynamicClient: Handles dynamic client initialization - collectDataSources: Collects DataSources from well-known and all namespaces - deduplicateAndMergeDataSources: Merges and deduplicates DataSource results This improves code readability and maintainability by following the single responsibility principle. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Lee Yarwood <lyarwood@redhat.com>
1 parent 1c173c5 commit 2d5687a

File tree

1 file changed

+58
-41
lines changed
  • pkg/toolsets/kubevirt/vm/create

1 file changed

+58
-41
lines changed

pkg/toolsets/kubevirt/vm/create/tool.go

Lines changed: 58 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -407,20 +407,8 @@ func getDefaultContainerDisks() []DataSourceInfo {
407407

408408
// searchDataSources searches for DataSource resources in the cluster
409409
func searchDataSources(params api.ToolHandlerParams, query string) ([]DataSourceInfo, error) {
410-
// Try to get dynamic client to query for DataSources
411-
// Handle nil or invalid clients gracefully (e.g., in test environments)
412-
if params.Kubernetes == nil {
413-
// Return just the built-in containerdisk images
414-
return getDefaultContainerDisks(), nil
415-
}
416-
417-
restConfig := params.RESTConfig()
418-
if restConfig == nil {
419-
// Return just the built-in containerdisk images
420-
return getDefaultContainerDisks(), nil
421-
}
422-
423-
dynamicClient, err := dynamic.NewForConfig(restConfig)
410+
// Get dynamic client for querying DataSources
411+
dynamicClient, err := getDynamicClient(params)
424412
if err != nil {
425413
// Return just the built-in containerdisk images
426414
return getDefaultContainerDisks(), nil
@@ -433,6 +421,43 @@ func searchDataSources(params api.ToolHandlerParams, query string) ([]DataSource
433421
Resource: "datasources",
434422
}
435423

424+
// Collect DataSources from well-known namespaces and all namespaces
425+
results := collectDataSources(params, dynamicClient, dataSourceGVR)
426+
427+
// Add common containerdisk images
428+
results = append(results, getDefaultContainerDisks()...)
429+
430+
// Return helpful message if no sources found
431+
if len(results) == 0 {
432+
return []DataSourceInfo{
433+
{
434+
Name: "No sources available",
435+
Namespace: "",
436+
Source: "No DataSources or containerdisks found",
437+
},
438+
}, nil
439+
}
440+
441+
return results, nil
442+
}
443+
444+
// getDynamicClient creates a dynamic Kubernetes client from the provided parameters
445+
func getDynamicClient(params api.ToolHandlerParams) (dynamic.Interface, error) {
446+
// Handle nil or invalid clients gracefully (e.g., in test environments)
447+
if params.Kubernetes == nil {
448+
return nil, fmt.Errorf("kubernetes client is nil")
449+
}
450+
451+
restConfig := params.RESTConfig()
452+
if restConfig == nil {
453+
return nil, fmt.Errorf("REST config is nil")
454+
}
455+
456+
return dynamic.NewForConfig(restConfig)
457+
}
458+
459+
// collectDataSources collects DataSources from well-known namespaces and all namespaces
460+
func collectDataSources(params api.ToolHandlerParams, dynamicClient dynamic.Interface, gvr schema.GroupVersionResource) []DataSourceInfo {
436461
var results []DataSourceInfo
437462

438463
// Try to list DataSources from well-known namespaces first
@@ -442,20 +467,18 @@ func searchDataSources(params api.ToolHandlerParams, query string) ([]DataSource
442467
}
443468

444469
for _, ns := range wellKnownNamespaces {
445-
dsInfos, err := listDataSourcesFromNamespace(params, dynamicClient, dataSourceGVR, ns)
470+
dsInfos, err := listDataSourcesFromNamespace(params, dynamicClient, gvr, ns)
446471
if err == nil {
447472
results = append(results, dsInfos...)
448473
}
449474
}
450475

451476
// List DataSources from all namespaces
452-
list, err := dynamicClient.Resource(dataSourceGVR).List(params.Context, metav1.ListOptions{})
477+
list, err := dynamicClient.Resource(gvr).List(params.Context, metav1.ListOptions{})
453478
if err != nil {
454-
// If we found DataSources from well-known namespaces but couldn't list all, continue
479+
// If we found DataSources from well-known namespaces but couldn't list all, return what we have
455480
if len(results) > 0 {
456-
// Add common containerdisk images as well
457-
results = append(results, getDefaultContainerDisks()...)
458-
return results, nil
481+
return results
459482
}
460483
// DataSources might not be available, return helpful message
461484
return []DataSourceInfo{
@@ -464,18 +487,26 @@ func searchDataSources(params api.ToolHandlerParams, query string) ([]DataSource
464487
Namespace: "",
465488
Source: "CDI may not be installed or DataSources are not available in this cluster",
466489
},
467-
}, nil
490+
}
468491
}
469492

470-
// Parse the results from all namespaces (this will include well-known namespaces again, but we'll deduplicate)
493+
// Deduplicate and add DataSources from all namespaces
494+
results = deduplicateAndMergeDataSources(results, list.Items)
495+
496+
return results
497+
}
498+
499+
// deduplicateAndMergeDataSources merges new DataSources with existing ones, avoiding duplicates
500+
func deduplicateAndMergeDataSources(existing []DataSourceInfo, items []unstructured.Unstructured) []DataSourceInfo {
501+
// Create a map to track already seen DataSources
471502
seen := make(map[string]bool)
472-
// Mark DataSources from well-known namespaces as already seen
473-
for _, ds := range results {
503+
for _, ds := range existing {
474504
key := ds.Namespace + "/" + ds.Name
475505
seen[key] = true
476506
}
477507

478-
for _, item := range list.Items {
508+
// Add new DataSources that haven't been seen
509+
for _, item := range items {
479510
name := item.GetName()
480511
namespace := item.GetNamespace()
481512
key := namespace + "/" + name
@@ -486,8 +517,6 @@ func searchDataSources(params api.ToolHandlerParams, query string) ([]DataSource
486517
}
487518

488519
labels := item.GetLabels()
489-
490-
// Extract source information from the DataSource spec
491520
source := extractDataSourceInfo(&item)
492521

493522
// Extract default instancetype and preference from labels
@@ -498,28 +527,16 @@ func searchDataSources(params api.ToolHandlerParams, query string) ([]DataSource
498527
defaultPreference = labels[defaultPreferenceLabel]
499528
}
500529

501-
results = append(results, DataSourceInfo{
530+
existing = append(existing, DataSourceInfo{
502531
Name: name,
503532
Namespace: namespace,
504533
Source: source,
505534
DefaultInstancetype: defaultInstancetype,
506535
DefaultPreference: defaultPreference,
507536
})
508537
}
509-
// Add common containerdisk images as well
510-
results = append(results, getDefaultContainerDisks()...)
511538

512-
if len(results) == 0 {
513-
return []DataSourceInfo{
514-
{
515-
Name: "No sources available",
516-
Namespace: "",
517-
Source: "No DataSources or containerdisks found",
518-
},
519-
}, nil
520-
}
521-
522-
return results, nil
539+
return existing
523540
}
524541

525542
// listDataSourcesFromNamespace lists DataSources from a specific namespace

0 commit comments

Comments
 (0)