@@ -25,6 +25,7 @@ import (
25
25
"k8s.io/apimachinery/pkg/runtime"
26
26
"k8s.io/apimachinery/pkg/types"
27
27
"k8s.io/apimachinery/pkg/util/json"
28
+ "k8s.io/apimachinery/pkg/util/strategicpatch"
28
29
)
29
30
30
31
var (
@@ -87,13 +88,15 @@ type MergeFromOptions struct {
87
88
}
88
89
89
90
type mergeFromPatch struct {
90
- from runtime.Object
91
- opts MergeFromOptions
91
+ patchType types.PatchType
92
+ createPatch func (originalJSON , modifiedJSON []byte , dataStruct interface {}) ([]byte , error )
93
+ from runtime.Object
94
+ opts MergeFromOptions
92
95
}
93
96
94
97
// Type implements patch.
95
98
func (s * mergeFromPatch ) Type () types.PatchType {
96
- return types . MergePatchType
99
+ return s . patchType
97
100
}
98
101
99
102
// Data implements Patch.
@@ -108,7 +111,7 @@ func (s *mergeFromPatch) Data(obj runtime.Object) ([]byte, error) {
108
111
return nil , err
109
112
}
110
113
111
- data , err := jsonpatch . CreateMergePatch (originalJSON , modifiedJSON )
114
+ data , err := s . createPatch (originalJSON , modifiedJSON , obj )
112
115
if err != nil {
113
116
return nil , err
114
117
}
@@ -137,18 +140,50 @@ func (s *mergeFromPatch) Data(obj runtime.Object) ([]byte, error) {
137
140
return data , nil
138
141
}
139
142
143
+ func createMergePatch (originalJSON , modifiedJSON []byte , _ interface {}) ([]byte , error ) {
144
+ return jsonpatch .CreateMergePatch (originalJSON , modifiedJSON )
145
+ }
146
+
147
+ func createStrategicMergePatch (originalJSON , modifiedJSON []byte , dataStruct interface {}) ([]byte , error ) {
148
+ return strategicpatch .CreateTwoWayMergePatch (originalJSON , modifiedJSON , dataStruct )
149
+ }
150
+
140
151
// MergeFrom creates a Patch that patches using the merge-patch strategy with the given object as base.
152
+ // The difference between MergeFrom and StrategicMergeFrom lays in the handling of modified list fields.
153
+ // When using MergeFrom, existing lists will be completely replaced by new lists.
154
+ // When using StrategicMergeFrom, the list field's `patchStrategy` is respected if specified in the API type,
155
+ // e.g. the existing list is not replaced completely but rather merged with the new one using the list's `patchMergeKey`.
156
+ // See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ for more details on
157
+ // the difference between merge-patch and strategic-merge-patch.
141
158
func MergeFrom (obj runtime.Object ) Patch {
142
- return & mergeFromPatch {from : obj }
159
+ return & mergeFromPatch {patchType : types . MergePatchType , createPatch : createMergePatch , from : obj }
143
160
}
144
161
145
162
// MergeFromWithOptions creates a Patch that patches using the merge-patch strategy with the given object as base.
163
+ // See MergeFrom for more details.
146
164
func MergeFromWithOptions (obj runtime.Object , opts ... MergeFromOption ) Patch {
147
165
options := & MergeFromOptions {}
148
166
for _ , opt := range opts {
149
167
opt .ApplyToMergeFrom (options )
150
168
}
151
- return & mergeFromPatch {from : obj , opts : * options }
169
+ return & mergeFromPatch {patchType : types .MergePatchType , createPatch : createMergePatch , from : obj , opts : * options }
170
+ }
171
+
172
+ // StrategicMergeFrom creates a Patch that patches using the strategic-merge-patch strategy with the given object as base.
173
+ // The difference between MergeFrom and StrategicMergeFrom lays in the handling of modified list fields.
174
+ // When using MergeFrom, existing lists will be completely replaced by new lists.
175
+ // When using StrategicMergeFrom, the list field's `patchStrategy` is respected if specified in the API type,
176
+ // e.g. the existing list is not replaced completely but rather merged with the new one using the list's `patchMergeKey`.
177
+ // See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ for more details on
178
+ // the difference between merge-patch and strategic-merge-patch.
179
+ // Please note, that CRDs don't support strategic-merge-patch, see
180
+ // https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#advanced-features-and-flexibility
181
+ func StrategicMergeFrom (obj Object , opts ... MergeFromOption ) Patch {
182
+ options := & MergeFromOptions {}
183
+ for _ , opt := range opts {
184
+ opt .ApplyToMergeFrom (options )
185
+ }
186
+ return & mergeFromPatch {patchType : types .StrategicMergePatchType , createPatch : createStrategicMergePatch , from : obj , opts : * options }
152
187
}
153
188
154
189
// mergePatch uses a raw merge strategy to patch the object.
0 commit comments