...
1
2
3
4 package merge2
5
6 import (
7 "fmt"
8
9 "sigs.k8s.io/kustomize/kyaml/yaml"
10 )
11
12
13
14
15
16 type smpDirective int
17
18 const (
19 smpUnknown smpDirective = iota
20 smpReplace
21 smpDelete
22 smpMerge
23 )
24
25 const strategicMergePatchDirectiveKey = "$patch"
26
27
28
29 func determineSmpDirective(patch *yaml.RNode) (smpDirective, error) {
30 if patch == nil {
31 return smpMerge, nil
32 }
33 switch patch.YNode().Kind {
34 case yaml.SequenceNode:
35 return determineSequenceNodePatchStrategy(patch)
36 case yaml.MappingNode:
37 return determineMappingNodePatchStrategy(patch)
38 default:
39 return smpUnknown, fmt.Errorf(
40 "no implemented strategic merge patch strategy for '%s' ('%s')",
41 patch.YNode().ShortTag(), patch.MustString())
42 }
43 }
44
45 func determineSequenceNodePatchStrategy(patch *yaml.RNode) (smpDirective, error) {
46
47 node, err := patch.Pipe(yaml.GetElementByKey(strategicMergePatchDirectiveKey))
48
49
50 if err != nil || node == nil || node.YNode() == nil || len(node.Content()) > 2 {
51 return smpMerge, nil
52 }
53
54 value, err := node.Pipe(yaml.Get(strategicMergePatchDirectiveKey))
55 if err != nil || value == nil || value.YNode() == nil {
56 return smpMerge, nil
57 }
58 v := value.YNode().Value
59 if v == smpDelete.String() {
60 return smpDelete, elideSequencePatchDirective(patch, v)
61 }
62 if v == smpReplace.String() {
63 return smpReplace, elideSequencePatchDirective(patch, v)
64 }
65 if v == smpMerge.String() {
66 return smpMerge, elideSequencePatchDirective(patch, v)
67 }
68 return smpUnknown, fmt.Errorf(
69 "unknown patch strategy '%s'", v)
70 }
71
72 func determineMappingNodePatchStrategy(patch *yaml.RNode) (smpDirective, error) {
73 node, err := patch.Pipe(yaml.Get(strategicMergePatchDirectiveKey))
74 if err != nil || node == nil || node.YNode() == nil {
75 return smpMerge, nil
76 }
77 v := node.YNode().Value
78 if v == smpDelete.String() {
79 return smpDelete, elideMappingPatchDirective(patch)
80 }
81 if v == smpReplace.String() {
82 return smpReplace, elideMappingPatchDirective(patch)
83 }
84 if v == smpMerge.String() {
85 return smpMerge, elideMappingPatchDirective(patch)
86 }
87 return smpUnknown, fmt.Errorf(
88 "unknown patch strategy '%s'", v)
89 }
90
91 func elideMappingPatchDirective(patch *yaml.RNode) error {
92 return patch.PipeE(yaml.Clear(strategicMergePatchDirectiveKey))
93 }
94
95 func elideSequencePatchDirective(patch *yaml.RNode, value string) error {
96 return patch.PipeE(yaml.ElementSetter{
97 Element: nil,
98 Keys: []string{strategicMergePatchDirectiveKey},
99 Values: []string{value},
100 })
101 }
102
View as plain text