This is an automated email from the ASF dual-hosted git repository. astefanutti pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit 6cf412a83e0c0cf525ea0a03229f5b7b884c37a1 Author: Antonin Stefanutti <anto...@stefanutti.fr> AuthorDate: Tue Nov 26 17:50:03 2019 +0100 chore: Use reflection to compute positive JSON merge patch --- pkg/trait/deployer.go | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/pkg/trait/deployer.go b/pkg/trait/deployer.go index 1a9550f..56b0322 100644 --- a/pkg/trait/deployer.go +++ b/pkg/trait/deployer.go @@ -18,10 +18,12 @@ limitations under the License. package trait import ( - jsonpatch "github.com/evanphx/json-patch" + "reflect" "github.com/pkg/errors" + jsonpatch "github.com/evanphx/json-patch" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/json" @@ -119,24 +121,47 @@ func (s *mergeFromPositivePatch) Data(obj runtime.Object) ([]byte, error) { return nil, err } - patch, err := jsonpatch.CreateMergePatch(originalJSON, modifiedJSON) + mergePatch, err := jsonpatch.CreateMergePatch(originalJSON, modifiedJSON) if err != nil { return nil, err } - // The following is a work-around to remove null fields from the JSON merge patch - // so that values defaulted by controllers server-side are not deleted. - // It's generally acceptable as these values are orthogonal to the values managed - // by the traits. - out := obj.DeepCopyObject() - err = json.Unmarshal(patch, out) + var positivePatch map[string]interface{} + err = json.Unmarshal(mergePatch, &positivePatch) if err != nil { return nil, err } - return json.Marshal(out) + // The following is a work-around to remove null fields from the JSON merge patch, + // so that values defaulted by controllers server-side are not deleted. + // It's generally acceptable as these values are orthogonal to the values managed + // by the traits. + removeNilValues(reflect.ValueOf(positivePatch)) + + return json.Marshal(positivePatch) } func mergeFrom(obj runtime.Object) client.Patch { return &mergeFromPositivePatch{obj} } + +func removeNilValues(v reflect.Value) { + for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface { + v = v.Elem() + } + switch v.Kind() { + case reflect.Array, reflect.Slice: + for i := 0; i < v.Len(); i++ { + removeNilValues(v.Index(i)) + } + case reflect.Map: + for _, k := range v.MapKeys() { + c := v.MapIndex(k) + if c.IsNil() { + v.SetMapIndex(k, reflect.Value{}) + } else { + removeNilValues(c) + } + } + } +}