You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2021/07/06 15:28:45 UTC

[camel-kamelets] branch main updated: chore(validator): additional checks on kamelets and fix infinispan source

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

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


The following commit(s) were added to refs/heads/main by this push:
     new d3d82d9  chore(validator): additional checks on kamelets and fix infinispan source
d3d82d9 is described below

commit d3d82d90a96d8fabe2ffc481b5e5ea3d6e4ff2cd
Author: nicolaferraro <ni...@gmail.com>
AuthorDate: Tue Jul 6 17:18:41 2021 +0200

    chore(validator): additional checks on kamelets and fix infinispan source
---
 infinispan-source.kamelet.yaml |  6 ++-
 script/validator/validator.go  | 94 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 99 insertions(+), 1 deletion(-)

diff --git a/infinispan-source.kamelet.yaml b/infinispan-source.kamelet.yaml
index aaf6f50..7ea50c2 100644
--- a/infinispan-source.kamelet.yaml
+++ b/infinispan-source.kamelet.yaml
@@ -25,12 +25,16 @@ spec:
     description: |-
       Get Events from an Infinispan cache
     required:
+      - cacheName
       - hosts
       - username
       - password
-      - hosts
     type: object
     properties:
+      cacheName:
+        title: Cache Name
+        description: The name of the Infinispan cache to use
+        type: String
       hosts:
         title: Hosts
         description: Specifies the host of the cache on Infinispan instance
diff --git a/script/validator/validator.go b/script/validator/validator.go
index 4d6ebcf..a224957 100644
--- a/script/validator/validator.go
+++ b/script/validator/validator.go
@@ -6,6 +6,7 @@ import (
 	"os"
 	"path"
 	"path/filepath"
+	"regexp"
 	"sort"
 	"strings"
 
@@ -29,6 +30,8 @@ import (
 var (
 	// Needed until this is fixed: https://issues.apache.org/jira/browse/CAMEL-16788
 	forbiddenParameterNames = []string{"home", "hostname", "language", "lang", "namespace", "path", "podname", "pod-name", "port", "pwd", "shell", "term"}
+
+	paramRegexp = regexp.MustCompile(`{{[?]?([A-Za-z0-9-._]+)(?:[:][^}]*)?}}`)
 )
 
 func main() {
@@ -49,6 +52,7 @@ func main() {
 	errors = append(errors, verifyDescriptors(kamelets)...)
 	errors = append(errors, verifyDuplicates(kamelets)...)
 	errors = append(errors, verifyMissingDependencies(kamelets)...)
+	errors = append(errors, verifyUsedParams(kamelets)...)
 
 	for _, err := range errors {
 		fmt.Printf("ERROR: %v\n", err)
@@ -203,6 +207,13 @@ func verifyParameters(kamelets []KameletInfo) (errors []error) {
 			errors = append(errors, fmt.Errorf("kamelet %q does not contain the JSON schema definition", kamelet.Name))
 			continue
 		}
+		requiredCheck := make(map[string]bool)
+		for _, p := range kamelet.Spec.Definition.Required {
+			if requiredCheck[p] {
+				errors = append(errors, fmt.Errorf("required kamelet property %q is listed twice in kamelet %q", p, kamelet.Name))
+			}
+			requiredCheck[p] = true
+		}
 		if kamelet.Spec.Definition.Title == "" {
 			errors = append(errors, fmt.Errorf("kamelet %q does not contain title", kamelet.Name))
 		} else {
@@ -359,6 +370,89 @@ func listKamelets(dir string) []KameletInfo {
 	return kamelets
 }
 
+func verifyUsedParams(kamelets []KameletInfo) (errors []error) {
+	for _, k := range kamelets {
+		used := getUsedParams(k.Kamelet)
+		declared := getDeclaredParams(k.Kamelet)
+		for p := range used {
+			if _, ok := declared[p]; !ok {
+				errors = append(errors, fmt.Errorf("parameter %q is not declared in the definition of kamelet %q", p, k.Kamelet.Name))
+			}
+		}
+		for p := range declared {
+			if _, ok := used[p]; !ok {
+				errors = append(errors, fmt.Errorf("parameter %q is declared in kamelet %q but never used", p, k.Kamelet.Name))
+			}
+		}
+	}
+	return errors
+}
+
+func getDeclaredParams(k camelapi.Kamelet) map[string]bool {
+	res := make(map[string]bool)
+	if k.Spec.Definition != nil {
+		for p := range k.Spec.Definition.Properties {
+			res[p] = true
+		}
+	}
+	// include beans
+	var flowData interface{}
+	if err := json.Unmarshal(k.Spec.Flow.RawMessage, &flowData); err != nil {
+		handleGeneralError("cannot unmarshal flow", err)
+	}
+	if fd, ok := flowData.(map[string]interface{}); ok {
+		beans := fd["beans"]
+		if bl, ok := beans.([]interface{}); ok {
+			for _, bdef := range bl {
+				if bmap, ok := bdef.(map[string]interface{}); ok {
+					beanName := bmap["name"]
+					if beanNameStr, ok := beanName.(string); ok {
+						res[beanNameStr] = true
+					}
+				}
+			}
+		}
+	}
+	return res
+}
+
+func getUsedParams(k camelapi.Kamelet) map[string]bool {
+	if k.Spec.Flow != nil {
+		var flowData interface{}
+		if err := json.Unmarshal(k.Spec.Flow.RawMessage, &flowData); err != nil {
+			handleGeneralError("cannot unmarshal flow", err)
+		}
+		params := make(map[string]bool)
+		inspectFlowParams(flowData, params)
+		return params
+	}
+	return nil
+}
+
+func inspectFlowParams(v interface{}, params map[string]bool) {
+	switch val := v.(type) {
+	case string:
+		res := paramRegexp.FindAllStringSubmatch(val, -1)
+		for _, m := range res {
+			if len(m) > 1 {
+				params[m[1]] = true
+			}
+		}
+	case []interface{}:
+		for _, c := range val {
+			inspectFlowParams(c, params)
+		}
+	case map[string]interface{}:
+		for _, c := range val {
+			inspectFlowParams(c, params)
+		}
+	case map[interface{}]interface{}:
+		for _, c := range val {
+			inspectFlowParams(c, params)
+		}
+	}
+}
+
 type KameletInfo struct {
 	camelapi.Kamelet
 	FileName string