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 2020/03/16 17:30:03 UTC

[camel-k] 02/02: Set default for rest based services #1347 #1347

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

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

commit a8f8db916698a2f6578aea5143bbe2e4749857f6
Author: lburgazzoli <lb...@gmail.com>
AuthorDate: Mon Mar 16 18:01:38 2020 +0100

    Set default for rest based services #1347 #1347
---
 pkg/metadata/metadata_dependencies_test.go | 13 ++++-
 pkg/trait/container.go                     | 42 ++++++++++++++-
 pkg/trait/cron.go                          | 12 +----
 pkg/trait/cron_test.go                     | 18 +------
 pkg/trait/dependencies.go                  | 12 +++++
 pkg/trait/dependencies_test.go             | 87 +++++++++++++++++++++++++++++-
 pkg/trait/openapi.go                       | 50 +++--------------
 pkg/trait/openapi_test.go                  | 50 -----------------
 pkg/util/source/inspector_groovy.go        |  3 ++
 pkg/util/source/inspector_java_script.go   |  7 ++-
 pkg/util/source/inspector_java_source.go   |  7 ++-
 pkg/util/source/inspector_kotlin.go        |  3 ++
 pkg/util/source/inspector_xml.go           |  2 +-
 pkg/util/source/inspector_yaml.go          |  2 +-
 pkg/util/source/types.go                   | 10 ++--
 15 files changed, 187 insertions(+), 131 deletions(-)

diff --git a/pkg/metadata/metadata_dependencies_test.go b/pkg/metadata/metadata_dependencies_test.go
index fe5c0e9..b0973e1 100644
--- a/pkg/metadata/metadata_dependencies_test.go
+++ b/pkg/metadata/metadata_dependencies_test.go
@@ -561,10 +561,11 @@ func TestXMLRestDependency(t *testing.T) {
 		t,
 		[]string{
 			"camel:direct",
-			"camel:rest",
 			"camel:mock",
 		},
 		meta.Dependencies.List())
