This is an automated email from the ASF dual-hosted git repository.
pcongiusti pushed a commit to branch release-1.12.x
in repository https://gitbox.apache.org/repos/asf/camel-k.git
The following commit(s) were added to refs/heads/release-1.12.x by this push:
new f3ee51f5d chore: Improve Camel dependency validation
f3ee51f5d is described below
commit f3ee51f5d2bb3fcfe7efd6f9f1f0d10db8e3327e
Author: Christoph Deppisch <[email protected]>
AuthorDate: Thu May 25 09:54:56 2023 +0200
chore: Improve Camel dependency validation
- Reuse logic in validate function just logging a warning and those
validate function raising errors
- Remove unused function ValidateDependencies
- Add some unit tests
- Add some documentation on Camel dependency resolution via catalog
---
.../ROOT/pages/configuration/dependencies.adoc | 7 ++
pkg/cmd/local/local.go | 2 +-
pkg/cmd/run_support.go | 2 +-
pkg/util/camel/camel_dependencies.go | 58 ++++++----
pkg/util/camel/camel_dependencies_test.go | 128 +++++++++++++++++++++
5 files changed, 172 insertions(+), 25 deletions(-)
diff --git a/docs/modules/ROOT/pages/configuration/dependencies.adoc
b/docs/modules/ROOT/pages/configuration/dependencies.adoc
index 40062af3b..d0cdeddd7 100644
--- a/docs/modules/ROOT/pages/configuration/dependencies.adoc
+++ b/docs/modules/ROOT/pages/configuration/dependencies.adoc
@@ -39,6 +39,13 @@ kamel run -d camel:http Integration.java
```
In this case, the dependency will be added with the correct version. Note that
the standard notation for specifying a Camel dependency is `camel:xxx`, while
`kamel` also accepts `camel-xxx` for usability.
+While resolving Camel dependencies (`camel:xxx` or `camel-xxx`) the Camel K
operator tries to find the dependency in the
xref:architecture/cr/camel-catalog.adoc[Camel catalog].
+In case the dependency is not listed in the catalog for some reason you will
be provided with am error.
+Please make sure to use Camel dependencies listed in the catalog as these
components are eligible to being used in Camel K (e.g. due to proper version
resolving and runtime optimization).
+Using Camel dependencies not listed in the catalog may lead to unexpected
behavior and is not supported.
+In case you do have a custom Camel component that you want to use as part of
an Integration you can add this as an external Maven dependency using the
respective Maven coordinates of your project.
+Please do not use one of the reserved the Camel groupIds (`org.apache.camel`)
in that case.
+
*External dependencies* can be added using the `-d` flag, the `mvn` prefix,
and the maven coordinates:
```
kamel run -d mvn:com.google.guava:guava:26.0-jre Integration.java
diff --git a/pkg/cmd/local/local.go b/pkg/cmd/local/local.go
index b1513a855..2955f0ed6 100644
--- a/pkg/cmd/local/local.go
+++ b/pkg/cmd/local/local.go
@@ -57,7 +57,7 @@ func GetDependencies(ctx context.Context, cmd *cobra.Command,
srcs, userDependen
}
// Validate user-provided dependencies against Camel catalog
- camel.ValidateDependencies(catalog, userDependencies, cmd)
+ camel.ValidateDependencies(catalog, userDependencies, cmd.ErrOrStderr())
// Get top-level dependencies from sources
dependencies, err := getTopLevelDependencies(ctx, catalog, srcs)
diff --git a/pkg/cmd/run_support.go b/pkg/cmd/run_support.go
index 812c7d326..985114387 100644
--- a/pkg/cmd/run_support.go
+++ b/pkg/cmd/run_support.go
@@ -42,7 +42,7 @@ import (
func addDependency(cmd *cobra.Command, it *v1.Integration, dependency string,
catalog *camel.RuntimeCatalog) {
normalized := camel.NormalizeDependency(dependency)
- camel.ValidateDependency(catalog, normalized, cmd)
+ camel.ValidateDependency(catalog, normalized, cmd.ErrOrStderr())
it.Spec.AddDependency(normalized)
}
diff --git a/pkg/util/camel/camel_dependencies.go
b/pkg/util/camel/camel_dependencies.go
index a3b65b003..0fd7be5b5 100644
--- a/pkg/util/camel/camel_dependencies.go
+++ b/pkg/util/camel/camel_dependencies.go
@@ -49,53 +49,65 @@ func NormalizeDependency(dependency string) string {
return newDep
}
-type Output interface {
- OutOrStdout() io.Writer
- ErrOrStderr() io.Writer
-}
-
// ValidateDependencies validates dependencies against Camel catalog.
// It only shows warning and does not throw error in case the Catalog is just
not complete
// and we don't want to let it stop the process.
-func ValidateDependencies(catalog *RuntimeCatalog, dependencies []string, out
Output) {
+func ValidateDependencies(catalog *RuntimeCatalog, dependencies []string, out
io.Writer) {
for _, d := range dependencies {
ValidateDependency(catalog, d, out)
}
}
// ValidateDependency validates a dependency against Camel catalog.
-// It only shows warning and does not throw error in case the Catalog is just
not complete
+// It only shows warning and does not throw error in case the Catalog is just
not complete,
// and we don't want to let it stop the process.
-func ValidateDependency(catalog *RuntimeCatalog, dependency string, out
Output) {
+func ValidateDependency(catalog *RuntimeCatalog, dependency string, out
io.Writer) {
+ if err := ValidateDependencyE(catalog, dependency); err != nil {
+ fmt.Fprintf(out, "Warning: %s\n", err.Error())
+ }
+
switch {
- case strings.HasPrefix(dependency, "camel:"):
- artifact := strings.TrimPrefix(dependency, "camel:")
- if ok := catalog.IsValidArtifact(artifact); !ok {
- fmt.Fprintf(out.ErrOrStderr(), "Warning: dependency %s
not found in Camel catalog\n", dependency)
- }
case strings.HasPrefix(dependency, "mvn:org.apache.camel:"):
component := strings.Split(dependency, ":")[2]
- fmt.Fprintf(out.ErrOrStderr(), "Warning: do not use %s. Use %s
instead\n",
+ fmt.Fprintf(out, "Warning: do not use %s. Use %s instead\n",
dependency, NormalizeDependency(component))
case strings.HasPrefix(dependency, "mvn:org.apache.camel.quarkus:"):
component := strings.Split(dependency, ":")[2]
- fmt.Fprintf(out.ErrOrStderr(), "Warning: do not use %s. Use %s
instead\n",
+ fmt.Fprintf(out, "Warning: do not use %s. Use %s instead\n",
dependency, NormalizeDependency(component))
}
+}
+// ValidateDependencyE validates a dependency against Camel catalog and throws
error
+// in case it does not exist in the catalog.
+func ValidateDependencyE(catalog *RuntimeCatalog, dependency string) error {
+ var artifact string
+ switch {
+ case strings.HasPrefix(dependency, "camel:"):
+ artifact = strings.TrimPrefix(dependency, "camel:")
+ case strings.HasPrefix(dependency, "camel-quarkus:"):
+ artifact = strings.TrimPrefix(dependency, "camel-quarkus:")
+ case strings.HasPrefix(dependency, "camel-"):
+ artifact = dependency
+ }
+
+ if artifact == "" {
+ return nil
+ }
+
+ if ok := catalog.IsValidArtifact(artifact); !ok {
+ return fmt.Errorf("dependency %s not found in Camel catalog",
dependency)
+ }
+
+ return nil
}
// ValidateDependenciesE validates dependencies against Camel catalog and
throws error
-// if it doesn't exist in the catalog.
+// in case it does not exist in the catalog.
func ValidateDependenciesE(catalog *RuntimeCatalog, dependencies []string)
error {
for _, dependency := range dependencies {
- if !strings.HasPrefix(dependency, "camel:") {
- continue
- }
-
- artifact := strings.TrimPrefix(dependency, "camel:")
- if ok := catalog.IsValidArtifact(artifact); !ok {
- return fmt.Errorf("dependency %s not found in Camel
catalog", dependency)
+ if err := ValidateDependencyE(catalog, dependency); err != nil {
+ return err
}
}
diff --git a/pkg/util/camel/camel_dependencies_test.go
b/pkg/util/camel/camel_dependencies_test.go
index 8bb78f3da..4469e0c17 100644
--- a/pkg/util/camel/camel_dependencies_test.go
+++ b/pkg/util/camel/camel_dependencies_test.go
@@ -18,8 +18,11 @@ limitations under the License.
package camel
import (
+ "fmt"
+ "strings"
"testing"
+ "github.com/apache/camel-k/pkg/util/maven"
"github.com/stretchr/testify/assert"
)
@@ -30,4 +33,129 @@ func TestNormalizeDependency(t *testing.T) {
assert.Equal(t, "camel:file", NormalizeDependency("camel-quarkus:file"))
assert.Equal(t, "camel-k:knative",
NormalizeDependency("camel-k-knative"))
assert.Equal(t, "camel-k:knative",
NormalizeDependency("camel-k:knative"))
+ assert.Equal(t, "mvn:org.apache.camel:camel-file",
NormalizeDependency("mvn:org.apache.camel:camel-file"))
+ assert.Equal(t, "mvn:org.apache.camel.quarkus:camel-quarkus-file",
NormalizeDependency("mvn:org.apache.camel.quarkus:camel-quarkus-file"))
+ assert.Equal(t, "mvn:org.apache.camel:camel-k-knative",
NormalizeDependency("mvn:org.apache.camel:camel-k-knative"))
+}
+
+func TestValidateDependency(t *testing.T) {
+ catalog, err := DefaultCatalog()
+ assert.Nil(t, err)
+
+ output := strings.Builder{}
+ ValidateDependency(catalog, "", &output)
+ assert.Equal(t, "", output.String())
+
+ output.Reset()
+ ValidateDependency(catalog, "camel:file", &output)
+ assert.Equal(t, "", output.String())
+
+ output.Reset()
+ ValidateDependency(catalog, "camel-quarkus-file", &output)
+ assert.Equal(t, "", output.String())
+
+ output.Reset()
+ ValidateDependency(catalog, "camel-quarkus:file", &output)
+ assert.Equal(t, "", output.String())
+
+ output.Reset()
+ ValidateDependency(catalog, "camel:unknown", &output)
+ assert.Equal(t, "Warning: dependency camel:unknown not found in Camel
catalog\n", output.String())
+
+ output.Reset()
+ ValidateDependency(catalog, "mvn:org.apache.camel:camel-foo", &output)
+ assert.Equal(t, "Warning: do not use mvn:org.apache.camel:camel-foo.
Use camel:foo instead\n", output.String())
+
+ output.Reset()
+ ValidateDependency(catalog,
"mvn:org.apache.camel.quarkus:camel-quarkus-foo", &output)
+ assert.Equal(t, "Warning: do not use
mvn:org.apache.camel.quarkus:camel-quarkus-foo. Use camel:foo instead\n",
output.String())
+}
+
+func TestManageIntegrationDependencies(t *testing.T) {
+ catalog, err := DefaultCatalog()
+ assert.Nil(t, err)
+
+ tests := []struct {
+ name string
+ dependencies []string
+ coordinates string
+ }{
+ {
+ name: "basic_camel",
+ dependencies: []string{
+ "camel:direct",
+ "camel:log",
+ "camel:core",
+ },
+ coordinates:
"org.apache.camel.quarkus:camel-quarkus-direct," +
+ "org.apache.camel.quarkus:camel-quarkus-log," +
+ "org.apache.camel.quarkus:camel-quarkus-core",
+ },
+ {
+ name: "camel_quarkus",
+ dependencies: []string{
+ "camel:direct",
+ "camel-quarkus:log",
+ "camel:camel-quarkus-core",
+ },
+ coordinates:
"org.apache.camel.quarkus:camel-quarkus-direct," +
+ "org.apache.camel.quarkus:camel-quarkus-log," +
+ "org.apache.camel.quarkus:camel-quarkus-core",
+ },
+ {
+ name: "camel_k",
+ dependencies: []string{
+ "camel:direct",
+ "camel-k:webhook",
+ },
+ coordinates:
"org.apache.camel.quarkus:camel-quarkus-direct," +
+ "org.apache.camel.k:camel-k-webhook",
+ },
+ {
+ name: "not_in_catalog",
+ dependencies: []string{
+ "camel:direct",
+ "camel:resiliance4j",
+ },
+ coordinates:
"org.apache.camel.quarkus:camel-quarkus-direct," +
+
"org.apache.camel.quarkus:camel-quarkus-resiliance4j",
+ },
+ {
+ name: "mvn",
+ dependencies: []string{
+ "mvn:org.foo:bar",
+ "mvn:org.apache.camel:camel-resiliance4j",
+ },
+ coordinates: "org.foo:bar," +
+ "org.apache.camel:camel-resiliance4j",
+ },
+ {
+ name: "jitpack",
+ dependencies: []string{
+ "github:apache/camel-sample/1.0",
+ },
+ coordinates: "com.github.apache:camel-sample",
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ project := maven.Project{}
+
+ err = ManageIntegrationDependencies(&project,
test.dependencies, catalog)
+ assert.Nil(t, err)
+
+ coordinates := strings.Builder{}
+ for i, d := range project.Dependencies {
+ if i == 0 {
+ _, err = fmt.Fprintf(&coordinates,
"%s:%s", d.GroupID, d.ArtifactID)
+ assert.Nil(t, err)
+ } else {
+ _, err = fmt.Fprintf(&coordinates,
",%s:%s", d.GroupID, d.ArtifactID)
+ assert.Nil(t, err)
+ }
+ }
+ assert.Equal(t, test.coordinates, coordinates.String(),
coordinates)
+ })
+ }
}