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 713d260d6dd3f604e5c0a09c4969eb59b4aa96c2
Author: nicolaferraro <[email protected]>
AuthorDate: Tue Sep 1 16:47:40 2020 +0200

    fix #1676: add kamelet binding resource
---
 ...pache.org.crd.yaml => crd-kamelet-binding.yaml} |  14 +-
 .../builds.camel.apache.org.crd.yaml               |   0
 .../camel-k.v1.1.0.clusterserviceversion.yaml}     |   8 +-
 .../camelcatalogs.camel.apache.org.crd.yaml        |   0
 .../integrationkits.camel.apache.org.crd.yaml      |   0
 .../integrationplatforms.camel.apache.org.crd.yaml |   0
 .../integrations.camel.apache.org.crd.yaml         |   0
 .../builds.camel.apache.org.crd.yaml               |   0
 ...l-k.v1.2.0-snapshot.clusterserviceversion.yaml} |  93 ++++++++++-
 .../camelcatalogs.camel.apache.org.crd.yaml        |   0
 .../integrationkits.camel.apache.org.crd.yaml      |   0
 .../integrationplatforms.camel.apache.org.crd.yaml |   0
 .../integrations.camel.apache.org.crd.yaml         |   0
 .../kameletbindings.camel.apache.org.crd.yaml}     |  14 +-
 .../kamelets.camel.apache.org.crd.yaml             |   0
 .../camel-k-dev/camel-k-dev.package.yaml           |   4 +-
 deploy/olm-catalog/csv-config.yaml                 |   1 +
 deploy/resources.go                                |   6 +-
 e2e/yaks/kamelets/kamelet.feature                  |   8 +-
 e2e/yaks/kamelets/{usage.groovy => logger.groovy}  |   2 +-
 .../yaks/kamelets/messages-channel.yaml            |  11 +-
 e2e/yaks/kamelets/timer-source.yaml                |  18 ++
 e2e/yaks/kamelets/yaks-config.yaml                 |   7 +-
 examples/kamelets/kamelet-binding-example.yaml     |  15 ++
 .../kamelets/messages-channel.yaml                 |  11 +-
 .../camel-k/crds/crd-kamelet-binding.yaml          |  14 +-
 pkg/apis/camel/v1alpha1/kamelet_binding_types.go   | 115 +++++++++++++
 .../v1alpha1/kamelet_binding_types_support.go      | 162 ++++++++++++++++++
 pkg/apis/camel/v1alpha1/kamelet_types_support.go   |  75 +++++++++
 pkg/apis/camel/v1alpha1/register.go                |   2 +
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go   | 165 +++++++++++++++++-
 pkg/cmd/reset.go                                   |  36 +++-
 pkg/controller/add_kameletbinding.go               |  26 +++
 pkg/controller/kamelet/common.go                   |   7 +
 pkg/controller/kameletbinding/action.go            |  54 ++++++
 pkg/controller/kameletbinding/initialize.go        | 154 +++++++++++++++++
 .../kameletbinding/kamelet_binding_controller.go   | 186 +++++++++++++++++++++
 pkg/controller/kameletbinding/log.go               |  23 +++
 pkg/controller/kameletbinding/monitor.go           |  87 ++++++++++
 pkg/event/manager.go                               |  36 ++++
 pkg/install/cluster.go                             |   5 +
 pkg/util/log/log.go                                |  12 +-
 pkg/util/uri/uri.go                                |  18 ++
 pkg/util/uri/uri_test.go                           |  53 ++++++
 44 files changed, 1374 insertions(+), 68 deletions(-)

diff --git 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/kamelets.camel.apache.org.crd.yaml
 b/deploy/crd-kamelet-binding.yaml
similarity index 86%
copy from 
deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/kamelets.camel.apache.org.crd.yaml
copy to deploy/crd-kamelet-binding.yaml
index 7d36aab..4366d36 100644
--- 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/kamelets.camel.apache.org.crd.yaml
+++ b/deploy/crd-kamelet-binding.yaml
@@ -18,7 +18,7 @@
 apiVersion: apiextensions.k8s.io/v1beta1
 kind: CustomResourceDefinition
 metadata:
-  name: kamelets.camel.apache.org
+  name: kameletbindings.camel.apache.org
   labels:
     app: "camel-k"
 spec:
@@ -32,14 +32,14 @@ spec:
   subresources:
     status: {}
   names:
-    kind: Kamelet
-    listKind: KameletList
-    plural: kamelets
-    singular: kamelet
+    kind: KameletBinding
+    listKind: KameletBindingList
+    plural: kameletbindings
+    singular: kameletbinding
     shortNames:
-    - kl
+    - klb
   additionalPrinterColumns:
   - name: Phase
     type: string
-    description: The Kamelet phase
+    description: The KameletBinding phase
     JSONPath: .status.phase
diff --git 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/builds.camel.apache.org.crd.yaml
 b/deploy/olm-catalog/camel-k-dev/1.1.0/builds.camel.apache.org.crd.yaml
similarity index 100%
copy from 
deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/builds.camel.apache.org.crd.yaml
copy to deploy/olm-catalog/camel-k-dev/1.1.0/builds.camel.apache.org.crd.yaml
diff --git 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/camel-k.v1.1.0-snapshot.clusterserviceversion.yaml
 
b/deploy/olm-catalog/camel-k-dev/1.1.0/camel-k.v1.1.0.clusterserviceversion.yaml
similarity index 98%
copy from 
deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/camel-k.v1.1.0-snapshot.clusterserviceversion.yaml
copy to 
deploy/olm-catalog/camel-k-dev/1.1.0/camel-k.v1.1.0.clusterserviceversion.yaml
index 4cc2a53..b0c1f48 100644
--- 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/camel-k.v1.1.0-snapshot.clusterserviceversion.yaml
+++ 
b/deploy/olm-catalog/camel-k-dev/1.1.0/camel-k.v1.1.0.clusterserviceversion.yaml
@@ -84,14 +84,14 @@ metadata:
     capabilities: Full Lifecycle
     categories: Integration & Delivery
     certified: "false"
-    containerImage: docker.io/apache/camel-k:1.1.0-SNAPSHOT
+    containerImage: docker.io/apache/camel-k:1.1.0
     createdAt: "2020-06-09T02:45:00Z"
     description: Apache Camel K is a lightweight integration platform, born on 
Kubernetes,
       with serverless superpowers.
     repository: https://github.com/apache/camel-k
     operators.operatorframework.io/internal-objects: 
'["builds.camel.apache.org","integrationkits.camel.apache.org","camelcatalogs.camel.apache.org"]'
     support: Camel
-  name: camel-k-operator.v1.1.0-snapshot
+  name: camel-k-operator.v1.1.0
   namespace: placeholder
 spec:
   apiservicedefinitions: {}
@@ -231,7 +231,7 @@ spec:
                   valueFrom:
                     fieldRef:
                       fieldPath: metadata.namespace
-                image: docker.io/apache/camel-k:1.1.0-SNAPSHOT
+                image: docker.io/apache/camel-k:1.1.0
                 imagePullPolicy: IfNotPresent
                 name: camel-k-operator
                 resources: {}
@@ -474,4 +474,4 @@ spec:
   selector:
     matchLabels:
       name: camel-k-operator
-  version: 1.1.0-snapshot
+  version: 1.1.0
diff --git 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/camelcatalogs.camel.apache.org.crd.yaml
 b/deploy/olm-catalog/camel-k-dev/1.1.0/camelcatalogs.camel.apache.org.crd.yaml
similarity index 100%
copy from 
deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/camelcatalogs.camel.apache.org.crd.yaml
copy to 
deploy/olm-catalog/camel-k-dev/1.1.0/camelcatalogs.camel.apache.org.crd.yaml
diff --git 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/integrationkits.camel.apache.org.crd.yaml
 
b/deploy/olm-catalog/camel-k-dev/1.1.0/integrationkits.camel.apache.org.crd.yaml
similarity index 100%
copy from 
deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/integrationkits.camel.apache.org.crd.yaml
copy to 
deploy/olm-catalog/camel-k-dev/1.1.0/integrationkits.camel.apache.org.crd.yaml
diff --git 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/integrationplatforms.camel.apache.org.crd.yaml
 
b/deploy/olm-catalog/camel-k-dev/1.1.0/integrationplatforms.camel.apache.org.crd.yaml
similarity index 100%
copy from 
deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/integrationplatforms.camel.apache.org.crd.yaml
copy to 
deploy/olm-catalog/camel-k-dev/1.1.0/integrationplatforms.camel.apache.org.crd.yaml
diff --git 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/integrations.camel.apache.org.crd.yaml
 b/deploy/olm-catalog/camel-k-dev/1.1.0/integrations.camel.apache.org.crd.yaml