+
+	assert.True(t, meta.RequiredCapabilities.Has("rest"))
 }
 
 func TestXMLLanguageDependencies(t *testing.T) {
@@ -683,7 +684,15 @@ func TestYAMLRestDependency(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.ElementsMatch(t, []string{"camel:direct", "camel:rest", "camel:log"}, meta.Dependencies.List())
+	assert.ElementsMatch(
+		t,
+		[]string{
+			"camel:direct",
+			"camel:log",
+		},
+		meta.Dependencies.List())
+
+	assert.True(t, meta.RequiredCapabilities.Has("rest"))
 }
 
 func TestYAMLHystrixDependency(t *testing.T) {
diff --git a/pkg/trait/container.go b/pkg/trait/container.go
index 6028936..a172543 100644
--- a/pkg/trait/container.go
+++ b/pkg/trait/container.go
@@ -43,6 +43,18 @@ const (
 	defaultServicePort   = 80
 	defaultProbePath     = "/health"
 	containerTraitID     = "container"
+
+	// CamelRestPortProperty ---
+	CamelRestPortProperty = "camel.context.rest-configuration.port"
+	// CamelRestDefaultPort ---
+	CamelRestDefaultPort = "8080"
+
+	// CamelRestComponentProperty ---
+	CamelRestComponentProperty = "camel.context.rest-configuration.component"
+	// CamelRestDefaultComponentMain ---
+	CamelRestDefaultComponentMain = "undertow"
+	// CamelRestDefaultComponentQuarkus ---
+	CamelRestDefaultComponentQuarkus = "platform-http"
 )
 
 // The Container trait can be used to configure properties of the container where the integration will run.
@@ -169,7 +181,7 @@ func (t *containerTrait) configureDependencies(e *Environment) {
 	}
 
 	if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
-		if capability, ok := e.CamelCatalog.Runtime.Capabilities["health"]; ok {
+		if capability, ok := e.CamelCatalog.Runtime.Capabilities[v1.CapabilityHealth]; ok {
 			for _, dependency := range capability.Dependencies {
 				util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, fmt.Sprintf("mvn:%s/%s", dependency.GroupID, dependency.ArtifactID))
 			}
@@ -204,6 +216,10 @@ func (t *containerTrait) configureContainer(e *Environment) error {
 		t.configureService(e, &container)
 	}
 
+	if err := t.configureCapabilities(e); err != nil {
+		return err
+	}
+
 	//
 	// Deployment
 	//
@@ -414,6 +430,30 @@ func (t *containerTrait) configureResources(_ *Environment, container *corev1.Co
 		}
 	}
 }
+
+func (t *containerTrait) configureCapabilities(e *Environment) error {
+	if !util.StringSliceExists(e.Integration.Status.Capabilities, v1.CapabilityRest) {
+		return nil
+	}
+
+	if e.ApplicationProperties == nil {
+		e.ApplicationProperties = make(map[string]string)
+	}
+
+	switch e.CamelCatalog.Runtime.Provider {
+	case v1.RuntimeProviderMain:
+		e.ApplicationProperties[CamelRestPortProperty] = CamelRestDefaultPort
+		e.ApplicationProperties[CamelRestComponentProperty] = CamelRestDefaultComponentMain
+	case v1.RuntimeProviderQuarkus:
+		// On quarkus, the rest endpoint is bound to the platform http service
+		e.ApplicationProperties[CamelRestComponentProperty] = CamelRestDefaultComponentQuarkus
+	default:
+		return fmt.Errorf("unsupported runtime: %s", e.CamelCatalog.Runtime.Provider)
+	}
+
+	return nil
+}
+
 func (t *containerTrait) configureProbes(e *Environment, container *corev1.Container, port int, path string) error {
 	if e.ApplicationProperties == nil {
 		e.ApplicationProperties = make(map[string]string)
diff --git a/pkg/trait/cron.go b/pkg/trait/cron.go
index 6b6ac85..6d4d332 100644
--- a/pkg/trait/cron.go
+++ b/pkg/trait/cron.go
@@ -20,7 +20,6 @@ package trait
 import (
 	"fmt"
 	"regexp"
-	"sort"
 	"strconv"
 	"strings"
 
@@ -129,7 +128,7 @@ func (t *cronTrait) Configure(e *Environment) (bool, error) {
 		return false, nil
 	}
 
-	if _, ok := e.CamelCatalog.Runtime.Capabilities["cron"]; !ok {
+	if _, ok := e.CamelCatalog.Runtime.Capabilities[v1.CapabilityCron]; !ok {
 		e.Integration.Status.SetCondition(
 			v1.IntegrationConditionCronJobAvailable,
 			corev1.ConditionFalse,
@@ -234,14 +233,7 @@ func (t *cronTrait) Configure(e *Environment) (bool, error) {
 
 func (t *cronTrait) Apply(e *Environment) error {
 	if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
-		if capability, ok := e.CamelCatalog.Runtime.Capabilities["cron"]; ok {
-			for _, dependency := range capability.Dependencies {
-				util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, fmt.Sprintf("mvn:%s/%s", dependency.GroupID, dependency.ArtifactID))
-			}
-
-			// sort the dependencies to get always the same list if they don't change
-			sort.Strings(e.Integration.Status.Dependencies)
-		}
+		util.StringSliceUniqueAdd(&e.Integration.Status.Capabilities, v1.CapabilityCron)
 
 		if t.Fallback != nil && *t.Fallback {
 			util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, genericCronComponentFallback)
diff --git a/pkg/trait/cron_test.go b/pkg/trait/cron_test.go
index c077fe2..a12aaab 100644
--- a/pkg/trait/cron_test.go
+++ b/pkg/trait/cron_test.go
@@ -19,7 +19,6 @@ package trait
 
 import (
 	"context"
-	"fmt"
 	"strings"
 	"testing"
 
@@ -286,13 +285,7 @@ func TestCronDeps(t *testing.T) {
 	ct := environment.GetTrait("cron").(*cronTrait)
 	assert.NotNil(t, ct)
 	assert.Nil(t, ct.Fallback)
-
-	capability, ok := environment.CamelCatalog.Runtime.Capabilities["cron"]
-	assert.True(t, ok)
-
-	for _, dependency := range capability.Dependencies {
-		assert.True(t, util.StringSliceExists(environment.Integration.Status.Dependencies, fmt.Sprintf("mvn:%s/%s", dependency.GroupID, dependency.ArtifactID)))
-	}
+	assert.True(t, util.StringSliceExists(environment.Integration.Status.Capabilities, v1.CapabilityCron))
 }
 
 func TestCronDepsFallback(t *testing.T) {
@@ -367,14 +360,7 @@ func TestCronDepsFallback(t *testing.T) {
 	ct := environment.GetTrait("cron").(*cronTrait)
 	assert.NotNil(t, ct)
 	assert.NotNil(t, ct.Fallback)
-
-	capability, ok := environment.CamelCatalog.Runtime.Capabilities["cron"]
-	assert.True(t, ok)
-
-	for _, dependency := range capability.Dependencies {
-		assert.True(t, util.StringSliceExists(environment.Integration.Status.Dependencies, fmt.Sprintf("mvn:%s/%s", dependency.GroupID, dependency.ArtifactID)))
-	}
-
+	assert.True(t, util.StringSliceExists(environment.Integration.Status.Capabilities, v1.CapabilityCron))
 	assert.True(t, util.StringSliceExists(environment.Integration.Status.Dependencies, genericCronComponentFallback))
 }
 
diff --git a/pkg/trait/dependencies.go b/pkg/trait/dependencies.go
index 79d5ecc..7d7e010 100644
--- a/pkg/trait/dependencies.go
+++ b/pkg/trait/dependencies.go
@@ -89,12 +89,24 @@ func (t *dependenciesTrait) Apply(e *Environment) error {
 				}
 			}
 		}
+
+		meta.RequiredCapabilities.Each(func(item string) bool {
+			util.StringSliceUniqueAdd(&e.Integration.Status.Capabilities, item)
+			return true
+		})
 	}
 
 	for _, dependency := range e.Integration.Spec.Dependencies {
 		util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, dependency)
 	}
 
+	// add runtime specific dependencies
+	for _, capability := range e.Integration.Status.Capabilities {
+		for _, dependency := range e.CamelCatalog.Runtime.CapabilityDependencies(capability) {
+			util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, fmt.Sprintf("mvn:%s/%s", dependency.GroupID, dependency.ArtifactID))
+		}
+	}
+
 	// add dependencies back to integration
 	dependencies.Each(func(item string) bool {
 		util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, item)
diff --git a/pkg/trait/dependencies_test.go b/pkg/trait/dependencies_test.go
index 8a376e2..d227d2f 100644
--- a/pkg/trait/dependencies_test.go
+++ b/pkg/trait/dependencies_test.go
@@ -185,7 +185,8 @@ func TestIntegrationAutoGeneratedDeps(t *testing.T) {
 		[]string{
 			"camel:direct",
 			"camel:log",
-			"camel:rest",
+			"mvn:org.apache.camel/camel-rest",
+			"mvn:org.apache.camel/camel-undertow",
 			"mvn:org.apache.camel.k/camel-k-loader-java",
 			"mvn:org.apache.camel.k/camel-k-loader-xml",
 			"mvn:org.apache.camel.k/camel-k-runtime-main"},
@@ -238,3 +239,87 @@ func TestIntegrationCustomLoader(t *testing.T) {
 		e.Integration.Status.Dependencies,
 	)
 }
+
+func TestRestDeps(t *testing.T) {
+	catalog, err := camel.DefaultCatalog()
+	assert.Nil(t, err)
+
+	e := &Environment{
+		Catalog:      NewEnvironmentTestCatalog(),
+		CamelCatalog: catalog,
+		Integration: &v1.Integration{
+			Spec: v1.IntegrationSpec{
+				Sources: []v1.SourceSpec{
+					{
+						DataSpec: v1.DataSpec{
+							Name:    "flow.java",
+							Content: `rest().to("log:bar");`,
+						},
+						Language: v1.LanguageJavaSource,
+					},
+				},
+			},
+			Status: v1.IntegrationStatus{
+				Phase: v1.IntegrationPhaseInitialization,
+			},
+		},
+	}
+
+	trait := newDependenciesTrait()
+	enabled, err := trait.Configure(e)
+	assert.Nil(t, err)
+	assert.True(t, enabled)
+
+	err = trait.Apply(e)
+	assert.Nil(t, err)
+	assert.Subset(
+		t,
+		e.Integration.Status.Dependencies,
+		[]string{
+			"mvn:org.apache.camel/camel-rest",
+			"mvn:org.apache.camel/camel-undertow",
+		},
+	)
+}
+
+func TestRestDepsQuarkus(t *testing.T) {
+	catalog, err := camel.QuarkusCatalog()
+	assert.Nil(t, err)
+
+	e := &Environment{
+		Catalog:      NewEnvironmentTestCatalog(),
+		CamelCatalog: catalog,
+		Integration: &v1.Integration{
+			Spec: v1.IntegrationSpec{
+				Sources: []v1.SourceSpec{
+					{
+						DataSpec: v1.DataSpec{
+							Name:    "flow.java",
+							Content: `rest().route().to("log:bar");`,
+						},
+						Language: v1.LanguageJavaSource,
+					},
+				},
+			},
+			Status: v1.IntegrationStatus{
+				Phase: v1.IntegrationPhaseInitialization,
+			},
+		},
+	}
+
+	trait := newDependenciesTrait()
+	enabled, err := trait.Configure(e)
+	assert.Nil(t, err)
+	assert.True(t, enabled)
+
+	err = trait.Apply(e)
+	assert.Nil(t, err)
+	assert.Subset(
+		t,
+		e.Integration.Status.Dependencies,
+		[]string{
+			"mvn:org.apache.camel.quarkus/camel-quarkus-rest",
+			"mvn:org.apache.camel.quarkus/camel-quarkus-platform-http",
+		},
+	)
+}
diff --git a/pkg/trait/openapi.go b/pkg/trait/openapi.go
index af40121..10d7828 100644
--- a/pkg/trait/openapi.go
+++ b/pkg/trait/openapi.go
@@ -24,16 +24,16 @@ import (
 	"os"
 	"path"
 	"path/filepath"
-	"sort"
 	"strconv"
 	"strings"
 
+	"github.com/apache/camel-k/pkg/util"
+
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 
-	"github.com/apache/camel-k/pkg/util"
 	"github.com/apache/camel-k/pkg/util/defaults"
 	"github.com/apache/camel-k/pkg/util/gzip"
 	"github.com/apache/camel-k/pkg/util/kubernetes"
@@ -43,12 +43,6 @@ import (
 // OpenAPITraitName ---
 const OpenAPITraitName = "openapi"
 
-// CamelRestPortProperty ---
-const CamelRestPortProperty = "camel.context.rest-configuration.port"
-
-// CamelRestDefaultPort ---
-const CamelRestDefaultPort = "8080"
-
 // The OpenAPI DSL trait is internally used to allow creating integrations from a OpenAPI specs.
 //
 // +camel-k:trait=openapi
@@ -77,17 +71,13 @@ func (t *openAPITrait) Configure(e *Environment) (bool, error) {
 	}
 
 	// check if the runtime provides 'rest' capabilities
-	if _, ok := e.CamelCatalog.Runtime.Capabilities["rest"]; !ok {
-		t.L.Infof("the runtime provider %s does not declare 'rest' capability", e.CamelCatalog.Runtime.Provider)
+	if _, ok := e.CamelCatalog.Runtime.Capabilities[v1.CapabilityRest]; !ok {
+		return false, fmt.Errorf("the runtime provider %s does not declare 'rest' capability", e.CamelCatalog.Runtime.Provider)
 	}
 
 	for _, resource := range e.Integration.Spec.Resources {
 		if resource.Type == v1.ResourceTypeOpenAPI {
-			return e.IntegrationInPhase(
-				v1.IntegrationPhaseInitialization,
-				v1.IntegrationPhaseDeploying,
-				v1.IntegrationPhaseRunning,
-			), nil
+			return e.IntegrationInPhase(v1.IntegrationPhaseInitialization), nil
 		}
 	}
 
@@ -95,24 +85,8 @@ func (t *openAPITrait) Configure(e *Environment) (bool, error) {
 }
 
 func (t *openAPITrait) Apply(e *Environment) error {
-	if len(e.Integration.Spec.Resources) == 0 {
-		return nil
-	}
-
-	if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
-		t.computeDependencies(e)
-		return t.generateRestDSL(e)
-	}
-
-	if e.IntegrationInPhase(v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) {
-		e.ApplicationProperties[CamelRestPortProperty] = CamelRestDefaultPort
-		return nil
-	}
+	util.StringSliceUniqueAdd(&e.Integration.Status.Capabilities, v1.CapabilityRest)
 
-	return nil
-}
-
-func (t *openAPITrait) generateRestDSL(e *Environment) error {
 	root := os.TempDir()
 	tmpDir, err := ioutil.TempDir(root, "openapi")
 	if err != nil {
@@ -278,15 +252,3 @@ func (t *openAPITrait) generateMavenProject(e *Environment) (maven.Project, erro
 
 	return p, nil
 }
-
-func (t *openAPITrait) computeDependencies(e *Environment) {
-	// check if the runtime provides 'rest' capabilities
-	if capability, ok := e.CamelCatalog.Runtime.Capabilities["rest"]; ok {
-		for _, dependency := range capability.Dependencies {
-			util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, fmt.Sprintf("mvn:%s/%s", dependency.GroupID, dependency.ArtifactID))
-		}
-
-		// sort the dependencies to get always the same list if they don't change
-		sort.Strings(e.Integration.Status.Dependencies)
-	}
-}
diff --git a/pkg/trait/openapi_test.go b/pkg/trait/openapi_test.go
index 791fbc5..dc09c01 100644
--- a/pkg/trait/openapi_test.go
+++ b/pkg/trait/openapi_test.go
@@ -62,53 +62,3 @@ func TestRestDslTraitApplicability(t *testing.T) {
 	assert.Nil(t, err)
 	assert.True(t, enabled)
 }
-
-func TestRestDslTraitDeps(t *testing.T) {
-	catalog, err := camel.DefaultCatalog()
-	assert.Nil(t, err)
-
-	e := &Environment{
-		CamelCatalog: catalog,
-		Integration: &v1.Integration{
-			Spec: v1.IntegrationSpec{
-				Resources: []v1.ResourceSpec{
-					{Type: v1.ResourceTypeOpenAPI},
-				},
-			},
-			Status: v1.IntegrationStatus{
-				Phase: v1.IntegrationPhaseInitialization,
-			},
-		},
-	}
-
-	trait := newOpenAPITrait().(*openAPITrait)
-	trait.computeDependencies(e)
-
-	assert.Contains(t, e.Integration.Status.Dependencies, "mvn:org.apache.camel/camel-rest")
-	assert.Contains(t, e.Integration.Status.Dependencies, "mvn:org.apache.camel/camel-undertow")
-}
-
-func TestRestDslTraitDepsQuarkus(t *testing.T) {
-	catalog, err := camel.QuarkusCatalog()
-	assert.Nil(t, err)
-
-	e := &Environment{
-		CamelCatalog: catalog,
-		Integration: &v1.Integration{
-			Spec: v1.IntegrationSpec{
-				Resources: []v1.ResourceSpec{
-					{Type: v1.ResourceTypeOpenAPI},
-				},
-			},
-			Status: v1.IntegrationStatus{
-				Phase: v1.IntegrationPhaseInitialization,
-			},
-		},
-	}
-
-	trait := newOpenAPITrait().(*openAPITrait)
-	trait.computeDependencies(e)
-
-	assert.Contains(t, e.Integration.Status.Dependencies, "mvn:org.apache.camel.quarkus/camel-quarkus-rest")
-	assert.Contains(t, e.Integration.Status.Dependencies, "mvn:org.apache.camel.quarkus/camel-quarkus-platform-http")
-}
diff --git a/pkg/util/source/inspector_groovy.go b/pkg/util/source/inspector_groovy.go
index a37bfc0..9f705c3 100644
--- a/pkg/util/source/inspector_groovy.go
+++ b/pkg/util/source/inspector_groovy.go
@@ -50,6 +50,9 @@ func (i GroovyInspector) Extract(source v1.SourceSpec, meta *Metadata) error {
 	i.discoverDependencies(source, meta)
 
 	hasRest := restRegexp.MatchString(source.Content) || restClosureRegexp.MatchString(source.Content)
+	if hasRest {
+		meta.RequiredCapabilities.Add(v1.CapabilityRest)
+	}
 
 	meta.ExposesHTTPServices = hasRest || i.containsHTTPURIs(meta.FromURIs)
 	meta.PassiveEndpoints = i.hasOnlyPassiveEndpoints(meta.FromURIs)
diff --git a/pkg/util/source/inspector_java_script.go b/pkg/util/source/inspector_java_script.go
index f79dd3a..dc5be41 100644
--- a/pkg/util/source/inspector_java_script.go
+++ b/pkg/util/source/inspector_java_script.go
@@ -49,7 +49,12 @@ func (i JavaScriptInspector) Extract(source v1.SourceSpec, meta *Metadata) error
 
 	i.discoverDependencies(source, meta)
 
-	meta.ExposesHTTPServices = restRegexp.MatchString(source.Content) || i.containsHTTPURIs(meta.FromURIs)
+	hasRest := restRegexp.MatchString(source.Content)
+	if hasRest {
+		meta.RequiredCapabilities.Add(v1.CapabilityRest)
+	}
+
+	meta.ExposesHTTPServices = hasRest || i.containsHTTPURIs(meta.FromURIs)
 	meta.PassiveEndpoints = i.hasOnlyPassiveEndpoints(meta.FromURIs)
 
 	return nil
diff --git a/pkg/util/source/inspector_java_source.go b/pkg/util/source/inspector_java_source.go
index 32bd0b0..e548267 100644
--- a/pkg/util/source/inspector_java_source.go
+++ b/pkg/util/source/inspector_java_source.go
@@ -45,7 +45,12 @@ func (i JavaSourceInspector) Extract(source v1.SourceSpec, meta *Metadata) error
 
 	i.discoverDependencies(source, meta)
 
-	meta.ExposesHTTPServices = restRegexp.MatchString(source.Content) || i.containsHTTPURIs(meta.FromURIs)
+	hasRest := restRegexp.MatchString(source.Content)
+	if hasRest {
+		meta.RequiredCapabilities.Add(v1.CapabilityRest)
+	}
+
+	meta.ExposesHTTPServices = hasRest || i.containsHTTPURIs(meta.FromURIs)
 	meta.PassiveEndpoints = i.hasOnlyPassiveEndpoints(meta.FromURIs)
 
 	return nil
diff --git a/pkg/util/source/inspector_kotlin.go b/pkg/util/source/inspector_kotlin.go
index b949318..4a405ce 100644
--- a/pkg/util/source/inspector_kotlin.go
+++ b/pkg/util/source/inspector_kotlin.go
@@ -46,6 +46,9 @@ func (i KotlinInspector) Extract(source v1.SourceSpec, meta *Metadata) error {
 	i.discoverDependencies(source, meta)
 
 	hasRest := restRegexp.MatchString(source.Content) || restClosureRegexp.MatchString(source.Content)
+	if hasRest {
+		meta.RequiredCapabilities.Add(v1.CapabilityRest)
+	}
 
 	meta.ExposesHTTPServices = hasRest || i.containsHTTPURIs(meta.FromURIs)
 	meta.PassiveEndpoints = i.hasOnlyPassiveEndpoints(meta.FromURIs)
diff --git a/pkg/util/source/inspector_xml.go b/pkg/util/source/inspector_xml.go
index 48777de..f9f2ab6 100644
--- a/pkg/util/source/inspector_xml.go
+++ b/pkg/util/source/inspector_xml.go
@@ -44,8 +44,8 @@ func (i XMLInspector) Extract(source v1.SourceSpec, meta *Metadata) error {
 		if se, ok := t.(xml.StartElement); ok {
 			switch se.Name.Local {
 			case "rest", "restConfiguration":
-				i.addDependency("camel:rest", meta)
 				meta.ExposesHTTPServices = true
+				meta.RequiredCapabilities.Add(v1.CapabilityRest)
 			case "circuitBreaker":
 				i.addDependency("camel:hystrix", meta)
 			case "language":
diff --git a/pkg/util/source/inspector_yaml.go b/pkg/util/source/inspector_yaml.go
index e42eb38..8ddf8c3 100644
--- a/pkg/util/source/inspector_yaml.go
+++ b/pkg/util/source/inspector_yaml.go
@@ -58,8 +58,8 @@ 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":
-		inspector.addDependency("camel:rest", meta)
 		meta.ExposesHTTPServices = true
+		meta.RequiredCapabilities.Add(v1.CapabilityRest)
 	case "circuitBreaker":
 		inspector.addDependency("camel:hystrix", meta)
 	}
diff --git a/pkg/util/source/types.go b/pkg/util/source/types.go
index 1802917..f6f15e0 100644
--- a/pkg/util/source/types.go
+++ b/pkg/util/source/types.go
@@ -34,13 +34,17 @@ type Metadata struct {
 	// are activated from external calls, including HTTP (useful to determine if the
 	// integration can scale to 0)
 	PassiveEndpoints bool
+	// RequiredCapabilities lists the capabilities required by the integration
+	// to run
+	RequiredCapabilities *strset.Set
 }
 
 // NewMetadata --
 func NewMetadata() Metadata {
 	return Metadata{
-		FromURIs:     make([]string, 0),
-		ToURIs:       make([]string, 0),
-		Dependencies: strset.New(),
+		FromURIs:             make([]string, 0),
+		ToURIs:               make([]string, 0),
+		Dependencies:         strset.New(),
+		RequiredCapabilities: strset.New(),
 	}
 }