Skip to content

Commit a15c7af

Browse files
committed
feat(kubevirt): Search namespaced preferences and instancetypes
Extend the VM creation tool to search for both cluster-wide and namespaced resources: - Update searchPreferences to query: - VirtualMachineClusterPreference (cluster-wide) - VirtualMachinePreference (namespaced) - Update searchInstancetypes to query: - VirtualMachineClusterInstancetype (cluster-wide) - VirtualMachineInstancetype (namespaced) This allows the tool to discover and use namespaced preferences and instancetypes in addition to cluster-wide resources, providing more flexibility for VM creation in multi-tenant environments where resources may be scoped to specific namespaces. The namespace context is passed from the VM creation request, enabling the search to include resources from the target namespace where the VM will be created. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Lee Yarwood <lyarwood@redhat.com>
1 parent ffae527 commit a15c7af

File tree

1 file changed

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

1 file changed

+68
-41
lines changed

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

Lines changed: 68 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ func create(params api.ToolHandlerParams) (*api.ToolCallResult, error) {
121121
matchedDataSource := matchDataSource(dataSources, createParams.Workload)
122122

123123
// Resolve preference from DataSource defaults or cluster resources
124-
preference := resolvePreference(params, createParams.Preference, matchedDataSource, createParams.Workload)
124+
preference := resolvePreference(params, createParams.Preference, matchedDataSource, createParams.Workload, createParams.Namespace)
125125

126126
// Resolve instancetype from DataSource defaults or size/performance hints
127127
instancetype := resolveInstancetype(params, createParams, matchedDataSource)
@@ -140,13 +140,13 @@ func create(params api.ToolHandlerParams) (*api.ToolCallResult, error) {
140140

141141
// createParameters holds parsed input parameters for VM creation
142142
type createParameters struct {
143-
Namespace string
144-
Name string
145-
Workload string
143+
Namespace string
144+
Name string
145+
Workload string
146146
Instancetype string
147-
Preference string
148-
Size string
149-
Performance string
147+
Preference string
148+
Size string
149+
Performance string
150150
}
151151

152152
// parseCreateParameters parses and validates input parameters
@@ -205,7 +205,7 @@ func matchDataSource(dataSources []DataSourceInfo, workload string) *DataSourceI
205205
}
206206

207207
// resolvePreference determines the preference to use from DataSource defaults or cluster resources
208-
func resolvePreference(params api.ToolHandlerParams, explicitPreference string, matchedDataSource *DataSourceInfo, workload string) string {
208+
func resolvePreference(params api.ToolHandlerParams, explicitPreference string, matchedDataSource *DataSourceInfo, workload string, namespace string) string {
209209
// Use explicitly specified preference if provided
210210
if explicitPreference != "" {
211211
return explicitPreference
@@ -217,7 +217,7 @@ func resolvePreference(params api.ToolHandlerParams, explicitPreference string,
217217
}
218218

219219
// Try to match preference name against the workload input
220-
preferences := searchPreferences(params)
220+
preferences := searchPreferences(params, namespace)
221221
normalizedInput := strings.ToLower(strings.TrimSpace(workload))
222222

223223
for i := range preferences {
@@ -245,15 +245,15 @@ func resolveInstancetype(params api.ToolHandlerParams, createParams *createParam
245245

246246
// Match instancetype based on size and performance hints
247247
if createParams.Size != "" {
248-
return matchInstancetypeBySize(params, createParams.Size, createParams.Performance)
248+
return matchInstancetypeBySize(params, createParams.Size, createParams.Performance, createParams.Namespace)
249249
}
250250

251251
return ""
252252
}
253253

254254
// matchInstancetypeBySize finds an instancetype that matches the size and performance hints
255-
func matchInstancetypeBySize(params api.ToolHandlerParams, size, performance string) string {
256-
instancetypes := searchInstancetypes(params)
255+
func matchInstancetypeBySize(params api.ToolHandlerParams, size, performance, namespace string) string {
256+
instancetypes := searchInstancetypes(params, namespace)
257257
normalizedSize := strings.ToLower(strings.TrimSpace(size))
258258
normalizedPerformance := strings.ToLower(strings.TrimSpace(performance))
259259

@@ -637,8 +637,8 @@ func listDataSourcesFromNamespace(params api.ToolHandlerParams, dynamicClient dy
637637
return results, nil
638638
}
639639

640-
// searchPreferences searches for VirtualMachineClusterPreference resources in the cluster
641-
func searchPreferences(params api.ToolHandlerParams) []PreferenceInfo {
640+
// searchPreferences searches for both cluster-wide and namespaced VirtualMachinePreference resources
641+
func searchPreferences(params api.ToolHandlerParams, namespace string) []PreferenceInfo {
642642
// Handle nil or invalid clients gracefully (e.g., in test environments)
643643
if params.Kubernetes == nil {
644644
return []PreferenceInfo{}
@@ -654,32 +654,45 @@ func searchPreferences(params api.ToolHandlerParams) []PreferenceInfo {
654654
return []PreferenceInfo{}
655655
}
656656

657-
// VirtualMachineClusterPreference GVR
658-
preferenceGVR := schema.GroupVersionResource{
657+
var results []PreferenceInfo
658+
659+
// Search for cluster-wide VirtualMachineClusterPreferences
660+
clusterPreferenceGVR := schema.GroupVersionResource{
659661
Group: "instancetype.kubevirt.io",
660662
Version: "v1beta1",
661663
Resource: "virtualmachineclusterpreferences",
662664
}
663665

664-
// List VirtualMachineClusterPreferences
665-
list, err := dynamicClient.Resource(preferenceGVR).List(params.Context, metav1.ListOptions{})
666-
if err != nil {
667-
// Preferences might not be available, return empty list
668-
return []PreferenceInfo{}
666+
clusterList, err := dynamicClient.Resource(clusterPreferenceGVR).List(params.Context, metav1.ListOptions{})
667+
if err == nil {
668+
for _, item := range clusterList.Items {
669+
results = append(results, PreferenceInfo{
670+
Name: item.GetName(),
671+
})
672+
}
669673
}
670674

671-
var results []PreferenceInfo
672-
for _, item := range list.Items {
673-
results = append(results, PreferenceInfo{
674-
Name: item.GetName(),
675-
})
675+
// Search for namespaced VirtualMachinePreferences
676+
namespacedPreferenceGVR := schema.GroupVersionResource{
677+
Group: "instancetype.kubevirt.io",
678+
Version: "v1beta1",
679+
Resource: "virtualmachinepreferences",
680+
}
681+
682+
namespacedList, err := dynamicClient.Resource(namespacedPreferenceGVR).Namespace(namespace).List(params.Context, metav1.ListOptions{})
683+
if err == nil {
684+
for _, item := range namespacedList.Items {
685+
results = append(results, PreferenceInfo{
686+
Name: item.GetName(),
687+
})
688+
}
676689
}
677690

678691
return results
679692
}
680693

681-
// searchInstancetypes searches for VirtualMachineClusterInstancetype resources in the cluster
682-
func searchInstancetypes(params api.ToolHandlerParams) []InstancetypeInfo {
694+
// searchInstancetypes searches for both cluster-wide and namespaced VirtualMachineInstancetype resources
695+
func searchInstancetypes(params api.ToolHandlerParams, namespace string) []InstancetypeInfo {
683696
// Handle nil or invalid clients gracefully (e.g., in test environments)
684697
if params.Kubernetes == nil {
685698
return []InstancetypeInfo{}
@@ -695,26 +708,40 @@ func searchInstancetypes(params api.ToolHandlerParams) []InstancetypeInfo {
695708
return []InstancetypeInfo{}
696709
}
697710

698-
// VirtualMachineClusterInstancetype GVR
699-
instancetypeGVR := schema.GroupVersionResource{
711+
var results []InstancetypeInfo
712+
713+
// Search for cluster-wide VirtualMachineClusterInstancetypes
714+
clusterInstancetypeGVR := schema.GroupVersionResource{
700715
Group: "instancetype.kubevirt.io",
701716
Version: "v1beta1",
702717
Resource: "virtualmachineclusterinstancetypes",
703718
}
704719

705-
// List VirtualMachineClusterInstancetypes
706-
list, err := dynamicClient.Resource(instancetypeGVR).List(params.Context, metav1.ListOptions{})
707-
if err != nil {
708-
// Instance types might not be available, return empty list
709-
return []InstancetypeInfo{}
720+
clusterList, err := dynamicClient.Resource(clusterInstancetypeGVR).List(params.Context, metav1.ListOptions{})
721+
if err == nil {
722+
for _, item := range clusterList.Items {
723+
results = append(results, InstancetypeInfo{
724+
Name: item.GetName(),
725+
Labels: item.GetLabels(),
726+
})
727+
}
710728
}
711729

712-
var results []InstancetypeInfo
713-
for _, item := range list.Items {
714-
results = append(results, InstancetypeInfo{
715-
Name: item.GetName(),
716-
Labels: item.GetLabels(),
717-
})
730+
// Search for namespaced VirtualMachineInstancetypes
731+
namespacedInstancetypeGVR := schema.GroupVersionResource{
732+
Group: "instancetype.kubevirt.io",
733+
Version: "v1beta1",
734+
Resource: "virtualmachineinstancetypes",
735+
}
736+
737+
namespacedList, err := dynamicClient.Resource(namespacedInstancetypeGVR).Namespace(namespace).List(params.Context, metav1.ListOptions{})
738+
if err == nil {
739+
for _, item := range namespacedList.Items {
740+
results = append(results, InstancetypeInfo{
741+
Name: item.GetName(),
742+
Labels: item.GetLabels(),
743+
})
744+
}
718745
}
719746

720747
return results

0 commit comments

Comments
 (0)