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 <[email protected]>
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)

Reply via email to