similarity index 100%
copy from 
deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/integrations.camel.apache.org.crd.yaml
copy to 
deploy/olm-catalog/camel-k-dev/1.1.0/integrations.camel.apache.org.crd.yaml
diff --git 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/builds.camel.apache.org.crd.yaml
 
b/deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/builds.camel.apache.org.crd.yaml
similarity index 100%
rename from 
deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/builds.camel.apache.org.crd.yaml
rename to 
deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/builds.camel.apache.org.crd.yaml
diff --git 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/camel-k.v1.1.0-snapshot.clusterserviceversion.yaml
 
b/deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/camel-k.v1.2.0-snapshot.clusterserviceversion.yaml
similarity index 85%
rename from 
deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/camel-k.v1.1.0-snapshot.clusterserviceversion.yaml
rename to 
deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/camel-k.v1.2.0-snapshot.clusterserviceversion.yaml
index 4cc2a53..554812f 100644
--- 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/camel-k.v1.1.0-snapshot.clusterserviceversion.yaml
+++ 
b/deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/camel-k.v1.2.0-snapshot.clusterserviceversion.yaml
@@ -80,20 +80,96 @@ metadata:
           "name": "example"
         },
         "spec": {}
+      },
+      {
+        "apiVersion": "camel.apache.org/v1alpha1",
+        "kind": "Kamelet",
+        "metadata": {
+          "name": "example"
+        },
+        "spec": {
+          "definition": {
+            "description": "Produces periodic events with a custom payload",
+            "properties": {
+              "message": {
+                "description": "The message to generate",
+                "title": "Message",
+                "type": "string"
+              },
+              "period": {
+                "default": 1000,
+                "description": "The time interval between two events",
+                "title": "Period",
+                "type": "integer"
+              }
+            },
+            "required": [
+              "message"
+            ],
+            "title": "Example Timer"
+          },
+          "flow": {
+            "from": {
+              "parameters": {
+                "period": "#property:period"
+              },
+              "steps": [
+                {
+                  "set-body": {
+                    "constant": "#property:message"
+                  }
+                },
+                {
+                  "to": "direct:#property:routeId"
+                }
+              ],
+              "uri": "timer:tick"
+            }
+          }
+        }
+      },
+      {
+        "apiVersion": "camel.apache.org/v1alpha1",
+        "kind": "KameletBinding",
+        "metadata": {
+          "name": "example"
+        },
+        "spec": {
+          "source": {
+            "ref": {
+              "apiVersion": "camel.apache.org/v1alpha1",
+              "kind": "Kamelet",
+              "name": "example"
+            },
+            "properties": {
+              "message": "Hello world"
+            }
+          },
+          "sink": {
+            "ref": {
+              "apiVersion": "messaging.knative.dev/v1beta1",
+              "kind": "InMemoryChannel",
+              "name": "example"
+            }
+          }
+        }
       }]
     capabilities: Full Lifecycle
     categories: Integration & Delivery
     certified: "false"
-    containerImage: docker.io/apache/camel-k:1.1.0-SNAPSHOT
+    containerImage: docker.io/apache/camel-k:1.2.0-SNAPSHOT
     createdAt: "2020-06-09T02:45:00Z"
     description: Apache Camel K is a lightweight integration platform, born on 
Kubernetes,
       with serverless superpowers.
     repository: https://github.com/apache/camel-k
     operators.operatorframework.io/internal-objects: 
'["builds.camel.apache.org","integrationkits.camel.apache.org","camelcatalogs.camel.apache.org"]'
     support: Camel
-  name: camel-k-operator.v1.1.0-snapshot
+  name: camel-k-operator.v1.2.0-snapshot
   namespace: placeholder
 spec:
+  relatedImages:
+  - name: integration-base-image
+    image: adoptopenjdk/openjdk11:slim
   apiservicedefinitions: {}
   customresourcedefinitions:
     owned:
@@ -122,11 +198,16 @@ spec:
       kind: IntegrationPlatform
       name: integrationplatforms.camel.apache.org
       version: v1
-    - description: A Camel K Kamelet resource
+    - description: A Camel K connector
       displayName: Kamelet
       kind: Kamelet
       name: kamelets.camel.apache.org
       version: v1alpha1
+    - description: A Camel K connector binding resource
+      displayName: Kamelet Binding
+      kind: KameletBinding
+      name: kameletbindings.camel.apache.org
+      version: v1alpha1
   description: |
     Apache Camel K
     ==============
@@ -231,7 +312,7 @@ spec:
                   valueFrom:
                     fieldRef:
                       fieldPath: metadata.namespace
-                image: docker.io/apache/camel-k:1.1.0-SNAPSHOT
+                image: docker.io/apache/camel-k:1.2.0-SNAPSHOT
                 imagePullPolicy: IfNotPresent
                 name: camel-k-operator
                 resources: {}
@@ -470,8 +551,8 @@ spec:
   minKubeVersion: 1.11.0
   provider:
     name: The Apache Software Foundation
-  replaces: camel-k-operator.v1.0.0
+  replaces: camel-k-operator.v1.1.0
   selector:
     matchLabels:
       name: camel-k-operator
-  version: 1.1.0-snapshot
+  version: 1.2.0
diff --git 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/camelcatalogs.camel.apache.org.crd.yaml
 
b/deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/camelcatalogs.camel.apache.org.crd.yaml
similarity index 100%
rename from 
deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/camelcatalogs.camel.apache.org.crd.yaml
rename to 
deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/camelcatalogs.camel.apache.org.crd.yaml
diff --git 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/integrationkits.camel.apache.org.crd.yaml
 
b/deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/integrationkits.camel.apache.org.crd.yaml
similarity index 100%
rename from 
deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/integrationkits.camel.apache.org.crd.yaml
rename to 
deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/integrationkits.camel.apache.org.crd.yaml
diff --git 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/integrationplatforms.camel.apache.org.crd.yaml
 
b/deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/integrationplatforms.camel.apache.org.crd.yaml
similarity index 100%
rename from 
deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/integrationplatforms.camel.apache.org.crd.yaml
rename to 
deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/integrationplatforms.camel.apache.org.crd.yaml
diff --git 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/integrations.camel.apache.org.crd.yaml
 
b/deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/integrations.camel.apache.org.crd.yaml
similarity index 100%
rename from 
deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/integrations.camel.apache.org.crd.yaml
rename to 
deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/integrations.camel.apache.org.crd.yaml
diff --git 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/kamelets.camel.apache.org.crd.yaml
 
b/deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/kameletbindings.camel.apache.org.crd.yaml
similarity index 86%
copy from 
deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/kamelets.camel.apache.org.crd.yaml
copy to 
deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/kameletbindings.camel.apache.org.crd.yaml
index 7d36aab..4366d36 100644
--- 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/kamelets.camel.apache.org.crd.yaml
+++ 
b/deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/kameletbindings.camel.apache.org.crd.yaml
@@ -18,7 +18,7 @@
 apiVersion: apiextensions.k8s.io/v1beta1
 kind: CustomResourceDefinition
 metadata:
-  name: kamelets.camel.apache.org
+  name: kameletbindings.camel.apache.org
   labels:
     app: "camel-k"
 spec:
@@ -32,14 +32,14 @@ spec:
   subresources:
     status: {}
   names:
-    kind: Kamelet
-    listKind: KameletList
-    plural: kamelets
-    singular: kamelet
+    kind: KameletBinding
+    listKind: KameletBindingList
+    plural: kameletbindings
+    singular: kameletbinding
     shortNames:
-    - kl
+    - klb
   additionalPrinterColumns:
   - name: Phase
     type: string
-    description: The Kamelet phase
+    description: The KameletBinding phase
     JSONPath: .status.phase
diff --git 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/kamelets.camel.apache.org.crd.yaml
 
b/deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/kamelets.camel.apache.org.crd.yaml
similarity index 100%
copy from 
deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/kamelets.camel.apache.org.crd.yaml
copy to 
deploy/olm-catalog/camel-k-dev/1.2.0-snapshot/kamelets.camel.apache.org.crd.yaml
diff --git a/deploy/olm-catalog/camel-k-dev/camel-k-dev.package.yaml 
b/deploy/olm-catalog/camel-k-dev/camel-k-dev.package.yaml
index fec2def..38dc116 100644
--- a/deploy/olm-catalog/camel-k-dev/camel-k-dev.package.yaml
+++ b/deploy/olm-catalog/camel-k-dev/camel-k-dev.package.yaml
@@ -16,9 +16,7 @@
 # ---------------------------------------------------------------------------
 
 channels:
-- currentCSV: camel-k-operator.v1.1.0-snapshot
+- currentCSV: camel-k-operator.v1.2.0-snapshot
   name: stable
-- currentCSV: camel-k-operator.v1.0.0-rc2
-  name: alpha
 defaultChannel: stable
 packageName: camel-k-dev
