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/10/06 08:03:12 UTC

[camel-k] 01/08: chore(binding): refactor binding mechanism and add many more tests

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 19b66cffb432f98f8e29ca0bf71e6112f375c989
Author: nicolaferraro <ni...@gmail.com>
AuthorDate: Thu Oct 1 18:04:54 2020 +0200

    chore(binding): refactor binding mechanism and add many more tests
---
 deploy/crd-kamelet-binding.yaml                    |  80 ++++----
 .../kameletbindings.camel.apache.org.crd.yaml      |  80 ++++----
 .../display.groovy}                                |   9 +-
 e2e/yaks/kamelet-binding/kamelet.feature           |   5 +
 .../logger-sink-binding.yaml}                      |  15 +-
 .../logger-sink.kamelet.yaml}                      |  13 +-
 .../messages-channel.yaml                          |   0
 .../timer-source-binding-display.yaml}             |  10 +-
 .../timer-source-binding.yaml                      |   0
 .../timer-source.kamelet.yaml                      |   0
 .../{kamelets => kamelet-binding}/yaks-config.yaml |  10 +-
 .../{kamelets => kamelet}/echo-sink.kamelet.yaml   |   0
 e2e/yaks/kamelet/kamelet.feature                   |   5 +
 e2e/yaks/{kamelets => kamelet}/source-sink.groovy  |   3 +-
 .../timer-source.kamelet.yaml                      |   0
 e2e/yaks/{kamelets => kamelet}/yaks-config.yaml    |   6 -
 e2e/yaks/kamelets/kamelet.feature                  |   9 -
 helm/camel-k/crds/crd-kamelet-binding.yaml         |  80 ++++----
 pkg/apis/camel/v1alpha1/kamelet_binding_types.go   |   9 +-
 .../v1alpha1/kamelet_binding_types_support.go      |  21 ++
 pkg/controller/kameletbinding/initialize.go        |  85 +-------
 pkg/util/bindings/api.go                           |  48 +++++
 pkg/util/bindings/bindings_test.go                 | 222 +++++++++++++++++++++
 pkg/util/bindings/camel_uri.go                     |  58 ++++++
 pkg/util/bindings/catalog.go                       |  61 ++++++
 pkg/util/bindings/kamelet.go                       |  68 +++++++
 pkg/util/bindings/knative_ref.go                   | 116 +++++++++++
 pkg/util/bindings/knative_uri.go                   | 102 ++++++++++
 pkg/util/knative/apis.go                           |  30 +++
 29 files changed, 915 insertions(+), 230 deletions(-)

diff --git a/deploy/crd-kamelet-binding.yaml b/deploy/crd-kamelet-binding.yaml
index 74575d8..53bf707 100644
--- a/deploy/crd-kamelet-binding.yaml
+++ b/deploy/crd-kamelet-binding.yaml
@@ -189,31 +189,35 @@ spec:
                     apiVersion:
                       description: API version of the referent.
                       type: string
-                    blockOwnerDeletion:
-                      description: If true, AND if the owner has the "foregroundDeletion"
-                        finalizer, then the owner cannot be deleted from the key-value
-                        store until this reference is removed. Defaults to false.
-                        To set this field, a user needs "delete" permission of the
-                        owner, otherwise 422 (Unprocessable Entity) will be returned.
-                      type: boolean
-                    controller:
-                      description: If true, this reference points to the managing
-                        controller.
-                      type: boolean
+                    fieldPath:
+                      description: 'If referring to a piece of an object instead of
+                        an entire object, this string should contain a valid JSON/Go
+                        field access statement, such as desiredState.manifest.containers[2].
+                        For example, if the object reference is to a container within
+                        a pod, this would take on a value like: "spec.containers{name}"
+                        (where "name" refers to the name of the container that triggered
+                        the event) or if no container name is specified "spec.containers[2]"
+                        (container with index 2 in this pod). This syntax is chosen
+                        only to have some well-defined way of referencing a part of
+                        an object. TODO: this design is not final and this field is
+                        subject to change in the future.'
+                      type: string
                     kind:
                       description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
                       type: string
                     name:
-                      description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
+                      description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                      type: string
+                    namespace:
+                      description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                      type: string
+                    resourceVersion:
+                      description: 'Specific resourceVersion to which this reference
+                        is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
                       type: string
                     uid:
-                      description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
+                      description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
                       type: string
-                  required:
-                  - apiVersion
-                  - kind
-                  - name
-                  - uid
                   type: object
                 uri:
                   description: URI can alternatively be used to specify the (Camel)
@@ -235,31 +239,35 @@ spec:
                     apiVersion:
                       description: API version of the referent.
                       type: string
-                    blockOwnerDeletion:
-                      description: If true, AND if the owner has the "foregroundDeletion"
-                        finalizer, then the owner cannot be deleted from the key-value
-                        store until this reference is removed. Defaults to false.
-                        To set this field, a user needs "delete" permission of the
-                        owner, otherwise 422 (Unprocessable Entity) will be returned.
-                      type: boolean
-                    controller:
-                      description: If true, this reference points to the managing
-                        controller.
-                      type: boolean
+                    fieldPath:
+                      description: 'If referring to a piece of an object instead of
+                        an entire object, this string should contain a valid JSON/Go
+                        field access statement, such as desiredState.manifest.containers[2].
+                        For example, if the object reference is to a container within
+                        a pod, this would take on a value like: "spec.containers{name}"
+                        (where "name" refers to the name of the container that triggered
+                        the event) or if no container name is specified "spec.containers[2]"
+                        (container with index 2 in this pod). This syntax is chosen
+                        only to have some well-defined way of referencing a part of
+                        an object. TODO: this design is not final and this field is
+                        subject to change in the future.'
+                      type: string
                     kind:
                       description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
                       type: string
                     name:
-                      description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
+                      description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                      type: string
+                    namespace:
+                      description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                      type: string
+                    resourceVersion:
+                      description: 'Specific resourceVersion to which this reference
+                        is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
                       type: string
                     uid:
-                      description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
+                      description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
                       type: string
-                  required:
-                  - apiVersion
-                  - kind
-                  - name
-                  - uid
                   type: object
                 uri:
                   description: URI can alternatively be used to specify the (Camel)
diff --git a/deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/kameletbindings.camel.apache.org.crd.yaml b/deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/kameletbindings.camel.apache.org.crd.yaml
index 74575d8..53bf707 100644
--- a/deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/kameletbindings.camel.apache.org.crd.yaml
+++ b/deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/kameletbindings.camel.apache.org.crd.yaml
@@ -189,31 +189,35 @@ spec:
                     apiVersion:
                       description: API version of the referent.
                       type: string
