@@ -12,71 +12,49 @@ import (
1212 "k8s.io/apimachinery/pkg/runtime/schema"
1313)
1414
15- // SearchResources searches for a query string in all resources across all namespaces.
16- func (k * Kubernetes ) SearchResources (ctx context.Context , query string , asTable bool ) (runtime.Unstructured , error ) {
17- // Discovery client is used to discover different supported API groups, versions and resources.
18- serverResources , err := k .manager .discoveryClient .ServerPreferredResources ()
19- if err != nil {
20- return nil , fmt .Errorf ("failed to get server resources: %w" , err )
21- }
22-
15+ // SearchResources searches for a query string in resources, with optional filters for resource type and namespace.
16+ func (k * Kubernetes ) SearchResources (ctx context.Context , query , apiVersion , kind , namespaceLabelSelector string , asTable bool ) (runtime.Unstructured , error ) {
2317 var matchingResources []unstructured.Unstructured
24- for _ , apiResourceList := range serverResources {
25- for _ , apiResource := range apiResourceList .APIResources {
26- // Skip resources that do not support the "list" verb
27- if ! contains (apiResource .Verbs , "list" ) {
28- continue
29- }
3018
31- gvk := schema.GroupVersionKind {
32- Group : apiResourceList .GroupVersion ,
33- Version : apiResource .Version ,
34- Kind : apiResource .Kind ,
35- }
36- if gvk .Group == "" {
37- gvk .Group = "core"
38- }
19+ if apiVersion != "" && kind != "" {
20+ // Search in a specific resource type
21+ gv , err := schema .ParseGroupVersion (apiVersion )
22+ if err != nil {
23+ return nil , fmt .Errorf ("invalid apiVersion: %w" , err )
24+ }
25+ gvk := gv .WithKind (kind )
26+ apiResource , err := k .getAPIResource (& gvk )
27+ if err != nil {
28+ return nil , fmt .Errorf ("failed to get API resource: %w" , err )
29+ }
30+ resources , err := k .searchInGVK (ctx , query , & gvk , apiResource , namespaceLabelSelector )
31+ if err != nil {
32+ return nil , err
33+ }
34+ matchingResources = append (matchingResources , resources ... )
35+ } else {
36+ // Search in all resources
37+ serverResources , err := k .manager .discoveryClient .ServerPreferredResources ()
38+ if err != nil {
39+ return nil , fmt .Errorf ("failed to get server resources: %w" , err )
40+ }
3941
40- if _ , err := k .resourceFor (& gvk ); err != nil {
41- // Ignore errors for resources that cannot be mapped
42- continue
43- }
44- var namespaces []string
45- if apiResource .Namespaced {
46- // Get all namespaces
47- nsListObj , err := k .NamespacesList (ctx , ResourceListOptions {})
48- if err != nil {
49- return nil , fmt .Errorf ("failed to list namespaces: %w" , err )
42+ for _ , apiResourceList := range serverResources {
43+ for _ , apiResource := range apiResourceList .APIResources {
44+ gvk := schema.GroupVersionKind {
45+ Group : apiResourceList .GroupVersion ,
46+ Version : apiResource .Version ,
47+ Kind : apiResource .Kind ,
5048 }
51- if unstructuredList , ok := nsListObj .(* unstructured.UnstructuredList ); ok {
52- for _ , ns := range unstructuredList .Items {
53- namespaces = append (namespaces , ns .GetName ())
54- }
49+ if gvk .Group == "" {
50+ gvk .Group = "core"
5551 }
56- } else {
57- // For cluster-scoped resources, use an empty namespace
58- namespaces = append (namespaces , "" )
59- }
60-
61- for _ , ns := range namespaces {
62- list , err := k .ResourcesList (ctx , & gvk , ns , ResourceListOptions {})
52+ resources , err := k .searchInGVK (ctx , query , & gvk , & apiResource , namespaceLabelSelector )
6353 if err != nil {
64- // Ignore errors for resources that cannot be listed
54+ // Ignore errors for resources that cannot be searched
6555 continue
6656 }
67-
68- if unstructuredList , ok := list .(* unstructured.UnstructuredList ); ok {
69- for _ , item := range unstructuredList .Items {
70- match , err := matchResource (item , query )
71- if err != nil {
72- // Ignore errors during matching
73- continue
74- }
75- if match {
76- matchingResources = append (matchingResources , item )
77- }
78- }
79- }
57+ matchingResources = append (matchingResources , resources ... )
8058 }
8159 }
8260 }
@@ -94,6 +72,65 @@ func (k *Kubernetes) SearchResources(ctx context.Context, query string, asTable
9472 }, nil
9573}
9674
75+ func (k * Kubernetes ) searchInGVK (ctx context.Context , query string , gvk * schema.GroupVersionKind , apiResource * metav1.APIResource , namespaceLabelSelector string ) ([]unstructured.Unstructured , error ) {
76+ if ! contains (apiResource .Verbs , "list" ) {
77+ return nil , nil // Skip resources that do not support the "list" verb
78+ }
79+
80+ var matchingResources []unstructured.Unstructured
81+ var namespaces []string
82+ if apiResource .Namespaced {
83+ nsListOptions := ResourceListOptions {}
84+ if namespaceLabelSelector != "" {
85+ nsListOptions .LabelSelector = namespaceLabelSelector
86+ }
87+ nsListObj , err := k .NamespacesList (ctx , nsListOptions )
88+ if err != nil {
89+ return nil , fmt .Errorf ("failed to list namespaces: %w" , err )
90+ }
91+ if unstructuredList , ok := nsListObj .(* unstructured.UnstructuredList ); ok {
92+ for _ , ns := range unstructuredList .Items {
93+ namespaces = append (namespaces , ns .GetName ())
94+ }
95+ }
96+ } else {
97+ namespaces = append (namespaces , "" ) // For cluster-scoped resources
98+ }
99+
100+ for _ , ns := range namespaces {
101+ list , err := k .ResourcesList (ctx , gvk , ns , ResourceListOptions {})
102+ if err != nil {
103+ continue // Ignore errors for resources that cannot be listed
104+ }
105+
106+ if unstructuredList , ok := list .(* unstructured.UnstructuredList ); ok {
107+ for _ , item := range unstructuredList .Items {
108+ match , err := matchResource (item , query )
109+ if err != nil {
110+ continue // Ignore errors during matching
111+ }
112+ if match {
113+ matchingResources = append (matchingResources , item )
114+ }
115+ }
116+ }
117+ }
118+ return matchingResources , nil
119+ }
120+
121+ func (k * Kubernetes ) getAPIResource (gvk * schema.GroupVersionKind ) (* metav1.APIResource , error ) {
122+ apiResourceList , err := k .manager .discoveryClient .ServerResourcesForGroupVersion (gvk .GroupVersion ().String ())
123+ if err != nil {
124+ return nil , err
125+ }
126+ for _ , apiResource := range apiResourceList .APIResources {
127+ if apiResource .Kind == gvk .Kind {
128+ return & apiResource , nil
129+ }
130+ }
131+ return nil , fmt .Errorf ("resource not found for GVK: %s" , gvk )
132+ }
133+
97134func (k * Kubernetes ) createTable (resources []unstructured.Unstructured ) (runtime.Unstructured , error ) {
98135 table := & metav1.Table {
99136 TypeMeta : metav1.TypeMeta {
@@ -141,4 +178,4 @@ func contains(slice []string, s string) bool {
141178 }
142179 }
143180 return false
144- }
181+ }
0 commit comments