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