You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by as...@apache.org on 2022/01/18 15:23:15 UTC

[camel-k] branch main updated (7bbf80e8 -> 467a697)

This is an automated email from the ASF dual-hosted git repository.

astefanutti pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git.


    from 7bbf80e8 doc: add more details about installation on IKS/ICR
     new 436a34f  fix(patch): Do not compute positive patch for unstructured object
     new 0e5c2ce  fix: Install Kamelets as unstructured resources
     new 467a697  fix: Use Kamelet serialized JSON as merge patch for client-side apply

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 e2e/support/test_support.go                 |  4 +-
 pkg/client/apply.go                         |  4 +-
 pkg/cmd/builder/builder.go                  |  2 +-
 pkg/cmd/install.go                          |  2 +-
 pkg/controller/build/monitor_routine.go     |  2 +-
 pkg/controller/kameletbinding/initialize.go |  2 +-
 pkg/install/kamelets.go                     | 34 +++++--------
 pkg/install/operator.go                     |  2 +-
 pkg/trait/deployer.go                       |  6 +--
 pkg/util/kubernetes/loader.go               | 15 +++---
 pkg/util/patch/patch.go                     | 75 +++++++++++++++--------------
 11 files changed, 70 insertions(+), 78 deletions(-)

[camel-k] 02/03: fix: Install Kamelets as unstructured resources

Posted by as...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

astefanutti pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 0e5c2ce0aec2d5198fb3d69e49fead8e25e5acce
Author: Antonin Stefanutti <an...@stefanutti.fr>
AuthorDate: Mon Jan 17 19:12:14 2022 +0100

    fix: Install Kamelets as unstructured resources
---
 pkg/install/kamelets.go       | 14 +++++++-------
 pkg/util/kubernetes/loader.go | 15 +++++++--------
 2 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/pkg/install/kamelets.go b/pkg/install/kamelets.go
