Skip to content

Commit 42f82c3

Browse files
committed
Add wildcard token to match all elements in an array
Useful for replace operations
1 parent b4a5eb3 commit 42f82c3

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

patch/pointer.go

+6
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

+29
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

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

0 commit comments

Comments
 (0)