Skip to content

Commit fad0cbb

Browse files
Add KeepEmptyFields option when Walk Template
added KeepEmptyFields to preserve old behavior to avoid removing empty fields which leads to unintended rollout. see https://vmw-jira.broadcom.net/browse/TKG-32450
1 parent a8e4187 commit fad0cbb

File tree

1 file changed

+64
-2
lines changed

1 file changed

+64
-2
lines changed

exp/runtime/topologymutation/walker.go

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ type WalkTemplatesOptions struct {
4242
failForUnknownTypes bool
4343
patchFormat runtimehooksv1.PatchType
4444
// TODO: add the possibility to set patchFormat for single patches only, eg. via a func(requestItem) format.
45+
KeepEmptyFields bool
4546
}
4647

4748
// newWalkTemplatesOptions returns a WalkTemplatesOptions with default values.
@@ -61,6 +62,14 @@ func (f FailForUnknownTypes) ApplyToWalkTemplates(in *WalkTemplatesOptions) {
6162
in.failForUnknownTypes = true
6263
}
6364

65+
// KeepEmptyFields defines if WalkTemplates should keep empty fields which is old behavior
66+
type KeepEmptyFields struct{}
67+
68+
// ApplyToWalkTemplates applies this configuration to the given WalkTemplatesOptions.
69+
func (f KeepEmptyFields) ApplyToWalkTemplates(in *WalkTemplatesOptions) {
70+
in.KeepEmptyFields = true
71+
}
72+
6473
// PatchFormat defines the patch format that WalkTemplates should generate.
6574
// If not set, JSONPatchType will be used.
6675
type PatchFormat struct {
@@ -147,14 +156,22 @@ func WalkTemplates(ctx context.Context, decoder runtime.Decoder, req *runtimehoo
147156
var patch []byte
148157
switch options.patchFormat {
149158
case runtimehooksv1.JSONPatchType:
150-
patch, err = createJSONPatch(requestItem.Object.Raw, modified)
159+
if options.KeepEmptyFields {
160+
patch, err = createJSONPatchKeepEmptyFields(original, modified)
161+
} else {
162+
patch, err = createJSONPatch(requestItem.Object.Raw, modified)
163+
}
151164
if err != nil {
152165
resp.Status = runtimehooksv1.ResponseStatusFailure
153166
resp.Message = err.Error()
154167
return
155168
}
156169
case runtimehooksv1.JSONMergePatchType:
157-
patch, err = createJSONMergePatch(requestItem.Object.Raw, modified)
170+
if options.KeepEmptyFields {
171+
patch, err = createJSONMergePatchKeepEmptyFields(original, modified)
172+
} else {
173+
patch, err = createJSONMergePatch(requestItem.Object.Raw, modified)
174+
}
158175
if err != nil {
159176
resp.Status = runtimehooksv1.ResponseStatusFailure
160177
resp.Message = err.Error()
@@ -207,3 +224,48 @@ func createJSONMergePatch(marshalledOriginal []byte, modified runtime.Object) ([
207224

208225
return patch, nil
209226
}
227+
228+
// createJSONPatchKeepEmptyFields creates a RFC 6902 JSON patch from the original and the modified object.
229+
func createJSONPatchKeepEmptyFields(original, modified runtime.Object) ([]byte, error) {
230+
marshalledOriginal, err := json.Marshal(original)
231+
if err != nil {
232+
return nil, errors.Errorf("failed to marshal original object: %v", err)
233+
}
234+
235+
marshalledModified, err := json.Marshal(modified)
236+
if err != nil {
237+
return nil, errors.Errorf("failed to marshal modified object: %v", err)
238+
}
239+
240+
patch, err := jsonpatch.CreatePatch(marshalledOriginal, marshalledModified)
241+
if err != nil {
242+
return nil, errors.Errorf("failed to create patch: %v", err)
243+
}
244+
245+
patchBytes, err := json.Marshal(patch)
246+
if err != nil {
247+
return nil, errors.Errorf("failed to marshal patch: %v", err)
248+
}
249+
250+
return patchBytes, nil
251+
}
252+
253+
// createJSONMergePatchKeepEmptyFields creates a RFC 7396 JSON merge patch from the original and the modified object.
254+
func createJSONMergePatchKeepEmptyFields(original, modified runtime.Object) ([]byte, error) {
255+
marshalledOriginal, err := json.Marshal(original)
256+
if err != nil {
257+
return nil, errors.Errorf("failed to marshal original object: %v", err)
258+
}
259+
260+
marshalledModified, err := json.Marshal(modified)
261+
if err != nil {
262+
return nil, errors.Errorf("failed to marshal modified object: %v", err)
263+
}
264+
265+
patch, err := mergepatch.CreateMergePatch(marshalledOriginal, marshalledModified)
266+
if err != nil {
267+
return nil, errors.Errorf("failed to create patch: %v", err)
268+
}
269+
270+
return patch, nil
271+
}

0 commit comments

Comments
 (0)