Skip to content

Commit 96a22f5

Browse files
Add KeepEmptyFields option when Walk Template
added KeepEmptyFields to preserve old behavior to avoid removing empty fields which leads to unintended rollout.
1 parent a8e4187 commit 96a22f5

1 file changed

Lines changed: 64 additions & 2 deletions

File tree

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)