-                    blockOwnerDeletion:
-                      description: If true, AND if the owner has the "foregroundDeletion"
-                        finalizer, then the owner cannot be deleted from the key-value
-                        store until this reference is removed. Defaults to false.
-                        To set this field, a user needs "delete" permission of the
-                        owner, otherwise 422 (Unprocessable Entity) will be returned.
-                      type: boolean
-                    controller:
-                      description: If true, this reference points to the managing
-                        controller.
-                      type: boolean
+                    fieldPath:
+                      description: 'If referring to a piece of an object instead of
+                        an entire object, this string should contain a valid JSON/Go
+                        field access statement, such as desiredState.manifest.containers[2].
+                        For example, if the object reference is to a container within
+                        a pod, this would take on a value like: "spec.containers{name}"
+                        (where "name" refers to the name of the container that triggered
+                        the event) or if no container name is specified "spec.containers[2]"
+                        (container with index 2 in this pod). This syntax is chosen
+                        only to have some well-defined way of referencing a part of
+                        an object. TODO: this design is not final and this field is
+                        subject to change in the future.'
+                      type: string
                     kind:
                       description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
                       type: string
                     name:
-                      description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
+                      description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                      type: string
+                    namespace:
+                      description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                      type: string
+                    resourceVersion:
+                      description: 'Specific resourceVersion to which this reference
+                        is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
                       type: string
                     uid:
-                      description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
+                      description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
                       type: string
-                  required:
-                  - apiVersion
-                  - kind
-                  - name
-                  - uid
                   type: object
                 uri:
                   description: URI can alternatively be used to specify the (Camel)
@@ -235,31 +239,35 @@ spec:
                     apiVersion:
                       description: API version of the referent.
                       type: string
-                    blockOwnerDeletion:
-                      description: If true, AND if the owner has the "foregroundDeletion"
-                        finalizer, then the owner cannot be deleted from the key-value
-                        store until this reference is removed. Defaults to false.
-                        To set this field, a user needs "delete" permission of the
-                        owner, otherwise 422 (Unprocessable Entity) will be returned.
-                      type: boolean
-                    controller:
-                      description: If true, this reference points to the managing
-                        controller.
-                      type: boolean
+                    fieldPath:
+                      description: 'If referring to a piece of an object instead of
+                        an entire object, this string should contain a valid JSON/Go
+                        field access statement, such as desiredState.manifest.containers[2].
+                        For example, if the object reference is to a container within
+                        a pod, this would take on a value like: "spec.containers{name}"
+                        (where "name" refers to the name of the container that triggered
+                        the event) or if no container name is specified "spec.containers[2]"
+                        (container with index 2 in this pod). This syntax is chosen
+                        only to have some well-defined way of referencing a part of
+                        an object. TODO: this design is not final and this field is
+                        subject to change in the future.'
+                      type: string
                     kind:
                       description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
                       type: string
                     name:
-                      description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
+                      description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                      type: string
+                    namespace:
+                      description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                      type: string
+                    resourceVersion:
+                      description: 'Specific resourceVersion to which this reference
+                        is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
                       type: string
                     uid:
-                      description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
+                      description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
                       type: string
-                  required:
-                  - apiVersion
-                  - kind
-                  - name
-                  - uid
                   type: object
                 uri:
                   description: URI can alternatively be used to specify the (Camel)
diff --git a/e2e/yaks/kamelets/logger.groovy b/e2e/yaks/kamelet-binding/display.groovy
old mode 100755
new mode 100644
similarity index 84%
rename from e2e/yaks/kamelets/logger.groovy
rename to e2e/yaks/kamelet-binding/display.groovy
index a28afe3..b3ba363
--- a/e2e/yaks/kamelets/logger.groovy
+++ b/e2e/yaks/kamelet-binding/display.groovy
@@ -1,5 +1,4 @@
-// camel-k: language=groovy dependency=mvn:org.apache.camel.k:camel-kamelet:1.5.1-SNAPSHOT
-
+// camel-k: language=groovy
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -17,5 +16,7 @@
  * limitations under the License.
  */
 
-from('knative:channel/messages')
-    .log('${body}')
+from('knative:endpoint/display')
+  .log('${body}')
+  .setBody().header('CE-Type')
+  .log('type: ${body}');
diff --git a/e2e/yaks/kamelet-binding/kamelet.feature b/e2e/yaks/kamelet-binding/kamelet.feature
new file mode 100644
index 0000000..2d04ce1
--- /dev/null
+++ b/e2e/yaks/kamelet-binding/kamelet.feature
@@ -0,0 +1,5 @@
+Feature: Camel K can bind Kamelets
+
+  Scenario: Running integration using a simple Kamelet with KameletBinding
+    Given integration logger-sink-binding is running
+    Then integration logger-sink-binding should print message: Hello Kamelets
diff --git a/e2e/yaks/kamelets/timer-source-binding.yaml b/e2e/yaks/kamelet-binding/logger-sink-binding.yaml
similarity index 69%
copy from e2e/yaks/kamelets/timer-source-binding.yaml
copy to e2e/yaks/kamelet-binding/logger-sink-binding.yaml
index 32aeefb..bcdd95e 100644
--- a/e2e/yaks/kamelets/timer-source-binding.yaml
+++ b/e2e/yaks/kamelet-binding/logger-sink-binding.yaml
@@ -1,18 +1,15 @@
 apiVersion: camel.apache.org/v1alpha1
 kind: KameletBinding
 metadata:
-  name: timer-source-binding
+  name: logger-sink-binding
 spec:
   source:
     ref:
-      kind: Kamelet
-      apiVersion: camel.apache.org/v1alpha1
-      name: timer-source
-    properties:
-      message: Hello Kamelets
-      period: 1000
-  sink:
-    ref:
       kind: InMemoryChannel
       apiVersion: messaging.knative.dev/v1beta1
       name: messages
+  sink:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1alpha1
+      name: logger-sink
diff --git a/e2e/yaks/kamelets/echo-sink.kamelet.yaml b/e2e/yaks/kamelet-binding/logger-sink.kamelet.yaml
similarity index 57%
copy from e2e/yaks/kamelets/echo-sink.kamelet.yaml
copy to e2e/yaks/kamelet-binding/logger-sink.kamelet.yaml
index c21ea6b..a28fc94 100644
--- a/e2e/yaks/kamelets/echo-sink.kamelet.yaml
+++ b/e2e/yaks/kamelet-binding/logger-sink.kamelet.yaml
@@ -1,19 +1,19 @@
 apiVersion: camel.apache.org/v1alpha1
 kind: Kamelet
 metadata:
-  name: echo-sink
+  name: logger-sink
   label:
     camel.apache.org/kamelet.type: "sink"
 spec:
   definition:
