...
1
16
17 package mergepatch
18
19 import (
20 "fmt"
21 "reflect"
22
23 "k8s.io/apimachinery/pkg/util/dump"
24 "sigs.k8s.io/yaml"
25 )
26
27
28 type PreconditionFunc func(interface{}) bool
29
30
31
32 func RequireKeyUnchanged(key string) PreconditionFunc {
33 return func(patch interface{}) bool {
34 patchMap, ok := patch.(map[string]interface{})
35 if !ok {
36 return true
37 }
38
39
40 _, ok = patchMap[key]
41 return !ok
42 }
43 }
44
45
46
47
48 func RequireMetadataKeyUnchanged(key string) PreconditionFunc {
49 return func(patch interface{}) bool {
50 patchMap, ok := patch.(map[string]interface{})
51 if !ok {
52 return true
53 }
54 patchMap1, ok := patchMap["metadata"]
55 if !ok {
56 return true
57 }
58 patchMap2, ok := patchMap1.(map[string]interface{})
59 if !ok {
60 return true
61 }
62 _, ok = patchMap2[key]
63 return !ok
64 }
65 }
66
67 func ToYAMLOrError(v interface{}) string {
68 y, err := toYAML(v)
69 if err != nil {
70 return err.Error()
71 }
72
73 return y
74 }
75
76 func toYAML(v interface{}) (string, error) {
77 y, err := yaml.Marshal(v)
78 if err != nil {
79 return "", fmt.Errorf("yaml marshal failed:%v\n%v\n", err, dump.Pretty(v))
80 }
81
82 return string(y), nil
83 }
84
85
86
87
88
89
90
91
92 func HasConflicts(left, right interface{}) (bool, error) {
93 switch typedLeft := left.(type) {
94 case map[string]interface{}:
95 switch typedRight := right.(type) {
96 case map[string]interface{}:
97 for key, leftValue := range typedLeft {
98 rightValue, ok := typedRight[key]
99 if !ok {
100 continue
101 }
102 if conflict, err := HasConflicts(leftValue, rightValue); err != nil || conflict {
103 return conflict, err
104 }
105 }
106
107 return false, nil
108 default:
109 return true, nil
110 }
111 case []interface{}:
112 switch typedRight := right.(type) {
113 case []interface{}:
114 if len(typedLeft) != len(typedRight) {
115 return true, nil
116 }
117
118 for i := range typedLeft {
119 if conflict, err := HasConflicts(typedLeft[i], typedRight[i]); err != nil || conflict {
120 return conflict, err
121 }
122 }
123
124 return false, nil
125 default:
126 return true, nil
127 }
128 case string, float64, bool, int64, nil:
129 return !reflect.DeepEqual(left, right), nil
130 default:
131 return true, fmt.Errorf("unknown type: %v", reflect.TypeOf(left))
132 }
133 }
134
View as plain text