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.ferr...@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