-    title: "Echo"
-    description: "Replies with an echo message to each incoming event"
+    title: "Logger"
+    description: "Logs the received payload of each incoming event"
     properties:
       prefix:
         title: Prefix
-        description: The prefix to prepend to the incoming event
+        description: The prefix to prepend to the logged message
         type: string
-        default: "echo: "
+        default: "message: "
   types:
     in:
       mediaType: text/plain
@@ -23,5 +23,4 @@ spec:
     from:
       uri: "direct:{{routeId}}"
       steps:
-        - set-body:
-            simple: "{{prefix}}${body}"
+        - log: "{{prefix}}${body}"
diff --git a/e2e/yaks/kamelets/messages-channel.yaml b/e2e/yaks/kamelet-binding/messages-channel.yaml
similarity index 100%
rename from e2e/yaks/kamelets/messages-channel.yaml
rename to e2e/yaks/kamelet-binding/messages-channel.yaml
diff --git a/e2e/yaks/kamelets/timer-source-binding.yaml b/e2e/yaks/kamelet-binding/timer-source-binding-display.yaml
similarity index 52%
copy from e2e/yaks/kamelets/timer-source-binding.yaml
copy to e2e/yaks/kamelet-binding/timer-source-binding-display.yaml
index 32aeefb..b217445 100644
--- a/e2e/yaks/kamelets/timer-source-binding.yaml
+++ b/e2e/yaks/kamelet-binding/timer-source-binding-display.yaml
@@ -1,7 +1,7 @@
 apiVersion: camel.apache.org/v1alpha1
 kind: KameletBinding
 metadata:
-  name: timer-source-binding
+  name: timer-source-binding-display
 spec:
   source:
     ref:
@@ -9,10 +9,6 @@ spec:
       apiVersion: camel.apache.org/v1alpha1
       name: timer-source
     properties:
-      message: Hello Kamelets
-      period: 1000
+      message: Hello
   sink:
-    ref:
-      kind: InMemoryChannel
-      apiVersion: messaging.knative.dev/v1beta1
-      name: messages
+    uri: http://display.{namespace}.svc.cluster.local
diff --git a/e2e/yaks/kamelets/timer-source-binding.yaml b/e2e/yaks/kamelet-binding/timer-source-binding.yaml
similarity index 100%
rename from e2e/yaks/kamelets/timer-source-binding.yaml
rename to e2e/yaks/kamelet-binding/timer-source-binding.yaml
diff --git a/e2e/yaks/kamelets/timer-source.kamelet.yaml b/e2e/yaks/kamelet-binding/timer-source.kamelet.yaml
similarity index 100%
copy from e2e/yaks/kamelets/timer-source.kamelet.yaml
copy to e2e/yaks/kamelet-binding/timer-source.kamelet.yaml
diff --git a/e2e/yaks/kamelets/yaks-config.yaml b/e2e/yaks/kamelet-binding/yaks-config.yaml
similarity index 72%
copy from e2e/yaks/kamelets/yaks-config.yaml
copy to e2e/yaks/kamelet-binding/yaks-config.yaml
index 8679b79..59fec0a 100644
--- a/e2e/yaks/kamelets/yaks-config.yaml
+++ b/e2e/yaks/kamelet-binding/yaks-config.yaml
@@ -26,10 +26,14 @@ pre:
     kubectl apply -f messages-channel.yaml -n $YAKS_NAMESPACE
 
     kubectl apply -f timer-source.kamelet.yaml -n $YAKS_NAMESPACE
-    kubectl apply -f echo-sink.kamelet.yaml -n $YAKS_NAMESPACE
+    kubectl apply -f logger-sink.kamelet.yaml -n $YAKS_NAMESPACE
 
     kubectl apply -f timer-source-binding.yaml -n $YAKS_NAMESPACE
+    kubectl apply -f logger-sink-binding.yaml -n $YAKS_NAMESPACE
+
     kubectl wait kameletbinding timer-source-binding --for=condition=Ready --timeout=10m -n $YAKS_NAMESPACE
+    kubectl wait kameletbinding logger-sink-binding --for=condition=Ready --timeout=10m -n $YAKS_NAMESPACE
 
-    kamel run logger.groovy -w -n $YAKS_NAMESPACE
-    kamel run source-sink.groovy -w -n $YAKS_NAMESPACE
+    kamel run display.groovy -w -n $YAKS_NAMESPACE
+    cat timer-source-binding-display.yaml | sed  's/{namespace}/'"${YAKS_NAMESPACE}"'/' | kubectl apply -f -
+    kubectl wait kameletbinding timer-source-binding-display --for=condition=Ready --timeout=10m -n $YAKS_NAMESPACE
diff --git a/e2e/yaks/kamelets/echo-sink.kamelet.yaml b/e2e/yaks/kamelet/echo-sink.kamelet.yaml
similarity index 100%
rename from e2e/yaks/kamelets/echo-sink.kamelet.yaml
rename to e2e/yaks/kamelet/echo-sink.kamelet.yaml
diff --git a/e2e/yaks/kamelet/kamelet.feature b/e2e/yaks/kamelet/kamelet.feature
new file mode 100644
index 0000000..01aca6f
--- /dev/null
+++ b/e2e/yaks/kamelet/kamelet.feature
@@ -0,0 +1,5 @@
+Feature: Camel K can run Kamelets
+
+  Scenario: Integrations can use multiple kamelets
+    Given integration source-sink is running
+    Then integration source-sink should print nice echo: Camel K
diff --git a/e2e/yaks/kamelets/source-sink.groovy b/e2e/yaks/kamelet/source-sink.groovy
similarity index 94%
rename from e2e/yaks/kamelets/source-sink.groovy
rename to e2e/yaks/kamelet/source-sink.groovy
index 3666bad..e607a9f 100755
--- a/e2e/yaks/kamelets/source-sink.groovy
+++ b/e2e/yaks/kamelet/source-sink.groovy
@@ -17,8 +17,7 @@
  * limitations under the License.
  */
 
-from('timer:tick')
-  .setBody().constant('Camel K')
+from('kamelet:timer-source?message=Camel+K')
   .to("kamelet:echo-sink")
   .to("kamelet:echo-sink?prefix=nice+")
   .log('${body}')