diff --git a/deploy/olm-catalog/csv-config.yaml 
b/deploy/olm-catalog/csv-config.yaml
index a5e2dd2..6a5a21c 100644
--- a/deploy/olm-catalog/csv-config.yaml
+++ b/deploy/olm-catalog/csv-config.yaml
@@ -23,6 +23,7 @@ crd-cr-paths:
   - deploy/crd-integration-kit.yaml
   - deploy/crd-integration-platform.yaml
   - deploy/crd-kamelet.yaml
+  - deploy/crd-kamelet-binding.yaml
 role-paths:
   - deploy/operator-role-olm.yaml
   - deploy/operator-role-olm-cluster.yaml
diff --git a/deploy/resources.go b/deploy/resources.go
index 1a944c4..a07493e 100644
--- a/deploy/resources.go
+++ b/deploy/resources.go
@@ -144,8 +144,8 @@ var assets = func() http.FileSystem {
 
                        compressedContent: 
[]byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x3a\x4f\x8f\xe2\x38\xf6\xf7\x7c\x8a\xa7\xe2\xd0\x33\x52\x01\xbf\x9e\xb9\xfc\xc4\x9e\x58\xba\x4b\xcb\x76\x37\x55\x02\x7a\x46\x73\x34\xce\x23\x78\xcb\xb1\xb3\xb6\x03\x5d\xbb\xda\xef\xbe\x7a\x76\x12\x92\x90\x50\x14\xd5\xad\x95\x46\x95\x1b\xf1\xfb\xff\xdf\x2f\x0c\x60\xf8\xfd\x9e\x68\x00\x9f\x05\x47\x65\x31\x06\xa7\xc1\xed\x10\xa6\x19\xe3\x3b\x84\x95\xde\xba\x03\x33\x08\x77\x3a\x57\x31\x73\x42\x2b\xf8\x69\xba\xba\xfb\x
 [...]
                },
