You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2022/06/20 07:13:48 UTC

[camel-k] 03/04: chore(cli): polished promote feature

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

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

commit fa3479b34c10728873299356687aeef043207548
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Thu Jun 16 17:24:30 2022 +0200

    chore(cli): polished promote feature
---
 pkg/cmd/promote.go        | 91 ++++++++++++++++++++++++++++++-----------------
 pkg/trait/kamelets.go     | 24 +++----------
 pkg/trait/mount.go        |  2 +-
 pkg/util/kamelets/util.go | 56 +++++++++++++++++++++++++++++
 4 files changed, 119 insertions(+), 54 deletions(-)

diff --git a/pkg/cmd/promote.go b/pkg/cmd/promote.go
index b24eafd80..28be8b28b 100644
--- a/pkg/cmd/promote.go
+++ b/pkg/cmd/promote.go
@@ -27,11 +27,10 @@ import (
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	"github.com/apache/camel-k/pkg/client"
-	"github.com/apache/camel-k/pkg/metadata"
-	"github.com/apache/camel-k/pkg/util"
 	"github.com/apache/camel-k/pkg/util/camel"
+	"github.com/apache/camel-k/pkg/util/kamelets"
 	"github.com/apache/camel-k/pkg/util/kubernetes"
-	"github.com/apache/camel-k/pkg/util/source"
+	"github.com/apache/camel-k/pkg/util/resource"
 	"github.com/spf13/cobra"
 	corev1 "k8s.io/api/core/v1"
 	k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
@@ -120,7 +119,7 @@ func checkOpsCompatibility(cmd *cobra.Command, source, dest map[string]string) e
 	if !compatibleVersions(source["Runtime Version"], dest["Runtime Version"], cmd) {
 		return fmt.Errorf("source (%s) and destination (%s) Camel K runtime versions are not compatible", source["Runtime Version"], dest["Runtime Version"])
 	}
-	if source["Registry Address"] != source["Registry Address"] {
+	if source["Registry Address"] != dest["Registry Address"] {
 		return fmt.Errorf("source (%s) and destination (%s) Camel K container images registries are not the same", source["Registry Address"], dest["Registry Address"])
 	}
 
@@ -148,27 +147,52 @@ func (o *promoteCmdOptions) validateDestResources(c client.Client, it *v1.Integr
 	var kamelets []string
 	// Mount trait
 	mounts := it.Spec.Traits["mount"]
-	json.Unmarshal(mounts.Configuration.RawMessage, &traits)
+	if err := json.Unmarshal(mounts.Configuration.RawMessage, &traits); err != nil {
+		return err
+	}
 	for t, v := range traits {
-		if t == "configs" || t == "resources" {
+		switch t {
+		case "configs":
 			for _, c := range v {
-				//TODO proper parse resources, now it does not account for complex parsing
-				if strings.HasPrefix(c, "configmap:") {
-					configmaps = append(configmaps, strings.Split(c, ":")[1])
+				if conf, parseErr := resource.ParseConfig(c); parseErr == nil {
+					if conf.StorageType() == resource.StorageTypeConfigmap {
+						configmaps = append(configmaps, conf.Name())
+					} else if conf.StorageType() == resource.StorageTypeSecret {
+						secrets = append(secrets, conf.Name())
+					}
+				} else {
+					return parseErr
 				}
-				if strings.HasPrefix(c, "secret:") {
-					secrets = append(secrets, strings.Split(c, ":")[1])
+			}
+		case "resources":
+			for _, c := range v {
+				if conf, parseErr := resource.ParseResource(c); parseErr == nil {
+					if conf.StorageType() == resource.StorageTypeConfigmap {
+						configmaps = append(configmaps, conf.Name())
+					} else if conf.StorageType() == resource.StorageTypeSecret {
+						secrets = append(secrets, conf.Name())
+					}
+				} else {
+					return parseErr
 				}
 			}
-		} else if t == "volumes" {
+		case "volumes":
 			for _, c := range v {
-				pvcs = append(pvcs, strings.Split(c, ":")[0])
+				if conf, parseErr := resource.ParseVolume(c); parseErr == nil {
+					if conf.StorageType() == resource.StorageTypePVC {
+						pvcs = append(pvcs, conf.Name())
+					}
+				} else {
+					return parseErr
+				}
 			}
 		}
 	}
 	// Openapi trait
 	openapis := it.Spec.Traits["openapi"]
-	json.Unmarshal(openapis.Configuration.RawMessage, &traits)
+	if err := json.Unmarshal(openapis.Configuration.RawMessage, &traits); err != nil {
+		return err
+	}
 	for k, v := range traits {
 		for _, c := range v {
 			if k == "configmaps" {
@@ -177,7 +201,17 @@ func (o *promoteCmdOptions) validateDestResources(c client.Client, it *v1.Integr
 		}
 	}
 	// Kamelet trait
-	kamelets = o.listKamelets(c, it)
+	kameletTrait := it.Spec.Traits["kamelets"]
+	var kameletListTrait map[string]string
+	if err := json.Unmarshal(kameletTrait.Configuration.RawMessage, &kameletListTrait); err != nil {
+		return err
+	}
+	kamelets = strings.Split(kameletListTrait["list"], ",")
+	sourceKamelets, err := o.listKamelets(c, it)
+	if err != nil {
+		return err
+	}
+	kamelets = append(kamelets, sourceKamelets...)
 
 	anyError := false
 	var errorTrace string
@@ -213,23 +247,14 @@ func (o *promoteCmdOptions) validateDestResources(c client.Client, it *v1.Integr
 	return nil
 }
 
-func (o *promoteCmdOptions) listKamelets(c client.Client, it *v1.Integration) []string {
-	// TODO collect any kamelets which may be coming into the kamelet trait as well
-	var kamelets []string
-
-	sources, _ := kubernetes.ResolveIntegrationSources(o.Context, c, it, &kubernetes.Collection{})
-	catalog, _ := camel.DefaultCatalog()
-	metadata.Each(catalog, sources, func(_ int, meta metadata.IntegrationMetadata) bool {
-		util.StringSliceUniqueConcat(&kamelets, meta.Kamelets)
-		return true
-	})
-
-	// Check if a Kamelet is configured as default error handler URI
-	defaultErrorHandlerURI := it.Spec.GetConfigurationProperty(v1alpha1.ErrorHandlerAppPropertiesPrefix + ".deadLetterUri")
-	if defaultErrorHandlerURI != "" {
-		if strings.HasPrefix(defaultErrorHandlerURI, "kamelet:") {
-			kamelets = append(kamelets, source.ExtractKamelet(defaultErrorHandlerURI))
-		}
+func (o *promoteCmdOptions) listKamelets(c client.Client, it *v1.Integration) ([]string, error) {
+	catalog, err := camel.DefaultCatalog()
+	if err != nil {
+		return nil, err
+	}
+	kamelets, err := kamelets.ExtractKameletFromSources(o.Context, c, catalog, &kubernetes.Collection{}, it)
+	if err != nil {
+		return nil, err
 	}
 
 	// We must remove any default source/sink
@@ -240,7 +265,7 @@ func (o *promoteCmdOptions) listKamelets(c client.Client, it *v1.Integration) []
 		}
 	}
 
-	return filtered
+	return filtered, nil
 }
 
 func existsCm(ctx context.Context, c client.Client, name string, namespace string) bool {
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index a5c1c936b..f8873cd7d 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -31,13 +31,11 @@ import (
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	kameletutils "github.com/apache/camel-k/pkg/kamelet"
 	"github.com/apache/camel-k/pkg/kamelet/repository"
-	"github.com/apache/camel-k/pkg/metadata"
 	"github.com/apache/camel-k/pkg/platform"
 	"github.com/apache/camel-k/pkg/util"
 	"github.com/apache/camel-k/pkg/util/digest"
 	"github.com/apache/camel-k/pkg/util/dsl"
-	"github.com/apache/camel-k/pkg/util/kubernetes"
-	"github.com/apache/camel-k/pkg/util/source"
+	"github.com/apache/camel-k/pkg/util/kamelets"
 )
 
 // The kamelets trait is a platform trait used to inject Kamelets into the integration runtime.
@@ -91,23 +89,9 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 	}
 
 	if IsNilOrTrue(t.Auto) {
-		var kamelets []string
-		if t.List == "" {
-			sources, err := kubernetes.ResolveIntegrationSources(e.Ctx, e.Client, e.Integration, e.Resources)
-			if err != nil {
-				return false, err
-			}
-			metadata.Each(e.CamelCatalog, sources, func(_ int, meta metadata.IntegrationMetadata) bool {
-				util.StringSliceUniqueConcat(&kamelets, meta.Kamelets)
-				return true
-			})
-		}
-		// Check if a Kamelet is configured as default error handler URI
-		defaultErrorHandlerURI := e.Integration.Spec.GetConfigurationProperty(v1alpha1.ErrorHandlerAppPropertiesPrefix + ".deadLetterUri")
-		if defaultErrorHandlerURI != "" {
-			if strings.HasPrefix(defaultErrorHandlerURI, "kamelet:") {
-				kamelets = append(kamelets, source.ExtractKamelet(defaultErrorHandlerURI))
-			}
+		kamelets, err := kamelets.ExtractKameletFromSources(e.Ctx, e.Client, e.CamelCatalog, e.Resources, e.Integration)
+		if err != nil {
+			return false, err
 		}
 
 		if len(kamelets) > 0 {
diff --git a/pkg/trait/mount.go b/pkg/trait/mount.go
index 6c8976a85..81d58c50f 100644
--- a/pkg/trait/mount.go
+++ b/pkg/trait/mount.go
@@ -43,7 +43,7 @@ type mountTrait struct {
 	// A list of configuration pointing to configmap/secret.
 	// The configuration are expected to be UTF-8 resources as they are processed by runtime Camel Context and tried to be parsed as property files.
 	// They are also made available on the classpath in order to ease their usage directly from the Route.
-	// Syntax: [configmap|secret]:name[key], where name represents the resource name and key optionally represents the resource key to be filtered
+	// Syntax: [configmap|secret]:name[/key], where name represents the resource name and key optionally represents the resource key to be filtered
 	Configs []string `property:"configs" json:"configs,omitempty"`
 	// A list of resources (text or binary content) pointing to configmap/secret.
 	// The resources are expected to be any resource type (text or binary content).
diff --git a/pkg/util/kamelets/util.go b/pkg/util/kamelets/util.go
new file mode 100644
index 000000000..2db03c7fc
--- /dev/null
+++ b/pkg/util/kamelets/util.go
@@ -0,0 +1,56 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package kamelets
+
+import (
+	"context"
+	"strings"
+
+	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/client"
+	"github.com/apache/camel-k/pkg/metadata"
+	"github.com/apache/camel-k/pkg/util"
+	"github.com/apache/camel-k/pkg/util/camel"
+	"github.com/apache/camel-k/pkg/util/kubernetes"
+	"github.com/apache/camel-k/pkg/util/source"
+)
+
+// ExtractKameletFromSources provide a list of Kamelets referred into the Integration sources.
+func ExtractKameletFromSources(context context.Context, c client.Client, catalog *camel.RuntimeCatalog, resources *kubernetes.Collection, it *v1.Integration) ([]string, error) {
+	var kamelets []string
+
+	sources, err := kubernetes.ResolveIntegrationSources(context, c, it, resources)
+	if err != nil {
+		return nil, err
+	}
+	metadata.Each(catalog, sources, func(_ int, meta metadata.IntegrationMetadata) bool {
+		util.StringSliceUniqueConcat(&kamelets, meta.Kamelets)
+		return true
+	})
+
+	// Check if a Kamelet is configured as default error handler URI
+	defaultErrorHandlerURI := it.Spec.GetConfigurationProperty(v1alpha1.ErrorHandlerAppPropertiesPrefix + ".deadLetterUri")
+	if defaultErrorHandlerURI != "" {
+		if strings.HasPrefix(defaultErrorHandlerURI, "kamelet:") {
+			kamelets = append(kamelets, source.ExtractKamelet(defaultErrorHandlerURI))
+		}
+	}
+
+	return kamelets, nil
+}