diff --git a/e2e/yaks/kamelets/timer-source.kamelet.yaml b/e2e/yaks/kamelet/timer-source.kamelet.yaml
similarity index 100%
rename from e2e/yaks/kamelets/timer-source.kamelet.yaml
rename to e2e/yaks/kamelet/timer-source.kamelet.yaml
diff --git a/e2e/yaks/kamelets/yaks-config.yaml b/e2e/yaks/kamelet/yaks-config.yaml
similarity index 81%
rename from e2e/yaks/kamelets/yaks-config.yaml
rename to e2e/yaks/kamelet/yaks-config.yaml
index 8679b79..6ff2355 100644
--- a/e2e/yaks/kamelets/yaks-config.yaml
+++ b/e2e/yaks/kamelet/yaks-config.yaml
@@ -23,13 +23,7 @@ pre:
   run: |
     kamel install -n $YAKS_NAMESPACE
 
-    kubectl apply -f messages-channel.yaml -n $YAKS_NAMESPACE
-
     kubectl apply -f timer-source.kamelet.yaml -n $YAKS_NAMESPACE
     kubectl apply -f echo-sink.kamelet.yaml -n $YAKS_NAMESPACE
 
-    kubectl apply -f timer-source-binding.yaml -n $YAKS_NAMESPACE
-    kubectl wait kameletbinding timer-source-binding --for=condition=Ready --timeout=10m -n $YAKS_NAMESPACE
-
-    kamel run logger.groovy -w -n $YAKS_NAMESPACE
     kamel run source-sink.groovy -w -n $YAKS_NAMESPACE
diff --git a/e2e/yaks/kamelets/kamelet.feature b/e2e/yaks/kamelets/kamelet.feature
deleted file mode 100644
index 2a4d932..0000000
--- a/e2e/yaks/kamelets/kamelet.feature
+++ /dev/null
@@ -1,9 +0,0 @@
-Feature: Camel K can run Kamelets and bind them
-
-  Scenario: Running integration using a simple Kamelet with KameletBinding
-    Given integration logger is running
-    Then integration logger should print Hello Kamelets
-
-  Scenario: Integrations can use multiple kamelets
-    Given integration source-sink is running
-    Then integration source-sink should print nice echo: Camel K
diff --git a/helm/camel-k/crds/crd-kamelet-binding.yaml b/helm/camel-k/crds/crd-kamelet-binding.yaml
index 74575d8..53bf707 100644
--- a/helm/camel-k/crds/crd-kamelet-binding.yaml
+++ b/helm/camel-k/crds/crd-kamelet-binding.yaml
@@ -189,31 +189,35 @@ spec:
                     apiVersion:
                       description: API version of the referent.
                       type: string
-                    blockOwnerDeletion:
-                      description: If true, AND if the owner has the "foregroundDeletion"
-                        finalizer, then the owner cannot be deleted from the key-value
-                        store until this reference is removed. Defaults to false.
-                        To set this field, a user needs "delete" permission of the
-                        owner, otherwise 422 (Unprocessable Entity) will be returned.
-                      type: boolean
-                    controller:
-                      description: If true, this reference points to the managing
-                        controller.
-                      type: boolean
+                    fieldPath:
+                      description: 'If referring to a piece of an object instead of
+                        an entire object, this string should contain a valid JSON/Go
+                        field access statement, such as desiredState.manifest.containers[2].
+                        For example, if the object reference is to a container within
+                        a pod, this would take on a value like: "spec.containers{name}"
+                        (where "name" refers to the name of the container that triggered
+                        the event) or if no container name is specified "spec.containers[2]"
+                        (container with index 2 in this pod). This syntax is chosen
+                        only to have some well-defined way of referencing a part of
+                        an object. TODO: this design is not final and this field is
+                        subject to change in the future.'
+                      type: string
                     kind:
                       description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
                       type: string
                     name:
-                      description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
+                      description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                      type: string
+                    namespace:
+                      description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                      type: string
+                    resourceVersion:
+                      description: 'Specific resourceVersion to which this reference
+                        is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
                       type: string
                     uid:
-                      description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
+                      description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
                       type: string
-                  required:
-                  - apiVersion
-                  - kind
-                  - name
-                  - uid
                   type: object
                 uri:
                   description: URI can alternatively be used to specify the (Camel)
@@ -235,31 +239,35 @@ spec:
                     apiVersion:
                       description: API version of the referent.
                       type: string
-                    blockOwnerDeletion:
-                      description: If true, AND if the owner has the "foregroundDeletion"
-                        finalizer, then the owner cannot be deleted from the key-value
-                        store until this reference is removed. Defaults to false.
-                        To set this field, a user needs "delete" permission of the
-                        owner, otherwise 422 (Unprocessable Entity) will be returned.
-                      type: boolean
-                    controller:
-                      description: If true, this reference points to the managing
-                        controller.
-                      type: boolean
+                    fieldPath:
+                      description: 'If referring to a piece of an object instead of
+                        an entire object, this string should contain a valid JSON/Go
+                        field access statement, such as desiredState.manifest.containers[2].
+                        For example, if the object reference is to a container within
+                        a pod, this would take on a value like: "spec.containers{name}"
+                        (where "name" refers to the name of the container that triggered
+                        the event) or if no container name is specified "spec.containers[2]"
+                        (container with index 2 in this pod). This syntax is chosen
+                        only to have some well-defined way of referencing a part of
+                        an object. TODO: this design is not final and this field is
+                        subject to change in the future.'
+                      type: string
                     kind:
                       description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
                       type: string
                     name:
-                      description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
+                      description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                      type: string
+                    namespace:
+                      description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                      type: string
+                    resourceVersion:
+                      description: 'Specific resourceVersion to which this reference
+                        is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
                       type: string
                     uid:
-                      description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
+                      description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
                       type: string
-                  required:
-                  - apiVersion
-                  - kind
-                  - name
-                  - uid
                   type: object
                 uri:
                   description: URI can alternatively be used to specify the (Camel)
