Skip to content

Commit d86cbba

Browse files
committed
Add wildcard token to match all elements in an array
Useful for replace operations
1 parent 976ba85 commit d86cbba

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed

patch/pointer.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ func NewPointerFromString(str string) (Pointer, error) {
5252
continue
5353
}
5454

55+
// parse wildcard
56+
if tok == "*" {
57+
tokens = append(tokens, WildcardToken{})
58+
continue
59+
}
60+
5561
// parse as index
5662
idx, err := strconv.Atoi(tok)
5763
if err == nil {

patch/replace_op_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,35 @@ import (
88
)
99

1010
var _ = Describe("ReplaceOp.Apply", func() {
11+
Describe("multiple replace", func() {
12+
It("replaces many items", func() {
13+
res, err := ReplaceOp{Path: MustNewPointerFromString("/instance_groups/*/vm_extensions?/-"), Value: "ex2"}.Apply(map[interface{}]interface{}{
14+
"instance_groups": []interface{}{
15+
map[interface{}]interface{}{
16+
"name": "foo",
17+
"vm_extensions": []interface{}{"ex1"},
18+
},
19+
map[interface{}]interface{}{
20+
"name": "bar",
21+
},
22+
},
23+
})
24+
Expect(err).ToNot(HaveOccurred())
25+
Expect(res).To(Equal(map[interface{}]interface{}{
26+
"instance_groups": []interface{}{
27+
map[interface{}]interface{}{
28+
"name": "foo",
29+
"vm_extensions": []interface{}{"ex1", "ex2"},
30+
},
31+
map[interface{}]interface{}{
32+
"name": "bar",
33+
"vm_extensions": []interface{}{"ex2"},
34+
},
35+
},
36+
}))
37+
})
38+
})
39+
1140
It("returns error if replacement value cloning fails", func() {
1241
_, err := ReplaceOp{Path: MustNewPointerFromString(""), Value: func() {}}.Apply("a")
1342
Expect(err).To(HaveOccurred())

patch/token_wildcard.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package patch
2+
3+
import "errors"
4+
5+
type WildcardToken struct{}
6+
7+
func (t WildcardToken) processDescent(ctx *tokenContext) (interface{}, error) {
8+
if ctx.IsLast() {
9+
return nil, errors.New("wildcard can't be used for last element. Use - instead")
10+
}
11+
typedArray, ok := ctx.Node.([]interface{})
12+
if !ok {
13+
return nil, newOpArrayMismatchTypeErr(ctx.Tokens[:ctx.TokenIndex+1], ctx.Node)
14+
}
15+
if ctx.Method == methodReplace || ctx.Method == methodRemove {
16+
for idx, e := range typedArray {
17+
ctx.Node = e
18+
ctx.Setter = func(newObj interface{}) { typedArray[idx] = newObj }
19+
_, err := ctx.Descend()
20+
if err != nil {
21+
return nil, err
22+
}
23+
}
24+
return nil, nil
25+
}
26+
return nil, errors.New("unsupported")
27+
}
28+
29+
func (t WildcardToken) createEmptyValueForNext() (interface{}, error) {
30+
return nil, errors.New("not supported")
31+
}

0 commit comments

Comments
 (0)