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 2021/12/09 13:25:35 UTC

[camel-k] 02/02: chore: Try SSA for Kamelet install only once

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 23401b21aebd9b26aaa3f4152813a4c1c718536b
Author: Antonin Stefanutti <an...@stefanutti.fr>
AuthorDate: Thu Dec 9 12:29:46 2021 +0100

    chore: Try SSA for Kamelet install only once
---
 pkg/install/kamelets.go | 116 ++++++++++++++++++++++++++----------------------
 1 file changed, 63 insertions(+), 53 deletions(-)

diff --git a/pkg/install/kamelets.go b/pkg/install/kamelets.go
index 5712b55..82a818b 100644
--- a/pkg/install/kamelets.go
+++ b/pkg/install/kamelets.go
@@ -27,6 +27,7 @@ import (
 	"path"
 	"path/filepath"
 	"strings"
+	"sync"
 	"sync/atomic"
 
 	"golang.org/x/sync/errgroup"
@@ -56,12 +57,9 @@ var (
 	log = logf.Log
 
 	hasServerSideApply atomic.Value
+	tryServerSideApply sync.Once
 )
 
-func init() {
-	hasServerSideApply.Store(true)
-}
-
 // KameletCatalog installs the bundled Kamelets into the specified namespace.
 func KameletCatalog(ctx context.Context, c client.Client, namespace string) error {
 	kameletDir := os.Getenv(kameletDirEnv)
@@ -92,7 +90,36 @@ 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 {
-			return applyKamelet(gCtx, c, path.Join(kameletDir, f.Name()), namespace)
+			kamelet, err := loadKamelet(path.Join(kameletDir, f.Name()), namespace, c.GetScheme())
+			if err != nil {
+				return err
+			}
+			once := false
+			tryServerSideApply.Do(func() {
+				once = true
+				if err = serverSideApply(gCtx, c, kamelet); err != nil {
+					if isIncompatibleServerError(err) {
+						log.Info("Fallback to client-side apply for installing bundled Kamelets")
+						hasServerSideApply.Store(false)
+						err = nil
+					} else {
+						tryServerSideApply = sync.Once{}
+					}
+				} else {
+					hasServerSideApply.Store(true)
+				}
+			})
+			if err != nil {
+				return err
+			}
+			if v := hasServerSideApply.Load(); v.(bool) {
+				if !once {
+					return serverSideApply(gCtx, c, kamelet)
+				}
+			} else {
+				return clientSideApply(gCtx, c, kamelet)
+			}
+			return nil
 		})
 		return nil
 	})
@@ -103,54 +130,6 @@ func KameletCatalog(ctx context.Context, c client.Client, namespace string) erro
 	return g.Wait()
 }
 
-func applyKamelet(ctx context.Context, c client.Client, path string, namespace string) error {
-	content, err := util.ReadFile(path)
-	if err != nil {
-		return err
-	}
-
-	obj, err := kubernetes.LoadResourceFromYaml(c.GetScheme(), string(content))
-	if err != nil {
-		return err
-	}
-	kamelet, ok := obj.(*v1alpha1.Kamelet)
-	if !ok {
-		return fmt.Errorf("cannot load Kamelet from file %q", path)
-	}
-
-	kamelet.Namespace = namespace
-
-	if kamelet.GetAnnotations() == nil {
-		kamelet.SetAnnotations(make(map[string]string))
-	}
-	kamelet.GetAnnotations()[kamelVersionAnnotation] = defaults.Version
-
-	if kamelet.GetLabels() == nil {
-		kamelet.SetLabels(make(map[string]string))
-	}
-	kamelet.GetLabels()[v1alpha1.KameletBundledLabel] = "true"
-	kamelet.GetLabels()[v1alpha1.KameletReadOnlyLabel] = "true"
-
-	if v := hasServerSideApply.Load(); v.(bool) {
-		err := serverSideApply(ctx, c, kamelet)
-		switch {
-		case err == nil:
-			return nil
-		case isIncompatibleServerError(err):
-			log.Info("Fallback to client-side apply for installing bundled Kamelets")
-			hasServerSideApply.Store(false)
-		default:
-			return fmt.Errorf("could not apply Kamelet from file %q: %w", path, err)
-		}
-	}
-	err = clientSideApply(ctx, c, kamelet)
-	if err != nil {
-		return fmt.Errorf("could not apply Kamelet from file %q: %w", path, err)
-	}
-
-	return nil
-}
-
 func serverSideApply(ctx context.Context, c client.Client, resource runtime.Object) error {
 	target, err := patch.PositiveApplyPatch(resource)
 	if err != nil {
@@ -198,6 +177,37 @@ func isIncompatibleServerError(err error) bool {
 	return false
 }
 
+func loadKamelet(path string, namespace string, scheme *runtime.Scheme) (*v1alpha1.Kamelet, error) {
+	content, err := util.ReadFile(path)
+	if err != nil {
+		return nil, err
+	}
+
+	obj, err := kubernetes.LoadResourceFromYaml(scheme, 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)
+	}
+
+	kamelet.Namespace = namespace
+
+	if kamelet.GetAnnotations() == nil {
+		kamelet.SetAnnotations(make(map[string]string))
+	}
+	kamelet.GetAnnotations()[kamelVersionAnnotation] = defaults.Version
+
+	if kamelet.GetLabels() == nil {
+		kamelet.SetLabels(make(map[string]string))
+	}
+	kamelet.GetLabels()[v1alpha1.KameletBundledLabel] = "true"
+	kamelet.GetLabels()[v1alpha1.KameletReadOnlyLabel] = "true"
+
+	return kamelet, nil
+}
+
 // KameletViewerRole installs the role that allows any user ro access kamelets in the global namespace.
 func KameletViewerRole(ctx context.Context, c client.Client, namespace string) error {
 	if err := Resource(ctx, c, namespace, true, IdentityResourceCustomizer, "/viewer/user-global-kamelet-viewer-role.yaml"); err != nil {