diff --git a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
index 64702c2..4214074 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
@@ -38,13 +38,20 @@ type KameletBindingSpec struct {
 // Endpoint represents a source/sink external entity
 type Endpoint struct {
 	// Ref can be used to declare a Kubernetes resource as source/sink endpoint
-	Ref *metav1.OwnerReference `json:"ref,omitempty"`
+	Ref *corev1.ObjectReference `json:"ref,omitempty"`
 	// URI can alternatively be used to specify the (Camel) endpoint explicitly
 	URI *string `json:"uri,omitempty"`
 	// Properties are a key value representation of endpoint properties
 	Properties EndpointProperties `json:"properties,omitempty"`
 }
 
+type EndpointType string
+
+const (
+	EndpointTypeSource EndpointType = "source"
+	EndpointTypeSink   EndpointType = "sink"
+)
+
 // EndpointProperties is a key/value struct represented as JSON raw to allow numeric/boolean values
 // +kubebuilder:validation:Type=object
 type EndpointProperties struct {
diff --git a/pkg/apis/camel/v1alpha1/kamelet_binding_types_support.go b/pkg/apis/camel/v1alpha1/kamelet_binding_types_support.go
index f630013..d470dc6 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_binding_types_support.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_binding_types_support.go
@@ -18,6 +18,9 @@ limitations under the License.
 package v1alpha1
 
 import (
+	"encoding/json"
+	"fmt"
+
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -137,6 +140,24 @@ func (in *KameletBindingStatus) RemoveCondition(condType KameletBindingCondition
 	in.Conditions = newConditions
 }
 
+// GetPropertyMap returns the EndpointProperties as map
+func (p EndpointProperties) GetPropertyMap() (map[string]string, error) {
+	if len(p.RawMessage) == 0 {
+		return nil, nil
+	}
+
+	// Convert json property values to objects before getting their string representation
+	var props map[string]interface{}
+	if err := json.Unmarshal(p.RawMessage, &props); err != nil {
+		return nil, err
+	}
+	stringProps := make(map[string]string, len(props))
+	for k, v := range props {
+		stringProps[k] = fmt.Sprintf("%v", v)
+	}
+	return stringProps, nil
+}
+
 // NewKameletBinding --
 func NewKameletBinding(namespace string, name string) KameletBinding {
 	return KameletBinding{
diff --git a/pkg/controller/kameletbinding/initialize.go b/pkg/controller/kameletbinding/initialize.go
index d047ae6..1054c3f 100644
--- a/pkg/controller/kameletbinding/initialize.go
+++ b/pkg/controller/kameletbinding/initialize.go
@@ -20,14 +20,11 @@ package kameletbinding
 import (
 	"context"
 	"encoding/json"
-	"fmt"
-	"net/url"
-	"strings"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/util/bindings"
 	"github.com/apache/camel-k/pkg/util/kubernetes"
-	"github.com/apache/camel-k/pkg/util/uri"
 	"github.com/pkg/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
@@ -61,40 +58,33 @@ func (action *initializeAction) Handle(ctx context.Context, kameletbinding *v1al
 		it.Spec = *kameletbinding.Spec.Integration.DeepCopy()
 	}
 
-	fromURI, err := getEndpointURI(kameletbinding.Spec.Source)
+	from, err := bindings.Translate(v1alpha1.EndpointTypeSource, kameletbinding.Spec.Source)
 	if err != nil {
 		return nil, errors.Wrap(err, "could not determine source URI")
 	}
-	toURI, err := getEndpointURI(kameletbinding.Spec.Sink)
+	to, err := bindings.Translate(v1alpha1.EndpointTypeSink, kameletbinding.Spec.Sink)
 	if err != nil {
 		return nil, errors.Wrap(err, "could not determine sink URI")
 	}
 
-	// TODO remove this after making sinkbinding the default (https://github.com/apache/camel-k/issues/1654)
-	if strings.HasPrefix(toURI, "knative:") {
-		knativeConfig := map[string]interface{}{
-			"sinkBinding": true,
-		}
-		knativeConfigJSON, err := json.Marshal(knativeConfig)
-		if err != nil {
-			return nil, err
-		}
+	if len(from.Traits) > 0 || len(to.Traits) > 0 {
 		if it.Spec.Traits == nil {
 			it.Spec.Traits = make(map[string]v1.TraitSpec)
 		}
-		it.Spec.Traits["knative"] = v1.TraitSpec{
-			Configuration: v1.TraitConfiguration{
-				RawMessage: knativeConfigJSON,
-			},
+		for k, v := range from.Traits {
+			it.Spec.Traits[k] = v
+		}
+		for k, v := range to.Traits {
+			it.Spec.Traits[k] = v
 		}
 	}
 
 	flow := map[string]interface{}{
 		"from": map[string]interface{}{
-			"uri": fromURI,
+			"uri": from.URI,
 			"steps": []map[string]interface{}{
 				{
-					"to": toURI,
+					"to": to.URI,
 				},
 			},
 		},
@@ -113,56 +103,3 @@ func (action *initializeAction) Handle(ctx context.Context, kameletbinding *v1al
 	target.Status.Phase = v1alpha1.KameletBindingPhaseCreating
 	return target, nil
 }
-
-func getEndpointURI(e v1alpha1.Endpoint) (string, error) {
-	baseURI, err := getEndpointBaseURI(e)
-	if err != nil {
-		return baseURI, err
-	}
-
-	// Convert json properties to string before using them in URI
-	if len(e.Properties.RawMessage) > 0 {
-		var props map[string]interface{}
-		if err := json.Unmarshal(e.Properties.RawMessage, &props); err != nil {
-			return "", err
-		}
-		stringProps := make(map[string]string, len(props))
-		for k, v := range props {
-			stringProps[k] = fmt.Sprintf("%v", v)
-		}
-		return uri.AppendParameters(baseURI, stringProps), nil
-	}
-
-	return baseURI, nil
-}
-
-func getEndpointBaseURI(e v1alpha1.Endpoint) (string, error) {
-	if err := validateEndpoint(e); err != nil {
-		return "", err
-	}
-
-	// return the URI if explicitly stated
-	if e.URI != nil {
-		return *e.URI, nil
-	}
-
-	// Kamelets are a known type
-	if e.Ref.Kind == v1alpha1.KameletKind {
-		return fmt.Sprintf("kamelet:%s", url.PathEscape(e.Ref.Name)), nil
-	}
-
-	// assume we're using Knative for the time being (Kafka resources may be added in the future)
-	return uri.AppendParameters(fmt.Sprintf("knative:endpoint/%s", url.PathEscape(e.Ref.Name)), map[string]string{
-		"apiVersion": e.Ref.APIVersion,
-		"kind":       e.Ref.Kind,
-	}), nil
-}
-
-func validateEndpoint(e v1alpha1.Endpoint) error {
-	if e.Ref == nil && e.URI == nil {
-		return errors.New("no ref or URI specified in endpoint")
-	} else if e.Ref != nil && e.URI != nil {
-		return errors.New("cannot use both ref and URI to specify an endpoint: only one of them should be used")
-	}
-	return nil
-}
diff --git a/pkg/util/bindings/api.go b/pkg/util/bindings/api.go
new file mode 100644
index 0000000..c9daf72
--- /dev/null
+++ b/pkg/util/bindings/api.go
@@ -0,0 +1,48 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Package bindings provides APIs to transform Kubernetes objects into Camel URIs equivalents
+package bindings
+
+import (
+	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+)
+
+const (
+	OrderFirst    = 0
+	OrderStandard = 50
+	OrderLast     = 100
+)
+
+// Binding represents how a Kubernetes object is represented in Camel K resources
+type Binding struct {
+	// URI is the Camel URI equivalent
+	URI string
+	// Traits is a partial trait specification that should be merged into the integration
+	Traits map[string]v1.TraitSpec
+}
+
+// BindingProvider maps a KameletBinding endpoint into Camel K resources
+type BindingProvider interface {
+	// ID returns the name of the binding provider
+	ID() string
+	// Translate does the actual mapping
+	Translate(endpointType v1alpha1.EndpointType, endpoint v1alpha1.Endpoint) (*Binding, error)
+	// Order returns the relative order of execution of the binding provider
+	Order() int
+}
diff --git a/pkg/util/bindings/bindings_test.go b/pkg/util/bindings/bindings_test.go
new file mode 100644
index 0000000..1f7696a
--- /dev/null
+++ b/pkg/util/bindings/bindings_test.go
@@ -0,0 +1,222 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package bindings
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/url"
+	"testing"
+
+	camelv1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+	knativeapis "github.com/apache/camel-k/pkg/apis/camel/v1/knative"
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/stretchr/testify/assert"
+	corev1 "k8s.io/api/core/v1"
+)
+
+func TestBindings(t *testing.T) {
+	testcases := []struct {
+		endpointType v1alpha1.EndpointType
+		endpoint     v1alpha1.Endpoint
+		uri          string
+		traits       map[string]camelv1.TraitSpec
+	}{
+		{
+			endpointType: v1alpha1.EndpointTypeSink,
+			endpoint: v1alpha1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       "Service",
+					APIVersion: "serving.knative.dev/v1",
+					Name:       "myservice",
+				},
+			},
+			uri: "knative:endpoint/myservice?apiVersion=serving.knative.dev%2Fv1&kind=Service",
+			traits: asTraitSpec("knative", map[string]interface{}{
+				"sinkBinding": true,
+			}),
+		},
+		{
+			endpointType: v1alpha1.EndpointTypeSink,
+			endpoint: v1alpha1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       "Service",
+					APIVersion: "serving.knative.dev/v1",
+					Name:       "myservice",
+				},
+				Properties: asEndpointProperties(map[string]string{
+					"ce.override.ce-type": "mytype",
+				}),
+			},
+			uri: "knative:endpoint/myservice?apiVersion=serving.knative.dev%2Fv1&ce.override.ce-type=mytype&kind=Service",
+			traits: asTraitSpec("knative", map[string]interface{}{
+				"sinkBinding": true,
+			}),
+		},
+		{
+			endpointType: v1alpha1.EndpointTypeSink,
+			endpoint: v1alpha1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       "Channel",
+					APIVersion: "messaging.knative.dev/v1",
+					Name:       "mychannel",
+				},
+			},
+			uri: "knative:channel/mychannel?apiVersion=messaging.knative.dev%2Fv1&kind=Channel",
+			traits: asTraitSpec("knative", map[string]interface{}{
+				"sinkBinding": true,
+			}),
+		},
+		{
+			endpointType: v1alpha1.EndpointTypeSource,
+			endpoint: v1alpha1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       "Channel",
+					APIVersion: "messaging.knative.dev/v1",
+					Name:       "mychannel",
+				},
+			},
+			uri: "knative:channel/mychannel?apiVersion=messaging.knative.dev%2Fv1&kind=Channel",
+		},
+		{
+			endpointType: v1alpha1.EndpointTypeSource,
+			endpoint: v1alpha1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       "KafkaChannel",
+					APIVersion: "messaging.knative.dev/v1beta1",
+					Name:       "mychannel",
+				},
+			},
+			uri: "knative:channel/mychannel?apiVersion=messaging.knative.dev%2Fv1beta1&kind=KafkaChannel",
+		},
+		{
+			endpointType: v1alpha1.EndpointTypeSource,
+			endpoint: v1alpha1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       "Broker",
+					APIVersion: "eventing.knative.dev/v1beta1",
+					Name:       "default",
+				},
+				Properties: asEndpointProperties(map[string]string{
+					"type": "myeventtype",
+				}),
+			},
+			uri: "knative:event/myeventtype?apiVersion=eventing.knative.dev%2Fv1beta1&kind=Broker",
+		},
+		{
+			endpoint: v1alpha1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       "Kamelet",
+					APIVersion: "camel.apache.org/v1any1",
+					Name:       "mykamelet",
+				},
+			},
+			uri: "kamelet:mykamelet",
+		},
+		{
+			endpoint: v1alpha1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       "Kamelet",
+					APIVersion: "camel.apache.org/v1any1",
+					Name:       "mykamelet",
+				},
+				Properties: asEndpointProperties(map[string]string{
+					"mymessage":   "myval",
+					"encodedkey?": "encoded=val",
+				}),
+			},
+			uri: "kamelet:mykamelet?encodedkey%3F=encoded%3Dval&mymessage=myval",
+		},
+		{
+			endpointType: v1alpha1.EndpointTypeSink,
+			endpoint: v1alpha1.Endpoint{
+				URI: asStringPointer("https://myurl/hey"),
+				Properties: asEndpointProperties(map[string]string{
+					"ce.override.ce-type": "mytype",
+				}),
+			},
+			uri: "knative:endpoint/sink?ce.override.ce-type=mytype",
+			traits: asTraitSpec("knative", map[string]interface{}{
+				"configuration": asKnativeConfig("https://myurl/hey"),
+			}),
+		},
+		{
+			endpointType: v1alpha1.EndpointTypeSink,
+			endpoint: v1alpha1.Endpoint{
+				URI: asStringPointer("docker://xxx"),
+			},
+			uri: "docker://xxx",
+		},
+	}
+
+	for i, tc := range testcases {
+		t.Run(fmt.Sprintf("test-%d-%s", i, tc.uri), func(t *testing.T) {
+			binding, err := Translate(tc.endpointType, tc.endpoint)
+			assert.NoError(t, err)
+			assert.NotNil(t, binding)
+			assert.Equal(t, tc.uri, binding.URI)
+			assert.Equal(t, tc.traits, binding.Traits)
+		})
+	}
+}
+
+func asEndpointProperties(props map[string]string) v1alpha1.EndpointProperties {
+	serialized, err := json.Marshal(props)
+	if err != nil {
+		panic(err)
+	}
+	return v1alpha1.EndpointProperties{
+		RawMessage: serialized,
+	}
+}
+
+func asTraitSpec(key string, data map[string]interface{}) map[string]camelv1.TraitSpec {
+	res := make(map[string]camelv1.TraitSpec)
+	serialized, err := json.Marshal(data)
+	if err != nil {
+		panic(err)
+	}
+	res[key] = camelv1.TraitSpec{
+		Configuration: camelv1.TraitConfiguration{
+			RawMessage: serialized,
+		},
+	}
+	return res
+}
+
+func asStringPointer(str string) *string {
+	return &str
+}
+
+func asKnativeConfig(endpointURL string) string {
+	serviceURL, err := url.Parse(endpointURL)
+	if err != nil {
+		panic(err)
+	}
+	def, err := knativeapis.BuildCamelServiceDefinition("sink", knativeapis.CamelEndpointKindSink, knativeapis.CamelServiceTypeEndpoint, *serviceURL, "", "")
+	if err != nil {
+		panic(err)
+	}
+	env := knativeapis.NewCamelEnvironment()
+	env.Services = append(env.Services, def)
+	serialized, err := json.Marshal(env)
+	if err != nil {
+		panic(err)
+	}
+	return string(serialized)
+}
diff --git a/pkg/util/bindings/camel_uri.go b/pkg/util/bindings/camel_uri.go
new file mode 100644
index 0000000..6dfea5f
--- /dev/null
+++ b/pkg/util/bindings/camel_uri.go
@@ -0,0 +1,58 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package bindings
+
+import (
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/util/uri"
+)
+
+// CamelURIBindingProvider converts an explicit URI into a Camel endpoint.
+// It's used as fallback if the URI scheme is not known by other providers.
+type CamelURIBindingProvider struct{}
+
+func (k CamelURIBindingProvider) ID() string {
+	return "camel-uri"
+}
+
+func (k CamelURIBindingProvider) Translate(endpointType v1alpha1.EndpointType, e v1alpha1.Endpoint) (*Binding, error) {
+	if e.URI == nil {
+		// works only on uris
+		return nil, nil
+	}
+
+	endpointURI := *e.URI
+	props, err := e.Properties.GetPropertyMap()
+	if err != nil {
+		return nil, err
+	}
+	endpointURI = uri.AppendParameters(endpointURI, props)
+
+	return &Binding{
+		URI: endpointURI,
+	}, nil
+}
+
+func (k CamelURIBindingProvider) Order() int {
+	// Using it as fallback
+	return OrderLast
+}
+
+func init() {
+	RegisterBindingProvider(CamelURIBindingProvider{})
+}
diff --git a/pkg/util/bindings/catalog.go b/pkg/util/bindings/catalog.go
new file mode 100644
index 0000000..0fa42ee
--- /dev/null
+++ b/pkg/util/bindings/catalog.go
@@ -0,0 +1,61 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package bindings
+
+import (
+	"errors"
+	"sort"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+)
+
+var bindingProviders []BindingProvider
+
+func RegisterBindingProvider(bp BindingProvider) {
+	bindingProviders = append(bindingProviders, bp)
+	sort.Slice(bindingProviders, func(i, j int) bool {
+		bi := bindingProviders[i]
+		bj := bindingProviders[j]
+		return (bi.Order() < bj.Order()) ||
+			(bi.Order() == bj.Order() && bi.ID() < bj.ID())
+	})
+}
+
+// Translate execute all chained binding providers, returning the first success or the first error
+func Translate(endpointType v1alpha1.EndpointType, endpoint v1alpha1.Endpoint) (*Binding, error) {
+	if err := validateEndpoint(endpoint); err != nil {
+		return nil, err
+	}
+
+	for _, bp := range bindingProviders {
+		b, err := bp.Translate(endpointType, endpoint)
+		if b != nil || err != nil {
+			return b, err
+		}
+	}
+	return nil, nil
+}
+
+func validateEndpoint(e v1alpha1.Endpoint) error {
+	if e.Ref == nil && e.URI == nil {
+		return errors.New("no ref or URI specified in endpoint")
+	} else if e.Ref != nil && e.URI != nil {
+		return errors.New("cannot use both ref and URI to specify an endpoint: only one of them should be used")
+	}
+	return nil
+}
diff --git a/pkg/util/bindings/kamelet.go b/pkg/util/bindings/kamelet.go
new file mode 100644
index 0000000..7e8d166
--- /dev/null
+++ b/pkg/util/bindings/kamelet.go
@@ -0,0 +1,68 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package bindings
+
+import (
+	"fmt"
+	"net/url"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/util/uri"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+)
+
+// KameletBindingProvider converts a reference to a Kamelet into a Camel URI
+type KameletBindingProvider struct{}
+
+func (k KameletBindingProvider) ID() string {
+	return "kamelet"
+}
+
+func (k KameletBindingProvider) Translate(endpointType v1alpha1.EndpointType, e v1alpha1.Endpoint) (*Binding, error) {
+	if e.Ref == nil {
+		// works only on refs
+		return nil, nil
+	}
+	gv, err := schema.ParseGroupVersion(e.Ref.APIVersion)
+	if err != nil {
+		return nil, err
+	}
+	// it translates only Kamelet refs
+	if e.Ref.Kind == v1alpha1.KameletKind && gv.Group == v1alpha1.SchemeGroupVersion.Group {
+		kameletURI := fmt.Sprintf("kamelet:%s", url.PathEscape(e.Ref.Name))
+
+		props, err := e.Properties.GetPropertyMap()
+		if err != nil {
+			return nil, err
+		}
+		kameletURI = uri.AppendParameters(kameletURI, props)
+
+		return &Binding{
+			URI: kameletURI,
+		}, nil
+	}
+	return nil, nil
+}
+
+func (k KameletBindingProvider) Order() int {
+	return OrderStandard
+}
+
+func init() {
+	RegisterBindingProvider(KameletBindingProvider{})
+}
diff --git a/pkg/util/bindings/knative_ref.go b/pkg/util/bindings/knative_ref.go
new file mode 100644
index 0000000..bd7f7a3
--- /dev/null
+++ b/pkg/util/bindings/knative_ref.go
@@ -0,0 +1,116 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package bindings
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/url"
+
+	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+	knativeapis "github.com/apache/camel-k/pkg/apis/camel/v1/knative"
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/util/knative"
+	"github.com/apache/camel-k/pkg/util/uri"
+)
+
+// KnativeRefBindingProvider converts a reference to a Kubernetes object into a Camel URI.
+// It's used as fallback if no other providers can decode the object reference.
+type KnativeRefBindingProvider struct{}
+
+func (k KnativeRefBindingProvider) ID() string {
+	return "knative-ref"
+}
+
+func (k KnativeRefBindingProvider) Translate(endpointType v1alpha1.EndpointType, e v1alpha1.Endpoint) (*Binding, error) {
+	if e.Ref == nil {
+		// works only on refs
+		return nil, nil
+	}
+
+	serviceType, err := knative.GetServiceType(*e.Ref)
+	if err != nil {
+		return nil, err
+	}
+
+	if serviceType == nil {
+		endpointType := knativeapis.CamelServiceTypeEndpoint
+		serviceType = &endpointType
+	}
+
+	props, err := e.Properties.GetPropertyMap()
+	if err != nil {
+		return nil, err
+	}
+	if props == nil {
+		props = make(map[string]string)
+	}
+	if props["apiVersion"] == "" {
+		props["apiVersion"] = e.Ref.APIVersion
+	}
+	if props["kind"] == "" {
+		props["kind"] = e.Ref.Kind
+	}
+
+	var serviceURI string
+	if *serviceType == knativeapis.CamelServiceTypeEvent {
+		if eventType, ok := props["type"]; ok {
+			// consume prop
+			delete(props, "type")
+			serviceURI = fmt.Sprintf("knative:%s/%s", *serviceType, eventType)
+		} else {
+			serviceURI = fmt.Sprintf("knative:%s", *serviceType)
+		}
+	} else {
+		serviceURI = fmt.Sprintf("knative:%s/%s", *serviceType, url.PathEscape(e.Ref.Name))
+	}
+
+	serviceURI = uri.AppendParameters(serviceURI, props)
+
+	var traits map[string]v1.TraitSpec
+	if endpointType == v1alpha1.EndpointTypeSink {
+		knativeConfig := make(map[string]interface{})
+		// TODO remove this after making sinkbinding the default (https://github.com/apache/camel-k/issues/1654)
+		knativeConfig["sinkBinding"] = true
+		knativeConfigJSON, err := json.Marshal(knativeConfig)
+		if err != nil {
+			return nil, err
+		}
+		traits = map[string]v1.TraitSpec{
+			"knative": {
+				Configuration: v1.TraitConfiguration{
+					RawMessage: knativeConfigJSON,
+				},
+			},
+		}
+	}
+
+	return &Binding{
+		URI:    serviceURI,
+		Traits: traits,
+	}, nil
+}
+
+func (k KnativeRefBindingProvider) Order() int {
+	// Executes as last, as it can be used as fallback for all unknown object references
+	return OrderLast
+}
+
+func init() {
+	RegisterBindingProvider(KnativeRefBindingProvider{})
+}
diff --git a/pkg/util/bindings/knative_uri.go b/pkg/util/bindings/knative_uri.go
new file mode 100644
index 0000000..0f43cfa
--- /dev/null
+++ b/pkg/util/bindings/knative_uri.go
@@ -0,0 +1,102 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package bindings
+
+import (
+	"encoding/json"
+	"net/url"
+	"strings"
+
+	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+	knativeapis "github.com/apache/camel-k/pkg/apis/camel/v1/knative"
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/util/uri"
+)
+
+// KnativeURIBindingProvider converts a HTTP/HTTPS URI into a Camel Knative endpoint (to call it via CloudEvents).
+type KnativeURIBindingProvider struct{}
+
+func (k KnativeURIBindingProvider) ID() string {
+	return "knative-uri"
+}
+
+func (k KnativeURIBindingProvider) Translate(endpointType v1alpha1.EndpointType, e v1alpha1.Endpoint) (*Binding, error) {
+	if e.URI == nil {
+		// works only on uris
+		return nil, nil
+	}
+	if !strings.HasPrefix(*e.URI, "http:") && !strings.HasPrefix(*e.URI, "https:") {
+		// only translates http/https uri to Knative calls
+		return nil, nil
+	}
+	if endpointType == v1alpha1.EndpointTypeSource {
+		// HTTP/HTTPS uri are translated to Knative endpoints only when used as sinks
+		return nil, nil
+	}
+
+	knativeConfig := make(map[string]interface{})
+	originalURI, err := url.Parse(*e.URI)
+	if err != nil {
+		return nil, err
+	}
+	env := knativeapis.NewCamelEnvironment()
+	svc, err := knativeapis.BuildCamelServiceDefinition("sink",
+		knativeapis.CamelEndpointKindSink,
+		knativeapis.CamelServiceTypeEndpoint,
+		*originalURI, "", "")
+	if err != nil {
+		return nil, err
+	}
+	env.Services = append(env.Services, svc)
+	config, err := env.Serialize()
+	if err != nil {
+		return nil, err
+	}
+	knativeConfig["configuration"] = config
+	knativeConfigJSON, err := json.Marshal(knativeConfig)
+	if err != nil {
+		return nil, err
+	}
+
+	// Rewrite URI to match the service definition
+	serviceURI := "knative:endpoint/sink"
+	props, err := e.Properties.GetPropertyMap()
+	if err != nil {
+		return nil, err
+	}
+	serviceURI = uri.AppendParameters(serviceURI, props)
+
+	return &Binding{
+		URI: serviceURI,
+		Traits: map[string]v1.TraitSpec{
+			"knative": {
+				Configuration: v1.TraitConfiguration{
+					RawMessage: knativeConfigJSON,
+				},
+			},
+		},
+	}, nil
+}
+
+func (k KnativeURIBindingProvider) Order() int {
+	return OrderStandard
+}
+
+func init() {
+	RegisterBindingProvider(KnativeURIBindingProvider{})
+}
diff --git a/pkg/util/knative/apis.go b/pkg/util/knative/apis.go
index 72607f1..67bf5b2 100644
--- a/pkg/util/knative/apis.go
+++ b/pkg/util/knative/apis.go
@@ -176,6 +176,36 @@ func FillMissingReferenceData(serviceType knativev1.CamelServiceType, ref v1.Obj
 	return refs
 }
 
+func GetServiceType(ref v1.ObjectReference) (*knativev1.CamelServiceType, error) {
+	refGV, err := schema.ParseGroupVersion(ref.APIVersion)
+	if err != nil {
+		return nil, err
+	}
+
+	for _, c := range KnownChannelKinds {
+		if c.Group == refGV.Group && c.Kind == ref.Kind {
+			channelType := knativev1.CamelServiceTypeChannel
+			return &channelType, nil
+		}
+	}
+
+	for _, c := range KnownBrokerKinds {
+		if c.Group == refGV.Group && c.Kind == ref.Kind {
+			eventType := knativev1.CamelServiceTypeEvent
+			return &eventType, nil
+		}
+	}
+
+	for _, c := range KnownEndpointKinds {
+		if c.Group == refGV.Group && c.Kind == ref.Kind {
+			endpointType := knativev1.CamelServiceTypeEndpoint
+			return &endpointType, nil
+		}
+	}
+
+	return nil, nil
+}
+
 // nolint: gocritic
 func fillMissingReferenceDataWith(serviceTypes []GroupVersionKindResource, ref v1.ObjectReference) []v1.ObjectReference {
 	list := make([]v1.ObjectReference, 0)