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)
+                       }
+               }
+       }
+}

Reply via email to