8
8
9
9
jsonpatch "github.com/evanphx/json-patch/v5"
10
10
"github.com/samber/lo"
11
- "k8s.io/klog/v2"
12
11
"sigs.k8s.io/controller-runtime/pkg/client"
13
12
)
14
13
@@ -57,23 +56,20 @@ func (p Patch) Clear() {
57
56
}
58
57
}
59
58
60
- type translateFn func (path string , val interface {}, exists bool ) (interface {}, error )
61
-
62
- func (p Patch ) MustTranslate (path string , translate translateFn ) {
59
+ func (p Patch ) MustTranslate (path string , translate func (path string , val interface {}) (interface {}, error )) {
63
60
err := p .Translate (path , translate )
64
61
if err != nil {
65
62
panic (err )
66
63
}
67
64
}
68
65
69
- // Translate changes values on the given path.
70
- func (p Patch ) Translate (path string , translate translateFn ) error {
71
- parsedPath , err := parsePathWithIndexing (path , true )
66
+ // Translate changes existing (!) values on the given path. If you want to set a value, use the set function instead .
67
+ func (p Patch ) Translate (path string , translate func ( path string , val interface {}) ( interface {}, error ) ) error {
68
+ parsedPath , err := parsePath (path )
72
69
if err != nil {
73
70
panic (err )
74
- }
75
- if len (parsedPath ) == 0 {
76
- retVal , err := translate ("" , map [string ]interface {}(p ), true )
71
+ } else if len (parsedPath ) == 0 {
72
+ retVal , err := translate ("" , map [string ]interface {}(p ))
77
73
if err != nil {
78
74
return err
79
75
}
@@ -88,8 +84,8 @@ func (p Patch) Translate(path string, translate translateFn) error {
88
84
89
85
// get last map / array
90
86
curs , ok := p .getValue (parsedPath , 1 )
87
+
91
88
if ! ok {
92
- klog .V (0 ).ErrorS (fmt .Errorf ("could not find path %q in patch" , path ), "not found" , "path" , path )
93
89
return nil
94
90
}
95
91
@@ -99,10 +95,9 @@ func (p Patch) Translate(path string, translate translateFn) error {
99
95
100
96
switch t := cur .Value .(type ) {
101
97
case []interface {}:
102
- segment = trimBracketsPair (segment )
103
98
if segment == "*" {
104
99
for k := range t {
105
- t [k ], err = translate (addPathElement (cur .Path , strconv .Itoa (k )), t [k ], true )
100
+ t [k ], err = translate (addPathElement (cur .Path , strconv .Itoa (k )), t [k ])
106
101
if err != nil {
107
102
return err
108
103
}
@@ -119,44 +114,30 @@ func (p Patch) Translate(path string, translate translateFn) error {
119
114
return nil
120
115
}
121
116
122
- ret , err := translate (addPathElement (cur .Path , segment ), t [index ], true )
117
+ ret , err := translate (addPathElement (cur .Path , segment ), t [index ])
123
118
if err != nil {
124
119
return err
125
120
}
126
121
127
122
t [index ] = ret
128
123
129
124
case map [string ]interface {}:
130
- switch {
131
- case segment == "[*]" :
125
+ if segment == "*" {
132
126
for k := range t {
133
- t [k ], err = translate (addPathElement (cur .Path , k ), t [k ], true )
127
+ t [k ], err = translate (addPathElement (cur .Path , k ), t [k ])
134
128
if err != nil {
135
129
return err
136
130
}
137
131
}
138
- case isBracketEnclosed (segment ): // a.path.to.some["segment"] case
139
- key := trimBracketsPair (segment )
140
- if key == "" {
141
- return fmt .Errorf ("empty key in bracket notation in path %q" , segment )
142
- }
143
- v , ok := t [key ]
144
- valueFromExpression , err := translate (cur .Path , v , ok )
145
- if err != nil {
146
- return fmt .Errorf ("translate value for key %q in path %q: %w" , key , cur .Path , err )
147
- }
148
- if valueFromExpression == nil {
149
- p .Delete (JoinPath (cur .Path , key ))
150
- continue
151
- }
152
- t [key ] = valueFromExpression
153
132
154
- default : // a.path.to.some.segment case
155
- if val , ok := t [segment ]; ok {
156
- t [segment ], err = translate (JoinPath (cur .Path , segment ), val , ok )
157
- if err != nil {
158
- return err
159
- }
133
+ continue
134
+ }
135
+
136
+ val , ok := t [segment ]
137
+ if ok {
138
+ t [segment ], err = translate (JoinPath (cur .Path , segment ), val )
139
+ if err != nil {
140
+ return err
160
141
}
161
142
}
162
143
}
@@ -209,8 +190,7 @@ func (p Patch) Delete(path string) {
209
190
210
191
// delete last element, we only support maps here for now.
211
192
for _ , cur := range curs {
212
- segment := parsedPath [len (parsedPath )- 1 ]
213
- if segment == "*" {
193
+ if parsedPath [len (parsedPath )- 1 ] == "*" {
214
194
if t , ok := cur .Value .(map [string ]interface {}); ok {
215
195
for k := range t {
216
196
delete (t , k )
@@ -220,7 +200,7 @@ func (p Patch) Delete(path string) {
220
200
}
221
201
222
202
if t , ok := cur .Value .(map [string ]interface {}); ok {
223
- delete (t , segment )
203
+ delete (t , parsedPath [ len ( parsedPath ) - 1 ] )
224
204
}
225
205
}
226
206
@@ -389,10 +369,9 @@ func nextValue(parsedPath []string, index int, cur *PathValue, create bool) ([]P
389
369
return []PathValue {* cur }, true
390
370
}
391
371
392
- firstPath := trimBracketsPair (parsedPath [0 ])
393
372
switch val := cur .Value .(type ) {
394
373
case map [string ]interface {}:
395
- if firstPath == "*" {
374
+ if parsedPath [ 0 ] == "*" {
396
375
retVals := make ([]PathValue , 0 , len (val ))
397
376
for k := range val {
398
377
retVal , ok := nextValue (parsedPath [1 :], index , & PathValue {
@@ -412,23 +391,23 @@ func nextValue(parsedPath []string, index int, cur *PathValue, create bool) ([]P
412
391
return retVals , true
413
392
}
414
393
415
- mapValue , ok := val [firstPath ]
394
+ mapValue , ok := val [parsedPath [ 0 ] ]
416
395
if ! ok && ! create {
417
396
return nil , false
418
397
} else if create && (! ok || mapValue == nil ) {
419
- val [firstPath ] = createValue (parsedPath [1 :])
420
- mapValue = val [firstPath ]
398
+ val [parsedPath [ 0 ] ] = createValue (parsedPath [1 :])
399
+ mapValue = val [parsedPath [ 0 ] ]
421
400
}
422
401
423
402
return nextValue (parsedPath [1 :], index , & PathValue {
424
403
Parent : cur ,
425
404
Value : mapValue ,
426
- Key : firstPath ,
427
- Path : addPathElement (cur .Path , firstPath ),
405
+ Key : parsedPath [ 0 ] ,
406
+ Path : addPathElement (cur .Path , parsedPath [ 0 ] ),
428
407
}, create )
429
408
case []interface {}:
430
409
// try to match all
431
- if firstPath == "*" {
410
+ if parsedPath [ 0 ] == "*" {
432
411
retVals := make ([]PathValue , 0 , len (val ))
433
412
for i := range val {
434
413
retVal , ok := nextValue (parsedPath [1 :], index , & PathValue {
@@ -449,7 +428,7 @@ func nextValue(parsedPath []string, index int, cur *PathValue, create bool) ([]P
449
428
}
450
429
451
430
// try to get index
452
- indexSegment , err := strconv .Atoi (firstPath )
431
+ indexSegment , err := strconv .Atoi (parsedPath [ 0 ] )
453
432
if err != nil {
454
433
return nil , false
455
434
}
@@ -475,7 +454,7 @@ func nextValue(parsedPath []string, index int, cur *PathValue, create bool) ([]P
475
454
Parent : cur ,
476
455
Value : arrVal ,
477
456
Index : indexSegment ,
478
- Path : addPathElement (cur .Path , firstPath ),
457
+ Path : addPathElement (cur .Path , parsedPath [ 0 ] ),
479
458
}, create )
480
459
}
481
460
@@ -487,8 +466,7 @@ func createValue(pathSegment []string) interface{} {
487
466
return map [string ]interface {}{}
488
467
}
489
468
490
- segment := trimBracketsPair (pathSegment [0 ])
491
- intVal , err := strconv .Atoi (segment )
469
+ intVal , err := strconv .Atoi (pathSegment [0 ])
492
470
if err == nil {
493
471
newVal := make ([]interface {}, 0 , intVal + 1 )
494
472
for i := 0 ; i <= intVal ; i ++ {
@@ -519,17 +497,3 @@ func JoinPath(root, next string) string {
519
497
}
520
498
return root + "." + next
521
499
}
522
-
523
- func trimBracketsPair (segment string ) string {
524
- if isBracketEnclosed (segment ) {
525
- return segment [1 : len (segment )- 1 ]
526
- }
527
- return segment
528
- }
529
-
530
- func isBracketEnclosed (segment string ) bool {
531
- if len (segment ) < 2 {
532
- return false
533
- }
534
- return segment [0 ] == '[' && segment [len (segment )- 1 ] == ']'
535
- }
0 commit comments