mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-18 03:45:12 +00:00
607 lines
8.8 KiB
Go
607 lines
8.8 KiB
Go
package yamlpatch_test
|
|
|
|
import (
|
|
yamlpatch "github.com/krishicks/yaml-patch"
|
|
yaml "gopkg.in/yaml.v2"
|
|
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/ginkgo/extensions/table"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var _ = Describe("Patch", func() {
|
|
Describe("Apply", func() {
|
|
DescribeTable(
|
|
"positive cases",
|
|
func(doc, ops, expectedYAML string) {
|
|
patch, err := yamlpatch.DecodePatch([]byte(ops))
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
actualBytes, err := patch.Apply([]byte(doc))
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
var actualIface interface{}
|
|
err = yaml.Unmarshal(actualBytes, &actualIface)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
var expectedIface interface{}
|
|
err = yaml.Unmarshal([]byte(expectedYAML), &expectedIface)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(actualIface).To(Equal(expectedIface))
|
|
},
|
|
Entry("adding an element to an object",
|
|
`---
|
|
foo: bar
|
|
`,
|
|
`---
|
|
- op: add
|
|
path: /baz
|
|
value: qux
|
|
`,
|
|
`---
|
|
foo: bar
|
|
baz: qux
|
|
`,
|
|
),
|
|
Entry("adding an element to an array",
|
|
`---
|
|
foo: [bar,baz]
|
|
`,
|
|
`---
|
|
- op: add
|
|
path: /foo/1
|
|
value: qux
|
|
`,
|
|
`---
|
|
foo: [bar,qux,baz]
|
|
`,
|
|
),
|
|
Entry("removing an element from an object",
|
|
`---
|
|
foo: bar
|
|
baz: qux
|
|
`,
|
|
`---
|
|
- op: remove
|
|
path: /baz
|
|
`,
|
|
`---
|
|
foo: bar
|
|
`,
|
|
),
|
|
Entry("removing an element from an array",
|
|
`---
|
|
foo: [bar,qux,baz]
|
|
`,
|
|
`---
|
|
- op: remove
|
|
path: /foo/1
|
|
`,
|
|
`---
|
|
foo: [bar,baz]
|
|
`,
|
|
),
|
|
Entry("replacing an element in an object",
|
|
`---
|
|
foo: bar
|
|
baz: qux
|
|
`,
|
|
`---
|
|
- op: replace
|
|
path: /baz
|
|
value: boo
|
|
`,
|
|
`---
|
|
foo: bar
|
|
baz: boo
|
|
`,
|
|
),
|
|
Entry("moving an element in an object",
|
|
`---
|
|
foo:
|
|
bar: baz
|
|
waldo: fred
|
|
qux:
|
|
corge: grault
|
|
`,
|
|
`---
|
|
- op: move
|
|
from: /foo/waldo
|
|
path: /qux/thud
|
|
`,
|
|
`---
|
|
foo:
|
|
bar: baz
|
|
qux:
|
|
corge: grault
|
|
thud: fred
|
|
`,
|
|
),
|
|
Entry("moving an element in an array",
|
|
`---
|
|
foo: [all, grass, cows, eat]
|
|
`,
|
|
`---
|
|
- op: move
|
|
from: /foo/1
|
|
path: /foo/3
|
|
`,
|
|
`---
|
|
foo: [all, cows, eat, grass]
|
|
`,
|
|
),
|
|
Entry("adding an object to an object",
|
|
`---
|
|
foo: bar
|
|
`,
|
|
`---
|
|
- op: add
|
|
path: /child
|
|
value:
|
|
grandchild: {}
|
|
`,
|
|
`---
|
|
foo: bar
|
|
child:
|
|
grandchild: {}
|
|
`,
|
|
),
|
|
Entry("appending an element to an array",
|
|
`---
|
|
foo: [bar]
|
|
`,
|
|
`---
|
|
- op: add
|
|
path: /foo/-
|
|
value: [abc,def]
|
|
`,
|
|
`---
|
|
foo: [bar, [abc, def]]
|
|
`,
|
|
),
|
|
Entry("removing a nil element from an object",
|
|
`---
|
|
foo: bar
|
|
qux:
|
|
baz: 1
|
|
bar: ~
|
|
`,
|
|
`---
|
|
- op: remove
|
|
path: /qux/bar
|
|
`,
|
|
`---
|
|
foo: bar
|
|
qux:
|
|
baz: 1
|
|
`,
|
|
),
|
|
Entry("adding a nil element to an object",
|
|
`---
|
|
foo: bar
|
|
`,
|
|
`---
|
|
- op: add
|
|
path: /baz
|
|
value: ~
|
|
`,
|
|
`---
|
|
foo: bar
|
|
baz: ~
|
|
`,
|
|
),
|
|
Entry("replacing the sole element in an array",
|
|
`---
|
|
foo: [bar]
|
|
`,
|
|
`---
|
|
- op: replace
|
|
path: /foo/0
|
|
value: baz
|
|
`,
|
|
`---
|
|
foo: [baz]
|
|
`,
|
|
),
|
|
Entry("replacing an element in an array within a root array",
|
|
`---
|
|
- foo: [bar, qux, baz]
|
|
`,
|
|
`---
|
|
- op: replace
|
|
path: /0/foo/0
|
|
value: bum
|
|
`,
|
|
`---
|
|
- foo: [bum, qux, baz]
|
|
`,
|
|
),
|
|
Entry("copying an element in an array within a root array with an index",
|
|
`---
|
|
- foo: [bar, qux, baz]
|
|
bar: [qux, baz]
|
|
`,
|
|
`---
|
|
- op: copy
|
|
from: /0/foo/0
|
|
path: /0/bar/0
|
|
`,
|
|
`---
|
|
- foo: [bar, qux, baz]
|
|
bar: [bar, baz]
|
|
`,
|
|
),
|
|
Entry("testing for the existence of a nil value in an object",
|
|
`---
|
|
baz: ~
|
|
`,
|
|
`---
|
|
- op: test
|
|
path: /baz
|
|
value: ~
|
|
`,
|
|
`---
|
|
baz: ~
|
|
`,
|
|
),
|
|
Entry("testing for the existence of a nil key in an object",
|
|
`---
|
|
baz: ~
|
|
`,
|
|
`---
|
|
- op: test
|
|
path: /foo
|
|
value: ~
|
|
`,
|
|
`---
|
|
baz: ~
|
|
`,
|
|
),
|
|
Entry("testing for the existence of a nil value in an object",
|
|
`---
|
|
baz: qux
|
|
`,
|
|
`---
|
|
- op: test
|
|
path: /baz
|
|
value: qux
|
|
`,
|
|
`---
|
|
baz: qux
|
|
`,
|
|
),
|
|
Entry("testing for the existence of an element in an array",
|
|
`---
|
|
foo: [a, 2, c]
|
|
`,
|
|
`---
|
|
- op: test
|
|
path: /foo/1
|
|
value: 2
|
|
`,
|
|
`---
|
|
foo: [a, 2, c]
|
|
`,
|
|
),
|
|
Entry("testing for the existence of an element in an object using escape ordering",
|
|
`---
|
|
baz/foo: qux
|
|
`,
|
|
`---
|
|
- op: test
|
|
path: /baz~1foo
|
|
value: qux
|
|
`,
|
|
`---
|
|
baz/foo: qux
|
|
`,
|
|
),
|
|
Entry("testing for the existence of an object",
|
|
`---
|
|
foo:
|
|
- bar: baz
|
|
qux: corge
|
|
`,
|
|
`---
|
|
- op: test
|
|
path: /foo/0
|
|
value:
|
|
bar: baz
|
|
qux: corge
|
|
`,
|
|
`---
|
|
foo:
|
|
- bar: baz
|
|
qux: corge
|
|
`,
|
|
),
|
|
XEntry("copying an element in an array within a root array to a destination without an index",
|
|
// this is in jsonpatch, but I'd like confirmation from the spec that this is intended
|
|
`---
|
|
- foo: [bar, qux, baz]
|
|
bar: [qux, baz]
|
|
`,
|
|
`---
|
|
- op: copy
|
|
from: /0/foo/0
|
|
path: /0/bar
|
|
`,
|
|
`---
|
|
- foo: [bar, qux, baz]
|
|
bar: [bar, qux, baz]
|
|
`,
|
|
),
|
|
XEntry("copying an element in an array within a root array to a destination without an index",
|
|
`---
|
|
- foo:
|
|
bar: [qux, baz]
|
|
baz:
|
|
qux: bum
|
|
`,
|
|
`---
|
|
- op: copy
|
|
from: /0/foo/bar
|
|
path: /0/baz/bar
|
|
`,
|
|
`---
|
|
- foo: [bar, qux, baz]
|
|
bar: [bar, qux, baz]
|
|
`,
|
|
),
|
|
)
|
|
|
|
DescribeTable(
|
|
"with extended syntax",
|
|
func(doc, ops, expectedYAML string) {
|
|
patch, err := yamlpatch.DecodePatch([]byte(ops))
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
actualBytes, err := patch.Apply([]byte(doc))
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
var actualIface interface{}
|
|
err = yaml.Unmarshal(actualBytes, &actualIface)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
var expectedIface interface{}
|
|
err = yaml.Unmarshal([]byte(expectedYAML), &expectedIface)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(actualIface).To(Equal(expectedIface))
|
|
},
|
|
Entry("a path that begins with a composite key",
|
|
`---
|
|
- foo: bar
|
|
`,
|
|
`---
|
|
- op: replace
|
|
path: /foo=bar
|
|
value:
|
|
baz: quux
|
|
`,
|
|
`---
|
|
- baz: quux
|
|
`,
|
|
),
|
|
Entry("a path that begins with an array index and ends with a composite key",
|
|
`---
|
|
- waldo:
|
|
- thud: boo
|
|
- foo: bar
|
|
- corge: grault
|
|
`,
|
|
`---
|
|
- op: replace
|
|
path: /0/foo=bar
|
|
value:
|
|
baz: quux
|
|
`,
|
|
`---
|
|
- waldo:
|
|
- thud: boo
|
|
- baz: quux
|
|
- corge: grault
|
|
`,
|
|
),
|
|
Entry("a path that begins with an object key and ends with a composite key",
|
|
`---
|
|
waldo:
|
|
- thud: boo
|
|
- foo: bar
|
|
corge: grault
|
|
`,
|
|
`---
|
|
- op: replace
|
|
path: /waldo/foo=bar
|
|
value:
|
|
baz: quux
|
|
`,
|
|
`---
|
|
waldo:
|
|
- thud: boo
|
|
- baz: quux
|
|
corge: grault
|
|
`,
|
|
),
|
|
Entry("a path that doesn't end with a composite key",
|
|
`---
|
|
jobs:
|
|
- name: upgrade-opsmgr
|
|
serial: true
|
|
plan:
|
|
- get: pivnet-opsmgr
|
|
- put: something-else
|
|
`,
|
|
`---
|
|
- op: replace
|
|
path: /jobs/name=upgrade-opsmgr/plan/1
|
|
value:
|
|
get: something-else
|
|
`,
|
|
`---
|
|
jobs:
|
|
- name: upgrade-opsmgr
|
|
serial: true
|
|
plan:
|
|
- get: pivnet-opsmgr
|
|
- get: something-else
|
|
`,
|
|
),
|
|
Entry("removes multiple entries in a single op",
|
|
`---
|
|
foo:
|
|
- bar: baz
|
|
- waldo: fred
|
|
qux:
|
|
corge: grault
|
|
thud:
|
|
- waldo: fred
|
|
- bar: baz
|
|
`,
|
|
`---
|
|
- op: remove
|
|
path: /waldo=fred
|
|
`,
|
|
`---
|
|
foo:
|
|
- bar: baz
|
|
qux:
|
|
corge: grault
|
|
thud:
|
|
- bar: baz
|
|
`,
|
|
),
|
|
)
|
|
|
|
DescribeTable(
|
|
"failure cases",
|
|
func(doc, ops string) {
|
|
patch, err := yamlpatch.DecodePatch([]byte(ops))
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
_, err = patch.Apply([]byte(doc))
|
|
Expect(err).To(HaveOccurred())
|
|
},
|
|
Entry("adding an element to an object with a bad pointer",
|
|
`---
|
|
foo: bar
|
|
`,
|
|
`---
|
|
- op: add
|
|
path: /baz/bat
|
|
value: qux
|
|
`,
|
|
),
|
|
Entry("removing an element from an object with a bad pointer",
|
|
`---
|
|
a:
|
|
b:
|
|
d: 1
|
|
`,
|
|
`---
|
|
- op: remove
|
|
path: /a/b/c
|
|
`,
|
|
),
|
|
Entry("moving an element in an object with a bad pointer",
|
|
`---
|
|
a:
|
|
b:
|
|
d: 1
|
|
`,
|
|
`---
|
|
- op: move
|
|
from: /a/b/c
|
|
path: /a/b/e
|
|
`,
|
|
),
|
|
Entry("removing an element from an array with a bad pointer",
|
|
`---
|
|
a:
|
|
b: [1]
|
|
`,
|
|
`---
|
|
- op: remove
|
|
path: /a/b/1
|
|
`,
|
|
),
|
|
Entry("moving an element from an array with a bad pointer",
|
|
`---
|
|
a:
|
|
b: [1]
|
|
`,
|
|
`---
|
|
- op: move
|
|
from: /a/b/1
|
|
path: /a/b/2
|
|
`,
|
|
),
|
|
Entry("an operation with an invalid pathz field",
|
|
`---
|
|
foo: bar
|
|
`,
|
|
`---
|
|
- op: add
|
|
pathz: /baz
|
|
value: qux
|
|
`,
|
|
),
|
|
Entry("an add operation with an empty path",
|
|
`---
|
|
foo: bar
|
|
`,
|
|
`---
|
|
- op: add
|
|
path: ''
|
|
value: qux
|
|
`,
|
|
),
|
|
Entry("a replace operation on an array with an invalid path",
|
|
`---
|
|
name:
|
|
foo:
|
|
bat
|
|
qux:
|
|
bum
|
|
`,
|
|
`---
|
|
- op: replace
|
|
path: /foo/2
|
|
value: bum
|
|
`,
|
|
),
|
|
)
|
|
})
|
|
|
|
Describe("DecodePatch", func() {
|
|
It("returns an empty patch when given nil", func() {
|
|
patch, err := yamlpatch.DecodePatch(nil)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(patch).To(HaveLen(0))
|
|
})
|
|
|
|
It("returns a patch with a single op when given a single op", func() {
|
|
ops := []byte(
|
|
`---
|
|
- op: add
|
|
path: /baz
|
|
value: qux`)
|
|
|
|
patch, err := yamlpatch.DecodePatch(ops)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
var v interface{} = "qux"
|
|
value := yamlpatch.NewNode(&v)
|
|
Expect(patch).To(Equal(yamlpatch.Patch{
|
|
{
|
|
Op: "add",
|
|
Path: "/baz",
|
|
Value: value,
|
|
},
|
|
}))
|
|
})
|
|
})
|
|
})
|