index f910436..024341c 100644
--- a/pkg/install/kamelets.go
+++ b/pkg/install/kamelets.go
@@ -90,7 +90,7 @@ func KameletCatalog(ctx context.Context, c client.Client, namespace string) erro
 		}
 		// We may want to throttle the creation of Go routines if the number of bundled Kamelets increases.
 		g.Go(func() error {
-			kamelet, err := loadKamelet(path.Join(kameletDir, f.Name()), namespace, c.GetScheme())
+			kamelet, err := loadKamelet(path.Join(kameletDir, f.Name()), namespace)
 			if err != nil {
 				return err
 			}
@@ -177,22 +177,22 @@ func isIncompatibleServerError(err error) bool {
 	return false
 }
 
-func loadKamelet(path string, namespace string, scheme *runtime.Scheme) (*v1alpha1.Kamelet, error) {
+func loadKamelet(path string, namespace string) (ctrl.Object, error) {
 	content, err := util.ReadFile(path)
 	if err != nil {
 		return nil, err
 	}
 
-	obj, err := kubernetes.LoadResourceFromYaml(scheme, string(content))
+	kamelet, err := kubernetes.LoadUnstructuredFromYaml(string(content))
 	if err != nil {
 		return nil, err
 	}
-	kamelet, ok := obj.(*v1alpha1.Kamelet)
-	if !ok {
-		return nil, fmt.Errorf("cannot load Kamelet from file %q", path)
+	gvk := kamelet.GetObjectKind().GroupVersionKind()
+	if gvk.Group != v1alpha1.SchemeGroupVersion.Group || gvk.Kind != "Kamelet" {
+		return nil, fmt.Errorf("file %q does not define a Kamelet", path)
 	}
 
-	kamelet.Namespace = namespace
+	kamelet.SetNamespace(namespace)
 
 	if kamelet.GetAnnotations() == nil {
 		kamelet.SetAnnotations(make(map[string]string))
diff --git a/pkg/util/kubernetes/loader.go b/pkg/util/kubernetes/loader.go
index ad4217b..e076eab 100644
--- a/pkg/util/kubernetes/loader.go
+++ b/pkg/util/kubernetes/loader.go
@@ -29,7 +29,7 @@ import (
 	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
 )
 
-// LoadResourceFromYaml loads a k8s resource from a yaml definition.
+// LoadResourceFromYaml returns a Kubernetes resource from its serialized YAML definition.
 func LoadResourceFromYaml(scheme *runtime.Scheme, data string) (ctrl.Object, error) {
 	source := []byte(data)
 	jsonSource, err := yaml.ToJSON(source)
@@ -53,19 +53,18 @@ func LoadResourceFromYaml(scheme *runtime.Scheme, data string) (ctrl.Object, err
 	return o, nil
 }
 
-// LoadRawResourceFromYaml loads a k8s resource from a yaml definition without making assumptions on the underlying type.
-func LoadRawResourceFromYaml(data string) (runtime.Object, error) {
-	source := []byte(data)
-	jsonSource, err := yaml.ToJSON(source)
+// LoadUnstructuredFromYaml returns an unstructured resource from its serialized YAML definition.
+func LoadUnstructuredFromYaml(data string) (ctrl.Object, error) {
+	source, err := yaml.ToJSON([]byte(data))
 	if err != nil {
 		return nil, err
 	}
-	var objmap map[string]interface{}
-	if err = json.Unmarshal(jsonSource, &objmap); err != nil {
+	var obj map[string]interface{}
+	if err = json.Unmarshal(source, &obj); err != nil {
 		return nil, err
 	}
 	return &unstructured.Unstructured{
-		Object: objmap,
+		Object: obj,
 	}, nil
 }
 

[camel-k] 03/03: fix: Use Kamelet serialized JSON as merge patch for client-side apply

Posted by as...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

astefanutti pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 467a69774d0756d2b15c32244b1dc55c90926ab6
Author: Antonin Stefanutti <an...@stefanutti.fr>
AuthorDate: Tue Jan 18 11:46:58 2022 +0100

    fix: Use Kamelet serialized JSON as merge patch for client-side apply
---
 pkg/install/kamelets.go | 18 ++++--------------
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/pkg/install/kamelets.go b/pkg/install/kamelets.go
index 024341c..6bd15f4 100644
--- a/pkg/install/kamelets.go
+++ b/pkg/install/kamelets.go
@@ -19,6 +19,7 @@ package install
 
 import (
 	"context"
+	"encoding/json"
 	"errors"
 	"fmt"
 	"io/fs"
@@ -33,7 +34,6 @@ import (
 	"golang.org/x/sync/errgroup"
 
 	k8serrors "k8s.io/apimachinery/pkg/api/errors"
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/types"
 
@@ -139,26 +139,16 @@ func serverSideApply(ctx context.Context, c client.Client, resource runtime.Obje
 }
 
 func clientSideApply(ctx context.Context, c client.Client, resource ctrl.Object) error {
-	err := c.Create(ctx, resource)
-	if err == nil {
+	if err := c.Create(ctx, resource); err == nil {
 		return nil
 	} else if !k8serrors.IsAlreadyExists(err) {
 		return fmt.Errorf("error during create resource: %s/%s: %w", resource.GetNamespace(), resource.GetName(), err)
 	}
-	object := &unstructured.Unstructured{}
-	object.SetNamespace(resource.GetNamespace())
-	object.SetName(resource.GetName())
-	object.SetGroupVersionKind(resource.GetObjectKind().GroupVersionKind())
-	err = c.Get(ctx, ctrl.ObjectKeyFromObject(object), object)
+	// Directly use the serialized resource as JSON merge patch since it's prescriptive
+	p, err := json.Marshal(resource)
 	if err != nil {
 		return err
 	}
-	p, err := patch.MergePatch(object, resource)
-	if err != nil {
-		return err
-	} else if len(p) == 0 {
-		return nil
-	}
 	return c.Patch(ctx, resource, ctrl.RawPatch(types.MergePatchType, p))
 }
 

[camel-k] 01/03: fix(patch): Do not compute positive patch for unstructured object

Posted by as...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

astefanutti pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 436a34ff835dcc8a1e31d116475f1ff7c0849f9f
Author: Antonin Stefanutti <an...@stefanutti.fr>
AuthorDate: Mon Jan 17 19:10:26 2022 +0100

    fix(patch): Do not compute positive patch for unstructured object
---
 e2e/support/test_support.go                 |  4 +-
 pkg/client/apply.go                         |  4 +-
 pkg/cmd/builder/builder.go                  |  2 +-
 pkg/cmd/install.go                          |  2 +-
 pkg/controller/build/monitor_routine.go     |  2 +-
 pkg/controller/kameletbinding/initialize.go |  2 +-
 pkg/install/kamelets.go                     |  4 +-
 pkg/install/operator.go                     |  2 +-
 pkg/trait/deployer.go                       |  6 +--
 pkg/util/patch/patch.go                     | 75 +++++++++++++++--------------
 10 files changed, 53 insertions(+), 50 deletions(-)

diff --git a/e2e/support/test_support.go b/e2e/support/test_support.go
index 319ab49..1a69db0 100644
--- a/e2e/support/test_support.go
+++ b/e2e/support/test_support.go
@@ -701,7 +701,7 @@ func PatchIntegration(ns string, name string, mutate func(it *v1.Integration)) e
 	}
 	target := it.DeepCopy()
 	mutate(target)
-	p, err := patch.PositiveMergePatch(it, target)
+	p, err := patch.MergePatch(it, target)
 	if err != nil {
 		return err
 	} else if len(p) == 0 {
@@ -774,7 +774,7 @@ func UpdateKameletBinding(ns string, name string, upd func(it *v1alpha1.KameletB
 	target := klb.DeepCopy()
 	upd(target)
 	// For some reasons, full patch fails on some clusters
-	p, err := patch.PositiveMergePatch(klb, target)
+	p, err := patch.MergePatch(klb, target)
 	if err != nil {
 		return err
 	} else if len(p) == 0 {
diff --git a/pkg/client/apply.go b/pkg/client/apply.go
index cfcc2c6..2a63bc2 100644
--- a/pkg/client/apply.go
+++ b/pkg/client/apply.go
@@ -77,7 +77,7 @@ func (a *ServerOrClientSideApplier) Apply(ctx context.Context, object ctrl.Objec
 }
 
 func (a *ServerOrClientSideApplier) serverSideApply(ctx context.Context, resource runtime.Object) error {
-	target, err := patch.PositiveApplyPatch(resource)
+	target, err := patch.ApplyPatch(resource)
 	if err != nil {
 		return err
 	}
@@ -99,7 +99,7 @@ func (a *ServerOrClientSideApplier) clientSideApply(ctx context.Context, resourc
 	if err != nil {
 		return err
 	}
-	p, err := patch.PositiveMergePatch(object, resource)
+	p, err := patch.MergePatch(object, resource)
 	if err != nil {
 		return err
 	} else if len(p) == 0 {
diff --git a/pkg/cmd/builder/builder.go b/pkg/cmd/builder/builder.go
index bd22ddf..390a535 100644
--- a/pkg/cmd/builder/builder.go
+++ b/pkg/cmd/builder/builder.go
@@ -78,7 +78,7 @@ func Run(namespace string, buildName string, taskName string) {
 	// is made on the build containers.
 	target.Status.Phase = v1.BuildPhaseNone
 	// Patch the build status with the result
-	p, err := patch.PositiveMergePatch(build, target)
+	p, err := patch.MergePatch(build, target)
 	exitOnError(err, "cannot create merge patch")
 
 	if len(p) > 0 {
diff --git a/pkg/cmd/install.go b/pkg/cmd/install.go
index f3869dd..878c15d 100644
--- a/pkg/cmd/install.go
+++ b/pkg/cmd/install.go
@@ -715,7 +715,7 @@ func createDefaultMavenSettingsConfigMap(ctx context.Context, client client.Clie
 			return err
 		}
 
-		p, err := patch.PositiveMergePatch(existing, cm)
+		p, err := patch.MergePatch(existing, cm)
 		if err != nil {
 			return err
 		} else if len(p) != 0 {
diff --git a/pkg/controller/build/monitor_routine.go b/pkg/controller/build/monitor_routine.go
index f9d0083..92e55af 100644
--- a/pkg/controller/build/monitor_routine.go
+++ b/pkg/controller/build/monitor_routine.go
@@ -186,7 +186,7 @@ func (action *monitorRoutineAction) updateBuildStatus(ctx context.Context, build
 	// Copy the failure field from the build to persist recovery state
 	target.Status.Failure = build.Status.Failure
 	// Patch the build status with the result
-	p, err := patch.PositiveMergePatch(build, target)
+	p, err := patch.MergePatch(build, target)
 	if err != nil {
 		action.L.Errorf(err, "Cannot patch build status: %s", build.Name)
 		event.NotifyBuildError(ctx, action.client, action.recorder, build, target, err)
diff --git a/pkg/controller/kameletbinding/initialize.go b/pkg/controller/kameletbinding/initialize.go
index d65656a..3f85198 100644
--- a/pkg/controller/kameletbinding/initialize.go
+++ b/pkg/controller/kameletbinding/initialize.go
@@ -85,7 +85,7 @@ func (action *initializeAction) propagateIcon(ctx context.Context, binding *v1al
 	if _, ok := clone.Annotations[v1alpha1.AnnotationIcon]; !ok {
 		clone.Annotations[v1alpha1.AnnotationIcon] = icon
 	}
-	p, err := patch.PositiveMergePatch(binding, clone)
+	p, err := patch.MergePatch(binding, clone)
 	if err != nil {
 		action.L.Errorf(err, "cannot compute patch to update icon for kamelet binding %q", binding.Name)
 		return
diff --git a/pkg/install/kamelets.go b/pkg/install/kamelets.go
index 82a818b..f910436 100644
--- a/pkg/install/kamelets.go
+++ b/pkg/install/kamelets.go
@@ -131,7 +131,7 @@ func KameletCatalog(ctx context.Context, c client.Client, namespace string) erro
 }
 
 func serverSideApply(ctx context.Context, c client.Client, resource runtime.Object) error {
-	target, err := patch.PositiveApplyPatch(resource)
+	target, err := patch.ApplyPatch(resource)
 	if err != nil {
 		return err
 	}
@@ -153,7 +153,7 @@ func clientSideApply(ctx context.Context, c client.Client, resource ctrl.Object)
 	if err != nil {
 		return err
 	}
-	p, err := patch.PositiveMergePatch(object, resource)
+	p, err := patch.MergePatch(object, resource)
 	if err != nil {
 		return err
 	} else if len(p) == 0 {
diff --git a/pkg/install/operator.go b/pkg/install/operator.go
index 33b8371..d602bb5 100644
--- a/pkg/install/operator.go
+++ b/pkg/install/operator.go
@@ -368,7 +368,7 @@ func installClusterRoleBinding(ctx context.Context, c client.Client, collection
 	// The ClusterRoleBinding.Subjects field does not have a patchStrategy key in its field tag,
 	// so a strategic merge patch would use the default patch strategy, which is replace.
 	// Let's compute a simple JSON merge patch from the existing resource, and patch it.
-	p, err := patch.PositiveMergePatch(existing, target)
+	p, err := patch.MergePatch(existing, target)
 	if err != nil {
 		return err
 	} else if len(p) == 0 {
diff --git a/pkg/trait/deployer.go b/pkg/trait/deployer.go
index 67cdb79..8bc3b23 100644
--- a/pkg/trait/deployer.go
+++ b/pkg/trait/deployer.go
@@ -62,7 +62,7 @@ func (t *deployerTrait) Apply(e *Environment) error {
 	e.PostActions = append(e.PostActions, func(env *Environment) error {
 		for _, resource := range env.Resources.Items() {
 			// We assume that server-side apply is enabled by default.
-			// It is currently convoluted to check pro-actively whether server-side apply
+			// It is currently convoluted to check proactively whether server-side apply
 			// is enabled. This is possible to fetch the OpenAPI endpoint, which returns
 			// the entire server API document, then lookup the resource PATCH endpoint, and
 			// check its list of accepted MIME types.
@@ -92,7 +92,7 @@ func (t *deployerTrait) Apply(e *Environment) error {
 }
 
 func (t *deployerTrait) serverSideApply(env *Environment, resource ctrl.Object) error {
-	target, err := patch.PositiveApplyPatch(resource)
+	target, err := patch.ApplyPatch(resource)
 	if err != nil {
 		return err
 	}
@@ -119,7 +119,7 @@ func (t *deployerTrait) clientSideApply(env *Environment, resource ctrl.Object)
 	if err != nil {
 		return err
 	}
-	p, err := patch.PositiveMergePatch(object, resource)
+	p, err := patch.MergePatch(object, resource)
 	if err != nil {
 		return err
 	} else if len(p) == 0 {
diff --git a/pkg/util/patch/patch.go b/pkg/util/patch/patch.go
index b672459..b7ad290 100644
--- a/pkg/util/patch/patch.go
+++ b/pkg/util/patch/patch.go
@@ -27,60 +27,63 @@ import (
 	"k8s.io/apimachinery/pkg/util/json"
 )
 
-func PositiveMergePatch(source interface{}, target interface{}) ([]byte, error) {
+func MergePatch(source interface{}, target interface{}) ([]byte, error) {
 	sourceJSON, err := json.Marshal(source)
 	if err != nil {
 		return nil, err
 	}
-
 	targetJSON, err := json.Marshal(target)
 	if err != nil {
 		return nil, err
 	}
-
 	mergePatch, err := jsonpatch.CreateMergePatch(sourceJSON, targetJSON)
 	if err != nil {
 		return nil, err
 	}
 
-	var positivePatch map[string]interface{}
-	err = json.Unmarshal(mergePatch, &positivePatch)
-	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.
-	removeNilValues(reflect.ValueOf(positivePatch), reflect.Value{})
-
-	// Return an empty patch if no keys remain
-	if len(positivePatch) == 0 {
-		return make([]byte, 0), nil
+	switch target.(type) {
+	case *unstructured.Unstructured:
+		// Take the JSON merge patch as is for unstructured objects
+		return mergePatch, nil
+	default:
+		// Otherwise, for typed objects, remove null fields from the JSON merge patch,
+		// so that values managed by controllers server-side are not deleted.
+		var positivePatch map[string]interface{}
+		err = json.Unmarshal(mergePatch, &positivePatch)
+		if err != nil {
+			return nil, err
+		}
+		removeNilValues(reflect.ValueOf(positivePatch), reflect.Value{})
+		// Return an empty patch if no keys remain
+		if len(positivePatch) == 0 {
+			return make([]byte, 0), nil
+		}
+		return json.Marshal(positivePatch)
 	}
-
-	return json.Marshal(positivePatch)
 }
 
-func PositiveApplyPatch(source runtime.Object) (*unstructured.Unstructured, error) {
-	sourceJSON, err := json.Marshal(source)
-	if err != nil {
-		return nil, err
-	}
+func ApplyPatch(source runtime.Object) (*unstructured.Unstructured, error) {
+	switch s := source.(type) {
+	case *unstructured.Unstructured:
+		// Directly take the unstructured object as apply patch
+		return s, nil
+	default:
+		// Otherwise, for typed objects, remove null fields from the apply patch,
+		// so that ownership is not taken for non-managed fields.
+		// See https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/2155-clientgo-apply
+		sourceJSON, err := json.Marshal(source)
+		if err != nil {
+			return nil, err
+		}
+		var positivePatch map[string]interface{}
+		err = json.Unmarshal(sourceJSON, &positivePatch)
+		if err != nil {
+			return nil, err
+		}
+		removeNilValues(reflect.ValueOf(positivePatch), reflect.Value{})
 
-	var positivePatch map[string]interface{}
-	err = json.Unmarshal(sourceJSON, &positivePatch)
-	if err != nil {
-		return nil, err
+		return &unstructured.Unstructured{Object: positivePatch}, nil
 	}
-
-	// The following is a work-around to remove null fields from the apply patch,
-	// so that ownership is not taken for non-managed fields.
-	// See https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/2155-clientgo-apply
-	removeNilValues(reflect.ValueOf(positivePatch), reflect.Value{})
-
-	return &unstructured.Unstructured{Object: positivePatch}, nil
 }
 
 func removeNilValues(v reflect.Value, parent reflect.Value) {