Skip to content

Commit abddd3e

Browse files
committed
feat(nestedArray): parsing * on array of array
1 parent 9ea3752 commit abddd3e

File tree

2 files changed

+144
-18
lines changed

2 files changed

+144
-18
lines changed

pkg/customresourcestate/registry_factory.go

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,6 @@ func (c *compiledGauge) Values(v interface{}) (result []eachValue, errs []error)
222222
onError := func(err error) {
223223
errs = append(errs, fmt.Errorf("%s: %v", c.Path(), err))
224224
}
225-
226225
switch iter := v.(type) {
227226
case map[string]interface{}:
228227
for key, it := range iter {
@@ -279,16 +278,33 @@ func (c *compiledGauge) Values(v interface{}) (result []eachValue, errs []error)
279278
}
280279
case []interface{}:
281280
for i, it := range iter {
282-
value, err := c.value(it)
283-
if err != nil {
284-
onError(fmt.Errorf("[%d]: %w", i, err))
285-
continue
286-
}
287-
if value == nil {
288-
continue
281+
// test si it est un []interface{} si oui boucle dessus
282+
if nestedIter, ok := it.([]interface{}); ok {
283+
for j, nestedIt := range nestedIter {
284+
value, err := c.value(nestedIt)
285+
286+
if err != nil {
287+
onError(fmt.Errorf("[%d]: %w", j, err))
288+
continue
289+
}
290+
if value == nil {
291+
continue
292+
}
293+
addPathLabels(nestedIt, c.LabelFromPath(), value.Labels)
294+
result = append(result, *value)
295+
}
296+
} else {
297+
value, err := c.value(it)
298+
if err != nil {
299+
onError(fmt.Errorf("[%d]: %w", i, err))
300+
continue
301+
}
302+
if value == nil {
303+
continue
304+
}
305+
addPathLabels(it, c.LabelFromPath(), value.Labels)
306+
result = append(result, *value)
289307
}
290-
addPathLabels(it, c.LabelFromPath(), value.Labels)
291-
result = append(result, *value)
292308
}
293309
default:
294310
value, err := c.value(v)
@@ -561,7 +577,26 @@ func (p valuePath) Get(obj interface{}) interface{} {
561577
if obj == nil {
562578
return nil
563579
}
564-
obj = op.op(obj)
580+
581+
if slice, ok := obj.([]interface{}); ok && op.part == "[*]" {
582+
// wildcard: garder tous les éléments
583+
var all []interface{}
584+
for _, el := range slice {
585+
all = append(all, el)
586+
}
587+
obj = all
588+
589+
} else if slice, ok := obj.([]interface{}); ok && op.part != "[*]" {
590+
var all []interface{}
591+
for _, el := range slice {
592+
all = append(all, op.op(el))
593+
}
594+
obj = all
595+
} else {
596+
obj = op.op(obj)
597+
}
598+
599+
//obj = op.op(obj)
565600
}
566601
return obj
567602
}
@@ -582,7 +617,23 @@ func (p valuePath) String() string {
582617
func compilePath(path []string) (out valuePath, _ error) {
583618
for i := range path {
584619
part := path[i]
620+
621+
if part == "[*]" {
622+
// wildcard: retourner tous les éléments d'un array
623+
out = append(out, pathOp{
624+
part: part,
625+
op: func(m interface{}) interface{} {
626+
if s, ok := m.([]interface{}); ok {
627+
return s
628+
}
629+
return nil
630+
},
631+
})
632+
continue
633+
}
634+
585635
if strings.HasPrefix(part, "[") && strings.HasSuffix(part, "]") {
636+
586637
// list lookup: [key=value]
587638
eq := strings.SplitN(part[1:len(part)-1], "=", 2)
588639
if len(eq) != 2 {
@@ -627,7 +678,9 @@ func compilePath(path []string) (out valuePath, _ error) {
627678
} else {
628679
out = append(out, pathOp{
629680
part: part,
681+
// Function qui sera utilisé dans le Get pour descendre dans l'arborescence (op.op(obj))
630682
op: func(m interface{}) interface{} {
683+
// On cherche du clé valeur dans une map
631684
if mp, ok := m.(map[string]interface{}); ok {
632685
kv := strings.Split(part, "=")
633686
if len(kv) == 2 /* k=v */ {
@@ -640,6 +693,8 @@ func compilePath(path []string) (out valuePath, _ error) {
640693
}
641694
}
642695
return mp[part]
696+
// On va checher un index dans une liste
697+
// ex: [0], [1], ... -> on pourrait ici faire le boulot si *
643698
} else if s, ok := m.([]interface{}); ok {
644699
i, err := strconv.Atoi(part)
645700
if err != nil {

pkg/customresourcestate/registry_factory_test.go

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package customresourcestate
1818

1919
import (
2020
"encoding/json"
21-
"errors"
2221
"reflect"
2322
"testing"
2423

@@ -88,6 +87,64 @@ func init() {
8887
"status": "False",
8988
},
9089
},
90+
"parents": Array{
91+
Obj{
92+
"conditions": Array{
93+
Obj{
94+
"type": "Ready",
95+
"status": "True",
96+
"message": "All good",
97+
"reason": "AsExpected",
98+
"lastTransitionTime": "2022-06-28T00:00:00Z",
99+
"observedGeneration": 42,
100+
},
101+
Obj{
102+
"type": "Synced",
103+
"status": "False",
104+
"message": "Not synced",
105+
"reason": "SyncError",
106+
"lastTransitionTime": "2022-06-28T00:00:00Z",
107+
"observedGeneration": 43,
108+
},
109+
},
110+
"controllerName": "foo.bar/baz",
111+
"parentRef": Obj{
112+
"group": "foo.bar",
113+
"kind": "Baz",
114+
"name": "baz-1",
115+
"namespace": "default",
116+
},
117+
},
118+
Obj{
119+
"conditions": Array{
120+
Obj{
121+
"type": "Ready",
122+
"status": "False",
123+
"message": "Not ready",
124+
"reason": "NotReady",
125+
"lastTransitionTime": "2022-06-28T00:00:00Z",
126+
"observedGeneration": 44,
127+
},
128+
},
129+
"controllerName": "qux.corge/grault",
130+
"parentRef": Obj{
131+
"group": "qux.corge",
132+
"kind": "Grault",
133+
"name": "grault-1",
134+
"namespace": "default",
135+
},
136+
},
137+
Obj{
138+
"conditions": Array{},
139+
"controllerName": "garply.waldo/fred",
140+
"parentRef": Obj{
141+
"group": "garply.waldo",
142+
"kind": "Fred",
143+
"name": "fred-1",
144+
"namespace": "default",
145+
},
146+
},
147+
},
91148
},
92149
"metadata": Obj{
93150
"name": "foo",
@@ -164,7 +221,7 @@ func Test_values(t *testing.T) {
164221
}
165222

166223
tests := []tc{
167-
{name: "single", each: &compiledGauge{
224+
/*{name: "single", each: &compiledGauge{
168225
compiledCommon: compiledCommon{
169226
path: mustCompilePath(t, "spec", "replicas"),
170227
},
@@ -351,16 +408,30 @@ func Test_values(t *testing.T) {
351408
}, wantResult: []eachValue{
352409
newEachValue(t, 0, "type", "Provisioned"),
353410
newEachValue(t, 1, "type", "Ready"),
354-
}},
355-
{name: "= expression matching", each: &compiledInfo{
411+
}},*/
412+
{name: "status_parents_conditions", each: &compiledGauge{
356413
compiledCommon: compiledCommon{
414+
path: mustCompilePath(t, "status", "parents", "[*]", "conditions"),
415+
//path: mustCompilePath(t, "status", "conditions"),
357416
labelFromPath: map[string]valuePath{
358-
"bar": mustCompilePath(t, "metadata", "annotations", "bar=baz"),
417+
"reason": mustCompilePath(t, "reason"),
359418
},
360419
},
420+
ValueFrom: mustCompilePath(t, "status"),
361421
}, wantResult: []eachValue{
362-
newEachValue(t, 1, "bar", "baz"),
363-
}},
422+
newEachValue(t, 1, "reason", "AsExpected"),
423+
newEachValue(t, 0, "reason", "NotReady"),
424+
newEachValue(t, 0, "reason", "SyncError"),
425+
}}, /*
426+
{name: "= expression matching", each: &compiledInfo{
427+
compiledCommon: compiledCommon{
428+
labelFromPath: map[string]valuePath{
429+
"bar": mustCompilePath(t, "metadata", "annotations", "bar=baz"),
430+
},
431+
},
432+
}, wantResult: []eachValue{
433+
newEachValue(t, 1, "bar", "baz"),
434+
}},*/
364435
}
365436
for _, tt := range tests {
366437
t.Run(tt.name, func(t *testing.T) {

0 commit comments

Comments
 (0)