@@ -25,6 +25,100 @@ import (
25
25
"github.com/openmfp/golang-commons/logger"
26
26
)
27
27
28
+ // convertLabels converts between map[string]string and []Label format
29
+ // toArray=true: converts maps to arrays (for GraphQL output)
30
+ // toArray=false: converts arrays to maps (for Kubernetes input)
31
+ func convertLabels (obj any , toArray bool ) any {
32
+ switch v := obj .(type ) {
33
+ case map [string ]interface {}:
34
+ return convertObject (v , toArray )
35
+ case []interface {}:
36
+ result := make ([]any , len (v ))
37
+ for i , item := range v {
38
+ result [i ] = convertLabels (item , toArray )
39
+ }
40
+ return result
41
+ default :
42
+ return obj
43
+ }
44
+ }
45
+
46
+ // convertObject handles object conversion with direction control
47
+ func convertObject (objMap map [string ]interface {}, toArray bool ) map [string ]interface {} {
48
+ result := make (map [string ]interface {})
49
+ for key , value := range objMap {
50
+ if key == "metadata" {
51
+ result [key ] = convertMetadata (value , toArray )
52
+ } else {
53
+ result [key ] = convertLabels (value , toArray )
54
+ }
55
+ }
56
+ return result
57
+ }
58
+
59
+ // convertMetadata handles metadata field conversion
60
+ func convertMetadata (metadataValue any , toArray bool ) any {
61
+ metadata , ok := metadataValue .(map [string ]interface {})
62
+ if ! ok {
63
+ return convertLabels (metadataValue , toArray )
64
+ }
65
+
66
+ result := make (map [string ]interface {})
67
+ for key , value := range metadata {
68
+ if isLabelField (key ) && value != nil {
69
+ result [key ] = convertLabelField (value , toArray )
70
+ } else {
71
+ result [key ] = convertLabels (value , toArray )
72
+ }
73
+ }
74
+ return result
75
+ }
76
+
77
+ // convertLabelField converts between label map and array formats
78
+ func convertLabelField (value any , toArray bool ) any {
79
+ if toArray {
80
+ // Convert map to array for GraphQL output
81
+ labelMap , ok := value .(map [string ]interface {})
82
+ if ! ok {
83
+ return convertLabels (value , toArray )
84
+ }
85
+
86
+ var labelArray []map [string ]interface {}
87
+ for k , v := range labelMap {
88
+ if strValue , ok := v .(string ); ok {
89
+ labelArray = append (labelArray , map [string ]interface {}{
90
+ "key" : k ,
91
+ "value" : strValue ,
92
+ })
93
+ }
94
+ }
95
+ return labelArray
96
+ } else {
97
+ // Convert array to map for Kubernetes input
98
+ labelArray , ok := value .([]interface {})
99
+ if ! ok {
100
+ return convertLabels (value , toArray )
101
+ }
102
+
103
+ labelMap := make (map [string ]string )
104
+ for _ , item := range labelArray {
105
+ if labelObj , ok := item .(map [string ]interface {}); ok {
106
+ if key , keyOk := labelObj ["key" ].(string ); keyOk {
107
+ if val , valOk := labelObj ["value" ].(string ); valOk {
108
+ labelMap [key ] = val
109
+ }
110
+ }
111
+ }
112
+ }
113
+ return labelMap
114
+ }
115
+ }
116
+
117
+ // isLabelField checks if a field is labels or annotations
118
+ func isLabelField (fieldName string ) bool {
119
+ return fieldName == "labels" || fieldName == "annotations"
120
+ }
121
+
28
122
type Provider interface {
29
123
CrudProvider
30
124
CustomQueriesProvider
@@ -129,7 +223,9 @@ func (r *Service) ListItems(gvk schema.GroupVersionKind, scope v1.ResourceScope)
129
223
130
224
items := make ([]map [string ]any , len (list .Items ))
131
225
for i , item := range list .Items {
132
- items [i ] = item .Object
226
+ // Convert maps back to label arrays for GraphQL response
227
+ convertedItem := convertLabels (item .Object , true ).(map [string ]interface {})
228
+ items [i ] = convertedItem
133
229
}
134
230
135
231
return items , nil
@@ -185,7 +281,9 @@ func (r *Service) GetItem(gvk schema.GroupVersionKind, scope v1.ResourceScope) g
185
281
return nil , err
186
282
}
187
283
188
- return obj .Object , nil
284
+ // Convert maps back to label arrays for GraphQL response
285
+ convertedResponse := convertLabels (obj .Object , true )
286
+ return convertedResponse , nil
189
287
}
190
288
}
191
289
@@ -220,8 +318,11 @@ func (r *Service) CreateItem(gvk schema.GroupVersionKind, scope v1.ResourceScope
220
318
221
319
objectInput := p .Args ["object" ].(map [string ]interface {})
222
320
321
+ // Convert label arrays back to maps for Kubernetes compatibility
322
+ convertedInput := convertLabels (objectInput , false ).(map [string ]interface {})
323
+
223
324
obj := & unstructured.Unstructured {
224
- Object : objectInput ,
325
+ Object : convertedInput ,
225
326
}
226
327
obj .SetGroupVersionKind (gvk )
227
328
@@ -251,7 +352,9 @@ func (r *Service) CreateItem(gvk schema.GroupVersionKind, scope v1.ResourceScope
251
352
return nil , err
252
353
}
253
354
254
- return obj .Object , nil
355
+ // Convert maps back to label arrays for GraphQL response
356
+ convertedResponse := convertLabels (obj .Object , true )
357
+ return convertedResponse , nil
255
358
}
256
359
}
257
360
@@ -270,8 +373,10 @@ func (r *Service) UpdateItem(gvk schema.GroupVersionKind, scope v1.ResourceScope
270
373
}
271
374
272
375
objectInput := p .Args ["object" ].(map [string ]interface {})
273
- // Marshal the input object to JSON to create the patch data
274
- patchData , err := json .Marshal (objectInput )
376
+ // Convert label arrays back to maps for Kubernetes compatibility
377
+ convertedInput := convertLabels (objectInput , false ).(map [string ]interface {})
378
+ // Marshal the converted input object to JSON to create the patch data
379
+ patchData , err := json .Marshal (convertedInput )
275
380
if err != nil {
276
381
return nil , fmt .Errorf ("failed to marshal object input: %v" , err )
277
382
}
@@ -312,7 +417,9 @@ func (r *Service) UpdateItem(gvk schema.GroupVersionKind, scope v1.ResourceScope
312
417
return nil , err
313
418
}
314
419
315
- return existingObj .Object , nil
420
+ // Convert maps back to label arrays for GraphQL response
421
+ convertedResponse := convertLabels (existingObj .Object , true )
422
+ return convertedResponse , nil
316
423
}
317
424
}
318
425
0 commit comments