-               "/crd-kamelet.yaml": &vfsgen۰CompressedFileInfo{
-                       name:             "crd-kamelet.yaml",
+               "/kamelets.camel.apache.org.crd.yaml": 
&vfsgen۰CompressedFileInfo{
+                       name:             "kamelets.camel.apache.org.crd.yaml",
                        modTime:          time.Time{},
                        uncompressedSize: 1498,
 
@@ -387,7 +387,7 @@ var assets = func() http.FileSystem {
                fs["/crd-integration-kit.yaml"].(os.FileInfo),
                fs["/crd-integration-platform.yaml"].(os.FileInfo),
                fs["/crd-integration.yaml"].(os.FileInfo),
-               fs["/crd-kamelet.yaml"].(os.FileInfo),
+               fs["/kamelets.camel.apache.org.crd.yaml"].(os.FileInfo),
                fs["/operator-deployment.yaml"].(os.FileInfo),
                fs["/operator-role-binding-events.yaml"].(os.FileInfo),
                fs["/operator-role-binding-knative.yaml"].(os.FileInfo),
diff --git a/e2e/yaks/kamelets/kamelet.feature 
b/e2e/yaks/kamelets/kamelet.feature
index 3f9e170..edae8bc 100644
--- a/e2e/yaks/kamelets/kamelet.feature
+++ b/e2e/yaks/kamelets/kamelet.feature
@@ -1,5 +1,5 @@
-Feature: Camel K can run Kamelets
+Feature: Camel K can run Kamelets and bind them
 
-  Scenario: Running integration using a simple Kamelet
-    Given integration usage is running
-    Then integration usage should print Hello Kamelets
+  Scenario: Running integration using a simple Kamelet with KameletBinding
+    Given integration logger is running
+    Then integration logger should print Hello Kamelets
diff --git a/e2e/yaks/kamelets/usage.groovy b/e2e/yaks/kamelets/logger.groovy
similarity index 94%
rename from e2e/yaks/kamelets/usage.groovy
rename to e2e/yaks/kamelets/logger.groovy
index d4c5de8..a28afe3 100755
--- a/e2e/yaks/kamelets/usage.groovy
+++ b/e2e/yaks/kamelets/logger.groovy
@@ -17,5 +17,5 @@
  * limitations under the License.
  */
 
-from('kamelet:timer?message=Hello+Kamelets&period=1000')
+from('knative:channel/messages')
     .log('${body}')
diff --git a/deploy/olm-catalog/camel-k-dev/camel-k-dev.package.yaml 
b/e2e/yaks/kamelets/messages-channel.yaml
similarity index 84%
copy from deploy/olm-catalog/camel-k-dev/camel-k-dev.package.yaml
copy to e2e/yaks/kamelets/messages-channel.yaml
index fec2def..abd3483 100644
--- a/deploy/olm-catalog/camel-k-dev/camel-k-dev.package.yaml
+++ b/e2e/yaks/kamelets/messages-channel.yaml
@@ -15,10 +15,7 @@
 # limitations under the License.
 # ---------------------------------------------------------------------------
 
-channels:
-- currentCSV: camel-k-operator.v1.1.0-snapshot
-  name: stable
-- currentCSV: camel-k-operator.v1.0.0-rc2
-  name: alpha
-defaultChannel: stable
-packageName: camel-k-dev
+apiVersion: messaging.knative.dev/v1beta1
+kind: InMemoryChannel
+metadata:
+  name: messages
diff --git a/e2e/yaks/kamelets/timer-source.yaml 
b/e2e/yaks/kamelets/timer-source.yaml
new file mode 100644
index 0000000..35bfe52
--- /dev/null
+++ b/e2e/yaks/kamelets/timer-source.yaml
@@ -0,0 +1,18 @@
+apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  name: timer-source
+spec:
+  source:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1alpha1
+      name: timer
+    properties:
+      message: Hello Kamelets
+      period: "1000"
+  sink:
+    ref:
+      kind: InMemoryChannel
+      apiVersion: messaging.knative.dev/v1beta1
+      name: messages
diff --git a/e2e/yaks/kamelets/yaks-config.yaml 
b/e2e/yaks/kamelets/yaks-config.yaml
index 1df07fc..947d1c1 100644
--- a/e2e/yaks/kamelets/yaks-config.yaml
+++ b/e2e/yaks/kamelets/yaks-config.yaml
@@ -23,6 +23,11 @@ pre:
   run: |
     kamel install -n $YAKS_NAMESPACE
 
+    kubectl apply -f messages-channel.yaml -n $YAKS_NAMESPACE
+
     kubectl apply -f timer.kamelet.yaml -n $YAKS_NAMESPACE
 
-    kamel run usage.groovy -w -n $YAKS_NAMESPACE
+    kubectl apply -f timer-source.yaml -n $YAKS_NAMESPACE
+    kubectl wait kameletbinding timer-source --for=condition=Ready 
--timeout=10m -n $YAKS_NAMESPACE
+
+    kamel run logger.groovy -w -n $YAKS_NAMESPACE
diff --git a/examples/kamelets/kamelet-binding-example.yaml 
b/examples/kamelets/kamelet-binding-example.yaml
new file mode 100644
index 0000000..7e3d95d
--- /dev/null
+++ b/examples/kamelets/kamelet-binding-example.yaml
@@ -0,0 +1,15 @@
+apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  name: timer-source
+spec:
+  source:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1alpha1
+      name: timer
+  sink:
+    ref:
+      kind: InMemoryChannel
+      apiVersion: messaging.knative.dev/v1beta1
+      name: messages
diff --git a/deploy/olm-catalog/camel-k-dev/camel-k-dev.package.yaml 
b/examples/kamelets/messages-channel.yaml
similarity index 84%
copy from deploy/olm-catalog/camel-k-dev/camel-k-dev.package.yaml
copy to examples/kamelets/messages-channel.yaml
index fec2def..abd3483 100644
--- a/deploy/olm-catalog/camel-k-dev/camel-k-dev.package.yaml
+++ b/examples/kamelets/messages-channel.yaml
@@ -15,10 +15,7 @@
 # limitations under the License.
 # ---------------------------------------------------------------------------
 
-channels:
-- currentCSV: camel-k-operator.v1.1.0-snapshot
-  name: stable
-- currentCSV: camel-k-operator.v1.0.0-rc2
-  name: alpha
-defaultChannel: stable
-packageName: camel-k-dev
+apiVersion: messaging.knative.dev/v1beta1
+kind: InMemoryChannel
+metadata:
+  name: messages
diff --git 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/kamelets.camel.apache.org.crd.yaml
 b/helm/camel-k/crds/crd-kamelet-binding.yaml
similarity index 86%
rename from 
deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/kamelets.camel.apache.org.crd.yaml
rename to helm/camel-k/crds/crd-kamelet-binding.yaml
index 7d36aab..4366d36 100644
--- 
a/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/kamelets.camel.apache.org.crd.yaml
+++ b/helm/camel-k/crds/crd-kamelet-binding.yaml
@@ -18,7 +18,7 @@
 apiVersion: apiextensions.k8s.io/v1beta1
 kind: CustomResourceDefinition
 metadata:
-  name: kamelets.camel.apache.org
+  name: kameletbindings.camel.apache.org
   labels:
     app: "camel-k"
 spec:
@@ -32,14 +32,14 @@ spec:
   subresources:
     status: {}
   names:
-    kind: Kamelet
-    listKind: KameletList
-    plural: kamelets
-    singular: kamelet
+    kind: KameletBinding
+    listKind: KameletBindingList
+    plural: kameletbindings
+    singular: kameletbinding
     shortNames:
-    - kl
+    - klb
   additionalPrinterColumns:
   - name: Phase
     type: string
-    description: The Kamelet phase
+    description: The KameletBinding phase
     JSONPath: .status.phase
diff --git a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go 
b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
new file mode 100644
index 0000000..844f5f0
--- /dev/null
+++ b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
@@ -0,0 +1,115 @@
+/*
+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 v1alpha1
+
+import (
+       v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+       corev1 "k8s.io/api/core/v1"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// KameletBindingSpec --
+type KameletBindingSpec struct {
+       // Integration is an optional integration used to specify custom 
parameters
+       Integration *v1.IntegrationSpec `json:"integration,omitempty"`
+       // Source is the starting point of the integration defined by this 
binding
+       Source Endpoint `json:"source,omitempty"`
+       // Sink is the destination of the integration defined by this binding
+       Sink Endpoint `json:"sink,omitempty"`
+}
+
+// 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"`
+       // 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 map[string]string `json:"properties,omitempty"`
+}
+
+// KameletBindingStatus --
+type KameletBindingStatus struct {
+       // Phase --
+       Phase KameletBindingPhase `json:"phase,omitempty"`
+       // Conditions --
+       Conditions []KameletBindingCondition `json:"conditions,omitempty"`
+}
+
+// KameletBindingCondition describes the state of a resource at a certain 
point.
+type KameletBindingCondition struct {
+       // Type of kameletBinding condition.
+       Type KameletBindingConditionType `json:"type"`
+       // Status of the condition, one of True, False, Unknown.
+       Status corev1.ConditionStatus `json:"status"`
+       // The last time this condition was updated.
+       LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"`
+       // Last time the condition transitioned from one status to another.
+       LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
+       // The reason for the condition's last transition.
+       Reason string `json:"reason,omitempty"`
+       // A human readable message indicating details about the transition.
+       Message string `json:"message,omitempty"`
+}
+
+type KameletBindingConditionType string
+
+const (
+       // KameletBindingConditionReady --
+       KameletBindingConditionReady KameletBindingConditionType = "Ready"
+)
+
+type KameletBindingPhase string
+
+const (
+       // KameletKind --
+       KameletBindingKind string = "KameletBinding"
+
+       // KameletBindingPhaseNone --
+       KameletBindingPhaseNone KameletBindingPhase = ""
+       // KameletBindingPhaseCreating --
+       KameletBindingPhaseCreating KameletBindingPhase = "Creating"
+       // KameletBindingPhaseError --
+       KameletBindingPhaseError KameletBindingPhase = "Error"
+       // KameletBindingPhaseReady --
+       KameletBindingPhaseReady KameletBindingPhase = "Ready"
+)
+
+// KameletBinding is the Schema for the kamelets binding API
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +k8s:openapi-gen=true
+// +genclient
+// 
+kubebuilder:resource:path=kameletbindings,scope=Namespaced,shortName=klb,categories=kamel;camel
+// +kubebuilder:subresource:status
+// 
+kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase`,description="The
 Kamelet Binding phase"
+type KameletBinding struct {
+       metav1.TypeMeta   `json:",inline"`
+       metav1.ObjectMeta `json:"metadata,omitempty"`
+
+       Spec   KameletBindingSpec   `json:"spec,omitempty"`
+       Status KameletBindingStatus `json:"status,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// KameletBindingList contains a list of KameletBinding
+type KameletBindingList struct {
+       metav1.TypeMeta `json:",inline"`
+       metav1.ListMeta `json:"metadata,omitempty"`
+       Items           []KameletBinding `json:"items"`
+}
diff --git a/pkg/apis/camel/v1alpha1/kamelet_binding_types_support.go 
b/pkg/apis/camel/v1alpha1/kamelet_binding_types_support.go
new file mode 100644
index 0000000..f630013
--- /dev/null
+++ b/pkg/apis/camel/v1alpha1/kamelet_binding_types_support.go
@@ -0,0 +1,162 @@
+/*
+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 v1alpha1
+
+import (
+       v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+       corev1 "k8s.io/api/core/v1"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// GetConditions --
+func (in *KameletBindingStatus) GetConditions() []v1.ResourceCondition {
+       res := make([]v1.ResourceCondition, 0, len(in.Conditions))
+       for _, c := range in.Conditions {
+               res = append(res, c)
+       }
+       return res
+}
+
+// GetType --
+func (c KameletBindingCondition) GetType() string {
+       return string(c.Type)
+}
+
+// GetStatus --
+func (c KameletBindingCondition) GetStatus() corev1.ConditionStatus {
+       return c.Status
+}
+
+// GetLastUpdateTime --
+func (c KameletBindingCondition) GetLastUpdateTime() metav1.Time {
+       return c.LastUpdateTime
+}
+
+// GetLastTransitionTime --
+func (c KameletBindingCondition) GetLastTransitionTime() metav1.Time {
+       return c.LastTransitionTime
+}
+
+// GetReason --
+func (c KameletBindingCondition) GetReason() string {
+       return c.Reason
+}
+
+// GetMessage --
+func (c KameletBindingCondition) GetMessage() string {
+       return c.Message
+}
+
+// GetCondition returns the condition with the provided type.
+func (in *KameletBindingStatus) GetCondition(condType 
KameletBindingConditionType) *KameletBindingCondition {
+       for i := range in.Conditions {
+               c := in.Conditions[i]
+               if c.Type == condType {
+                       return &c
+               }
+       }
+       return nil
+}
+
+// SetCondition --
+func (in *KameletBindingStatus) SetCondition(condType 
KameletBindingConditionType, status corev1.ConditionStatus, reason string, 
message string) {
+       in.SetConditions(KameletBindingCondition{
+               Type:               condType,
+               Status:             status,
+               LastUpdateTime:     metav1.Now(),
+               LastTransitionTime: metav1.Now(),
+               Reason:             reason,
+               Message:            message,
+       })
+}
+
+// SetErrorCondition --
+func (in *KameletBindingStatus) SetErrorCondition(condType 
KameletBindingConditionType, reason string, err error) {
+       in.SetConditions(KameletBindingCondition{
+               Type:               condType,
+               Status:             corev1.ConditionFalse,
+               LastUpdateTime:     metav1.Now(),
+               LastTransitionTime: metav1.Now(),
+               Reason:             reason,
+               Message:            err.Error(),
+       })
+}
+
+// SetConditions updates the resource to include the provided conditions.
+//
+// If a condition that we are about to add already exists and has the same 
status and
+// reason then we are not going to update.
+func (in *KameletBindingStatus) SetConditions(conditions 
...KameletBindingCondition) {
+       for _, condition := range conditions {
+               if condition.LastUpdateTime.IsZero() {
+                       condition.LastUpdateTime = metav1.Now()
+               }
+               if condition.LastTransitionTime.IsZero() {
+                       condition.LastTransitionTime = metav1.Now()
+               }
+
+               currentCond := in.GetCondition(condition.Type)
+
+               if currentCond != nil && currentCond.Status == condition.Status 
&& currentCond.Reason == condition.Reason {
+                       return
+               }
+               // Do not update lastTransitionTime if the status of the 
condition doesn't change.
+               if currentCond != nil && currentCond.Status == condition.Status 
{
+                       condition.LastTransitionTime = 
currentCond.LastTransitionTime
+               }
+
+               in.RemoveCondition(condition.Type)
+               in.Conditions = append(in.Conditions, condition)
+       }
+}
+
+// RemoveCondition removes the resource condition with the provided type.
+func (in *KameletBindingStatus) RemoveCondition(condType 
KameletBindingConditionType) {
+       newConditions := in.Conditions[:0]
+       for _, c := range in.Conditions {
+               if c.Type != condType {
+                       newConditions = append(newConditions, c)
+               }
+       }
+
+       in.Conditions = newConditions
+}
+
+// NewKameletBinding --
+func NewKameletBinding(namespace string, name string) KameletBinding {
+       return KameletBinding{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: SchemeGroupVersion.String(),
+                       Kind:       KameletBindingKind,
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: namespace,
+                       Name:      name,
+               },
+       }
+}
+
+// NewKameletBindingList --
+func NewKameletBindingList() KameletBindingList {
+       return KameletBindingList{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: SchemeGroupVersion.String(),
+                       Kind:       KameletBindingKind,
+               },
+       }
+}
diff --git a/pkg/apis/camel/v1alpha1/kamelet_types_support.go 
b/pkg/apis/camel/v1alpha1/kamelet_types_support.go
index b4f25c1..9a9fcfd 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_types_support.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_types_support.go
@@ -61,3 +61,78 @@ func (c KameletCondition) GetReason() string {
 func (c KameletCondition) GetMessage() string {
        return c.Message
 }
+
+// GetCondition returns the condition with the provided type.
+func (in *KameletStatus) GetCondition(condType KameletConditionType) 
*KameletCondition {
+       for i := range in.Conditions {
+               c := in.Conditions[i]
+               if c.Type == condType {
+                       return &c
+               }
+       }
+       return nil
+}
+
+// SetCondition --
+func (in *KameletStatus) SetCondition(condType KameletConditionType, status 
corev1.ConditionStatus, reason string, message string) {
+       in.SetConditions(KameletCondition{
+               Type:               condType,
+               Status:             status,
+               LastUpdateTime:     metav1.Now(),
+               LastTransitionTime: metav1.Now(),
+               Reason:             reason,
+               Message:            message,
+       })
+}
+
+// SetErrorCondition --
+func (in *KameletStatus) SetErrorCondition(condType KameletConditionType, 
reason string, err error) {
+       in.SetConditions(KameletCondition{
+               Type:               condType,
+               Status:             corev1.ConditionFalse,
+               LastUpdateTime:     metav1.Now(),
+               LastTransitionTime: metav1.Now(),
+               Reason:             reason,
+               Message:            err.Error(),
+       })
+}
+
+// SetConditions updates the resource to include the provided conditions.
+//
+// If a condition that we are about to add already exists and has the same 
status and
+// reason then we are not going to update.
+func (in *KameletStatus) SetConditions(conditions ...KameletCondition) {
+       for _, condition := range conditions {
+               if condition.LastUpdateTime.IsZero() {
+                       condition.LastUpdateTime = metav1.Now()
+               }
+               if condition.LastTransitionTime.IsZero() {
+                       condition.LastTransitionTime = metav1.Now()
+               }
+
+               currentCond := in.GetCondition(condition.Type)
+
+               if currentCond != nil && currentCond.Status == condition.Status 
&& currentCond.Reason == condition.Reason {
+                       return
+               }
+               // Do not update lastTransitionTime if the status of the 
condition doesn't change.
+               if currentCond != nil && currentCond.Status == condition.Status 
{
+                       condition.LastTransitionTime = 
currentCond.LastTransitionTime
+               }
+
+               in.RemoveCondition(condition.Type)
+               in.Conditions = append(in.Conditions, condition)
+       }
+}
+
+// RemoveCondition removes the resource condition with the provided type.
+func (in *KameletStatus) RemoveCondition(condType KameletConditionType) {
+       newConditions := in.Conditions[:0]
+       for _, c := range in.Conditions {
+               if c.Type != condType {
+                       newConditions = append(newConditions, c)
+               }
+       }
+
+       in.Conditions = newConditions
+}
diff --git a/pkg/apis/camel/v1alpha1/register.go 
b/pkg/apis/camel/v1alpha1/register.go
index 5bafade..5ae4530 100644
--- a/pkg/apis/camel/v1alpha1/register.go
+++ b/pkg/apis/camel/v1alpha1/register.go
@@ -49,6 +49,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
        scheme.AddKnownTypes(SchemeGroupVersion,
                &Kamelet{},
                &KameletList{},
+               &KameletBinding{},
+               &KameletBindingList{},
        )
        metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
        return nil
diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go 
b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index 2014759..32596ba 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -7,7 +7,8 @@ package v1alpha1
 import (
        json "encoding/json"
 
-       v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+       camelv1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+       v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
        runtime "k8s.io/apimachinery/pkg/runtime"
 )
 
@@ -28,6 +29,39 @@ func (in *AuthorizationSpec) DeepCopy() *AuthorizationSpec {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *Endpoint) DeepCopyInto(out *Endpoint) {
+       *out = *in
+       if in.Ref != nil {
+               in, out := &in.Ref, &out.Ref
+               *out = new(v1.OwnerReference)
+               (*in).DeepCopyInto(*out)
+       }
+       if in.URI != nil {
+               in, out := &in.URI, &out.URI
+               *out = new(string)
+               **out = **in
+       }
+       if in.Properties != nil {
+               in, out := &in.Properties, &out.Properties
+               *out = make(map[string]string, len(*in))
+               for key, val := range *in {
+                       (*out)[key] = val
+               }
+       }
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new Endpoint.
+func (in *Endpoint) DeepCopy() *Endpoint {
+       if in == nil {
+               return nil
+       }
+       out := new(Endpoint)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
 func (in *EventTypeSpec) DeepCopyInto(out *EventTypeSpec) {
        *out = *in
        if in.Schema != nil {
@@ -431,6 +465,131 @@ func (in *Kamelet) DeepCopyObject() runtime.Object {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *KameletBinding) DeepCopyInto(out *KameletBinding) {
+       *out = *in
+       out.TypeMeta = in.TypeMeta
+       in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+       in.Spec.DeepCopyInto(&out.Spec)
+       in.Status.DeepCopyInto(&out.Status)
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new KameletBinding.
+func (in *KameletBinding) DeepCopy() *KameletBinding {
+       if in == nil {
+               return nil
+       }
+       out := new(KameletBinding)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, 
creating a new runtime.Object.
+func (in *KameletBinding) DeepCopyObject() runtime.Object {
+       if c := in.DeepCopy(); c != nil {
+               return c
+       }
+       return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *KameletBindingCondition) DeepCopyInto(out *KameletBindingCondition) {
+       *out = *in
+       in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime)
+       in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new KameletBindingCondition.
+func (in *KameletBindingCondition) DeepCopy() *KameletBindingCondition {
+       if in == nil {
+               return nil
+       }
+       out := new(KameletBindingCondition)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *KameletBindingList) DeepCopyInto(out *KameletBindingList) {
+       *out = *in
+       out.TypeMeta = in.TypeMeta
+       in.ListMeta.DeepCopyInto(&out.ListMeta)
+       if in.Items != nil {
+               in, out := &in.Items, &out.Items
+               *out = make([]KameletBinding, len(*in))
+               for i := range *in {
+                       (*in)[i].DeepCopyInto(&(*out)[i])
+               }
+       }
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new KameletBindingList.
+func (in *KameletBindingList) DeepCopy() *KameletBindingList {
+       if in == nil {
+               return nil
+       }
+       out := new(KameletBindingList)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, 
creating a new runtime.Object.
+func (in *KameletBindingList) DeepCopyObject() runtime.Object {
+       if c := in.DeepCopy(); c != nil {
+               return c
+       }
+       return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *KameletBindingSpec) DeepCopyInto(out *KameletBindingSpec) {
+       *out = *in
+       if in.Integration != nil {
+               in, out := &in.Integration, &out.Integration
+               *out = new(camelv1.IntegrationSpec)
+               (*in).DeepCopyInto(*out)
+       }
+       in.Source.DeepCopyInto(&out.Source)
+       in.Sink.DeepCopyInto(&out.Sink)
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new KameletBindingSpec.
+func (in *KameletBindingSpec) DeepCopy() *KameletBindingSpec {
+       if in == nil {
+               return nil
+       }
+       out := new(KameletBindingSpec)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *KameletBindingStatus) DeepCopyInto(out *KameletBindingStatus) {
+       *out = *in
+       if in.Conditions != nil {
+               in, out := &in.Conditions, &out.Conditions
+               *out = make([]KameletBindingCondition, len(*in))
+               for i := range *in {
+                       (*in)[i].DeepCopyInto(&(*out)[i])
+               }
+       }
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new KameletBindingStatus.
+func (in *KameletBindingStatus) DeepCopy() *KameletBindingStatus {
+       if in == nil {
+               return nil
+       }
+       out := new(KameletBindingStatus)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
 func (in *KameletCondition) DeepCopyInto(out *KameletCondition) {
        *out = *in
        in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime)
@@ -503,14 +662,14 @@ func (in *KameletSpec) DeepCopyInto(out *KameletSpec) {
        in.Definition.DeepCopyInto(&out.Definition)
        if in.Sources != nil {
                in, out := &in.Sources, &out.Sources
-               *out = make([]v1.SourceSpec, len(*in))
+               *out = make([]camelv1.SourceSpec, len(*in))
                for i := range *in {
                        (*in)[i].DeepCopyInto(&(*out)[i])
                }
        }
        if in.Flow != nil {
                in, out := &in.Flow, &out.Flow
-               *out = new(v1.Flow)
+               *out = new(camelv1.Flow)
                (*in).DeepCopyInto(*out)
        }
        out.Authorization = in.Authorization
diff --git a/pkg/cmd/reset.go b/pkg/cmd/reset.go
index e45f174..f6fa6f6 100644
--- a/pkg/cmd/reset.go
+++ b/pkg/cmd/reset.go
@@ -20,13 +20,12 @@ package cmd
 import (
        "fmt"
 
+       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/client"
        "github.com/pkg/errors"
        "github.com/spf13/cobra"
-
        k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
-
-       v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
-       "github.com/apache/camel-k/pkg/client"
 )
 
 func newCmdReset(rootCmdOptions *RootCmdOptions) (*cobra.Command, 
*resetCmdOptions) {
@@ -49,8 +48,9 @@ func newCmdReset(rootCmdOptions *RootCmdOptions) 
(*cobra.Command, *resetCmdOptio
 
 type resetCmdOptions struct {
        *RootCmdOptions
-       SkipKits         bool `mapstructure:"skip-kits"`
-       SkipIntegrations bool `mapstructure:"skip-integrations"`
+       SkipKits            bool `mapstructure:"skip-kits"`
+       SkipIntegrations    bool `mapstructure:"skip-integrations"`
+       SkipKameletBindings bool `mapstructure:"skip-kamelet-bindings"`
 }
 
 func (o *resetCmdOptions) reset(_ *cobra.Command, _ []string) {
@@ -74,7 +74,15 @@ func (o *resetCmdOptions) reset(_ *cobra.Command, _ 
[]string) {
                        fmt.Print(err)
                        return
                }
-               fmt.Printf("%d integration Kits deleted from namespace %s\n", 
n, o.Namespace)
+               fmt.Printf("%d integration kits deleted from namespace %s\n", 
n, o.Namespace)
+       }
+
+       if !o.SkipKameletBindings {
+               if n, err = o.deleteAllKameletBindings(c); err != nil {
+                       fmt.Print(err)
+                       return
+               }
+               fmt.Printf("%d kamelet bindings deleted from namespace %s\n", 
n, o.Namespace)
        }
 
        if err = o.resetIntegrationPlatform(c); err != nil {
@@ -113,6 +121,20 @@ func (o *resetCmdOptions) deleteAllIntegrationKits(c 
client.Client) (int, error)
        return len(list.Items), nil
 }
 
+func (o *resetCmdOptions) deleteAllKameletBindings(c client.Client) (int, 
error) {
+       list := v1alpha1.NewKameletBindingList()
+       if err := c.List(o.Context, &list, k8sclient.InNamespace(o.Namespace)); 
err != nil {
+               return 0, errors.Wrap(err, fmt.Sprintf("could not retrieve 
kamelet bindings from namespace %s", o.Namespace))
+       }
+       for _, i := range list.Items {
+               klb := i
+               if err := c.Delete(o.Context, &klb); err != nil {
+                       return 0, errors.Wrap(err, fmt.Sprintf("could not 
delete kamelet binding %s from namespace %s", klb.Name, klb.Namespace))
+               }
+       }
+       return len(list.Items), nil
+}
+
 func (o *resetCmdOptions) resetIntegrationPlatform(c client.Client) error {
        list := v1.NewIntegrationPlatformList()
        if err := c.List(o.Context, &list, k8sclient.InNamespace(o.Namespace)); 
err != nil {
diff --git a/pkg/controller/add_kameletbinding.go 
b/pkg/controller/add_kameletbinding.go
new file mode 100644
index 0000000..480c4df
--- /dev/null
+++ b/pkg/controller/add_kameletbinding.go
@@ -0,0 +1,26 @@
+/*
+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 controller
+
+import (
+       "github.com/apache/camel-k/pkg/controller/kameletbinding"
+)
+
+func init() {
+       // AddToManagerFuncs is a list of functions to create controllers and 
add them to a manager.
+       AddToManagerFuncs = append(AddToManagerFuncs, kameletbinding.Add)
+}
diff --git a/pkg/controller/kamelet/common.go b/pkg/controller/kamelet/common.go
index d95b27a..8b75ffd 100644
--- a/pkg/controller/kamelet/common.go
+++ b/pkg/controller/kamelet/common.go
@@ -7,11 +7,18 @@ import (
 
        "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
        "github.com/pkg/errors"
+       corev1 "k8s.io/api/core/v1"
 )
 
 func updateStatus(kamelet *v1alpha1.Kamelet) (*v1alpha1.Kamelet, error) {
        target := kamelet.DeepCopy()
        target.Status.Phase = v1alpha1.KameletPhaseReady
+       target.Status.SetCondition(
+               v1alpha1.KameletConditionReady,
+               corev1.ConditionTrue,
+               "",
+               "",
+       )
        if err := recomputeProperties(target); err != nil {
                return nil, err
        }
diff --git a/pkg/controller/kameletbinding/action.go 
b/pkg/controller/kameletbinding/action.go
new file mode 100644
index 0000000..b0688c0
--- /dev/null
+++ b/pkg/controller/kameletbinding/action.go
@@ -0,0 +1,54 @@
+/*
+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 kameletbinding
+
+import (
+       "context"
+
+       "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+       "github.com/apache/camel-k/pkg/client"
+       "github.com/apache/camel-k/pkg/util/log"
+)
+
+// Action --
+type Action interface {
+       client.Injectable
+       log.Injectable
+
+       // a user friendly name for the action
+       Name() string
+
+       // returns true if the action can handle the kameletBinding
+       CanHandle(kamelet *v1alpha1.KameletBinding) bool
+
+       // executes the handling function
+       Handle(ctx context.Context, kamelet *v1alpha1.KameletBinding) 
(*v1alpha1.KameletBinding, error)
+}
+
+type baseAction struct {
+       client client.Client
+       L      log.Logger
+}
+
+func (action *baseAction) InjectClient(client client.Client) {
+       action.client = client
+}
+
+func (action *baseAction) InjectLogger(log log.Logger) {
+       action.L = log
+}
diff --git a/pkg/controller/kameletbinding/initialize.go 
b/pkg/controller/kameletbinding/initialize.go
new file mode 100644
index 0000000..dd43839
--- /dev/null
+++ b/pkg/controller/kameletbinding/initialize.go
@@ -0,0 +1,154 @@
+/*
+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 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/kubernetes"
+       "github.com/apache/camel-k/pkg/util/uri"
+       "github.com/pkg/errors"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// NewInitializeAction returns a action that initializes the kamelet binding 
configuration when not provided by the user
+func NewInitializeAction() Action {
+       return &initializeAction{}
+}
+
+type initializeAction struct {
+       baseAction
+}
+
+func (action *initializeAction) Name() string {
+       return "initialize"
+}
+
+func (action *initializeAction) CanHandle(kameletbinding 
*v1alpha1.KameletBinding) bool {
+       return kameletbinding.Status.Phase == v1alpha1.KameletBindingPhaseNone
+}
+
+func (action *initializeAction) Handle(ctx context.Context, kameletbinding 
*v1alpha1.KameletBinding) (*v1alpha1.KameletBinding, error) {
+       it := v1.Integration{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: kameletbinding.Namespace,
+                       Name:      kameletbinding.Name,
+               },
+       }
+       // start from the integration spec defined in the binding
+       if kameletbinding.Spec.Integration != nil {
+               it.Spec = *kameletbinding.Spec.Integration.DeepCopy()
+       }
+
+       fromURI, err := getEndpointURI(kameletbinding.Spec.Source)
+       if err != nil {
+               return nil, errors.Wrap(err, "could not determine source URI")
+       }
+       toURI, err := getEndpointURI(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 it.Spec.Traits == nil {
+                       it.Spec.Traits = make(map[string]v1.TraitSpec)
+               }
+               it.Spec.Traits["knative"] = v1.TraitSpec{
+                       Configuration: v1.TraitConfiguration{
+                               RawMessage: knativeConfigJSON,
+                       },
+               }
+       }
+
+       flow := map[string]interface{}{
+               "from": map[string]interface{}{
+                       "uri": fromURI,
+                       "steps": []map[string]interface{}{
+                               {
+                                       "to": toURI,
+                               },
+                       },
+               },
+       }
+       encodedFlow, err := json.Marshal(flow)
+       if err != nil {
+               return nil, err
+       }
+       it.Spec.Flows = append(it.Spec.Flows, v1.Flow{RawMessage: encodedFlow})
+
+       if err := kubernetes.ReplaceResource(ctx, action.client, &it); err != 
nil {
+               return nil, errors.Wrap(err, "could not create integration for 
kamelet binding")
+       }
+
+       target := kameletbinding.DeepCopy()
+       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
+       }
+       return uri.AppendParameters(baseURI, e.Properties), 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/controller/kameletbinding/kamelet_binding_controller.go 
b/pkg/controller/kameletbinding/kamelet_binding_controller.go
new file mode 100644
index 0000000..459c69c
--- /dev/null
+++ b/pkg/controller/kameletbinding/kamelet_binding_controller.go
@@ -0,0 +1,186 @@
+/*
+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 kameletbinding
+
+import (
+       "context"
+       "time"
+
+       "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+       "github.com/apache/camel-k/pkg/client"
+       camelevent "github.com/apache/camel-k/pkg/event"
+       "k8s.io/apimachinery/pkg/api/errors"
+       "k8s.io/apimachinery/pkg/runtime"
+       "k8s.io/client-go/tools/record"
+       k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
+       "sigs.k8s.io/controller-runtime/pkg/controller"
+       "sigs.k8s.io/controller-runtime/pkg/event"
+       "sigs.k8s.io/controller-runtime/pkg/handler"
+       "sigs.k8s.io/controller-runtime/pkg/manager"
+       "sigs.k8s.io/controller-runtime/pkg/predicate"
+       "sigs.k8s.io/controller-runtime/pkg/reconcile"
+       "sigs.k8s.io/controller-runtime/pkg/source"
+)
+
+// Add creates a new KameletBinding Controller and adds it to the Manager. The 
Manager will set fields on the Controller
+// and Start it when the Manager is Started.
+func Add(mgr manager.Manager) error {
+       c, err := client.FromManager(mgr)
+       if err != nil {
+               return err
+       }
+       return add(mgr, newReconciler(mgr, c))
+}
+
+// newReconciler returns a new reconcile.Reconciler
+func newReconciler(mgr manager.Manager, c client.Client) reconcile.Reconciler {
+       return &ReconcileKameletBinding{
+               client:   c,
+               scheme:   mgr.GetScheme(),
+               recorder: 
mgr.GetEventRecorderFor("camel-k-kamelet-binding-controller"),
+       }
+}
+
+// add adds a new Controller to mgr with r as the reconcile.Reconciler
+func add(mgr manager.Manager, r reconcile.Reconciler) error {
+       // Create a new controller
+       c, err := controller.New("kamelet-binding-controller", mgr, 
controller.Options{Reconciler: r})
+       if err != nil {
+               return err
+       }
+
+       // Watch for changes to primary resource KameletBinding
+       err = c.Watch(&source.Kind{Type: &v1alpha1.KameletBinding{}}, 
&handler.EnqueueRequestForObject{}, predicate.Funcs{
+               UpdateFunc: func(e event.UpdateEvent) bool {
+                       oldKameletBinding := 
e.ObjectOld.(*v1alpha1.KameletBinding)
+                       newKameletBinding := 
e.ObjectNew.(*v1alpha1.KameletBinding)
+                       // Ignore updates to the kameletBinding status in which 
case metadata.Generation
+                       // does not change, or except when the kameletBinding 
phase changes as it's used
+                       // to transition from one phase to another
+                       return oldKameletBinding.Generation != 
newKameletBinding.Generation ||
+                               oldKameletBinding.Status.Phase != 
newKameletBinding.Status.Phase
+               },
+               DeleteFunc: func(e event.DeleteEvent) bool {
+                       // Evaluates to false if the object has been confirmed 
deleted
+                       return !e.DeleteStateUnknown
+               },
+       })
+       if err != nil {
+               return err
+       }
+
+       return nil
+}
+
+var _ reconcile.Reconciler = &ReconcileKameletBinding{}
+
+// ReconcileKameletBinding reconciles a KameletBinding object
+type ReconcileKameletBinding struct {
+       // This client, initialized using mgr.Client() above, is a split client
+       // that reads objects from the cache and writes to the apiserver
+       client   client.Client
+       scheme   *runtime.Scheme
+       recorder record.EventRecorder
+}
+
+// Reconcile reads that state of the cluster for a KameletBinding object and 
makes changes based
+// on the state read and what is in the KameletBinding.Spec
+// Note:
+// The Controller will requeue the Request to be processed again if the 
returned error is non-nil or
+// Result.Requeue is true, otherwise upon completion it will remove the work 
from the queue.
+func (r *ReconcileKameletBinding) Reconcile(request reconcile.Request) 
(reconcile.Result, error) {
+       rlog := Log.WithValues("request-namespace", request.Namespace, 
"request-name", request.Name)
+       rlog.Info("Reconciling KameletBinding")
+
+       ctx := context.TODO()
+
+       // Fetch the KameletBinding instance
+       var instance v1alpha1.KameletBinding
+
+       if err := r.client.Get(ctx, request.NamespacedName, &instance); err != 
nil {
+               if errors.IsNotFound(err) {
+                       // Request object not found, could have been deleted 
after reconcile request.
+                       // Owned objects are automatically garbage collected. 
For additional cleanup
+                       // logic use finalizers.
+
+                       // Return and don't requeue
+                       return reconcile.Result{}, nil
+               }
+               // Error reading the object - requeue the request.
+               return reconcile.Result{}, err
+       }
+
+       actions := []Action{
+               NewInitializeAction(),
+               NewMonitorAction(),
+       }
+
+       var targetPhase v1alpha1.KameletBindingPhase
+       var err error
+
+       target := instance.DeepCopy()
+       targetLog := rlog.ForKameletBinding(target)
+
+       for _, a := range actions {
+               a.InjectClient(r.client)
+               a.InjectLogger(targetLog)
+
+               if a.CanHandle(target) {
+                       targetLog.Infof("Invoking action %s", a.Name())
+
+                       phaseFrom := target.Status.Phase
+
+                       target, err = a.Handle(ctx, target)
+                       if err != nil {
+                               camelevent.NotifyKameletBindingError(ctx, 
r.client, r.recorder, &instance, target, err)
+                               return reconcile.Result{}, err
+                       }
+
+                       if target != nil {
+                               if err := r.client.Status().Patch(ctx, target, 
k8sclient.MergeFrom(&instance)); err != nil {
+                                       
camelevent.NotifyKameletBindingError(ctx, r.client, r.recorder, &instance, 
target, err)
+                                       return reconcile.Result{}, err
+                               }
+
+                               targetPhase = target.Status.Phase
+
+                               if targetPhase != phaseFrom {
+                                       targetLog.Info(
+                                               "state transition",
+                                               "phase-from", phaseFrom,
+                                               "phase-to", target.Status.Phase,
+                                       )
+                               }
+                       }
+
+                       // handle one action at time so the resource
+                       // is always at its latest state
+                       camelevent.NotifyKameletBindingUpdated(ctx, r.client, 
r.recorder, &instance, target)
+                       break
+               }
+       }
+
+       if targetPhase == v1alpha1.KameletBindingPhaseReady {
+               return reconcile.Result{}, nil
+       }
+
+       // Requeue
+       return reconcile.Result{
+               RequeueAfter: 5 * time.Second,
+       }, nil
+}
diff --git a/pkg/controller/kameletbinding/log.go 
b/pkg/controller/kameletbinding/log.go
new file mode 100644
index 0000000..0162b6d
--- /dev/null
+++ b/pkg/controller/kameletbinding/log.go
@@ -0,0 +1,23 @@
+/*
+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 kameletbinding
+
+import "github.com/apache/camel-k/pkg/util/log"
+
+// Log --
+var Log = log.Log.WithName("controller").WithName("kameletbinding")
diff --git a/pkg/controller/kameletbinding/monitor.go 
b/pkg/controller/kameletbinding/monitor.go
new file mode 100644
index 0000000..9980dc5
--- /dev/null
+++ b/pkg/controller/kameletbinding/monitor.go
@@ -0,0 +1,87 @@
+/*
+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 kameletbinding
+
+import (
+       "context"
+       v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+       "github.com/pkg/errors"
+       corev1 "k8s.io/api/core/v1"
+       "sigs.k8s.io/controller-runtime/pkg/client"
+
+       "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+)
+
+// NewMonitorAction returns an action that monitors the kamelet binding after 
it's fully initialized
+func NewMonitorAction() Action {
+       return &monitorAction{}
+}
+
+type monitorAction struct {
+       baseAction
+}
+
+func (action *monitorAction) Name() string {
+       return "monitor"
+}
+
+func (action *monitorAction) CanHandle(kameletbinding 
*v1alpha1.KameletBinding) bool {
+       return kameletbinding.Status.Phase == 
v1alpha1.KameletBindingPhaseCreating ||
+               kameletbinding.Status.Phase == 
v1alpha1.KameletBindingPhaseError ||
+               kameletbinding.Status.Phase == v1alpha1.KameletBindingPhaseReady
+}
+
+func (action *monitorAction) Handle(ctx context.Context, kameletbinding 
*v1alpha1.KameletBinding) (*v1alpha1.KameletBinding, error) {
+       key := client.ObjectKey{
+               Namespace: kameletbinding.Namespace,
+               Name:      kameletbinding.Name,
+       }
+       it := v1.Integration{}
+       if err := action.client.Get(ctx, key, &it); err != nil {
+               return nil, errors.Wrapf(err, "could not load integration for 
KameletBinding %q", kameletbinding.Name)
+       }
+
+       // Map integration phases to KameletBinding phases
+       target := kameletbinding.DeepCopy()
+       if it.Status.Phase == v1.IntegrationPhaseRunning {
+               target.Status.Phase = v1alpha1.KameletBindingPhaseReady
+               target.Status.SetCondition(
+                       v1alpha1.KameletBindingConditionReady,
+                       corev1.ConditionTrue,
+                       "",
+                       "",
+               )
+       } else if it.Status.Phase == v1.IntegrationPhaseError {
+               target.Status.Phase = v1alpha1.KameletBindingPhaseError
+               target.Status.SetCondition(
+                       v1alpha1.KameletBindingConditionReady,
+                       corev1.ConditionFalse,
+                       string(target.Status.Phase),
+                       "",
+               )
+       } else {
+               target.Status.Phase = v1alpha1.KameletBindingPhaseCreating
+               target.Status.SetCondition(
+                       v1alpha1.KameletBindingConditionReady,
+                       corev1.ConditionFalse,
+                       string(target.Status.Phase),
+                       "",
+               )
+       }
+       return target, nil
+}
diff --git a/pkg/event/manager.go b/pkg/event/manager.go
index a2b2eb8..6278ba8 100644
--- a/pkg/event/manager.go
+++ b/pkg/event/manager.go
@@ -68,6 +68,13 @@ const (
        // ReasonKameletPhaseUpdated --
        ReasonKameletPhaseUpdated = "KameletPhaseUpdated"
 
+       // ReasonKameletBindingError --
+       ReasonKameletBindingError = "KameletBindingError"
+       // ReasonKameletBindingConditionChanged --
+       ReasonKameletBindingConditionChanged = "KameletBindingConditionChanged"
+       // ReasonKameletBindingPhaseUpdated --
+       ReasonKameletBindingPhaseUpdated = "KameletBindingPhaseUpdated"
+
        // ReasonRelatedObjectChanged --
        ReasonRelatedObjectChanged = "ReasonRelatedObjectChanged"
 )
@@ -188,6 +195,35 @@ func NotifyKameletError(ctx context.Context, c 
client.Client, recorder record.Ev
        recorder.Eventf(k, corev1.EventTypeWarning, ReasonKameletError, "Cannot 
reconcile Kamelet %s: %v", k.Name, err)
 }
 
+// NotifyKameletBindingUpdated automatically generates events when a 
KameletBinding changes
+func NotifyKameletBindingUpdated(ctx context.Context, c client.Client, 
recorder record.EventRecorder, old, new *v1alpha1.KameletBinding) {
+       if new == nil {
+               return
+       }
+       oldPhase := ""
+       var oldConditions []v1.ResourceCondition
+       if old != nil {
+               oldPhase = string(old.Status.Phase)
+               oldConditions = old.Status.GetConditions()
+       }
+       if new.Status.Phase != v1alpha1.KameletBindingPhaseNone {
+               notifyIfConditionUpdated(recorder, new, oldConditions, 
new.Status.GetConditions(), "KameletBinding", new.Name, 
ReasonKameletBindingConditionChanged)
+       }
+       notifyIfPhaseUpdated(ctx, c, recorder, new, oldPhase, 
string(new.Status.Phase), "KameletBinding", new.Name, 
ReasonKameletBindingPhaseUpdated, "")
+}
+
+// NotifyKameletBindingError automatically generates error events when the 
kameletBinding reconcile cycle phase has an error
+func NotifyKameletBindingError(ctx context.Context, c client.Client, recorder 
record.EventRecorder, old, new *v1alpha1.KameletBinding, err error) {
+       k := old
+       if new != nil {
+               k = new
+       }
+       if k == nil {
+               return
+       }
+       recorder.Eventf(k, corev1.EventTypeWarning, ReasonKameletError, "Cannot 
reconcile KameletBinding %s: %v", k.Name, err)
+}
+
 // NotifyBuildUpdated automatically generates events when a build changes
 func NotifyBuildUpdated(ctx context.Context, c client.Client, recorder 
record.EventRecorder, old, new *v1.Build) {
        if new == nil {
diff --git a/pkg/install/cluster.go b/pkg/install/cluster.go
index ae55328..8fdc902 100644
--- a/pkg/install/cluster.go
+++ b/pkg/install/cluster.go
@@ -75,6 +75,11 @@ func SetupClusterWideResourcesOrCollect(ctx context.Context, 
clientProvider clie
                return err
        }
 
+       // Install CRD for KameletBinding (if needed)
+       if err := installCRD(ctx, c, "KameletBinding", "v1alpha1", 
"crd-kamelet-binding.yaml", collection); err != nil {
+               return err
+       }
+
        // Installing ClusterRole
        clusterRoleInstalled, err := IsClusterRoleInstalled(ctx, c)
        if err != nil {
diff --git a/pkg/util/log/log.go b/pkg/util/log/log.go
index 7d290f0..f3ca598 100644
--- a/pkg/util/log/log.go
+++ b/pkg/util/log/log.go
@@ -129,7 +129,7 @@ func (l Logger) ForIntegrationPlatform(target 
*v1.IntegrationPlatform) Logger {
        )
 }
 
-// ForIntegrationPlatform --
+// ForKamelet --
 func (l Logger) ForKamelet(target *v1alpha1.Kamelet) Logger {
        return l.WithValues(
                "api-version", target.APIVersion,
@@ -139,6 +139,16 @@ func (l Logger) ForKamelet(target *v1alpha1.Kamelet) 
Logger {
        )
 }
 
+// ForKameletBinding --
+func (l Logger) ForKameletBinding(target *v1alpha1.KameletBinding) Logger {
+       return l.WithValues(
+               "api-version", target.APIVersion,
+               "kind", target.Kind,
+               "ns", target.Namespace,
+               "name", target.Name,
+       )
+}
+
 // ***********************************
 //
 // Helpers
diff --git a/pkg/util/uri/uri.go b/pkg/util/uri/uri.go
index 6e9122d..1e0cf1e 100644
--- a/pkg/util/uri/uri.go
+++ b/pkg/util/uri/uri.go
@@ -21,6 +21,7 @@ import (
        "fmt"
        "net/url"
        "regexp"
+       "sort"
        "strings"
 
        "github.com/apache/camel-k/pkg/util/log"
@@ -56,3 +57,20 @@ func matchOrEmpty(reg *regexp.Regexp, str string) string {
        }
        return ""
 }
+
+func AppendParameters(uri string, params map[string]string) string {
+       prefix := "&"
+       if !strings.Contains(uri, "?") {
+               prefix = "?"
+       }
+       keys := make([]string, 0, len(params))
+       for k := range params {
+               keys = append(keys, k)
+       }
+       sort.Strings(keys)
+       for _, k := range keys {
+               uri += fmt.Sprintf("%s%s=%s", prefix, url.QueryEscape(k), 
url.QueryEscape(params[k]))
+               prefix = "&"
+       }
+       return uri
+}
diff --git a/pkg/util/uri/uri_test.go b/pkg/util/uri/uri_test.go
index 8908fec..ae22ff8 100644
--- a/pkg/util/uri/uri_test.go
+++ b/pkg/util/uri/uri_test.go
@@ -18,6 +18,7 @@ limitations under the License.
 package uri
 
 import (
+       "fmt"
        "testing"
 
        "github.com/stretchr/testify/assert"
@@ -89,3 +90,55 @@ func TestQueryParameter(t *testing.T) {
        }
 
 }
+
+func TestAppendParameters(t *testing.T) {
+       tests := []struct {
+               prefix   string
+               params   map[string]string
+               expected string
+       }{
+               {
+                       prefix:   "kamelet://mykamelet",
+                       params:   nil,
+                       expected: "kamelet://mykamelet",
+               },
+               {
+                       prefix: "kamelet://mykamelet",
+                       params: map[string]string{
+                               "a": "b",
+                       },
+                       expected: "kamelet://mykamelet?a=b",
+               },
+               {
+                       prefix: "kamelet://mykamelet",
+                       params: map[string]string{
+                               "a": "b",
+                               "c": "d",
+                       },
+                       expected: "kamelet://mykamelet?a=b&c=d",
+               },
+               {
+                       prefix: "kamelet://mykamelet",
+                       params: map[string]string{
+                               "z": "y",
+                               "c": "d",
+                       },
+                       expected: "kamelet://mykamelet?c=d&z=y",
+               },
+               {
+                       prefix: "kamelet://mykamelet?h=m",
+                       params: map[string]string{
+                               "z": "y",
+                               "c": "d",
+                       },
+                       expected: "kamelet://mykamelet?h=m&c=d&z=y",
+               },
+       }
+
+       for i, test := range tests {
+               t.Run(fmt.Sprintf("appendParameters-%d-%s", i, test.expected), 
func(t *testing.T) {
+                       uri := AppendParameters(test.prefix, test.params)
+                       assert.Equal(t, test.expected, uri)
+               })
+       }
+}

Reply via email to