66 "errors"
77 "fmt"
88 "gopkg.in/yaml.v3"
9+ v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
910 "regexp"
1011
1112 "github.com/graphql-go/graphql"
@@ -23,19 +24,24 @@ import (
2324
2425type Provider interface {
2526 CrudProvider
27+ CustomQueriesProvider
2628 CommonResolver () graphql.FieldResolveFn
2729 SanitizeGroupName (string ) string
2830}
2931
3032type CrudProvider interface {
31- ListItems (gvk schema.GroupVersionKind ) graphql.FieldResolveFn
32- GetItem (gvk schema.GroupVersionKind ) graphql.FieldResolveFn
33- GetItemAsYAML (gvk schema.GroupVersionKind ) graphql.FieldResolveFn
34- CreateItem (gvk schema.GroupVersionKind ) graphql.FieldResolveFn
35- UpdateItem (gvk schema.GroupVersionKind ) graphql.FieldResolveFn
36- DeleteItem (gvk schema.GroupVersionKind ) graphql.FieldResolveFn
37- SubscribeItem (gvk schema.GroupVersionKind ) graphql.FieldResolveFn
38- SubscribeItems (gvk schema.GroupVersionKind ) graphql.FieldResolveFn
33+ ListItems (gvk schema.GroupVersionKind , scope v1.ResourceScope ) graphql.FieldResolveFn
34+ GetItem (gvk schema.GroupVersionKind , scope v1.ResourceScope ) graphql.FieldResolveFn
35+ GetItemAsYAML (gvk schema.GroupVersionKind , scope v1.ResourceScope ) graphql.FieldResolveFn
36+ CreateItem (gvk schema.GroupVersionKind , scope v1.ResourceScope ) graphql.FieldResolveFn
37+ UpdateItem (gvk schema.GroupVersionKind , scope v1.ResourceScope ) graphql.FieldResolveFn
38+ DeleteItem (gvk schema.GroupVersionKind , scope v1.ResourceScope ) graphql.FieldResolveFn
39+ SubscribeItem (gvk schema.GroupVersionKind , scope v1.ResourceScope ) graphql.FieldResolveFn
40+ SubscribeItems (gvk schema.GroupVersionKind , scope v1.ResourceScope ) graphql.FieldResolveFn
41+ }
42+
43+ type CustomQueriesProvider interface {
44+ TypeByCategory (m map [string ][]TypeByCategory ) graphql.FieldResolveFn
3945}
4046
4147type Service struct {
@@ -54,7 +60,7 @@ func New(log *logger.Logger, runtimeClient client.WithWatch) *Service {
5460}
5561
5662// ListItems returns a GraphQL CommonResolver function that lists Kubernetes resources of the given GroupVersionKind.
57- func (r * Service ) ListItems (gvk schema.GroupVersionKind ) graphql.FieldResolveFn {
63+ func (r * Service ) ListItems (gvk schema.GroupVersionKind , scope v1. ResourceScope ) graphql.FieldResolveFn {
5864 return func (p graphql.ResolveParams ) (interface {}, error ) {
5965 ctx , span := otel .Tracer ("" ).Start (p .Context , "ListItems" , trace .WithAttributes (attribute .String ("kind" , gvk .Kind )))
6066 defer span .End ()
@@ -88,9 +94,14 @@ func (r *Service) ListItems(gvk schema.GroupVersionKind) graphql.FieldResolveFn
8894 opts = append (opts , client.MatchingLabelsSelector {Selector : selector })
8995 }
9096
91- // Handle namespace argument
92- if namespace , ok := p .Args [NamespaceArg ].(string ); ok && namespace != "" {
93- opts = append (opts , client .InNamespace (namespace ))
97+ if isResourceNamespaceScoped (scope ) {
98+ namespace , err := getStringArg (p .Args , NamespaceArg , false )
99+ if err != nil {
100+ return nil , err
101+ }
102+ if namespace != "" {
103+ opts = append (opts , client .InNamespace (namespace ))
104+ }
94105 }
95106
96107 if err = r .runtimeClient .List (ctx , list , opts ... ); err != nil {
@@ -108,7 +119,7 @@ func (r *Service) ListItems(gvk schema.GroupVersionKind) graphql.FieldResolveFn
108119}
109120
110121// GetItem returns a GraphQL CommonResolver function that retrieves a single Kubernetes resource of the given GroupVersionKind.
111- func (r * Service ) GetItem (gvk schema.GroupVersionKind ) graphql.FieldResolveFn {
122+ func (r * Service ) GetItem (gvk schema.GroupVersionKind , scope v1. ResourceScope ) graphql.FieldResolveFn {
112123 return func (p graphql.ResolveParams ) (interface {}, error ) {
113124 ctx , span := otel .Tracer ("" ).Start (p .Context , "GetItem" , trace .WithAttributes (attribute .String ("kind" , gvk .Kind )))
114125 defer span .End ()
@@ -128,7 +139,7 @@ func (r *Service) GetItem(gvk schema.GroupVersionKind) graphql.FieldResolveFn {
128139 }
129140
130141 // Retrieve required arguments
131- name , namespace , err := getRequiredNameAndNamespaceArgs (p .Args )
142+ name , err := getStringArg (p .Args , NameArg , true )
132143 if err != nil {
133144 return nil , err
134145 }
@@ -137,26 +148,36 @@ func (r *Service) GetItem(gvk schema.GroupVersionKind) graphql.FieldResolveFn {
137148 obj := & unstructured.Unstructured {}
138149 obj .SetGroupVersionKind (gvk )
139150
151+ key := client.ObjectKey {
152+ Name : name ,
153+ }
154+
155+ if isResourceNamespaceScoped (scope ) {
156+ namespace , err := getStringArg (p .Args , NamespaceArg , true )
157+ if err != nil {
158+ return nil , err
159+ }
160+
161+ key .Namespace = namespace
162+ }
163+
140164 // Get the object using the runtime client
141- if err = r .runtimeClient .Get (ctx , client.ObjectKey {
142- Namespace : namespace ,
143- Name : name ,
144- }, obj ); err != nil {
145- log .Error ().Err (err ).Str ("name" , name ).Str ("namespace" , namespace ).Msg ("Unable to get object" )
165+ if err = r .runtimeClient .Get (ctx , key , obj ); err != nil {
166+ log .Error ().Err (err ).Str ("name" , name ).Str ("scope" , string (scope )).Msg ("Unable to get object" )
146167 return nil , err
147168 }
148169
149170 return obj .Object , nil
150171 }
151172}
152173
153- func (r * Service ) GetItemAsYAML (gvk schema.GroupVersionKind ) graphql.FieldResolveFn {
174+ func (r * Service ) GetItemAsYAML (gvk schema.GroupVersionKind , scope v1. ResourceScope ) graphql.FieldResolveFn {
154175 return func (p graphql.ResolveParams ) (interface {}, error ) {
155176 var span trace.Span
156177 p .Context , span = otel .Tracer ("" ).Start (p .Context , "GetItemAsYAML" , trace .WithAttributes (attribute .String ("kind" , gvk .Kind )))
157178 defer span .End ()
158179
159- out , err := r .GetItem (gvk )(p )
180+ out , err := r .GetItem (gvk , scope )(p )
160181 if err != nil {
161182 return "" , err
162183 }
@@ -170,7 +191,7 @@ func (r *Service) GetItemAsYAML(gvk schema.GroupVersionKind) graphql.FieldResolv
170191 }
171192}
172193
173- func (r * Service ) CreateItem (gvk schema.GroupVersionKind ) graphql.FieldResolveFn {
194+ func (r * Service ) CreateItem (gvk schema.GroupVersionKind , scope v1. ResourceScope ) graphql.FieldResolveFn {
174195 return func (p graphql.ResolveParams ) (interface {}, error ) {
175196 ctx , span := otel .Tracer ("" ).Start (p .Context , "CreateItem" , trace .WithAttributes (attribute .String ("kind" , gvk .Kind )))
176197 defer span .End ()
@@ -179,14 +200,20 @@ func (r *Service) CreateItem(gvk schema.GroupVersionKind) graphql.FieldResolveFn
179200
180201 log := r .log .With ().Str ("operation" , "create" ).Str ("kind" , gvk .Kind ).Logger ()
181202
182- namespace := p .Args [NamespaceArg ].(string )
183203 objectInput := p .Args ["object" ].(map [string ]interface {})
184204
185205 obj := & unstructured.Unstructured {
186206 Object : objectInput ,
187207 }
188208 obj .SetGroupVersionKind (gvk )
189- obj .SetNamespace (namespace )
209+
210+ if isResourceNamespaceScoped (scope ) {
211+ namespace , err := getStringArg (p .Args , NamespaceArg , true )
212+ if err != nil {
213+ return nil , err
214+ }
215+ obj .SetNamespace (namespace )
216+ }
190217
191218 if obj .GetName () == "" {
192219 return nil , errors .New ("object metadata.name is required" )
@@ -201,7 +228,7 @@ func (r *Service) CreateItem(gvk schema.GroupVersionKind) graphql.FieldResolveFn
201228 }
202229}
203230
204- func (r * Service ) UpdateItem (gvk schema.GroupVersionKind ) graphql.FieldResolveFn {
231+ func (r * Service ) UpdateItem (gvk schema.GroupVersionKind , scope v1. ResourceScope ) graphql.FieldResolveFn {
205232 return func (p graphql.ResolveParams ) (interface {}, error ) {
206233 ctx , span := otel .Tracer ("" ).Start (p .Context , "UpdateItem" , trace .WithAttributes (attribute .String ("kind" , gvk .Kind )))
207234 defer span .End ()
@@ -210,7 +237,7 @@ func (r *Service) UpdateItem(gvk schema.GroupVersionKind) graphql.FieldResolveFn
210237
211238 log := r .log .With ().Str ("operation" , "update" ).Str ("kind" , gvk .Kind ).Logger ()
212239
213- name , namespace , err := getRequiredNameAndNamespaceArgs (p .Args )
240+ name , err := getStringArg (p .Args , NameArg , true )
214241 if err != nil {
215242 return nil , err
216243 }
@@ -226,8 +253,17 @@ func (r *Service) UpdateItem(gvk schema.GroupVersionKind) graphql.FieldResolveFn
226253 existingObj := & unstructured.Unstructured {}
227254 existingObj .SetGroupVersionKind (gvk )
228255
256+ key := client.ObjectKey {Name : name }
257+ if isResourceNamespaceScoped (scope ) {
258+ namespace , err := getStringArg (p .Args , NamespaceArg , true )
259+ if err != nil {
260+ return nil , err
261+ }
262+ key .Namespace = namespace
263+ }
264+
229265 // Fetch the existing object from the cluster
230- err = r .runtimeClient .Get (ctx , client. ObjectKey { Namespace : namespace , Name : name } , existingObj )
266+ err = r .runtimeClient .Get (ctx , key , existingObj )
231267 if err != nil {
232268 log .Error ().Err (err ).Msg ("Failed to get existing object" )
233269 return nil , err
@@ -245,7 +281,7 @@ func (r *Service) UpdateItem(gvk schema.GroupVersionKind) graphql.FieldResolveFn
245281}
246282
247283// DeleteItem returns a CommonResolver function for deleting a resource.
248- func (r * Service ) DeleteItem (gvk schema.GroupVersionKind ) graphql.FieldResolveFn {
284+ func (r * Service ) DeleteItem (gvk schema.GroupVersionKind , scope v1. ResourceScope ) graphql.FieldResolveFn {
249285 return func (p graphql.ResolveParams ) (interface {}, error ) {
250286 ctx , span := otel .Tracer ("" ).Start (p .Context , "DeleteItem" , trace .WithAttributes (attribute .String ("kind" , gvk .Kind )))
251287 defer span .End ()
@@ -254,16 +290,23 @@ func (r *Service) DeleteItem(gvk schema.GroupVersionKind) graphql.FieldResolveFn
254290
255291 log := r .log .With ().Str ("operation" , "delete" ).Str ("kind" , gvk .Kind ).Logger ()
256292
257- name , namespace , err := getRequiredNameAndNamespaceArgs (p .Args )
293+ name , err := getStringArg (p .Args , NameArg , true )
258294 if err != nil {
259295 return nil , err
260296 }
261297
262298 obj := & unstructured.Unstructured {}
263299 obj .SetGroupVersionKind (gvk )
264- obj .SetNamespace (namespace )
265300 obj .SetName (name )
266301
302+ if isResourceNamespaceScoped (scope ) {
303+ namespace , err := getStringArg (p .Args , NamespaceArg , true )
304+ if err != nil {
305+ return nil , err
306+ }
307+ obj .SetNamespace (namespace )
308+ }
309+
267310 if err := r .runtimeClient .Delete (ctx , obj ); err != nil {
268311 log .Error ().Err (err ).Msg ("Failed to delete object" )
269312 return nil , err
0 commit comments