Repository: apache/camel-k
Pull request #1279 (2020-02-17 08:11:58)

Fix Quarkus dependency detection
**Release Note**
```release-note
NONE
```



Patch:
diff --git a/pkg/util/source/inspector.go b/pkg/util/source/inspector.go
index 427984953..0f1a21912 100644
--- a/pkg/util/source/inspector.go
+++ b/pkg/util/source/inspector.go
@@ -27,42 +27,53 @@ import (
 )
 
 var (
-	singleQuotedFrom = regexp.MustCompile(`from\s*\(\s*'([a-zA-Z0-9-]+:[^']+)'`)
-	doubleQuotedFrom = regexp.MustCompile(`from\s*\(\s*"([a-zA-Z0-9-]+:[^"]+)"`)
-	singleQuotedTo   = regexp.MustCompile(`\.to\s*\(\s*'([a-zA-Z0-9-]+:[^']+)'`)
-	singleQuotedToD  = regexp.MustCompile(`\.toD\s*\(\s*'([a-zA-Z0-9-]+:[^']+)'`)
-	singleQuotedToF  = regexp.MustCompile(`\.toF\s*\(\s*'([a-zA-Z0-9-]+:[^']+)'`)
-	doubleQuotedTo   = regexp.MustCompile(`\.to\s*\(\s*"([a-zA-Z0-9-]+:[^"]+)"`)
-	doubleQuotedToD  = regexp.MustCompile(`\.toD\s*\(\s*"([a-zA-Z0-9-]+:[^"]+)"`)
-	doubleQuotedToF  = regexp.MustCompile(`\.toF\s*\(\s*"([a-zA-Z0-9-]+:[^"]+)"`)
-	languageRegexp   = regexp.MustCompile(`language\s*\(\s*["|']([a-zA-Z0-9-]+[^"|']+)["|']\s*,.*\)`)
-	camelTypeRegexp  = regexp.MustCompile(`.*(org.apache.camel.*Component|DataFormat|Language)`)
+	singleQuotedFrom        = regexp.MustCompile(`from\s*\(\s*'([a-zA-Z0-9-]+:[^']+)'`)
+	doubleQuotedFrom        = regexp.MustCompile(`from\s*\(\s*"([a-zA-Z0-9-]+:[^"]+)"`)
+	singleQuotedTo          = regexp.MustCompile(`\.to\s*\(\s*'([a-zA-Z0-9-]+:[^']+)'`)
+	singleQuotedToD         = regexp.MustCompile(`\.toD\s*\(\s*'([a-zA-Z0-9-]+:[^']+)'`)
+	singleQuotedToF         = regexp.MustCompile(`\.toF\s*\(\s*'([a-zA-Z0-9-]+:[^']+)'`)
+	doubleQuotedTo          = regexp.MustCompile(`\.to\s*\(\s*"([a-zA-Z0-9-]+:[^"]+)"`)
+	doubleQuotedToD         = regexp.MustCompile(`\.toD\s*\(\s*"([a-zA-Z0-9-]+:[^"]+)"`)
+	doubleQuotedToF         = regexp.MustCompile(`\.toF\s*\(\s*"([a-zA-Z0-9-]+:[^"]+)"`)
+	languageRegexp          = regexp.MustCompile(`language\s*\(\s*["|']([a-zA-Z0-9-]+[^"|']+)["|']\s*,.*\)`)
+	camelTypeRegexp         = regexp.MustCompile(`.*(org.apache.camel.*Component|DataFormat|Language)`)
+	jsonLibraryRegexp       = regexp.MustCompile(`.*JsonLibrary\.Jackson.*`)
+	jsonLanguageRegexp      = regexp.MustCompile(`.*\.json\(\).*`)
+	circuitBreakerRegexp    = regexp.MustCompile(`.*\.circuitBreaker\(\).*`)
+	restConfigurationRegexp = regexp.MustCompile(`.*restConfiguration\(\).*`)
+	restRegexp              = regexp.MustCompile(`.*rest\(("[a-zA-Z0-9-/]+")*\).*`)
+	restXMLRegexp           = regexp.MustCompile(`^\s*rest\s*{.*`)
+	groovyLanguageRegexp    = regexp.MustCompile(`.*\.groovy\s*\(.*\).*`)
+	jsonPathLanguageRegexp  = regexp.MustCompile(`.*\.?(jsonpath|jsonpathWriteAsString)\s*\(.*\).*`)
+	ognlRegexp              = regexp.MustCompile(`.*\.ognl\s*\(.*\).*`)
+	mvelRegexp              = regexp.MustCompile(`.*\.mvel\s*\(.*\).*`)
+	simpleLanguageRegexp    = regexp.MustCompile(`.*\.?simple\s*\(.*\).*`)
+	xqueryRegexp            = regexp.MustCompile(`.*\.xquery\s*\(.*\).*`)
+	xpathRegexp             = regexp.MustCompile(`.*\.?xpath\s*\(.*\).*`)
+	xtokenizeRegexp         = regexp.MustCompile(`.*\.xtokenize\s*\(.*\).*`)
 
 	sourceDependencies = struct {
-		main    map[string]string
-		quarkus map[string]string
+		main    map[*regexp.Regexp]string
+		quarkus map[*regexp.Regexp]string
 	}{
-		main: map[string]string{
-			`.*JsonLibrary\.Jackson.*`:                         "camel:jackson",
-			`.*\.json\(\).*`:                                   "camel:jackson",
-			`.*\.circuitBreaker\(\).*`:                         "camel:hystrix",
-			`.*restConfiguration\(\).*`:                        "camel:rest",
-			`.*rest\(("[a-zA-Z0-9-/]+")*\).*`:                  "camel:rest",
-			`^\s*rest\s*{.*`:                                   "camel:rest",
-			`.*\.groovy\s*\(.*\).*`:                            "camel:groovy",
-			`.*\.?(jsonpath|jsonpathWriteAsString)\s*\(.*\).*`: "camel:jsonpath",
-			`.*\.ognl\s*\(.*\).*`:                              "camel:ognl",
-			`.*\.mvel\s*\(.*\).*`:                              "camel:mvel",
-			`.*\.?simple\s*\(.*\).*`:                           "camel:bean",
-			`.*\.xquery\s*\(.*\).*`:                            "camel:saxon",
-			`.*\.?xpath\s*\(.*\).*`:                            "camel:xpath",
-			`.*\.xtokenize\s*\(.*\).*`:                         "camel:jaxp",
+		main: map[*regexp.Regexp]string{
+			jsonLibraryRegexp:       "camel:jackson",
+			jsonLanguageRegexp:      "camel:jackson",
+			circuitBreakerRegexp:    "camel:hystrix",
+			restConfigurationRegexp: "camel:rest",
+			restRegexp:              "camel:rest",
+			restXMLRegexp:           "camel:rest",
+			groovyLanguageRegexp:    "camel:groovy",
+			jsonPathLanguageRegexp:  "camel:jsonpath",
+			ognlRegexp:              "camel:ognl",
+			mvelRegexp:              "camel:mvel",
+			simpleLanguageRegexp:    "camel:bean",
+			xqueryRegexp:            "camel:saxon",
+			xpathRegexp:             "camel:xpath",
+			xtokenizeRegexp:         "camel:jaxp",
 		},
-		quarkus: map[string]string{
-			`.*restConfiguration\(\).*`:       "camel-quarkus:rest",
-			`.*rest\(("[a-zA-Z0-9-/]+")*\).*`: "camel-quarkus:rest",
-			`^\s*rest\s*{.*`:                  "camel-quarkus:rest",
-			`.*\.?simple\s*\(.*\).*`:          "camel-quarkus:bean",
+		quarkus: map[*regexp.Regexp]string{
+			xtokenizeRegexp: "camel-quarkus:core-xml",
 		},
 	}
 )
@@ -130,27 +141,26 @@ func (i *baseInspector) discoverDependencies(source v1.SourceSpec, meta *Metadat
 	for _, uri := range uris {
 		candidateComp := i.decodeComponent(uri)
 		if candidateComp != "" {
-			meta.Dependencies.Add(candidateComp)
+			i.addDependency(candidateComp, meta)
 		}
 	}
 
-	var additionalDependencies map[string]string
-	if i.catalog.Runtime.Provider == v1.RuntimeProviderQuarkus {
-		additionalDependencies = sourceDependencies.quarkus
-	} else {
-		additionalDependencies = sourceDependencies.main
-	}
-	for pattern, dep := range additionalDependencies {
-		pat := regexp.MustCompile(pattern)
-		if pat.MatchString(source.Content) {
-			meta.Dependencies.Add(dep)
+	for pattern, dep := range sourceDependencies.main {
+		if i.catalog.Runtime.Provider == v1.RuntimeProviderQuarkus {
+			// Check whether quarkus has its own artifact that differs from the standard one
+			if _, ok := sourceDependencies.quarkus[pattern]; ok {
+				dep = sourceDependencies.quarkus[pattern]
+			}
+		}
+		if pattern.MatchString(source.Content) {
+			i.addDependency(dep, meta)
 		}
 	}
 
 	for _, match := range languageRegexp.FindAllStringSubmatch(source.Content, -1) {
 		if len(match) > 1 {
 			if dependency, ok := i.catalog.GetLanguageDependency(match[1]); ok {
-				meta.Dependencies.Add(dependency)
+				i.addDependency(dependency, meta)
 			}
 		}
 	}
@@ -158,12 +168,21 @@ func (i *baseInspector) discoverDependencies(source v1.SourceSpec, meta *Metadat
 	for _, match := range camelTypeRegexp.FindAllStringSubmatch(source.Content, -1) {
 		if len(match) > 1 {
 			if dependency, ok := i.catalog.GetJavaTypeDependency(match[1]); ok {
-				meta.Dependencies.Add(dependency)
+				i.addDependency(dependency, meta)
 			}
 		}
 	}
 }
 
+func (i *baseInspector) addDependency(dependency string, meta *Metadata) {
+	if i.catalog.Runtime.Provider == v1.RuntimeProviderQuarkus {
+		if strings.HasPrefix(dependency, "camel:") {
+			dependency = "camel-quarkus:" + strings.TrimPrefix(dependency, "camel:")
+		}
+	}
+	meta.Dependencies.Add(dependency)
+}
+
 func (i *baseInspector) decodeComponent(uri string) string {
 	uriSplit := strings.SplitN(uri, ":", 2)
 	if len(uriSplit) < 2 {
diff --git a/pkg/util/source/inspector_xml.go b/pkg/util/source/inspector_xml.go
index f68d974cd..952b7991b 100644
--- a/pkg/util/source/inspector_xml.go
+++ b/pkg/util/source/inspector_xml.go
@@ -44,16 +44,16 @@ func (i XMLInspector) Extract(source v1.SourceSpec, meta *Metadata) error {
 		if se, ok := t.(xml.StartElement); ok {
 			switch se.Name.Local {
 			case "rest", "restConfiguration":
-				meta.Dependencies.Add("camel:rest")
+				i.addDependency("camel:rest", meta)
 			case "circuitBreaker":
-				meta.Dependencies.Add("camel:hystrix")
+				i.addDependency("camel:hystrix", meta)
 			case "simple":
-				meta.Dependencies.Add("camel:bean")
+				i.addDependency("camel:bean", meta)
 			case "language":
 				for _, a := range se.Attr {
 					if a.Name.Local == "language" {
 						if dependency, ok := i.catalog.GetLanguageDependency(a.Value); ok {
-							meta.Dependencies.Add(dependency)
+							i.addDependency(dependency, meta)
 						}
 					}
 				}
@@ -72,7 +72,7 @@ func (i XMLInspector) Extract(source v1.SourceSpec, meta *Metadata) error {
 			}
 
 			if dependency, ok := i.catalog.GetLanguageDependency(se.Name.Local); ok {
-				meta.Dependencies.Add(dependency)
+				i.addDependency(dependency, meta)
 			}
 		}
 	}
diff --git a/pkg/util/source/inspector_yaml.go b/pkg/util/source/inspector_yaml.go
index 1a4ed4791..b56f99690 100644
--- a/pkg/util/source/inspector_yaml.go
+++ b/pkg/util/source/inspector_yaml.go
@@ -55,9 +55,9 @@ func (inspector YAMLInspector) Extract(source v1.SourceSpec, meta *Metadata) err
 func (inspector YAMLInspector) parseStep(key string, content interface{}, meta *Metadata) error {
 	switch key {
 	case "rest":
-		meta.Dependencies.Add("camel:rest")
+		inspector.addDependency("camel:rest", meta)
 	case "circuitBreaker":
-		meta.Dependencies.Add("camel:hystrix")
+		inspector.addDependency("camel:hystrix", meta)
 	}
 
 	var maybeURI string
@@ -71,13 +71,13 @@ func (inspector YAMLInspector) parseStep(key string, content interface{}, meta *
 		}
 
 		if _, ok := t["simple"]; ok {
-			meta.Dependencies.Add("camel:bean")
+			inspector.addDependency("camel:bean", meta)
 		}
 
 		if _, ok := t["language"]; ok {
 			if s, ok := t["language"].(string); ok {
 				if dependency, ok := inspector.catalog.GetLanguageDependency(s); ok {
-					meta.Dependencies.Add(dependency)
+					inspector.addDependency(dependency, meta)
 				}
 			} else if m, ok := t["language"].(map[interface{}]interface{}); ok {
 				if err := inspector.parseStep("language", m, meta); err != nil {
@@ -89,7 +89,7 @@ func (inspector YAMLInspector) parseStep(key string, content interface{}, meta *
 		for k := range t {
 			if s, ok := k.(string); ok {
 				if dependency, ok := inspector.catalog.GetLanguageDependency(s); ok {
-					meta.Dependencies.Add(dependency)
+					inspector.addDependency(dependency, meta)
 				}
 			}
 		}


Test patch:
diff --git a/pkg/metadata/metadata_dependencies_test.go b/pkg/metadata/metadata_dependencies_test.go
index 29635e4b9..291259b78 100644
--- a/pkg/metadata/metadata_dependencies_test.go
+++ b/pkg/metadata/metadata_dependencies_test.go
@@ -139,6 +139,8 @@ func TestDependenciesQuarkus(t *testing.T) {
 			    from("http:test").to("log:end");
 			    from("https:test").to("log:end");
 			    from("twitter-timeline:test").to("mock:end");
+			    from("direct:start").circuitBreaker().hystrixConfiguration().executionTimeoutInMilliseconds(100).end()
+			    .to("direct:other").onFallback().setBody(constant("Fallback response")).end();
 		    `,
 		},
 		Language: v1.LanguageJavaSource,
@@ -156,6 +158,8 @@ func TestDependenciesQuarkus(t *testing.T) {
 			"camel-quarkus:log",
 			"camel-quarkus:timer",
 			"camel-quarkus:twitter",
+			"camel-quarkus:direct",
+			"camel-quarkus:hystrix",
 		},
 		meta.Dependencies.List())
 }