You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2020/09/17 09:09:55 UTC

[camel-k] branch master updated (79ed5b9 -> 931b761)

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

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


    from 79ed5b9  Updated CHANGELOG.md
     new 7e4d661  kamelets: initial structure
     new 7d3663a  kamelets: adding event types
     new f1533fe  kamelets: improving kamelet format
     new 9f0c5ec  kamelets: initial scaffolding of kamelets trait
     new 69c2ecc  kamelets: adding mount paths and implement kamelets trait
     new 7d17bfc  kamelets: adding support for kamelet dependencies
     new cf92c4f  kamelet: fix icon definition
     new 69a6947  kamelets: support automatic configuration
     new 11a6500  kamelets: add schema to sources and map them in application.properties
     new 0fbbdd9  kamelet: compelete e2e example
     new b9c2cbe  kamelet: fix tests and lint
     new 4bea9af  Fix #1574: implement changes in source loading
     new 3fceb04  Fix #1574: add property names in source specification
     new 5656cba  Fix #1574: fix examples
     new 7e32e94  Fix #1574: add e2e test for Kamelets
     new 713d260  fix #1676: add kamelet binding resource
     new 86ce1cd  fix #1676: allow using non-string values in properties
     new eb5258d  chore(doc): add x-descriptors and fix
     new 279cfb9  Fix #1574: update runtime
     new 4316b03  Fix #1574: fix waiting for CRD installation
     new 931b761  Fix #1574: fix naming convention for property-defined sources

The 21 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 deploy/camel-catalog-1.5.1-SNAPSHOT-main.yaml      |   96 +-
 deploy/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml   | 2165 ++++++++++++++++----
 ...camel-catalog.yaml => crd-kamelet-binding.yaml} |   29 +-
 .../crd-camel-catalog.yaml => crd-kamelet.yaml}    |   29 +-
 .../builds.camel.apache.org.crd.yaml               |    0
 .../camel-k.v1.1.0.clusterserviceversion.yaml}     |   13 +-
 .../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} |   96 +-
 .../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}     |   29 +-
 .../kamelets.camel.apache.org.crd.yaml}            |   29 +-
 .../camel-k-dev/camel-k-dev.package.yaml           |    4 +-
 deploy/olm-catalog/csv-config.yaml                 |    2 +
 deploy/resources.go                                |   30 +-
 deploy/traits.yaml                                 |   17 +
 docs/modules/ROOT/nav.adoc                         |    1 +
 .../traits/pages/{deployer.adoc => kamelets.adoc}  |   19 +-
 e2e/knative/knative_platform_test.go               |    4 +-
 e2e/yaks/kamelets/kamelet.feature                  |    5 +
 .../kamelets/logger.groovy}                        |    4 +-
 .../yaks/kamelets}/messages-channel.yaml           |    0
 e2e/yaks/kamelets/timer-source.yaml                |   18 +
 e2e/yaks/kamelets/timer.kamelet.yaml               |   37 +
 .../yaks-config.yaml                               |   10 +-
 examples/kamelets/kamelet-binding-example.yaml     |   17 +
 .../{knative => kamelets}/messages-channel.yaml    |    0
 examples/kamelets/timer-source.kamelet.yaml        |   37 +
 .../kamelets/usage.groovy                          |    4 +-
 go.sum                                             |    2 +
 .../camel-k/crds/crd-kamelet-binding.yaml          |   29 +-
 .../camel-k/crds/crd-kamelet.yaml                  |   29 +-
 ...e_camel_v1.go => addtoscheme_camel_v1alpha1.go} |    4 +-
 pkg/apis/camel/group.go                            |    6 +
 pkg/apis/camel/v1/integration_types.go             |   11 +
 pkg/apis/camel/v1/integration_types_support.go     |   16 +
 pkg/apis/camel/v1/zz_generated.deepcopy.go         |    5 +
 pkg/apis/camel/v1alpha1/doc.go                     |    4 +
 pkg/apis/camel/v1alpha1/jsonschema_types.go        |  266 +++
 pkg/apis/camel/v1alpha1/kamelet_binding_types.go   |  123 ++
 .../kamelet_binding_types_support.go}              |  135 +-
 pkg/apis/camel/v1alpha1/kamelet_types.go           |  126 ++
 .../kamelet_types_support.go}                      |  121 +-
 pkg/apis/camel/{v1 => v1alpha1}/register.go        |   20 +-
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go   |  742 +++++++
 pkg/cmd/reset.go                                   |   36 +-
 pkg/cmd/run.go                                     |    2 +-
 pkg/controller/{add_build.go => add_kamelet.go}    |    4 +-
 ...add_integrationkit.go => add_kameletbinding.go} |    4 +-
 .../{integrationkit => kamelet}/action.go          |   10 +-
 pkg/controller/kamelet/common.go                   |   55 +
 .../{build/error.go => kamelet/initialize.go}      |   27 +-
 .../kamelet_controller.go}                         |   64 +-
 pkg/controller/{build => kamelet}/log.go           |    4 +-
 .../{integrationkit => kamelet}/monitor.go         |   28 +-
 .../{integration => kameletbinding}/action.go      |   10 +-
 pkg/controller/kameletbinding/initialize.go        |  168 ++
 .../kamelet_binding_controller.go}                 |   64 +-
 pkg/controller/{build => kameletbinding}/log.go    |    4 +-
 pkg/controller/kameletbinding/monitor.go           |   87 +
 pkg/event/manager.go                               |   73 +
 pkg/install/cluster.go                             |   59 +-
 pkg/metadata/metadata.go                           |   28 +-
 pkg/trait/container.go                             |   11 +-
 pkg/trait/dependencies.go                          |   13 +-
 pkg/trait/init.go                                  |    2 +-
 pkg/trait/kamelets.go                              |  382 ++++
 pkg/trait/kamelets_test.go                         |  529 +++++
 pkg/trait/knative.go                               |   43 +-
 pkg/trait/knative_service_test.go                  |   26 +-
 pkg/trait/service_test.go                          |   24 +-
 pkg/trait/trait_register.go                        |    1 +
 pkg/trait/trait_test.go                            |   10 +-
 pkg/trait/trait_types.go                           |   54 +-
 pkg/util/digest/digest.go                          |   46 +-
 pkg/util/flow/flow.go                              |   14 +-
 pkg/util/flow/flow_test.go                         |    4 +-
 pkg/util/kubernetes/resolver.go                    |   20 +-
 pkg/util/log/log.go                                |   21 +
 pkg/util/test/client.go                            |   25 +-
 pkg/util/uri/uri.go                                |   18 +
 pkg/util/uri/uri_test.go                           |   53 +
 88 files changed, 5373 insertions(+), 984 deletions(-)
 copy deploy/{olm-catalog/camel-k-dev/0.3.4/crd-camel-catalog.yaml => crd-kamelet-binding.yaml} (78%)
 copy deploy/{olm-catalog/camel-k-dev/0.3.4/crd-camel-catalog.yaml => crd-kamelet.yaml} (80%)
 copy deploy/olm-catalog/camel-k-dev/{1.1.0-snapshot => 1.1.0}/builds.camel.apache.org.crd.yaml (100%)
 copy deploy/olm-catalog/camel-k-dev/{1.1.0-snapshot/camel-k.v1.1.0-snapshot.clusterserviceversion.yaml => 1.1.0/camel-k.v1.1.0.clusterserviceversion.yaml} (97%)
 copy deploy/olm-catalog/camel-k-dev/{1.1.0-snapshot => 1.1.0}/camelcatalogs.camel.apache.org.crd.yaml (100%)
 copy deploy/olm-catalog/camel-k-dev/{1.1.0-snapshot => 1.1.0}/integrationkits.camel.apache.org.crd.yaml (100%)
 copy deploy/olm-catalog/camel-k-dev/{1.1.0-snapshot => 1.1.0}/integrationplatforms.camel.apache.org.crd.yaml (100%)
 copy deploy/olm-catalog/camel-k-dev/{1.1.0-snapshot => 1.1.0}/integrations.camel.apache.org.crd.yaml (100%)
 rename deploy/olm-catalog/camel-k-dev/{1.1.0-snapshot => 1.2.0-snapshot}/builds.camel.apache.org.crd.yaml (100%)
 rename deploy/olm-catalog/camel-k-dev/{1.1.0-snapshot/camel-k.v1.1.0-snapshot.clusterserviceversion.yaml => 1.2.0-snapshot/camel-k.v1.2.0-snapshot.clusterserviceversion.yaml} (84%)
 rename deploy/olm-catalog/camel-k-dev/{1.1.0-snapshot => 1.2.0-snapshot}/camelcatalogs.camel.apache.org.crd.yaml (100%)
 rename deploy/olm-catalog/camel-k-dev/{1.1.0-snapshot => 1.2.0-snapshot}/integrationkits.camel.apache.org.crd.yaml (100%)
 rename deploy/olm-catalog/camel-k-dev/{1.1.0-snapshot => 1.2.0-snapshot}/integrationplatforms.camel.apache.org.crd.yaml (100%)
 rename deploy/olm-catalog/camel-k-dev/{1.1.0-snapshot => 1.2.0-snapshot}/integrations.camel.apache.org.crd.yaml (100%)
 copy deploy/olm-catalog/camel-k-dev/{0.3.4/crd-camel-catalog.yaml => 1.2.0-snapshot/kameletbindings.camel.apache.org.crd.yaml} (78%)
 copy deploy/olm-catalog/camel-k-dev/{0.3.4/crd-camel-catalog.yaml => 1.2.0-snapshot/kamelets.camel.apache.org.crd.yaml} (80%)
 copy docs/modules/traits/pages/{deployer.adoc => kamelets.adoc} (60%)
 create mode 100644 e2e/yaks/kamelets/kamelet.feature
 copy e2e/{knative/files/knativech2.groovy => yaks/kamelets/logger.groovy} (88%)
 mode change 100644 => 100755
 copy {examples/knative => e2e/yaks/kamelets}/messages-channel.yaml (100%)
 create mode 100644 e2e/yaks/kamelets/timer-source.yaml
 create mode 100644 e2e/yaks/kamelets/timer.kamelet.yaml
 copy e2e/yaks/{knative-sinkbinding => kamelets}/yaks-config.yaml (76%)
 create mode 100644 examples/kamelets/kamelet-binding-example.yaml
 copy examples/{knative => kamelets}/messages-channel.yaml (100%)
 create mode 100644 examples/kamelets/timer-source.kamelet.yaml
 copy e2e/common/files/RestProducer.groovy => examples/kamelets/usage.groovy (84%)
 mode change 100644 => 100755
 copy deploy/olm-catalog/camel-k-dev/0.3.4/crd-camel-catalog.yaml => helm/camel-k/crds/crd-kamelet-binding.yaml (78%)
 copy deploy/olm-catalog/camel-k-dev/0.3.4/crd-camel-catalog.yaml => helm/camel-k/crds/crd-kamelet.yaml (80%)
 copy pkg/apis/{addtoscheme_camel_v1.go => addtoscheme_camel_v1alpha1.go} (87%)
 create mode 100644 pkg/apis/camel/group.go
 create mode 100644 pkg/apis/camel/v1alpha1/doc.go
 create mode 100644 pkg/apis/camel/v1alpha1/jsonschema_types.go
 create mode 100644 pkg/apis/camel/v1alpha1/kamelet_binding_types.go
 copy pkg/apis/camel/{v1/build_types_support.go => v1alpha1/kamelet_binding_types_support.go} (65%)
 create mode 100644 pkg/apis/camel/v1alpha1/kamelet_types.go
 copy pkg/apis/camel/{v1/build_types_support.go => v1alpha1/kamelet_types_support.go} (60%)
 copy pkg/apis/camel/{v1 => v1alpha1}/register.go (85%)
 create mode 100644 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
 copy pkg/controller/{add_build.go => add_kamelet.go} (88%)
 copy pkg/controller/{add_integrationkit.go => add_kameletbinding.go} (88%)
 copy pkg/controller/{integrationkit => kamelet}/action.go (83%)
 create mode 100644 pkg/controller/kamelet/common.go
 copy pkg/controller/{build/error.go => kamelet/initialize.go} (56%)
 copy pkg/controller/{integrationplatform/integrationplatform_controller.go => kamelet/kamelet_controller.go} (66%)
 copy pkg/controller/{build => kamelet}/log.go (91%)
 copy pkg/controller/{integrationkit => kamelet}/monitor.go (56%)
 copy pkg/controller/{integration => kameletbinding}/action.go (81%)
 create mode 100644 pkg/controller/kameletbinding/initialize.go
 copy pkg/controller/{integrationplatform/integrationplatform_controller.go => kameletbinding/kamelet_binding_controller.go} (66%)
 copy pkg/controller/{build => kameletbinding}/log.go (90%)
 create mode 100644 pkg/controller/kameletbinding/monitor.go
 create mode 100644 pkg/trait/kamelets.go
 create mode 100644 pkg/trait/kamelets_test.go


[camel-k] 10/21: kamelet: compelete e2e example

Posted by nf...@apache.org.
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 0fbbdd93342bcfb6e654723766d3144486961d5a
Author: Nicola Ferraro <ni...@gmail.com>
AuthorDate: Fri Jul 10 12:24:42 2020 +0200

    kamelet: compelete e2e example
---
 e2e/knative/knative_platform_test.go               |  4 +-
 examples/kamelets/fake-usage.groovy                | 21 +++++++++
 examples/kamelets/usage.groovy                     | 20 ++++++++
 go.sum                                             |  2 +
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go   |  2 +-
 pkg/cmd/run.go                                     |  2 +-
 pkg/controller/kamelet/kamelet_controller.go       |  1 +
 .../flow_test.go => controller/kamelet/monitor.go} | 53 ++++++++++------------
 pkg/metadata/metadata.go                           | 28 ++----------
 pkg/trait/dependencies.go                          |  7 ++-
 pkg/trait/init.go                                  |  2 +-
 pkg/trait/kamelets.go                              | 33 ++++++++++----
 pkg/trait/kamelets_test.go                         | 22 ++++-----
 pkg/trait/knative.go                               | 43 +++++++++++++-----
 pkg/util/digest/digest.go                          |  2 +-
 pkg/util/flow/flow.go                              | 14 +++---
 pkg/util/flow/flow_test.go                         |  4 +-
 pkg/util/kubernetes/resolver.go                    | 19 +++++++-
 18 files changed, 175 insertions(+), 104 deletions(-)

diff --git a/e2e/knative/knative_platform_test.go b/e2e/knative/knative_platform_test.go
index 857a72f..c32711d 100644
--- a/e2e/knative/knative_platform_test.go
+++ b/e2e/knative/knative_platform_test.go
@@ -58,10 +58,10 @@ func TestKnativePlatformTest(t *testing.T) {
 			// Change something in the integration to produce a redeploy
 			Expect(UpdateIntegration(ns, "yaml", func(it *v1.Integration) {
 				it.Spec.Profile = ""
-				content, err := flow.Marshal(it.Spec.Flows)
+				content, err := flow.ToYamlDSL(it.Spec.Flows)
 				assert.NoError(t, err)
 				newData := strings.ReplaceAll(string(content), "string!", "string!!!")
-				newFlows, err := flow.UnmarshalString(newData)
+				newFlows, err := flow.FromYamlDSLString(newData)
 				assert.NoError(t, err)
 				it.Spec.Flows = newFlows
 			})).To(BeNil())
diff --git a/examples/kamelets/fake-usage.groovy b/examples/kamelets/fake-usage.groovy
new file mode 100755
index 0000000..bff523b
--- /dev/null
+++ b/examples/kamelets/fake-usage.groovy
@@ -0,0 +1,21 @@
+// camel-k: language=groovy trait=kamelets.list=timer
+/*
+ * 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.
+ */
+
+// The integration should contain the kamelet as source
+
+// Until the kamelet component is added in runtime
\ No newline at end of file
diff --git a/examples/kamelets/usage.groovy b/examples/kamelets/usage.groovy
new file mode 100755
index 0000000..15090c9
--- /dev/null
+++ b/examples/kamelets/usage.groovy
@@ -0,0 +1,20 @@
+// camel-k: language=groovy
+/*
+ * 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.
+ */
+
+from('kamelet:timer')
+    .to('log:info')
diff --git a/go.sum b/go.sum
index 40b5e55..34d32df 100644
--- a/go.sum
+++ b/go.sum
@@ -984,6 +984,8 @@ github.com/opencontainers/runc v1.0.0-rc2.0.20190611121236-6cc515888830/go.mod h
 github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
 github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
 github.com/openshift/api v0.0.0-20200205133042-34f0ec8dab87/go.mod h1:fT6U/JfG8uZzemTRwZA2kBDJP5nWz7v05UHnty/D+pk=
+github.com/openshift/api v0.0.0-20200221181648-8ce0047d664f h1:ATPK7UhEwglONJc8qGsq41TbPk0XA4Kpm7XZZ3mlhAY=
+github.com/openshift/api v0.0.0-20200221181648-8ce0047d664f/go.mod h1:dh9o4Fs58gpFXGSYfnVxGR9PnV53I8TW84pQaJDdGiY=
 github.com/openshift/api v3.9.1-0.20190927182313-d4a64ec2cbd8+incompatible h1:YwFnUQ5RQ17CmkxHyjpQnWAQOGkLKXY0shOUEyqaCGk=
 github.com/openshift/api v3.9.1-0.20190927182313-d4a64ec2cbd8+incompatible/go.mod h1:dh9o4Fs58gpFXGSYfnVxGR9PnV53I8TW84pQaJDdGiY=
 github.com/openshift/client-go v0.0.0-20190923180330-3b6373338c9b/go.mod h1:6rzn+JTr7+WYS2E1TExP4gByoABxMznR6y2SnUIkmxk=
diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index 1292dc3..e6c991c 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -477,7 +477,7 @@ func (in *KameletSpec) DeepCopyInto(out *KameletSpec) {
 	if in.Flow != nil {
 		in, out := &in.Flow, &out.Flow
 		*out = new(v1.Flow)
-		**out = **in
+		(*in).DeepCopyInto(*out)
 	}
 	out.Authorization = in.Authorization
 	if in.Types != nil {
diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go
index 5c7e4c3..744f635 100644
--- a/pkg/cmd/run.go
+++ b/pkg/cmd/run.go
@@ -498,7 +498,7 @@ func (o *runCmdOptions) updateIntegrationCode(c client.Client, sources []string,
 		}
 
 		if o.UseFlows && (strings.HasSuffix(source, ".yaml") || strings.HasSuffix(source, ".yml")) {
-			flows, err := flow.UnmarshalString(data)
+			flows, err := flow.FromYamlDSLString(data)
 			if err != nil {
 				return nil, err
 			}
diff --git a/pkg/controller/kamelet/kamelet_controller.go b/pkg/controller/kamelet/kamelet_controller.go
index 048cf22..baad186 100644
--- a/pkg/controller/kamelet/kamelet_controller.go
+++ b/pkg/controller/kamelet/kamelet_controller.go
@@ -129,6 +129,7 @@ func (r *ReconcileKamelet) Reconcile(request reconcile.Request) (reconcile.Resul
 
 	actions := []Action{
 		NewInitializeAction(),
+		NewMonitorAction(),
 	}
 
 	var targetPhase v1alpha1.KameletPhase
diff --git a/pkg/util/flow/flow_test.go b/pkg/controller/kamelet/monitor.go
similarity index 52%
copy from pkg/util/flow/flow_test.go
copy to pkg/controller/kamelet/monitor.go
index c9248cb..49935d2 100644
--- a/pkg/util/flow/flow_test.go
+++ b/pkg/controller/kamelet/monitor.go
@@ -15,39 +15,32 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package flow
+package kamelet
 
 import (
-	"bytes"
-	"encoding/json"
-	"testing"
+	"context"
 
-	"github.com/stretchr/testify/assert"
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 )
 
-func TestReadWriteYaml(t *testing.T) {
-	// yaml in conventional form as marshalled by the go runtime
-	yaml := `- from:
-    steps:
-    - to: log:info
-    uri: timer:tick
-`
-
-	yamlReader := bytes.NewReader([]byte(yaml))
-	flows, err := Unmarshal(yamlReader)
-	assert.NoError(t, err)
-	assert.NotNil(t, flows)
-	assert.Len(t, flows, 1)
-
-	flow := map[string]interface{}{}
-	err = json.Unmarshal(flows[0].RawMessage, &flow)
-	assert.NoError(t, err)
-
-	assert.NotNil(t, flow["from"])
-	assert.Nil(t, flow["xx"])
-
-	data, err := Marshal(flows)
-	assert.NoError(t, err)
-	assert.NotNil(t, data)
-	assert.Equal(t, yaml, string(data))
+// NewMonitorAction returns an action that monitors the kamelet 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(kamelet *v1alpha1.Kamelet) bool {
+	return kamelet.Status.Phase == v1alpha1.KameletPhaseReady
+}
+
+func (action *monitorAction) Handle(ctx context.Context, kamelet *v1alpha1.Kamelet) (*v1alpha1.Kamelet, error) {
+	// Doing nothing for now
+	return kamelet, nil
 }
diff --git a/pkg/metadata/metadata.go b/pkg/metadata/metadata.go
index 27a2c8d..03c8ca1 100644
--- a/pkg/metadata/metadata.go
+++ b/pkg/metadata/metadata.go
@@ -22,9 +22,6 @@ import (
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	"github.com/apache/camel-k/pkg/util/camel"
-	"github.com/apache/camel-k/pkg/util/gzip"
-	"github.com/apache/camel-k/pkg/util/log"
-
 	src "github.com/apache/camel-k/pkg/util/source"
 )
 
@@ -64,10 +61,11 @@ func merge(m1 src.Metadata, m2 src.Metadata) src.Metadata {
 
 // Extract returns metadata information from the source code
 func Extract(catalog *camel.RuntimeCatalog, source v1.SourceSpec) IntegrationMetadata {
-	var err error
-	source, err = uncompress(source)
-	if err != nil {
-		log.Errorf(err, "unable to uncompress source %s: %v", source.Name, err)
+	if source.ContentRef != "" {
+		panic("source must be dereferenced before calling this method")
+	}
+	if source.Compression {
+		panic("source must be uncompressed before calling this method")
 	}
 
 	language := source.InferLanguage()
@@ -94,19 +92,3 @@ func Each(catalog *camel.RuntimeCatalog, sources []v1.SourceSpec, consumer func(
 		}
 	}
 }
-
-func uncompress(spec v1.SourceSpec) (v1.SourceSpec, error) {
-	if spec.Compression {
-		data := []byte(spec.Content)
-		var uncompressed []byte
-		var err error
-		if uncompressed, err = gzip.UncompressBase64(data); err != nil {
-			return spec, err
-		}
-		newSpec := spec
-		newSpec.Compression = false
-		newSpec.Content = string(uncompressed)
-		return newSpec, nil
-	}
-	return spec, nil
-}
diff --git a/pkg/trait/dependencies.go b/pkg/trait/dependencies.go
index 8a13087..4a704b6 100644
--- a/pkg/trait/dependencies.go
+++ b/pkg/trait/dependencies.go
@@ -19,6 +19,7 @@ package trait
 
 import (
 	"fmt"
+	"github.com/apache/camel-k/pkg/util/kubernetes"
 
 	"github.com/apache/camel-k/pkg/metadata"
 
@@ -66,7 +67,11 @@ func (t *dependenciesTrait) Apply(e *Environment) error {
 		dependencies.Add(fmt.Sprintf("mvn:%s/%s", d.GroupID, d.ArtifactID))
 	}
 
-	for _, s := range e.Integration.Sources() {
+	sources, err := kubernetes.ResolveIntegrationSources(e.C, e.Client, e.Integration, e.Resources)
+	if err != nil {
+		return err
+	}
+	for _, s := range sources {
 		meta := metadata.Extract(e.CamelCatalog, s)
 		lang := s.InferLanguage()
 
diff --git a/pkg/trait/init.go b/pkg/trait/init.go
index 32236e9..9685832 100644
--- a/pkg/trait/init.go
+++ b/pkg/trait/init.go
@@ -54,7 +54,7 @@ func (t *initTrait) Apply(e *Environment) error {
 
 		// Flows need to be turned into a generated source
 		if len(e.Integration.Spec.Flows) > 0 {
-			content, err := flow.Marshal(e.Integration.Spec.Flows)
+			content, err := flow.ToYamlDSL(e.Integration.Spec.Flows)
 			if err != nil {
 				return err
 			}
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index 80d4bc2..994ddcb 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -20,6 +20,8 @@ package trait
 import (
 	"encoding/json"
 	"fmt"
+	"github.com/apache/camel-k/pkg/util/flow"
+	"github.com/apache/camel-k/pkg/util/kubernetes"
 	"regexp"
 	"sort"
 	"strconv"
@@ -83,10 +85,18 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 		return false, nil
 	}
 
+	if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
+		return false, nil
+	}
+
 	if t.Auto == nil || *t.Auto {
 		if t.List == "" {
 			var kamelets []string
-			metadata.Each(e.CamelCatalog, e.Integration.Sources(), func(_ int, meta metadata.IntegrationMetadata) bool {
+			sources, err := kubernetes.ResolveIntegrationSources(e.C, e.Client, e.Integration, e.Resources)
+			if err != nil {
+				return false, err
+			}
+			metadata.Each(e.CamelCatalog, sources, func(_ int, meta metadata.IntegrationMetadata) bool {
 				util.StringSliceUniqueConcat(&kamelets, extractKamelets(meta.FromURIs))
 				util.StringSliceUniqueConcat(&kamelets, extractKamelets(meta.ToURIs))
 				return true
@@ -121,6 +131,10 @@ func (t *kameletsTrait) addKamelets(e *Environment) error {
 			return err
 		}
 
+		if kamelet.Status.Phase != v1alpha1.KameletPhaseReady {
+			return fmt.Errorf("kamelet %q is not %s: %s", k, v1alpha1.KameletPhaseReady, kamelet.Status.Phase)
+		}
+
 		if err := t.addKameletAsSource(e, kamelet); err != nil {
 			return err
 		}
@@ -137,21 +151,20 @@ func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet v1alpha1.Kame
 	var sources []v1.SourceSpec
 
 	if kamelet.Spec.Flow != nil {
-		// TODO fixme removed for changes to Flow
-		//flowData, err := flows.Marshal([]v1.Flow{*kamelet.Spec.Flow})
-		//if err != nil {
-		//	return err
-		//}
+
+		flowData, err := flow.ToYamlDSL([]v1.Flow{*kamelet.Spec.Flow})
+		if err != nil {
+			return err
+		}
 		flowSource := v1.SourceSpec{
 			DataSpec: v1.DataSpec{
-				Name: fmt.Sprintf("%s.yaml", kamelet.Name),
-				//Content: string(flowData),
-				Content: string(*kamelet.Spec.Flow),
+				Name:    fmt.Sprintf("%s.yaml", kamelet.Name),
+				Content: string(flowData),
 			},
 			Language: v1.LanguageYaml,
 			Type:     v1.SourceTypeKamelet,
 		}
-		flowSource, err := integrationSourceFromKameletSource(e, kamelet, flowSource, fmt.Sprintf("%s-kamelet-%s-flow", e.Integration.Name, kamelet.Name))
+		flowSource, err = integrationSourceFromKameletSource(e, kamelet, flowSource, fmt.Sprintf("%s-kamelet-%s-flow", e.Integration.Name, kamelet.Name))
 		if err != nil {
 			return err
 		}
diff --git a/pkg/trait/kamelets_test.go b/pkg/trait/kamelets_test.go
index 59657be..d2a1321 100644
--- a/pkg/trait/kamelets_test.go
+++ b/pkg/trait/kamelets_test.go
@@ -19,7 +19,7 @@ package trait
 
 import (
 	"context"
-	"gopkg.in/yaml.v2"
+	"encoding/json"
 	"testing"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
@@ -88,7 +88,7 @@ func TestKameletLookup(t *testing.T) {
 			Name:      "timer",
 		},
 		Spec: v1alpha1.KameletSpec{
-			Flow: deleteMeAtSomePoint(map[string]interface{}{
+			Flow: marshalOrFail(map[string]interface{}{
 				"from": map[string]interface{}{
 					"uri": "timer:tick",
 				},
@@ -131,7 +131,7 @@ func TestKameletSecondarySourcesLookup(t *testing.T) {
 			Name:      "timer",
 		},
 		Spec: v1alpha1.KameletSpec{
-			Flow: deleteMeAtSomePoint(map[string]interface{}{
+			Flow: marshalOrFail(map[string]interface{}{
 				"from": map[string]interface{}{
 					"uri": "timer:tick",
 				},
@@ -236,7 +236,7 @@ func TestErrorMultipleKameletSources(t *testing.T) {
 					Type: v1.SourceTypeKamelet,
 				},
 			},
-			Flow: deleteMeAtSomePoint(map[string]interface{}{
+			Flow: marshalOrFail(map[string]interface{}{
 				"from": map[string]interface{}{
 					"uri": "timer:tick",
 				},
@@ -265,7 +265,7 @@ func TestMultipleKamelets(t *testing.T) {
 			Name:      "timer",
 		},
 		Spec: v1alpha1.KameletSpec{
-			Flow: deleteMeAtSomePoint(map[string]interface{}{
+			Flow: marshalOrFail(map[string]interface{}{
 				"from": map[string]interface{}{
 					"uri": "timer:tick",
 				},
@@ -290,7 +290,7 @@ func TestMultipleKamelets(t *testing.T) {
 			Name:      "logger",
 		},
 		Spec: v1alpha1.KameletSpec{
-			Flow: deleteMeAtSomePoint(map[string]interface{}{
+			Flow: marshalOrFail(map[string]interface{}{
 				"from": map[string]interface{}{
 					"uri": "tbd:endpoint",
 					"steps": []interface{}{
@@ -358,7 +358,7 @@ func TestKameletConfigLookup(t *testing.T) {
 			Name:      "timer",
 		},
 		Spec: v1alpha1.KameletSpec{
-			Flow: deleteMeAtSomePoint(map[string]interface{}{
+			Flow: marshalOrFail(map[string]interface{}{
 				"from": map[string]interface{}{
 					"uri": "timer:tick",
 				},
@@ -420,7 +420,7 @@ func TestKameletNamedConfigLookup(t *testing.T) {
 			Name:      "timer",
 		},
 		Spec: v1alpha1.KameletSpec{
-			Flow: deleteMeAtSomePoint(map[string]interface{}{
+			Flow: marshalOrFail(map[string]interface{}{
 				"from": map[string]interface{}{
 					"uri": "timer:tick",
 				},
@@ -511,11 +511,11 @@ func createKameletsTestEnvironment(flow string, objects ...runtime.Object) (*kam
 	return trait, environment
 }
 
-func deleteMeAtSomePoint(flow map[string]interface{}) *v1.Flow {
-	data, err := yaml.Marshal(flow)
+func marshalOrFail(flow map[string]interface{}) *v1.Flow {
+	data, err := json.Marshal(flow)
 	if err != nil {
 		panic(err)
 	}
-	f := v1.Flow(data)
+	f := v1.Flow{data}
 	return &f
 }
diff --git a/pkg/trait/knative.go b/pkg/trait/knative.go
index 92103f4..5ff9c46 100644
--- a/pkg/trait/knative.go
+++ b/pkg/trait/knative.go
@@ -23,6 +23,7 @@ import (
 	"reflect"
 	"strings"
 
+	"github.com/apache/camel-k/pkg/util/kubernetes"
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	knativeapi "github.com/apache/camel-k/pkg/apis/camel/v1/knative"
 	"github.com/apache/camel-k/pkg/metadata"
@@ -110,8 +111,11 @@ func (t *knativeTrait) Configure(e *Environment) (bool, error) {
 	if t.Auto == nil || *t.Auto {
 		if len(t.ChannelSources) == 0 {
 			items := make([]string, 0)
-
-			metadata.Each(e.CamelCatalog, e.Integration.Sources(), func(_ int, meta metadata.IntegrationMetadata) bool {
+			sources, err := kubernetes.ResolveIntegrationSources(e.C, e.Client, e.Integration, e.Resources)
+			if err != nil {
+				return false, err
+			}
+			metadata.Each(e.CamelCatalog, sources, func(_ int, meta metadata.IntegrationMetadata) bool {
 				items = append(items, knativeutil.FilterURIs(meta.FromURIs, knativeapi.CamelServiceTypeChannel)...)
 				return true
 			})
@@ -120,8 +124,11 @@ func (t *knativeTrait) Configure(e *Environment) (bool, error) {
 		}
 		if len(t.ChannelSinks) == 0 {
 			items := make([]string, 0)
-
-			metadata.Each(e.CamelCatalog, e.Integration.Sources(), func(_ int, meta metadata.IntegrationMetadata) bool {
+			sources, err := kubernetes.ResolveIntegrationSources(e.C, e.Client, e.Integration, e.Resources)
+			if err != nil {
+				return false, err
+			}
+			metadata.Each(e.CamelCatalog, sources, func(_ int, meta metadata.IntegrationMetadata) bool {
 				items = append(items, knativeutil.FilterURIs(meta.ToURIs, knativeapi.CamelServiceTypeChannel)...)
 				return true
 			})
@@ -130,8 +137,11 @@ func (t *knativeTrait) Configure(e *Environment) (bool, error) {
 		}
 		if len(t.EndpointSources) == 0 {
 			items := make([]string, 0)
-
-			metadata.Each(e.CamelCatalog, e.Integration.Sources(), func(_ int, meta metadata.IntegrationMetadata) bool {
+			sources, err := kubernetes.ResolveIntegrationSources(e.C, e.Client, e.Integration, e.Resources)
+			if err != nil {
+				return false, err
+			}
+			metadata.Each(e.CamelCatalog, sources, func(_ int, meta metadata.IntegrationMetadata) bool {
 				items = append(items, knativeutil.FilterURIs(meta.FromURIs, knativeapi.CamelServiceTypeEndpoint)...)
 				return true
 			})
@@ -140,8 +150,11 @@ func (t *knativeTrait) Configure(e *Environment) (bool, error) {
 		}
 		if len(t.EndpointSinks) == 0 {
 			items := make([]string, 0)
-
-			metadata.Each(e.CamelCatalog, e.Integration.Sources(), func(_ int, meta metadata.IntegrationMetadata) bool {
+			sources, err := kubernetes.ResolveIntegrationSources(e.C, e.Client, e.Integration, e.Resources)
+			if err != nil {
+				return false, err
+			}
+			metadata.Each(e.CamelCatalog, sources, func(_ int, meta metadata.IntegrationMetadata) bool {
 				items = append(items, knativeutil.FilterURIs(meta.ToURIs, knativeapi.CamelServiceTypeEndpoint)...)
 				return true
 			})
@@ -150,8 +163,11 @@ func (t *knativeTrait) Configure(e *Environment) (bool, error) {
 		}
 		if len(t.EventSources) == 0 {
 			items := make([]string, 0)
-
-			metadata.Each(e.CamelCatalog, e.Integration.Sources(), func(_ int, meta metadata.IntegrationMetadata) bool {
+			sources, err := kubernetes.ResolveIntegrationSources(e.C, e.Client, e.Integration, e.Resources)
+			if err != nil {
+				return false, err
+			}
+			metadata.Each(e.CamelCatalog, sources, func(_ int, meta metadata.IntegrationMetadata) bool {
 				items = append(items, knativeutil.FilterURIs(meta.FromURIs, knativeapi.CamelServiceTypeEvent)...)
 				return true
 			})
@@ -160,8 +176,11 @@ func (t *knativeTrait) Configure(e *Environment) (bool, error) {
 		}
 		if len(t.EventSinks) == 0 {
 			items := make([]string, 0)
-
-			metadata.Each(e.CamelCatalog, e.Integration.Sources(), func(_ int, meta metadata.IntegrationMetadata) bool {
+			sources, err := kubernetes.ResolveIntegrationSources(e.C, e.Client, e.Integration, e.Resources)
+			if err != nil {
+				return false, err
+			}
+			metadata.Each(e.CamelCatalog, sources, func(_ int, meta metadata.IntegrationMetadata) bool {
 				items = append(items, knativeutil.FilterURIs(meta.ToURIs, knativeapi.CamelServiceTypeEvent)...)
 				return true
 			})
diff --git a/pkg/util/digest/digest.go b/pkg/util/digest/digest.go
index 6ccd3ed..4b2dfba 100644
--- a/pkg/util/digest/digest.go
+++ b/pkg/util/digest/digest.go
@@ -71,7 +71,7 @@ func ComputeForIntegration(integration *v1.Integration) (string, error) {
 
 	// Integration flows
 	if len(integration.Spec.Flows) > 0 {
-		flows, err := flow.Marshal(integration.Spec.Flows)
+		flows, err := flow.ToYamlDSL(integration.Spec.Flows)
 		if err != nil {
 			return "", err
 		}
diff --git a/pkg/util/flow/flow.go b/pkg/util/flow/flow.go
index e495d55..fa963cf 100644
--- a/pkg/util/flow/flow.go
+++ b/pkg/util/flow/flow.go
@@ -31,13 +31,13 @@ import (
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 )
 
-// UnmarshalString reads flows contained in a string
-func UnmarshalString(flowsString string) ([]v1.Flow, error) {
-	return Unmarshal(bytes.NewReader([]byte(flowsString)))
+// FromYamlDSLString creates a slice of flows from a Camel YAML DSL string
+func FromYamlDSLString(flowsString string) ([]v1.Flow, error) {
+	return FromYamlDSL(bytes.NewReader([]byte(flowsString)))
 }
 
-// Unmarshal flows from a stream
-func Unmarshal(reader io.Reader) ([]v1.Flow, error) {
+// FromYamlDSL creates a slice of flows from a Camel YAML DSL stream
+func FromYamlDSL(reader io.Reader) ([]v1.Flow, error) {
 	buffered, err := ioutil.ReadAll(reader)
 	if err != nil {
 		return nil, err
@@ -56,8 +56,8 @@ func Unmarshal(reader io.Reader) ([]v1.Flow, error) {
 	return flows, err
 }
 
-// Marshal flows as byte array
-func Marshal(flows []v1.Flow) ([]byte, error) {
+// ToYamlDSL converts a flow into its Camel YAML DSL equivalent
+func ToYamlDSL(flows []v1.Flow) ([]byte, error) {
 	data, err := json.Marshal(&flows)
 	if err != nil {
 		return nil, err
diff --git a/pkg/util/flow/flow_test.go b/pkg/util/flow/flow_test.go
index c9248cb..731e2ff 100644
--- a/pkg/util/flow/flow_test.go
+++ b/pkg/util/flow/flow_test.go
@@ -34,7 +34,7 @@ func TestReadWriteYaml(t *testing.T) {
 `
 
 	yamlReader := bytes.NewReader([]byte(yaml))
-	flows, err := Unmarshal(yamlReader)
+	flows, err := FromYamlDSL(yamlReader)
 	assert.NoError(t, err)
 	assert.NotNil(t, flows)
 	assert.Len(t, flows, 1)
@@ -46,7 +46,7 @@ func TestReadWriteYaml(t *testing.T) {
 	assert.NotNil(t, flow["from"])
 	assert.Nil(t, flow["xx"])
 
-	data, err := Marshal(flows)
+	data, err := ToYamlDSL(flows)
 	assert.NoError(t, err)
 	assert.NotNil(t, data)
 	assert.Equal(t, yaml, string(data))
diff --git a/pkg/util/kubernetes/resolver.go b/pkg/util/kubernetes/resolver.go
index fbb3eff..ae7621a 100644
--- a/pkg/util/kubernetes/resolver.go
+++ b/pkg/util/kubernetes/resolver.go
@@ -22,7 +22,7 @@ import (
 	"fmt"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
-
+	"github.com/apache/camel-k/pkg/util/gzip"
 	corev1 "k8s.io/api/core/v1"
 	controller "sigs.k8s.io/controller-runtime/pkg/client"
 )
@@ -71,10 +71,25 @@ func Resolve(data *v1.DataSpec, mapLookup func(string) (*corev1.ConfigMap, error
 		//
 		// Replace ref source content with real content
 		//
-		data.Content = cm.Data["content"]
+		key := data.ContentKey
+		if key == "" {
+			key = "content"
+		}
+		data.Content = cm.Data[key]
 		data.ContentRef = ""
 	}
 
+	if data.Compression {
+		cnt := []byte(data.Content)
+		var uncompressed []byte
+		var err error
+		if uncompressed, err = gzip.UncompressBase64(cnt); err != nil {
+			return err
+		}
+		data.Compression = false
+		data.Content = string(uncompressed)
+	}
+
 	return nil
 }
 


[camel-k] 18/21: chore(doc): add x-descriptors and fix

Posted by nf...@apache.org.
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 eb5258d5cff288e26c2391fd7f53876ef6695361
Author: nicolaferraro <ni...@gmail.com>
AuthorDate: Thu Sep 10 16:23:37 2020 +0200

    chore(doc): add x-descriptors and fix
---
 examples/kamelets/kamelet-binding-example.yaml |  4 ++-
 examples/kamelets/timer-source.kamelet.yaml    | 37 ++++++++++++++++++++++++++
 examples/kamelets/timer.kamelet.yaml           | 37 --------------------------
 pkg/apis/camel/v1alpha1/jsonschema_types.go    |  4 +++
 4 files changed, 44 insertions(+), 38 deletions(-)

diff --git a/examples/kamelets/kamelet-binding-example.yaml b/examples/kamelets/kamelet-binding-example.yaml
index 7e3d95d..d2fe9e6 100644
--- a/examples/kamelets/kamelet-binding-example.yaml
+++ b/examples/kamelets/kamelet-binding-example.yaml
@@ -7,7 +7,9 @@ spec:
     ref:
       kind: Kamelet
       apiVersion: camel.apache.org/v1alpha1
-      name: timer
+      name: timer-source
+    properties:
+      message: "Hello world!"
   sink:
     ref:
       kind: InMemoryChannel
diff --git a/examples/kamelets/timer-source.kamelet.yaml b/examples/kamelets/timer-source.kamelet.yaml
new file mode 100644
index 0000000..983a948
--- /dev/null
+++ b/examples/kamelets/timer-source.kamelet.yaml
@@ -0,0 +1,37 @@
+apiVersion: camel.apache.org/v1alpha1
+kind: Kamelet
+metadata:
+  name: timer-source
+  annotations:
+    camel.apache.org/kamelet.icon: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gU3ZnIFZlY3RvciBJY29ucyA6IGh0dHA6Ly93d3cub25saW5ld2ViZm9udHMuY29tL2ljb24gLS0+DQo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm [...]
+  labels:
+    camel.apache.org/kamelet.type: "source"
+spec:
+  definition:
+    title: "Timer Source"
+    description: "Produces periodic events with a custom payload"
+    required:
+      - message
+    properties:
+      period:
+        title: Period
+        description: The interval between two events
+        type: integer
+        default: 1000
+      message:
+        title: Message
+        description: The message to generate
+        type: string
+        example: "hello world"
+  types:
+    out:
+      mediaType: text/plain
+  flow:
+    from:
+      uri: timer:tick
+      parameters:
+        period: "#property:period"
+      steps:
+      - set-body:
+          constant: "#property:message"
+      - to: "direct:#property:routeId"
diff --git a/examples/kamelets/timer.kamelet.yaml b/examples/kamelets/timer.kamelet.yaml
deleted file mode 100644
index 554e15b..0000000
--- a/examples/kamelets/timer.kamelet.yaml
+++ /dev/null
@@ -1,37 +0,0 @@
-apiVersion: camel.apache.org/v1alpha1
-kind: Kamelet
-metadata:
-  name: timer
-  annotations:
-    camel.apache.org/kamelet.icon: timer
-spec:
-  definition:
-    title: "Timer"
-    description: "Produces periodic events with a custom payload"
-    required:
-      - message
-    properties:
-      period:
-        title: Period
-        description: The time interval between two events
-        type: integer
-        default: 1000
-      message:
-        title: Message
-        description: The message to generate
-        type: string
-  types:
-    out:
-      mediaType: application/json
-      schema:
-        id: text.camel.apache.org
-        type: string
-  flow:
-    from:
-      uri: timer:tick
-      parameters:
-        period: "{{period}}"
-      steps:
-        - set-body:
-            constant: "{{message}}"
-        - to: "direct:{{routeId}}"
diff --git a/pkg/apis/camel/v1alpha1/jsonschema_types.go b/pkg/apis/camel/v1alpha1/jsonschema_types.go
index a66b131..6c3322c 100644
--- a/pkg/apis/camel/v1alpha1/jsonschema_types.go
+++ b/pkg/apis/camel/v1alpha1/jsonschema_types.go
@@ -166,6 +166,10 @@ type JSONSchemaProps struct {
 	//      Atomic maps will be entirely replaced when updated.
 	// +optional
 	XMapType *string `json:"x-kubernetes-map-type,omitempty" protobuf:"bytes,43,opt,name=xKubernetesMapType"`
+
+	// x-descriptors annotates an object to define additional display options.
+	// +optional
+	XDescriptors []string `json:"x-descriptors,omitempty" protobuf:"bytes,44,opt,name=xDescriptors"`
 }
 
 // JSON represents any valid JSON value.


[camel-k] 12/21: Fix #1574: implement changes in source loading

Posted by nf...@apache.org.
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 4bea9af710a7d05869e6c0e1baa660b62ad34bb4
Author: nicolaferraro <ni...@gmail.com>
AuthorDate: Tue Aug 11 16:37:23 2020 +0200

    Fix #1574: implement changes in source loading
---
 deploy/resources.go                              |  12 +-
 deploy/traits.yaml                               |  17 +++
 docs/modules/ROOT/nav.adoc                       |   1 +
 docs/modules/traits/pages/kamelets.adoc          |  39 +++++
 pkg/apis/camel/v1/integration_types.go           |   6 +-
 pkg/apis/camel/v1/zz_generated.deepcopy.go       |   5 +
 pkg/apis/camel/v1alpha1/jsonschema_types.go      |   8 +-
 pkg/apis/camel/v1alpha1/kamelet_types.go         |  14 +-
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go |  51 ++++++-
 pkg/controller/kamelet/common.go                 |  48 ++++++
 pkg/controller/kamelet/initialize.go             |   4 +-
 pkg/controller/kamelet/monitor.go                |   3 +-
 pkg/trait/container.go                           |   9 +-
 pkg/trait/kamelets.go                            |  44 ++++--
 pkg/trait/kamelets_test.go                       |  14 +-
 pkg/trait/knative_service_test.go                |  10 +-
 pkg/trait/trait_test.go                          |   8 +-
 pkg/trait/trait_types.go                         | 183 ++++++-----------------
 18 files changed, 284 insertions(+), 192 deletions(-)

diff --git a/deploy/resources.go b/deploy/resources.go
index 0741e84..673756d 100644
--- a/deploy/resources.go
+++ b/deploy/resources.go
@@ -144,6 +144,13 @@ 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",
+			modTime:          time.Time{},
+			uncompressedSize: 1498,
+
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x54\xc1\x6e\xe3\x36\x10\xbd\xeb\x2b\x1e\xac\xcb\x2e\x10\xcb\x4d\x4f\x85\x7a\x72\xbd\x09\xea\x26\x90\x83\xc8\xdb\xc5\x1e\xc7\xd2\x58\x1a\x98\x22\x59\x92\xb2\x63\x14\xfd\xf7\x82\x92\x1c\x3b\x68\x8f\xab\x93\xfd\x66\x38\xf3\xde\xbc\x21\x53\xcc\x7f\xdc\x97\xa4\x78\x96\x8a\xb5\xe7\x1a\xc1\x20\xb4\x8c\xa5\xa5\xaa\x65\x94\x66\x1f\x4e\xe4\x18\x8f\xa6\xd7\x35\x05\x31\x1a\x9f\x96\xe5\xe3\x67\xf4\xba\x66\x07\xa3\x19\xc6\xa1\x [...]
+		},
 		"/operator-deployment.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "operator-deployment.yaml",
 			modTime:          time.Time{},
@@ -354,9 +361,9 @@ var assets = func() http.FileSystem {
 		"/traits.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "traits.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 32177,
+			uncompressedSize: 32786,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\x6d\x73\x1b\x37\x92\xf0\xf7\xfc\x0a\x94\x9e\xa7\x4a\xa2\x8a\x1c\xc9\xd9\xca\x26\xab\xbb\x5c\x4a\xeb\x38\xbb\x72\x62\x5b\x67\x39\xc9\x5d\xe5\xb6\x96\xe0\x4c\x93\x84\x85\x01\x66\x01\x0c\x65\xe6\xea\xfe\xfb\x55\x37\x5e\x06\x33\x1c\x49\x94\x63\xa5\xb4\x55\x57\xf9\x10\x93\x9a\x69\x34\x1a\xfd\xfe\x02\x3a\xc3\x85\xb3\x67\x9f\xcd\x98\xe2\x35\x9c\x31\xbe\x5c\x0a\x25\xdc\xf6\x33\xc6\x1a\xc9\xdd\x52\x9b\xfa\x8c\x2d\xb9\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\x6d\x73\x1b\x37\x92\xf0\xf7\xfc\x0a\x94\x9e\xa7\x4a\xa2\x8a\x1c\xc9\xd9\xca\x26\xab\xbb\x5c\x4a\xeb\x38\xbb\x72\x62\x5b\x67\x39\xc9\x5d\xe5\xb6\x96\xe0\x4c\x93\x84\x85\x01\x66\x01\x0c\x65\xe6\xea\xfe\xfb\x55\x37\x5e\x06\x33\x1c\x49\x94\x63\xa5\xb4\x55\x57\xf9\x10\x93\x9a\x69\x34\x1a\xfd\xfe\x02\x3a\xc3\x85\xb3\x67\x9f\xcd\x98\xe2\x35\x9c\x31\xbe\x5c\x0a\x25\xdc\xf6\x33\xc6\x1a\xc9\xdd\x52\x9b\xfa\x8c\x2d\xb9\x [...]
 		},
 		"/user-cluster-role.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "user-cluster-role.yaml",
@@ -380,6 +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["/operator-deployment.yaml"].(os.FileInfo),
 		fs["/operator-role-binding-events.yaml"].(os.FileInfo),
 		fs["/operator-role-binding-knative.yaml"].(os.FileInfo),
diff --git a/deploy/traits.yaml b/deploy/traits.yaml
index 070d61c..c2d85f0 100755
--- a/deploy/traits.yaml
+++ b/deploy/traits.yaml
@@ -319,6 +319,23 @@ traits:
   - name: options
     type: '[]string'
     description: A list of JVM options
+- name: kamelets
+  platform: true
+  profiles:
+  - Kubernetes
+  - Knative
+  - OpenShift
+  description: The kamelets trait is a platform trait used to inject Kamelets into the integration runtime.
+  properties:
+  - name: enabled
+    type: bool
+    description: Can be used to enable or disable a trait. All traits share this common property.
+  - name: auto
+    type: bool
+    description: Automatically inject all referenced Kamelets and their default configuration (enabled by default)
+  - name: list
+    type: string
+    description: Comma separated list of Kamelet names to load into the current integration
 - name: knative-service
   platform: false
   profiles:
diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index 039d5c3..7c00b89 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -37,6 +37,7 @@
 ** xref:traits:istio.adoc[Istio]
 ** xref:traits:jolokia.adoc[Jolokia]
 ** xref:traits:jvm.adoc[Jvm]
+** xref:traits:kamelets.adoc[Kamelets]
 ** xref:traits:knative-service.adoc[Knative Service]
 ** xref:traits:knative.adoc[Knative]
 ** xref:traits:master.adoc[Master]
diff --git a/docs/modules/traits/pages/kamelets.adoc b/docs/modules/traits/pages/kamelets.adoc
new file mode 100755
index 0000000..7409709
--- /dev/null
+++ b/docs/modules/traits/pages/kamelets.adoc
@@ -0,0 +1,39 @@
+= Kamelets Trait
+
+// Start of autogenerated code - DO NOT EDIT! (description)
+The kamelets trait is a platform trait used to inject Kamelets into the integration runtime.
+
+
+This trait is available in the following profiles: **Kubernetes, Knative, OpenShift**.
+
+WARNING: The kamelets trait is a *platform trait*: disabling it may compromise the platform functionality.
+
+// End of autogenerated code - DO NOT EDIT! (description)
+// Start of autogenerated code - DO NOT EDIT! (configuration)
+== Configuration
+
+Trait properties can be specified when running any integration with the CLI:
+```
+kamel run --trait kamelets.[key]=[value] --trait kamelets.[key2]=[value2] integration.groovy
+```
+The following configuration options are available:
+
+[cols="2,1,5a"]
+|===
+|Property | Type | Description
+
+| kamelets.enabled
+| bool
+| Can be used to enable or disable a trait. All traits share this common property.
+
+| kamelets.auto
+| bool
+| Automatically inject all referenced Kamelets and their default configuration (enabled by default)
+
+| kamelets.list
+| string
+| Comma separated list of Kamelet names to load into the current integration
+
+|===
+
+// End of autogenerated code - DO NOT EDIT! (configuration)
diff --git a/pkg/apis/camel/v1/integration_types.go b/pkg/apis/camel/v1/integration_types.go
index 7e985a2..47aeb44 100644
--- a/pkg/apis/camel/v1/integration_types.go
+++ b/pkg/apis/camel/v1/integration_types.go
@@ -127,13 +127,15 @@ type SourceSpec struct {
 	Interceptors []string `json:"interceptors,omitempty"`
 	// Type defines the kind of source described by this object
 	Type SourceType `json:"type,omitempty"`
+	// List of property names defined in the source (e.g. if type is "template")
+	PropertyNames []string `json:"property-names,omitempty"`
 }
 
 type SourceType string
 
 const (
-	SourceTypeDefault SourceType = ""
-	SourceTypeKamelet SourceType = "kamelet"
+	SourceTypeDefault  SourceType = ""
+	SourceTypeTemplate SourceType = "template"
 )
 
 // Language --
diff --git a/pkg/apis/camel/v1/zz_generated.deepcopy.go b/pkg/apis/camel/v1/zz_generated.deepcopy.go
index d48aa41..534a75d 100644
--- a/pkg/apis/camel/v1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1/zz_generated.deepcopy.go
@@ -1312,6 +1312,11 @@ func (in *SourceSpec) DeepCopyInto(out *SourceSpec) {
 		*out = make([]string, len(*in))
 		copy(*out, *in)
 	}
+	if in.PropertyNames != nil {
+		in, out := &in.PropertyNames, &out.PropertyNames
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
 	return
 }
 
diff --git a/pkg/apis/camel/v1alpha1/jsonschema_types.go b/pkg/apis/camel/v1alpha1/jsonschema_types.go
index 6ebdf1e..a66b131 100644
--- a/pkg/apis/camel/v1alpha1/jsonschema_types.go
+++ b/pkg/apis/camel/v1alpha1/jsonschema_types.go
@@ -19,6 +19,8 @@ limitations under the License.
 
 package v1alpha1
 
+import "encoding/json"
+
 // JSONSchemaProps is a JSON-Schema following Specification Draft 4 (http://json-schema.org/).
 type JSONSchemaProps struct {
 	ID          string        `json:"id,omitempty" protobuf:"bytes,1,opt,name=id"`
@@ -59,7 +61,7 @@ type JSONSchemaProps struct {
 	// default is a default value for undefined object fields.
 	// Defaulting is a beta feature under the CustomResourceDefaulting feature gate.
 	// Defaulting requires spec.preserveUnknownFields to be false.
-	Default              *JSON                      `json:"default,omitempty" protobuf:"bytes,8,opt,name=default"`
+	Default              *json.RawMessage           `json:"default,omitempty" protobuf:"bytes,8,opt,name=default"`
 	Maximum              *float64                   `json:"maximum,omitempty" protobuf:"bytes,9,opt,name=maximum"`
 	ExclusiveMaximum     bool                       `json:"exclusiveMaximum,omitempty" protobuf:"bytes,10,opt,name=exclusiveMaximum"`
 	Minimum              *float64                   `json:"minimum,omitempty" protobuf:"bytes,11,opt,name=minimum"`
@@ -71,7 +73,7 @@ type JSONSchemaProps struct {
 	MinItems             *int64                     `json:"minItems,omitempty" protobuf:"bytes,17,opt,name=minItems"`
 	UniqueItems          bool                       `json:"uniqueItems,omitempty" protobuf:"bytes,18,opt,name=uniqueItems"`
 	MultipleOf           *float64                   `json:"multipleOf,omitempty" protobuf:"bytes,19,opt,name=multipleOf"`
-	Enum                 []JSON                     `json:"enum,omitempty" protobuf:"bytes,20,rep,name=enum"`
+	Enum                 []*json.RawMessage         `json:"enum,omitempty" protobuf:"bytes,20,rep,name=enum"`
 	MaxProperties        *int64                     `json:"maxProperties,omitempty" protobuf:"bytes,21,opt,name=maxProperties"`
 	MinProperties        *int64                     `json:"minProperties,omitempty" protobuf:"bytes,22,opt,name=minProperties"`
 	Required             []string                   `json:"required,omitempty" protobuf:"bytes,23,rep,name=required"`
@@ -87,7 +89,7 @@ type JSONSchemaProps struct {
 	AdditionalItems      *JSONSchemaPropsOrBool     `json:"additionalItems,omitempty" protobuf:"bytes,33,opt,name=additionalItems"`
 	Definitions          JSONSchemaDefinitions      `json:"definitions,omitempty" protobuf:"bytes,34,opt,name=definitions"`
 	ExternalDocs         *ExternalDocumentation     `json:"externalDocs,omitempty" protobuf:"bytes,35,opt,name=externalDocs"`
-	Example              *JSON                      `json:"example,omitempty" protobuf:"bytes,36,opt,name=example"`
+	Example              *json.RawMessage           `json:"example,omitempty" protobuf:"bytes,36,opt,name=example"`
 	Nullable             bool                       `json:"nullable,omitempty" protobuf:"bytes,37,opt,name=nullable"`
 
 	// x-kubernetes-preserve-unknown-fields stops the API server
diff --git a/pkg/apis/camel/v1alpha1/kamelet_types.go b/pkg/apis/camel/v1alpha1/kamelet_types.go
index 34594b2..81557a1 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_types.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_types.go
@@ -58,6 +58,12 @@ type AuthorizationSpec struct {
 type KameletStatus struct {
 	Phase      KameletPhase       `json:"phase,omitempty"`
 	Conditions []KameletCondition `json:"conditions,omitempty"`
+	Properties []KameletProperty  `json:"properties,omitempty"`
+}
+
+type KameletProperty struct {
+	Name    string `json:"name,omitempty"`
+	Default string `json:"default,omitempty"`
 }
 
 // KameletCondition describes the state of a resource at a certain point.
@@ -95,11 +101,13 @@ const (
 	KameletPhaseReady KameletPhase = "Ready"
 )
 
-// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
-
 // Kamelet is the Schema for the kamelets API
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +k8s:openapi-gen=true
+// +genclient
+// +kubebuilder:resource:path=kamelets,scope=Namespaced,shortName=kl,categories=kamel;camel
 // +kubebuilder:subresource:status
-// +kubebuilder:resource:path=kamelets,scope=Namespaced
+// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase`,description="The Kamelet phase"
 type Kamelet struct {
 	metav1.TypeMeta   `json:",inline"`
 	metav1.ObjectMeta `json:"metadata,omitempty"`
diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index e6c991c..2014759 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -5,6 +5,8 @@
 package v1alpha1
 
 import (
+	json "encoding/json"
+
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	runtime "k8s.io/apimachinery/pkg/runtime"
 )
@@ -137,8 +139,12 @@ func (in *JSONSchemaProps) DeepCopyInto(out *JSONSchemaProps) {
 	}
 	if in.Default != nil {
 		in, out := &in.Default, &out.Default
-		*out = new(JSON)
-		(*in).DeepCopyInto(*out)
+		*out = new(json.RawMessage)
+		if **in != nil {
+			in, out := *in, *out
+			*out = make([]byte, len(*in))
+			copy(*out, *in)
+		}
 	}
 	if in.Maximum != nil {
 		in, out := &in.Maximum, &out.Maximum
@@ -177,9 +183,17 @@ func (in *JSONSchemaProps) DeepCopyInto(out *JSONSchemaProps) {
 	}
 	if in.Enum != nil {
 		in, out := &in.Enum, &out.Enum
-		*out = make([]JSON, len(*in))
+		*out = make([]*json.RawMessage, len(*in))
 		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
+			if (*in)[i] != nil {
+				in, out := &(*in)[i], &(*out)[i]
+				*out = new(json.RawMessage)
+				if **in != nil {
+					in, out := *in, *out
+					*out = make([]byte, len(*in))
+					copy(*out, *in)
+				}
+			}
 		}
 	}
 	if in.MaxProperties != nil {
@@ -273,8 +287,12 @@ func (in *JSONSchemaProps) DeepCopyInto(out *JSONSchemaProps) {
 	}
 	if in.Example != nil {
 		in, out := &in.Example, &out.Example
-		*out = new(JSON)
-		(*in).DeepCopyInto(*out)
+		*out = new(json.RawMessage)
+		if **in != nil {
+			in, out := *in, *out
+			*out = make([]byte, len(*in))
+			copy(*out, *in)
+		}
 	}
 	if in.XPreserveUnknownFields != nil {
 		in, out := &in.XPreserveUnknownFields, &out.XPreserveUnknownFields
@@ -464,6 +482,22 @@ func (in *KameletList) DeepCopyObject() runtime.Object {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *KameletProperty) DeepCopyInto(out *KameletProperty) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KameletProperty.
+func (in *KameletProperty) DeepCopy() *KameletProperty {
+	if in == nil {
+		return nil
+	}
+	out := new(KameletProperty)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *KameletSpec) DeepCopyInto(out *KameletSpec) {
 	*out = *in
 	in.Definition.DeepCopyInto(&out.Definition)
@@ -515,6 +549,11 @@ func (in *KameletStatus) DeepCopyInto(out *KameletStatus) {
 			(*in)[i].DeepCopyInto(&(*out)[i])
 		}
 	}
+	if in.Properties != nil {
+		in, out := &in.Properties, &out.Properties
+		*out = make([]KameletProperty, len(*in))
+		copy(*out, *in)
+	}
 	return
 }
 
diff --git a/pkg/controller/kamelet/common.go b/pkg/controller/kamelet/common.go
new file mode 100644
index 0000000..d95b27a
--- /dev/null
+++ b/pkg/controller/kamelet/common.go
@@ -0,0 +1,48 @@
+package kamelet
+
+import (
+	"encoding/json"
+	"fmt"
+	"sort"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/pkg/errors"
+)
+
+func updateStatus(kamelet *v1alpha1.Kamelet) (*v1alpha1.Kamelet, error) {
+	target := kamelet.DeepCopy()
+	target.Status.Phase = v1alpha1.KameletPhaseReady
+	if err := recomputeProperties(target); err != nil {
+		return nil, err
+	}
+	return target, nil
+}
+
+func recomputeProperties(kamelet *v1alpha1.Kamelet) error {
+	kamelet.Status.Properties = make([]v1alpha1.KameletProperty, 0, len(kamelet.Spec.Definition.Properties))
+	propSet := make(map[string]bool)
+	for k, v := range kamelet.Spec.Definition.Properties {
+		if propSet[k] {
+			continue
+		}
+		propSet[k] = true
+		defValue := ""
+		if v.Default != nil {
+			var val interface{}
+			if err := json.Unmarshal(*v.Default, &val); err != nil {
+				return errors.Wrapf(err, "cannot decode default value for property %q", k)
+			}
+			defValue = fmt.Sprintf("%v", val)
+		}
+		kamelet.Status.Properties = append(kamelet.Status.Properties, v1alpha1.KameletProperty{
+			Name:    k,
+			Default: defValue,
+		})
+	}
+	sort.SliceStable(kamelet.Status.Properties, func(i, j int) bool {
+		pi := kamelet.Status.Properties[i].Name
+		pj := kamelet.Status.Properties[j].Name
+		return pi < pj
+	})
+	return nil
+}
diff --git a/pkg/controller/kamelet/initialize.go b/pkg/controller/kamelet/initialize.go
index 0b3f0aa..eeae301 100644
--- a/pkg/controller/kamelet/initialize.go
+++ b/pkg/controller/kamelet/initialize.go
@@ -41,7 +41,5 @@ func (action *initializeAction) CanHandle(kamelet *v1alpha1.Kamelet) bool {
 }
 
 func (action *initializeAction) Handle(ctx context.Context, kamelet *v1alpha1.Kamelet) (*v1alpha1.Kamelet, error) {
-	target := kamelet.DeepCopy()
-	target.Status.Phase = v1alpha1.KameletPhaseReady
-	return target, nil
+	return updateStatus(kamelet)
 }
diff --git a/pkg/controller/kamelet/monitor.go b/pkg/controller/kamelet/monitor.go
index 49935d2..99e5224 100644
--- a/pkg/controller/kamelet/monitor.go
+++ b/pkg/controller/kamelet/monitor.go
@@ -41,6 +41,5 @@ func (action *monitorAction) CanHandle(kamelet *v1alpha1.Kamelet) bool {
 }
 
 func (action *monitorAction) Handle(ctx context.Context, kamelet *v1alpha1.Kamelet) (*v1alpha1.Kamelet, error) {
-	// Doing nothing for now
-	return kamelet, nil
+	return updateStatus(kamelet)
 }
diff --git a/pkg/trait/container.go b/pkg/trait/container.go
index 9c19e5e..485b302 100644
--- a/pkg/trait/container.go
+++ b/pkg/trait/container.go
@@ -21,19 +21,16 @@ import (
 	"fmt"
 	"sort"
 	"strconv"
-	"strings"
 
+	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	"github.com/apache/camel-k/pkg/util"
+	"github.com/apache/camel-k/pkg/util/envvar"
 	appsv1 "k8s.io/api/apps/v1"
 	"k8s.io/api/batch/v1beta1"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/resource"
 	"k8s.io/apimachinery/pkg/util/intstr"
-
 	serving "knative.dev/serving/pkg/apis/serving/v1"
-
-	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
-	"github.com/apache/camel-k/pkg/util/envvar"
 )
 
 const (
@@ -195,8 +192,6 @@ func (t *containerTrait) configureContainer(e *Environment) error {
 	envvar.SetVal(&container.Env, "CAMEL_K_CONF", "/etc/camel/conf/application.properties")
 	envvar.SetVal(&container.Env, "CAMEL_K_CONF_D", "/etc/camel/conf.d")
 
-	// Configure sources
-	envvar.SetVal(&container.Env, "CAMEL_K_ROUTES", strings.Join(e.ComputeSourcesURI(), ","))
 	e.AddSourcesProperties()
 
 	t.configureResources(e, &container)
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index d1b3bef..05f734f 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -88,7 +88,7 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 		return false, nil
 	}
 
-	if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
+	if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization, v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) {
 		return false, nil
 	}
 
@@ -114,11 +114,16 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 }
 
 func (t *kameletsTrait) Apply(e *Environment) error {
-	if err := t.addKamelets(e); err != nil {
-		return err
-	}
-	if err := t.addConfigurationSecrets(e); err != nil {
-		return err
+
+	if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
+		if err := t.addKamelets(e); err != nil {
+			return err
+		}
+		if err := t.addConfigurationSecrets(e); err != nil {
+			return err
+		}
+	} else if e.IntegrationInPhase(v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) {
+		return t.configureApplicationProperties(e)
 	}
 	return nil
 }
@@ -150,6 +155,27 @@ func (t *kameletsTrait) addKamelets(e *Environment) error {
 	return nil
 }
 
+func (t *kameletsTrait) configureApplicationProperties(e *Environment) error {
+	for _, k := range t.getKameletKeys() {
+		var kamelet v1alpha1.Kamelet
+		key := client.ObjectKey{
+			Namespace: e.Integration.Namespace,
+			Name:      k,
+		}
+		if err := t.Client.Get(t.Ctx, key, &kamelet); err != nil {
+			return err
+		}
+
+		// Configuring defaults from Kamelet
+		for _, prop := range kamelet.Status.Properties {
+			if prop.Default != "" {
+				e.ApplicationProperties[fmt.Sprintf("camel.kamelet.%s.%s", kamelet.Name, prop.Name)] = prop.Default
+			}
+		}
+	}
+	return nil
+}
+
 func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet v1alpha1.Kamelet) error {
 	sources := make([]v1.SourceSpec, 0)
 
@@ -165,7 +191,7 @@ func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet v1alpha1.Kame
 				Content: string(flowData),
 			},
 			Language: v1.LanguageYaml,
-			Type:     v1.SourceTypeKamelet,
+			Type:     v1.SourceTypeTemplate,
 		}
 		flowSource, err = integrationSourceFromKameletSource(e, kamelet, flowSource, fmt.Sprintf("%s-kamelet-%s-flow", e.Integration.Name, kamelet.Name))
 		if err != nil {
@@ -184,7 +210,7 @@ func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet v1alpha1.Kame
 
 	kameletCounter := 0
 	for _, source := range sources {
-		if source.Type == v1.SourceTypeKamelet {
+		if source.Type == v1.SourceTypeTemplate {
 			kameletCounter++
 		}
 		replaced := false
@@ -279,7 +305,7 @@ func (t *kameletsTrait) getConfigurationKeys() []configurationKey {
 }
 
 func integrationSourceFromKameletSource(e *Environment, kamelet v1alpha1.Kamelet, source v1.SourceSpec, name string) (v1.SourceSpec, error) {
-	if source.Type == v1.SourceTypeKamelet {
+	if source.Type == v1.SourceTypeTemplate {
 		// Kamelets must be named "<kamelet-name>.extension"
 		language := source.InferLanguage()
 		source.Name = fmt.Sprintf("%s.%s", kamelet.Name, string(language))
diff --git a/pkg/trait/kamelets_test.go b/pkg/trait/kamelets_test.go
index 4f37b1d..e72ad78 100644
--- a/pkg/trait/kamelets_test.go
+++ b/pkg/trait/kamelets_test.go
@@ -115,7 +115,7 @@ func TestKameletLookup(t *testing.T) {
 	assert.Len(t, environment.Integration.Status.GeneratedSources, 1)
 	source := environment.Integration.Status.GeneratedSources[0]
 	assert.Equal(t, "timer.yaml", source.Name)
-	assert.Equal(t, "kamelet", string(source.Type))
+	assert.Equal(t, "template", string(source.Type))
 
 	assert.Equal(t, []string{"camel:log", "camel:timer"}, environment.Integration.Status.Dependencies)
 }
@@ -165,7 +165,7 @@ func TestKameletSecondarySourcesLookup(t *testing.T) {
 
 	flowSource := environment.Integration.Status.GeneratedSources[0]
 	assert.Equal(t, "timer.yaml", flowSource.Name)
-	assert.Equal(t, "kamelet", string(flowSource.Type))
+	assert.Equal(t, "template", string(flowSource.Type))
 	assert.Equal(t, "it-kamelet-timer-flow", flowSource.ContentRef)
 	assert.Equal(t, "content", flowSource.ContentKey)
 
@@ -194,7 +194,7 @@ func TestNonYAMLKameletLookup(t *testing.T) {
 						Name:    "mykamelet.groovy",
 						Content: `from("timer").to("log:info")`,
 					},
-					Type: v1.SourceTypeKamelet,
+					Type: v1.SourceTypeTemplate,
 				},
 			},
 		},
@@ -215,7 +215,7 @@ func TestNonYAMLKameletLookup(t *testing.T) {
 	assert.Len(t, environment.Integration.Status.GeneratedSources, 1)
 	source := environment.Integration.Status.GeneratedSources[0]
 	assert.Equal(t, "timer.groovy", source.Name)
-	assert.Equal(t, "kamelet", string(source.Type))
+	assert.Equal(t, "template", string(source.Type))
 }
 
 func TestErrorMultipleKameletSources(t *testing.T) {
@@ -236,7 +236,7 @@ func TestErrorMultipleKameletSources(t *testing.T) {
 						Name:    "mykamelet.groovy",
 						Content: `from("timer").to("log:info")`,
 					},
-					Type: v1.SourceTypeKamelet,
+					Type: v1.SourceTypeTemplate,
 				},
 			},
 			Flow: marshalOrFail(map[string]interface{}{
@@ -333,13 +333,13 @@ func TestMultipleKamelets(t *testing.T) {
 
 	flowSource2 := environment.Integration.Status.GeneratedSources[0]
 	assert.Equal(t, "logger.yaml", flowSource2.Name)
-	assert.Equal(t, "kamelet", string(flowSource2.Type))
+	assert.Equal(t, "template", string(flowSource2.Type))
 	assert.Equal(t, "it-kamelet-logger-flow", flowSource2.ContentRef)
 	assert.Equal(t, "content", flowSource2.ContentKey)
 
 	flowSource := environment.Integration.Status.GeneratedSources[1]
 	assert.Equal(t, "timer.yaml", flowSource.Name)
-	assert.Equal(t, "kamelet", string(flowSource.Type))
+	assert.Equal(t, "template", string(flowSource.Type))
 	assert.Equal(t, "it-kamelet-timer-flow", flowSource.ContentRef)
 	assert.Equal(t, "content", flowSource.ContentKey)
 
diff --git a/pkg/trait/knative_service_test.go b/pkg/trait/knative_service_test.go
index 9406d32..731eec9 100644
--- a/pkg/trait/knative_service_test.go
+++ b/pkg/trait/knative_service_test.go
@@ -118,7 +118,7 @@ func TestKnativeService(t *testing.T) {
 	assert.NotEmpty(t, environment.ExecutedTraits)
 	assert.NotNil(t, environment.GetTrait("knative"))
 	assert.NotNil(t, envvar.Get(environment.EnvVars, "CAMEL_KNATIVE_CONFIGURATION"))
-	assert.Equal(t, 4, environment.Resources.Size())
+	assert.Equal(t, 5, environment.Resources.Size())
 
 	s := environment.Resources.GetKnativeService(func(service *serving.Service) bool {
 		return service.Name == KnativeServiceTestName
@@ -128,8 +128,8 @@ func TestKnativeService(t *testing.T) {
 
 	spec := s.Spec.ConfigurationSpec.Template.Spec
 
-	assert.Len(t, spec.Containers[0].VolumeMounts, 5)
-	assert.Len(t, spec.Volumes, 5)
+	assert.Len(t, spec.Containers[0].VolumeMounts, 6)
+	assert.Len(t, spec.Volumes, 6)
 
 	assert.Condition(t, func() bool {
 		for _, v := range spec.Containers[0].VolumeMounts {
@@ -172,7 +172,9 @@ func TestKnativeService(t *testing.T) {
 		}
 	})
 
-	test.EnvVarHasValue(t, spec.Containers[0].Env, "CAMEL_K_ROUTES", "file:/etc/camel/sources/i-source-000/routes.js?language=js&compression=true")
+	assert.Equal(t, "file:/etc/camel/sources/i-source-000/routes.js", environment.ApplicationProperties["camel.k.sources[0].location"])
+	assert.Equal(t, "js", environment.ApplicationProperties["camel.k.sources[0].language"])
+	assert.Equal(t, "true", environment.ApplicationProperties["camel.k.sources[0].compression"])
 	test.EnvVarHasValue(t, spec.Containers[0].Env, "CAMEL_K_CONF", "/etc/camel/conf/application.properties")
 	test.EnvVarHasValue(t, spec.Containers[0].Env, "CAMEL_K_CONF_D", "/etc/camel/conf.d")
 }
diff --git a/pkg/trait/trait_test.go b/pkg/trait/trait_test.go
index bcf3519..d936c56 100644
--- a/pkg/trait/trait_test.go
+++ b/pkg/trait/trait_test.go
@@ -49,7 +49,7 @@ func TestOpenShiftTraits(t *testing.T) {
 	assert.Nil(t, env.GetTrait("service"))
 	assert.Nil(t, env.GetTrait("route"))
 	assert.NotNil(t, env.GetTrait("owner"))
-	assert.Nil(t, res.GetConfigMap(func(cm *corev1.ConfigMap) bool {
+	assert.NotNil(t, res.GetConfigMap(func(cm *corev1.ConfigMap) bool {
 		return cm.Labels["camel.apache.org/properties.type"] != ""
 	}))
 	assert.NotNil(t, res.GetDeployment(func(deployment *appsv1.Deployment) bool {
@@ -64,7 +64,7 @@ func TestOpenShiftTraitsWithWeb(t *testing.T) {
 	assert.NotNil(t, env.GetTrait("service"))
 	assert.NotNil(t, env.GetTrait("route"))
 	assert.NotNil(t, env.GetTrait("owner"))
-	assert.Nil(t, res.GetConfigMap(func(cm *corev1.ConfigMap) bool {
+	assert.NotNil(t, res.GetConfigMap(func(cm *corev1.ConfigMap) bool {
 		return cm.Labels["camel.apache.org/properties.type"] != ""
 	}))
 	assert.NotNil(t, res.GetDeployment(func(deployment *appsv1.Deployment) bool {
@@ -114,7 +114,7 @@ func TestKubernetesTraits(t *testing.T) {
 	assert.Nil(t, env.GetTrait("service"))
 	assert.Nil(t, env.GetTrait("route"))
 	assert.NotNil(t, env.GetTrait("owner"))
-	assert.Nil(t, res.GetConfigMap(func(cm *corev1.ConfigMap) bool {
+	assert.NotNil(t, res.GetConfigMap(func(cm *corev1.ConfigMap) bool {
 		return cm.Labels["camel.apache.org/properties.type"] != ""
 	}))
 	assert.NotNil(t, res.GetDeployment(func(deployment *appsv1.Deployment) bool {
@@ -129,7 +129,7 @@ func TestKubernetesTraitsWithWeb(t *testing.T) {
 	assert.NotNil(t, env.GetTrait("service"))
 	assert.Nil(t, env.GetTrait("route"))
 	assert.NotNil(t, env.GetTrait("owner"))
-	assert.Nil(t, res.GetConfigMap(func(cm *corev1.ConfigMap) bool {
+	assert.NotNil(t, res.GetConfigMap(func(cm *corev1.ConfigMap) bool {
 		return cm.Labels["camel.apache.org/properties.type"] != ""
 	}))
 	assert.NotNil(t, res.GetDeployment(func(deployment *appsv1.Deployment) bool {
diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go
index c397c2f..3d38531 100644
--- a/pkg/trait/trait_types.go
+++ b/pkg/trait/trait_types.go
@@ -54,9 +54,6 @@ var (
 	// SourcesMountPath --
 	SourcesMountPath = path.Join(BasePath, "sources")
 
-	// KameletsMountPath --
-	KameletsMountPath = path.Join(BasePath, "kamelets.d")
-
 	// ResourcesMountPath --
 	ResourcesMountPath = path.Join(BasePath, "resources")
 
@@ -478,34 +475,43 @@ func (e *Environment) ComputeConfigMaps() []runtime.Object {
 	return maps
 }
 
-// ComputeSourcesURI --
-func (e *Environment) ComputeSourcesURI() []string {
-	sources := e.Integration.Sources()
-	paths := make([]string, 0, len(sources))
-
-	for i, s := range sources {
-		if s.Type == v1.SourceTypeKamelet {
-			// Kamelet information is added to application.properties
-			continue
-		}
+// AddSourcesProperties --
+func (e *Environment) AddSourcesProperties() {
+	if e.ApplicationProperties == nil {
+		e.ApplicationProperties = make(map[string]string)
+	}
+	for i, s := range e.Integration.Sources() {
 		root := path.Join(SourcesMountPath, fmt.Sprintf("i-source-%03d", i))
 
 		srcName := strings.TrimPrefix(s.Name, "/")
 		src := path.Join(root, srcName)
 		src = "file:" + src
-		interceptors := make([]string, 0, len(s.Interceptors))
+		e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].location", i)] = src
 
-		params := make([]string, 0)
+		simpleName := srcName
+		if strings.Contains(srcName, ".") {
+			simpleName = srcName[0:strings.Index(srcName, ".")]
+		}
+		e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].name", i)] = simpleName
+
+		for pid, p := range s.PropertyNames {
+			e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].property-names[%d]", i, pid)] = p
+		}
+
+		if s.Type != "" {
+			e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].type", i)] = string(s.Type)
+		}
 		if s.InferLanguage() != "" {
-			params = append(params, "language="+string(s.InferLanguage()))
+			e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].language", i)] = string(s.InferLanguage())
 		}
 		if s.Loader != "" {
-			params = append(params, "loader="+s.Loader)
+			e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].loader", i)] = string(s.Loader)
 		}
 		if s.Compression {
-			params = append(params, "compression=true")
+			e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].compression", i)] = "true"
 		}
 
+		interceptors := make([]string, 0, len(s.Interceptors))
 		if s.Interceptors != nil {
 			interceptors = append(interceptors, s.Interceptors...)
 		}
@@ -513,73 +519,7 @@ func (e *Environment) ComputeSourcesURI() []string {
 			interceptors = append(interceptors, e.Interceptors...)
 		}
 		if len(interceptors) > 0 {
-			params = append(params, "interceptors="+strings.Join(interceptors, ","))
-		}
-
-		if len(params) > 0 {
-			src = fmt.Sprintf("%s?%s", src, strings.Join(params, "&"))
-		}
-
-		paths = append(paths, src)
-	}
-
-	return paths
-}
-
-// AddSourcesProperties --
-func (e *Environment) AddSourcesProperties() {
-	sources := e.Integration.Sources()
-	properties := make(map[string]string)
-
-	for _, s := range sources {
-		if s.Type == v1.SourceTypeKamelet {
-			// We compute properties only for Kamelets
-			// TODO move other sources types to this format instead of ENV_VAR
-
-			srcName := strings.TrimPrefix(s.Name, "/")
-			kameletName := srcName
-			if strings.Contains(kameletName, ".") {
-				kameletName = kameletName[0:strings.LastIndex(kameletName, ".")]
-			}
-			root := path.Join(KameletsMountPath, kameletName)
-
-			src := path.Join(root, srcName)
-			src = "file:" + src
-			properties[fmt.Sprintf("camel.k.kamelets[%s].location", kameletName)] = src
-
-			schemaName := path.Join(root, fmt.Sprintf("%s-schema.json", kameletName))
-			properties[fmt.Sprintf("camel.k.kamelets[%s].schema", kameletName)] = schemaName
-
-			if s.InferLanguage() != "" {
-				properties[fmt.Sprintf("camel.k.kamelets[%s].language", kameletName)] = string(s.InferLanguage())
-			}
-			if s.Loader != "" {
-				properties[fmt.Sprintf("camel.k.kamelets[%s].loader", kameletName)] = s.Loader
-			}
-			if s.Compression {
-				properties[fmt.Sprintf("camel.k.kamelets[%s].compression", kameletName)] = True
-			}
-
-			interceptors := make([]string, 0, len(s.Interceptors))
-			if s.Interceptors != nil {
-				interceptors = append(interceptors, s.Interceptors...)
-			}
-			if e.Interceptors != nil {
-				interceptors = append(interceptors, e.Interceptors...)
-			}
-			for i, interceptor := range interceptors {
-				properties[fmt.Sprintf("camel.k.kamelets[%s].interceptors[%d]", kameletName, i)] = interceptor
-			}
-		}
-	}
-
-	if len(properties) > 0 {
-		if e.ApplicationProperties == nil {
-			e.ApplicationProperties = properties
-		} else {
-			for k, v := range properties {
-				e.ApplicationProperties[k] = v
-			}
+			e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].interceptors", i)] = strings.Join(interceptors, ",")
 		}
 	}
 }
@@ -596,67 +536,30 @@ func (e *Environment) ConfigureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]c
 			cmName = s.ContentRef
 		}
 		resName := strings.TrimPrefix(s.Name, "/")
+		refName := fmt.Sprintf("i-source-%03d", i)
+		resPath := path.Join(SourcesMountPath, refName)
 
-		if s.Type == v1.SourceTypeKamelet {
-			kameletName := resName
-			if strings.Contains(kameletName, ".") {
-				kameletName = kameletName[0:strings.LastIndex(kameletName, ".")]
-			}
-			refName := fmt.Sprintf("i-kamelet-source-%03d", i)
-			resPath := path.Join(KameletsMountPath, kameletName)
-			schemaResName := fmt.Sprintf("%s-schema.json", kameletName)
-
-			*vols = append(*vols, corev1.Volume{
-				Name: refName,
-				VolumeSource: corev1.VolumeSource{
-					ConfigMap: &corev1.ConfigMapVolumeSource{
-						LocalObjectReference: corev1.LocalObjectReference{
-							Name: cmName,
-						},
-						Items: []corev1.KeyToPath{
-							{
-								Key:  "content",
-								Path: resName,
-							},
-							{
-								Key:  "schema",
-								Path: schemaResName,
-							},
-						},
+		*vols = append(*vols, corev1.Volume{
+			Name: refName,
+			VolumeSource: corev1.VolumeSource{
+				ConfigMap: &corev1.ConfigMapVolumeSource{
+					LocalObjectReference: corev1.LocalObjectReference{
+						Name: cmName,
 					},
-				},
-			})
-
-			*mnts = append(*mnts, corev1.VolumeMount{
-				Name:      refName,
-				MountPath: resPath,
-			})
-		} else {
-			refName := fmt.Sprintf("i-source-%03d", i)
-			resPath := path.Join(SourcesMountPath, refName)
-
-			*vols = append(*vols, corev1.Volume{
-				Name: refName,
-				VolumeSource: corev1.VolumeSource{
-					ConfigMap: &corev1.ConfigMapVolumeSource{
-						LocalObjectReference: corev1.LocalObjectReference{
-							Name: cmName,
-						},
-						Items: []corev1.KeyToPath{
-							{
-								Key:  "content",
-								Path: resName,
-							},
+					Items: []corev1.KeyToPath{
+						{
+							Key:  "content",
+							Path: resName,
 						},
 					},
 				},
-			})
+			},
+		})
 
-			*mnts = append(*mnts, corev1.VolumeMount{
-				Name:      refName,
-				MountPath: resPath,
-			})
-		}
+		*mnts = append(*mnts, corev1.VolumeMount{
+			Name:      refName,
+			MountPath: resPath,
+		})
 	}
 
 	for i, r := range e.Integration.Resources() {


[camel-k] 09/21: kamelets: add schema to sources and map them in application.properties

Posted by nf...@apache.org.
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 11a6500a8af8e63af823dc8356d214a91d8f3d99
Author: Nicola Ferraro <ni...@gmail.com>
AuthorDate: Fri Jul 3 18:06:57 2020 +0200

    kamelets: add schema to sources and map them in application.properties
---
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go |   3 +-
 pkg/trait/container.go                           |   6 +-
 pkg/trait/kamelets.go                            |  33 ++++--
 pkg/trait/kamelets_test.go                       |  52 +++++----
 pkg/trait/trait_types.go                         | 142 ++++++++++++++++++-----
 pkg/util/test/client.go                          |  12 +-
 6 files changed, 181 insertions(+), 67 deletions(-)

diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index 61e8aa0..1292dc3 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -476,7 +476,8 @@ func (in *KameletSpec) DeepCopyInto(out *KameletSpec) {
 	}
 	if in.Flow != nil {
 		in, out := &in.Flow, &out.Flow
-		*out = (*in).DeepCopy()
+		*out = new(v1.Flow)
+		**out = **in
 	}
 	out.Authorization = in.Authorization
 	if in.Types != nil {
diff --git a/pkg/trait/container.go b/pkg/trait/container.go
index be1ea20..9c19e5e 100644
--- a/pkg/trait/container.go
+++ b/pkg/trait/container.go
@@ -24,7 +24,6 @@ import (
 	"strings"
 
 	"github.com/apache/camel-k/pkg/util"
-
 	appsv1 "k8s.io/api/apps/v1"
 	"k8s.io/api/batch/v1beta1"
 	corev1 "k8s.io/api/core/v1"
@@ -193,10 +192,13 @@ func (t *containerTrait) configureContainer(e *Environment) error {
 	}
 
 	envvar.SetVal(&container.Env, "CAMEL_K_DIGEST", e.Integration.Status.Digest)
-	envvar.SetVal(&container.Env, "CAMEL_K_ROUTES", strings.Join(e.ComputeSourcesURI(), ","))
 	envvar.SetVal(&container.Env, "CAMEL_K_CONF", "/etc/camel/conf/application.properties")
 	envvar.SetVal(&container.Env, "CAMEL_K_CONF_D", "/etc/camel/conf.d")
 
+	// Configure sources
+	envvar.SetVal(&container.Env, "CAMEL_K_ROUTES", strings.Join(e.ComputeSourcesURI(), ","))
+	e.AddSourcesProperties()
+
 	t.configureResources(e, &container)
 
 	if t.Expose != nil && *t.Expose {
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index 2a98a3a..80d4bc2 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -18,20 +18,21 @@ limitations under the License.
 package trait
 
 import (
+	"encoding/json"
 	"fmt"
+	"regexp"
+	"sort"
+	"strconv"
+	"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/metadata"
 	"github.com/apache/camel-k/pkg/util"
 	"github.com/apache/camel-k/pkg/util/digest"
-	"github.com/apache/camel-k/pkg/util/flows"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"regexp"
 	"sigs.k8s.io/controller-runtime/pkg/client"
-	"sort"
-	"strconv"
-	"strings"
 )
 
 // The kamelets trait is a platform trait used to inject Kamelets into the integration runtime.
@@ -136,19 +137,21 @@ func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet v1alpha1.Kame
 	var sources []v1.SourceSpec
 
 	if kamelet.Spec.Flow != nil {
-		flowData, err := flows.Marshal([]v1.Flow{*kamelet.Spec.Flow})
-		if err != nil {
-			return err
-		}
+		// TODO fixme removed for changes to Flow
+		//flowData, err := flows.Marshal([]v1.Flow{*kamelet.Spec.Flow})
+		//if err != nil {
+		//	return err
+		//}
 		flowSource := v1.SourceSpec{
 			DataSpec: v1.DataSpec{
-				Name:    fmt.Sprintf("%s.yaml", kamelet.Name),
-				Content: string(flowData),
+				Name: fmt.Sprintf("%s.yaml", kamelet.Name),
+				//Content: string(flowData),
+				Content: string(*kamelet.Spec.Flow),
 			},
 			Language: v1.LanguageYaml,
 			Type:     v1.SourceTypeKamelet,
 		}
-		flowSource, err = integrationSourceFromKameletSource(e, kamelet, flowSource, fmt.Sprintf("%s-kamelet-%s-flow", e.Integration.Name, kamelet.Name))
+		flowSource, err := integrationSourceFromKameletSource(e, kamelet, flowSource, fmt.Sprintf("%s-kamelet-%s-flow", e.Integration.Name, kamelet.Name))
 		if err != nil {
 			return err
 		}
@@ -272,6 +275,11 @@ func integrationSourceFromKameletSource(e *Environment, kamelet v1alpha1.Kamelet
 
 	// Create configmaps to avoid storing kamelet definitions in the integration CR
 
+	schema, err := json.Marshal(kamelet.Spec.Definition)
+	if err != nil {
+		return v1.SourceSpec{}, err
+	}
+
 	// Compute the input digest and store it along with the configmap
 	hash, err := digest.ComputeForSource(source)
 	if err != nil {
@@ -301,6 +309,7 @@ func integrationSourceFromKameletSource(e *Environment, kamelet v1alpha1.Kamelet
 		},
 		Data: map[string]string{
 			"content": source.Content,
+			"schema":  string(schema),
 		},
 	}
 
diff --git a/pkg/trait/kamelets_test.go b/pkg/trait/kamelets_test.go
index 4916046..59657be 100644
--- a/pkg/trait/kamelets_test.go
+++ b/pkg/trait/kamelets_test.go
@@ -19,19 +19,18 @@ package trait
 
 import (
 	"context"
-	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
-	corev1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/runtime"
+	"gopkg.in/yaml.v2"
 	"testing"
 
-	"github.com/apache/camel-k/pkg/util/camel"
-
-	"github.com/stretchr/testify/assert"
-
 	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/camel"
 	"github.com/apache/camel-k/pkg/util/kubernetes"
 	"github.com/apache/camel-k/pkg/util/test"
+	"github.com/stretchr/testify/assert"
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
 )
 
 func TestConfigurationNoKameletsUsed(t *testing.T) {
@@ -89,11 +88,11 @@ func TestKameletLookup(t *testing.T) {
 			Name:      "timer",
 		},
 		Spec: v1alpha1.KameletSpec{
-			Flow: &v1.Flow{
+			Flow: deleteMeAtSomePoint(map[string]interface{}{
 				"from": map[string]interface{}{
 					"uri": "timer:tick",
 				},
-			},
+			}),
 			Dependencies: []string{
 				"camel:timer",
 				"camel:log",
@@ -132,11 +131,11 @@ func TestKameletSecondarySourcesLookup(t *testing.T) {
 			Name:      "timer",
 		},
 		Spec: v1alpha1.KameletSpec{
-			Flow: &v1.Flow{
+			Flow: deleteMeAtSomePoint(map[string]interface{}{
 				"from": map[string]interface{}{
 					"uri": "timer:tick",
 				},
-			},
+			}),
 			Sources: []v1.SourceSpec{
 				{
 					DataSpec: v1.DataSpec{
@@ -237,11 +236,11 @@ func TestErrorMultipleKameletSources(t *testing.T) {
 					Type: v1.SourceTypeKamelet,
 				},
 			},
-			Flow: &v1.Flow{
+			Flow: deleteMeAtSomePoint(map[string]interface{}{
 				"from": map[string]interface{}{
 					"uri": "timer:tick",
 				},
-			},
+			}),
 		},
 	})
 	enabled, err := trait.Configure(environment)
@@ -266,11 +265,11 @@ func TestMultipleKamelets(t *testing.T) {
 			Name:      "timer",
 		},
 		Spec: v1alpha1.KameletSpec{
-			Flow: &v1.Flow{
+			Flow: deleteMeAtSomePoint(map[string]interface{}{
 				"from": map[string]interface{}{
 					"uri": "timer:tick",
 				},
-			},
+			}),
 			Sources: []v1.SourceSpec{
 				{
 					DataSpec: v1.DataSpec{
@@ -291,7 +290,7 @@ func TestMultipleKamelets(t *testing.T) {
 			Name:      "logger",
 		},
 		Spec: v1alpha1.KameletSpec{
-			Flow: &v1.Flow{
+			Flow: deleteMeAtSomePoint(map[string]interface{}{
 				"from": map[string]interface{}{
 					"uri": "tbd:endpoint",
 					"steps": []interface{}{
@@ -302,7 +301,7 @@ func TestMultipleKamelets(t *testing.T) {
 						},
 					},
 				},
-			},
+			}),
 			Dependencies: []string{
 				"camel:log",
 				"camel:tbd",
@@ -359,11 +358,11 @@ func TestKameletConfigLookup(t *testing.T) {
 			Name:      "timer",
 		},
 		Spec: v1alpha1.KameletSpec{
-			Flow: &v1.Flow{
+			Flow: deleteMeAtSomePoint(map[string]interface{}{
 				"from": map[string]interface{}{
 					"uri": "timer:tick",
 				},
-			},
+			}),
 			Dependencies: []string{
 				"camel:timer",
 				"camel:log",
@@ -421,11 +420,11 @@ func TestKameletNamedConfigLookup(t *testing.T) {
 			Name:      "timer",
 		},
 		Spec: v1alpha1.KameletSpec{
-			Flow: &v1.Flow{
+			Flow: deleteMeAtSomePoint(map[string]interface{}{
 				"from": map[string]interface{}{
 					"uri": "timer:tick",
 				},
-			},
+			}),
 			Dependencies: []string{
 				"camel:timer",
 				"camel:log",
@@ -511,3 +510,12 @@ func createKameletsTestEnvironment(flow string, objects ...runtime.Object) (*kam
 
 	return trait, environment
 }
+
+func deleteMeAtSomePoint(flow map[string]interface{}) *v1.Flow {
+	data, err := yaml.Marshal(flow)
+	if err != nil {
+		panic(err)
+	}
+	f := v1.Flow(data)
+	return &f
+}
diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go
index e815469..f1666f7 100644
--- a/pkg/trait/trait_types.go
+++ b/pkg/trait/trait_types.go
@@ -484,6 +484,10 @@ func (e *Environment) ComputeSourcesURI() []string {
 	paths := make([]string, 0, len(sources))
 
 	for i, s := range sources {
+		if s.Type == v1.SourceTypeKamelet {
+			// Kamelet information is added to application.properties
+			continue
+		}
 		root := path.Join(SourcesMountPath, fmt.Sprintf("i-source-%03d", i))
 
 		srcName := strings.TrimPrefix(s.Name, "/")
@@ -522,6 +526,64 @@ func (e *Environment) ComputeSourcesURI() []string {
 	return paths
 }
 
+// AddSourcesProperties --
+func (e *Environment) AddSourcesProperties() {
+	sources := e.Integration.Sources()
+	properties := make(map[string]string)
+
+	for _, s := range sources {
+		if s.Type == v1.SourceTypeKamelet {
+			// We compute properties only for Kamelets
+			// TODO move other sources types to this format instead of ENV_VAR
+
+			srcName := strings.TrimPrefix(s.Name, "/")
+			kameletName := srcName
+			if strings.Contains(kameletName, ".") {
+				kameletName = kameletName[0:strings.LastIndex(kameletName, ".")]
+			}
+			root := path.Join(KameletsMountPath, kameletName)
+
+			src := path.Join(root, srcName)
+			src = "file:" + src
+			properties[fmt.Sprintf("camel.k.kamelets[%s].location", kameletName)] = src
+
+			schemaName := path.Join(root, fmt.Sprintf("%s-schema.json", kameletName))
+			properties[fmt.Sprintf("camel.k.kamelets[%s].schema", kameletName)] = schemaName
+
+			if s.InferLanguage() != "" {
+				properties[fmt.Sprintf("camel.k.kamelets[%s].language", kameletName)] = string(s.InferLanguage())
+			}
+			if s.Loader != "" {
+				properties[fmt.Sprintf("camel.k.kamelets[%s].loader", kameletName)] = s.Loader
+			}
+			if s.Compression {
+				properties[fmt.Sprintf("camel.k.kamelets[%s].compression", kameletName)] = "true"
+			}
+
+			interceptors := make([]string, 0, len(s.Interceptors))
+			if s.Interceptors != nil {
+				interceptors = append(interceptors, s.Interceptors...)
+			}
+			if e.Interceptors != nil {
+				interceptors = append(interceptors, e.Interceptors...)
+			}
+			for i, interceptor := range interceptors {
+				properties[fmt.Sprintf("camel.k.kamelets[%s].interceptors[%d]", kameletName, i)] = interceptor
+			}
+		}
+	}
+
+	if len(properties) > 0 {
+		if e.ApplicationProperties == nil {
+			e.ApplicationProperties = properties
+		} else {
+			for k, v := range properties {
+				e.ApplicationProperties[k] = v
+			}
+		}
+	}
+}
+
 // ConfigureVolumesAndMounts --
 func (e *Environment) ConfigureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]corev1.VolumeMount) {
 	//
@@ -533,40 +595,68 @@ func (e *Environment) ConfigureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]c
 		if s.ContentRef != "" {
 			cmName = s.ContentRef
 		}
-
-		refName := fmt.Sprintf("i-source-%03d", i)
-		if s.Type == v1.SourceTypeKamelet {
-			refName = fmt.Sprintf("i-kamelet-source-%03d", i)
-		}
-
 		resName := strings.TrimPrefix(s.Name, "/")
 
-		resPath := path.Join(SourcesMountPath, refName)
 		if s.Type == v1.SourceTypeKamelet {
-			resPath = KameletsMountPath
-		}
-
-		*vols = append(*vols, corev1.Volume{
-			Name: refName,
-			VolumeSource: corev1.VolumeSource{
-				ConfigMap: &corev1.ConfigMapVolumeSource{
-					LocalObjectReference: corev1.LocalObjectReference{
-						Name: cmName,
+			kameletName := resName
+			if strings.Contains(kameletName, ".") {
+				kameletName = kameletName[0:strings.LastIndex(kameletName, ".")]
+			}
+			refName := fmt.Sprintf("i-kamelet-source-%03d", i)
+			resPath := path.Join(KameletsMountPath, kameletName)
+			schemaResName := fmt.Sprintf("%s-schema.json", kameletName)
+
+			*vols = append(*vols, corev1.Volume{
+				Name: refName,
+				VolumeSource: corev1.VolumeSource{
+					ConfigMap: &corev1.ConfigMapVolumeSource{
+						LocalObjectReference: corev1.LocalObjectReference{
+							Name: cmName,
+						},
+						Items: []corev1.KeyToPath{
+							{
+								Key:  "content",
+								Path: resName,
+							},
+							{
+								Key:  "schema",
+								Path: schemaResName,
+							},
+						},
 					},
-					Items: []corev1.KeyToPath{
-						{
-							Key:  "content",
-							Path: resName,
+				},
+			})
+
+			*mnts = append(*mnts, corev1.VolumeMount{
+				Name:      refName,
+				MountPath: resPath,
+			})
+		} else {
+			refName := fmt.Sprintf("i-source-%03d", i)
+			resPath := path.Join(SourcesMountPath, refName)
+
+			*vols = append(*vols, corev1.Volume{
+				Name: refName,
+				VolumeSource: corev1.VolumeSource{
+					ConfigMap: &corev1.ConfigMapVolumeSource{
+						LocalObjectReference: corev1.LocalObjectReference{
+							Name: cmName,
+						},
+						Items: []corev1.KeyToPath{
+							{
+								Key:  "content",
+								Path: resName,
+							},
 						},
 					},
 				},
-			},
-		})
+			})
 
-		*mnts = append(*mnts, corev1.VolumeMount{
-			Name:      refName,
-			MountPath: resPath,
-		})
+			*mnts = append(*mnts, corev1.VolumeMount{
+				Name:      refName,
+				MountPath: resPath,
+			})
+		}
 	}
 
 	for i, r := range e.Integration.Resources() {
diff --git a/pkg/util/test/client.go b/pkg/util/test/client.go
index b223f95..22e7d0b 100644
--- a/pkg/util/test/client.go
+++ b/pkg/util/test/client.go
@@ -18,6 +18,8 @@ limitations under the License.
 package test
 
 import (
+	"strings"
+
 	"github.com/apache/camel-k/pkg/apis"
 	"github.com/apache/camel-k/pkg/client"
 	"k8s.io/apimachinery/pkg/runtime"
@@ -25,7 +27,6 @@ import (
 	fakeclientset "k8s.io/client-go/kubernetes/fake"
 	clientscheme "k8s.io/client-go/kubernetes/scheme"
 	"k8s.io/client-go/rest"
-
 	controller "sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
 )
@@ -41,13 +42,16 @@ func NewFakeClient(initObjs ...runtime.Object) (client.Client, error) {
 
 	c := fake.NewFakeClientWithScheme(scheme, initObjs...)
 	filtered := make([]runtime.Object, 0, len(initObjs))
+	skipList := []string{"camel", "knative"}
 	for _, o := range initObjs {
 		kinds, _, _ := scheme.ObjectKinds(o)
 		allow := true
 		for _, k := range kinds {
-			if k.Group == "camel.apache.org" {
-				allow = false
-				break
+			for _, skip := range skipList {
+				if strings.Contains(k.Group, skip) {
+					allow = false
+					break
+				}
 			}
 		}
 		if allow {


[camel-k] 02/21: kamelets: adding event types

Posted by nf...@apache.org.
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 7d3663ac0cf71f15eba2602c87a2613c5d54239e
Author: Nicola Ferraro <ni...@gmail.com>
AuthorDate: Tue Jun 23 11:46:38 2020 +0200

    kamelets: adding event types
---
 examples/kamelets/timer.kamelet.yaml     | 24 ++++++++++++++++++++++++
 pkg/apis/camel/v1alpha1/kamelet_types.go | 12 ++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/examples/kamelets/timer.kamelet.yaml b/examples/kamelets/timer.kamelet.yaml
new file mode 100644
index 0000000..9a2ec5d
--- /dev/null
+++ b/examples/kamelets/timer.kamelet.yaml
@@ -0,0 +1,24 @@
+apiVersion: camel.apache.org/v1alpha1
+kind: Kamelet
+metadata:
+  name: timer
+spec:
+  displayName: "Timer"
+  description: "Produces produces periodic events with a custom payload"
+  parameters:
+    - name: message
+      description: The message to generate
+      schema:
+        type: string
+  produces:
+    type: text.types.camel.apache.org
+    schema:
+      content:
+        type: string
+  flow:
+    from:
+      uri: timer:tick
+      steps:
+        - set-body:
+            constant: "Hello [here there'll be the message] !!!"
+        - to: "log:info"
diff --git a/pkg/apis/camel/v1alpha1/kamelet_types.go b/pkg/apis/camel/v1alpha1/kamelet_types.go
index ed99b66..190a71d 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_types.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_types.go
@@ -14,9 +14,21 @@ type KameletSpec struct {
 	Authorization AuthorizationSpec   `json:"authorization,omitempty"`
 	Sources       *camelv1.SourceSpec `json:"sources,omitempty"`
 	Flow          *camelv1.Flow       `json:"flow,omitempty"`
+	Consumes      *EventType          `json:"consumes,omitempty"`
+	Produces      *EventType          `json:"produces,omitempty"`
 	Dependencies  []string            `json:"dependencies,omitempty"`
 }
 
+type EventType struct {
+	Type   string      `json:"type,omitempty"`
+	Schema *DataSchema `json:"schema,omitempty"`
+}
+
+type DataSchema struct {
+	Ref     *corev1.ObjectReference `json:"ref,omitempty"`
+	Content *openapi.Schema         `json:"schema,omitempty"`
+}
+
 type KameletInfo struct {
 	DisplayName string      `json:"displayName,omitempty"`
 	Description string      `json:"description,omitempty"`


[camel-k] 06/21: kamelets: adding support for kamelet dependencies

Posted by nf...@apache.org.
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 7d17bfc3928e5b01f9f1127e1db3c2f87886190d
Author: Nicola Ferraro <ni...@gmail.com>
AuthorDate: Thu Jun 25 11:29:37 2020 +0200

    kamelets: adding support for kamelet dependencies
---
 pkg/trait/kamelets.go      |   7 ++++
 pkg/trait/kamelets_test.go | 100 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 107 insertions(+)

diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index 180985a..55b61a2 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -86,6 +86,7 @@ func (t *kameletsTrait) Apply(e *Environment) error {
 	if err := t.addKamelets(e); err != nil {
 		return err
 	}
+
 	return nil
 }
 
@@ -99,10 +100,16 @@ func (t *kameletsTrait) addKamelets(e *Environment) error {
 		if err := t.Client.Get(t.Ctx, key, &kamelet); err != nil {
 			return err
 		}
+
 		if err := t.addKameletAsSource(e, kamelet); err != nil {
 			return err
 		}
+
+		// Adding dependencies from Kamelets
+		util.StringSliceUniqueConcat(&e.Integration.Status.Dependencies, kamelet.Spec.Dependencies)
 	}
+	// resort dependencies
+	sort.Strings(e.Integration.Status.Dependencies)
 	return nil
 }
 
diff --git a/pkg/trait/kamelets_test.go b/pkg/trait/kamelets_test.go
index 30585c3..500baba 100644
--- a/pkg/trait/kamelets_test.go
+++ b/pkg/trait/kamelets_test.go
@@ -84,6 +84,10 @@ func TestKameletLookup(t *testing.T) {
 					"uri": "timer:tick",
 				},
 			},
+			Dependencies: []string{
+				"camel:timer",
+				"camel:log",
+			},
 		},
 	})
 	enabled, err := trait.Configure(environment)
@@ -102,6 +106,8 @@ func TestKameletLookup(t *testing.T) {
 	source := environment.Integration.Status.GeneratedSources[0]
 	assert.Equal(t, "timer.yaml", source.Name)
 	assert.Equal(t, "kamelet", string(source.Type))
+
+	assert.Equal(t, []string{"camel:log", "camel:timer"}, environment.Integration.Status.Dependencies)
 }
 
 func TestKameletSecondarySourcesLookup(t *testing.T) {
@@ -237,6 +243,100 @@ func TestErrorMultipleKameletSources(t *testing.T) {
 	assert.Error(t, err)
 }
 
+func TestMultipleKamelets(t *testing.T) {
+	trait, environment := createKameletsTestEnvironment(`
+- from:
+    uri: kamelet:timer
+    steps:
+    - to: kamelet:logger
+    - to: kamelet:logger
+`, &v1alpha1.Kamelet{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "test",
+			Name:      "timer",
+		},
+		Spec: v1alpha1.KameletSpec{
+			Flow: &v1.Flow{
+				"from": map[string]interface{}{
+					"uri": "timer:tick",
+				},
+			},
+			Sources: []v1.SourceSpec{
+				{
+					DataSpec: v1.DataSpec{
+						Name:    "support.groovy",
+						Content: "from('xxx:xxx').('to:log:info')",
+					},
+					Language: v1.LanguageGroovy,
+				},
+			},
+			Dependencies: []string{
+				"camel:timer",
+				"camel:xxx",
+			},
+		},
+	}, &v1alpha1.Kamelet{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "test",
+			Name:      "logger",
+		},
+		Spec: v1alpha1.KameletSpec{
+			Flow: &v1.Flow{
+				"from": map[string]interface{}{
+					"uri": "tbd:endpoint",
+					"steps": []interface{}{
+						map[string]interface{}{
+							"to": map[string]interface{}{
+								"uri": "log:info",
+							},
+						},
+					},
+				},
+			},
+			Dependencies: []string{
+				"camel:log",
+				"camel:tbd",
+			},
+		},
+	})
+	enabled, err := trait.Configure(environment)
+	assert.NoError(t, err)
+	assert.True(t, enabled)
+	assert.Equal(t, []string{"logger", "timer"}, trait.getKamelets())
+
+	err = trait.Apply(environment)
+	assert.NoError(t, err)
+
+	cmFlow := environment.Resources.GetConfigMap(func(c *corev1.ConfigMap) bool { return c.Name == "it-kamelet-timer-flow" })
+	assert.NotNil(t, cmFlow)
+	cmRes := environment.Resources.GetConfigMap(func(c *corev1.ConfigMap) bool { return c.Name == "it-kamelet-timer-000" })
+	assert.NotNil(t, cmRes)
+	cmFlow2 := environment.Resources.GetConfigMap(func(c *corev1.ConfigMap) bool { return c.Name == "it-kamelet-logger-flow" })
+	assert.NotNil(t, cmFlow2)
+
+	assert.Len(t, environment.Integration.Status.GeneratedSources, 3)
+
+	flowSource2 := environment.Integration.Status.GeneratedSources[0]
+	assert.Equal(t, "logger.yaml", flowSource2.Name)
+	assert.Equal(t, "kamelet", string(flowSource2.Type))
+	assert.Equal(t, "it-kamelet-logger-flow", flowSource2.ContentRef)
+	assert.Equal(t, "content", flowSource2.ContentKey)
+
+	flowSource := environment.Integration.Status.GeneratedSources[1]
+	assert.Equal(t, "timer.yaml", flowSource.Name)
+	assert.Equal(t, "kamelet", string(flowSource.Type))
+	assert.Equal(t, "it-kamelet-timer-flow", flowSource.ContentRef)
+	assert.Equal(t, "content", flowSource.ContentKey)
+
+	supportSource := environment.Integration.Status.GeneratedSources[2]
+	assert.Equal(t, "support.groovy", supportSource.Name)
+	assert.Equal(t, "", string(supportSource.Type))
+	assert.Equal(t, "it-kamelet-timer-000", supportSource.ContentRef)
+	assert.Equal(t, "content", supportSource.ContentKey)
+
+	assert.Equal(t, []string{"camel:log", "camel:tbd", "camel:timer", "camel:xxx"}, environment.Integration.Status.Dependencies)
+}
+
 func createKameletsTestEnvironment(flow string, objects ...runtime.Object) (*kameletsTrait, *Environment) {
 	catalog, _ := camel.DefaultCatalog()
 


[camel-k] 04/21: kamelets: initial scaffolding of kamelets trait

Posted by nf...@apache.org.
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 9f0c5ec4370ad61751b18a2d05886f617601f2cf
Author: Nicola Ferraro <ni...@gmail.com>
AuthorDate: Wed Jun 24 10:37:39 2020 +0200

    kamelets: initial scaffolding of kamelets trait
---
 pkg/apis/camel/v1/integration_types.go           |   9 ++
 pkg/apis/camel/v1alpha1/kamelet_types.go         |   4 +-
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go |  34 +++-
 pkg/trait/kamelets.go                            | 195 +++++++++++++++++++++++
 pkg/trait/kamelets_test.go                       |  84 ++++++++++
 pkg/trait/trait_register.go                      |   1 +
 pkg/util/digest/digest.go                        |  44 +++++
 7 files changed, 362 insertions(+), 9 deletions(-)

diff --git a/pkg/apis/camel/v1/integration_types.go b/pkg/apis/camel/v1/integration_types.go
index 1f473d5..7e985a2 100644
--- a/pkg/apis/camel/v1/integration_types.go
+++ b/pkg/apis/camel/v1/integration_types.go
@@ -125,8 +125,17 @@ type SourceSpec struct {
 	// Interceptors are optional identifiers the org.apache.camel.k.RoutesLoader
 	// uses to pre/post process sources
 	Interceptors []string `json:"interceptors,omitempty"`
+	// Type defines the kind of source described by this object
+	Type SourceType `json:"type,omitempty"`
 }
 
+type SourceType string
+
+const (
+	SourceTypeDefault SourceType = ""
+	SourceTypeKamelet SourceType = "kamelet"
+)
+
 // Language --
 type Language string
 
diff --git a/pkg/apis/camel/v1alpha1/kamelet_types.go b/pkg/apis/camel/v1alpha1/kamelet_types.go
index 0855489..fa53584 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_types.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_types.go
@@ -30,8 +30,8 @@ const (
 // KameletSpec defines the desired state of Kamelet
 type KameletSpec struct {
 	Definition    JSONSchemaProps             `json:"definition,omitempty"`
-	Sources       *camelv1.SourceSpec         `json:"sources,omitempty"`
-	Flow          *camelv1.Flow               `json:"flow,omitempty"`
+	Sources       []camelv1.SourceSpec        `json:"sources,omitempty"`
+	Flow          camelv1.Flow                `json:"flow,omitempty"`
 	Authorization AuthorizationSpec           `json:"authorization,omitempty"`
 	Types         map[EventSlot]EventTypeSpec `json:"types,omitempty"`
 	Dependencies  []string                    `json:"dependencies,omitempty"`
diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index b81d3ca..2f7512c 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -26,6 +26,27 @@ func (in *AuthorizationSpec) DeepCopy() *AuthorizationSpec {
 }
 
 // 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 {
+		in, out := &in.Schema, &out.Schema
+		*out = new(JSONSchemaProps)
+		(*in).DeepCopyInto(*out)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EventTypeSpec.
+func (in *EventTypeSpec) DeepCopy() *EventTypeSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(EventTypeSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *ExternalDocumentation) DeepCopyInto(out *ExternalDocumentation) {
 	*out = *in
 	return
@@ -448,17 +469,16 @@ func (in *KameletSpec) DeepCopyInto(out *KameletSpec) {
 	in.Definition.DeepCopyInto(&out.Definition)
 	if in.Sources != nil {
 		in, out := &in.Sources, &out.Sources
-		*out = new(v1.SourceSpec)
-		(*in).DeepCopyInto(*out)
-	}
-	if in.Flow != nil {
-		in, out := &in.Flow, &out.Flow
-		*out = (*in).DeepCopy()
+		*out = make([]v1.SourceSpec, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
 	}
+	in.Flow.DeepCopyInto(&out.Flow)
 	out.Authorization = in.Authorization
 	if in.Types != nil {
 		in, out := &in.Types, &out.Types
-		*out = make(map[string]JSONSchemaProps, len(*in))
+		*out = make(map[EventSlot]EventTypeSpec, len(*in))
 		for key, val := range *in {
 			(*out)[key] = *val.DeepCopy()
 		}
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
new file mode 100644
index 0000000..4ba9d67
--- /dev/null
+++ b/pkg/trait/kamelets.go
@@ -0,0 +1,195 @@
+/*
+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 trait
+
+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/metadata"
+	"github.com/apache/camel-k/pkg/util"
+	"github.com/apache/camel-k/pkg/util/digest"
+	"github.com/apache/camel-k/pkg/util/flows"
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+)
+
+// The kamelets trait is a platform trait used to inject Kamelets into the integration runtime.
+//
+// +camel-k:trait=kamelets
+type kameletsTrait struct {
+	BaseTrait `property:",squash"`
+	// Automatically inject all referenced Kamelets and their default configuration (enabled by default)
+	Auto *bool `property:"auto"`
+	// Comma separated list of Kamelet names to load into the current integration
+	List string `property:"list"`
+}
+
+var (
+	kameletNameRegexp = regexp.MustCompile("kamelet:(?://)?([a-z0-9-.]+)(?:$|[^a-z0-9-.].*)")
+)
+
+func newKameletsTrait() Trait {
+	return &kameletsTrait{
+		BaseTrait: NewBaseTrait("kamelets", 450),
+	}
+}
+
+func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
+	if t.Enabled != nil && !*t.Enabled {
+		return false, nil
+	}
+
+	if t.Auto == nil || *t.Auto {
+		if t.List == "" {
+			var kamelets []string
+			metadata.Each(e.CamelCatalog, e.Integration.Sources(), func(_ int, meta metadata.IntegrationMetadata) bool {
+				util.StringSliceUniqueConcat(&kamelets, extractKamelets(meta.FromURIs))
+				util.StringSliceUniqueConcat(&kamelets, extractKamelets(meta.ToURIs))
+				return true
+			})
+			sort.Strings(kamelets)
+			t.List = strings.Join(kamelets, ",")
+		}
+
+	}
+
+	return t.List != "", nil
+}
+
+func (t *kameletsTrait) Apply(e *Environment) error {
+
+	return nil
+}
+
+// IsPlatformTrait overrides base class method
+func (t *kameletsTrait) IsPlatformTrait() bool {
+	return true
+}
+
+func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet *v1alpha1.Kamelet) error {
+	var sources []v1.SourceSpec
+
+	flowData, err := flows.Marshal([]v1.Flow{kamelet.Spec.Flow})
+	if err != nil {
+		return err
+	}
+	flowSource := v1.SourceSpec{
+		DataSpec: v1.DataSpec{
+			Name:    "flow.yaml",
+			Content: string(flowData),
+		},
+		Language: v1.LanguageYaml,
+		Type:     v1.SourceTypeKamelet,
+	}
+	flowSource, err = integrationSourceFromKameletSource(e, kamelet, flowSource, fmt.Sprintf("%s-kamelet-%s-flow", e.Integration.Name, kamelet.Name))
+	if err != nil {
+		return err
+	}
+	sources = append(sources, flowSource)
+
+	for idx, s := range kamelet.Spec.Sources {
+		intSource, err := integrationSourceFromKameletSource(e, kamelet, s, fmt.Sprintf("%s-kamelet-%s-source-%03d", e.Integration.Name, kamelet.Name, idx))
+		if err != nil {
+			return err
+		}
+		sources = append(sources, intSource)
+	}
+	return nil
+}
+
+func (t *kameletsTrait) getKamelets() []string {
+	answer := make([]string, 0)
+	for _, item := range strings.Split(t.List, ",") {
+		i := strings.Trim(item, " \t\"")
+		if i != "" {
+			answer = append(answer, i)
+		}
+	}
+	return answer
+}
+
+func integrationSourceFromKameletSource(e *Environment, kamelet *v1alpha1.Kamelet, source v1.SourceSpec, name string) (v1.SourceSpec, error) {
+	if source.DataSpec.ContentRef != "" {
+		return renameSource(kamelet, source), nil
+	}
+
+	// Create configmaps to avoid storing kamelet definitions in the integration CR
+
+	// Compute the input digest and store it along with the configmap
+	hash, err := digest.ComputeForSource(source)
+	if err != nil {
+		return v1.SourceSpec{}, err
+	}
+
+	cm := corev1.ConfigMap{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "ConfigMap",
+			APIVersion: "v1",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      name,
+			Namespace: e.Integration.Namespace,
+			Labels: map[string]string{
+				"camel.apache.org/integration": e.Integration.Name,
+				"camel.apache.org/kamelet":     kamelet.Name,
+			},
+			Annotations: map[string]string{
+				"camel.apache.org/source.language":    string(source.Language),
+				"camel.apache.org/source.name":        name,
+				"camel.apache.org/source.compression": strconv.FormatBool(source.Compression),
+				"camel.apache.org/source.generated":   "true",
+				"camel.apache.org/source.type":        string(source.Type),
+				"camel.apache.org/source.digest":      hash,
+			},
+		},
+		Data: map[string]string{
+			"content": source.Content,
+		},
+	}
+
+	e.Resources.Add(&cm)
+
+	target := renameSource(kamelet, source)
+	target.Content = ""
+	target.ContentRef = name
+	target.ContentKey = "content"
+	return target, nil
+}
+
+func renameSource(kamelet *v1alpha1.Kamelet, source v1.SourceSpec) v1.SourceSpec {
+	target := source.DeepCopy()
+	if !strings.HasPrefix(target.Name, fmt.Sprintf("kamelet-%s-", kamelet.Name)) {
+		target.Name = fmt.Sprintf("kamelet-%s-%s", kamelet.Name, target.Name)
+	}
+	return *target
+}
+
+func extractKamelets(uris []string) (kamelets []string) {
+	for _, uri := range uris {
+		matches := kameletNameRegexp.FindStringSubmatch(uri)
+		if len(matches) == 2 {
+			kamelets = append(kamelets, matches[1])
+		}
+	}
+	return
+}
diff --git a/pkg/trait/kamelets_test.go b/pkg/trait/kamelets_test.go
new file mode 100644
index 0000000..b7d4fe7
--- /dev/null
+++ b/pkg/trait/kamelets_test.go
@@ -0,0 +1,84 @@
+/*
+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 trait
+
+import (
+	"context"
+	"testing"
+
+	"github.com/apache/camel-k/pkg/util/camel"
+
+	"github.com/stretchr/testify/assert"
+
+	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+	"github.com/apache/camel-k/pkg/util/kubernetes"
+	"github.com/apache/camel-k/pkg/util/test"
+)
+
+func TestKameletsFinding(t *testing.T) {
+	trait, environment := createKameletsTestEnvironment(`
+- from:
+    uri: kamelet:c1
+    steps:
+    - to: kamelet:c2
+    - to: telegram:bots
+    - to: kamelet://c0?prop=x
+    - to: kamelet://complex-.-.-1a?prop=x&prop2
+    - to: kamelet://complex-.-.-1b
+    - to: kamelet:complex-.-.-1b
+    - to: kamelet://complex-.-.-1b/a
+    - to: kamelet://complex-.-.-1c/b
+`)
+	enabled, err := trait.Configure(environment)
+	assert.NoError(t, err)
+	assert.True(t, enabled)
+	assert.Equal(t, []string{"c0", "c1", "c2", "complex-.-.-1a", "complex-.-.-1b", "complex-.-.-1c"}, trait.getKamelets())
+}
+
+func createKameletsTestEnvironment(flow string) (*kameletsTrait, *Environment) {
+	catalog, _ := camel.DefaultCatalog()
+
+	client, _ := test.NewFakeClient()
+	trait := newKameletsTrait().(*kameletsTrait)
+	trait.Ctx = context.TODO()
+	trait.Client = client
+
+	environment := &Environment{
+		Catalog:      NewCatalog(context.TODO(), nil),
+		CamelCatalog: catalog,
+		Integration: &v1.Integration{
+			Spec: v1.IntegrationSpec{
+				Sources: []v1.SourceSpec{
+					{
+						DataSpec: v1.DataSpec{
+							Name:    "flow.yaml",
+							Content: flow,
+						},
+						Language: v1.LanguageYaml,
+					},
+				},
+			},
+			Status: v1.IntegrationStatus{
+				Phase: v1.IntegrationPhaseInitialization,
+			},
+		},
+		Resources: kubernetes.NewCollection(),
+	}
+
+	return trait, environment
+}
diff --git a/pkg/trait/trait_register.go b/pkg/trait/trait_register.go
index 993efdf..30c4356 100644
--- a/pkg/trait/trait_register.go
+++ b/pkg/trait/trait_register.go
@@ -25,6 +25,7 @@ func init() {
 	AddToTraits(newCamelTrait)
 	AddToTraits(newOpenAPITrait)
 	AddToTraits(newKnativeTrait)
+	AddToTraits(newKameletsTrait)
 	AddToTraits(newDependenciesTrait)
 	AddToTraits(newBuilderTrait)
 	AddToTraits(newQuarkusTrait)
diff --git a/pkg/util/digest/digest.go b/pkg/util/digest/digest.go
index 097d08a..6ccd3ed 100644
--- a/pkg/util/digest/digest.go
+++ b/pkg/util/digest/digest.go
@@ -184,6 +184,50 @@ func ComputeForResource(res v1.ResourceSpec) (string, error) {
 	return digest, nil
 }
 
+// ComputeForSource returns a digest for the specific source
+func ComputeForSource(s v1.SourceSpec) (string, error) {
+	hash := sha256.New()
+	// Operator version is relevant
+	if _, err := hash.Write([]byte(defaults.Version)); err != nil {
+		return "", err
+	}
+
+	if _, err := hash.Write([]byte(s.Content)); err != nil {
+		return "", err
+	}
+	if _, err := hash.Write([]byte(s.Name)); err != nil {
+		return "", err
+	}
+	if _, err := hash.Write([]byte(s.Type)); err != nil {
+		return "", err
+	}
+	if _, err := hash.Write([]byte(s.Language)); err != nil {
+		return "", err
+	}
+	if _, err := hash.Write([]byte(s.ContentKey)); err != nil {
+		return "", err
+	}
+	if _, err := hash.Write([]byte(s.ContentRef)); err != nil {
+		return "", err
+	}
+	if _, err := hash.Write([]byte(s.Loader)); err != nil {
+		return "", err
+	}
+	for _, i := range s.Interceptors {
+		if _, err := hash.Write([]byte(i)); err != nil {
+			return "", err
+		}
+	}
+
+	if _, err := hash.Write([]byte(strconv.FormatBool(s.Compression))); err != nil {
+		return "", err
+	}
+
+	// Add a letter at the beginning and use URL safe encoding
+	digest := "v" + base64.RawURLEncoding.EncodeToString(hash.Sum(nil))
+	return digest, nil
+}
+
 func sortedTraitSpecMapKeys(m map[string]v1.TraitSpec) []string {
 	res := make([]string, len(m))
 	i := 0


[camel-k] 13/21: Fix #1574: add property names in source specification

Posted by nf...@apache.org.
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 3fceb04ace9d412bca86cef9d44e91b6118f660a
Author: nicolaferraro <ni...@gmail.com>
AuthorDate: Tue Aug 11 16:43:37 2020 +0200

    Fix #1574: add property names in source specification
---
 pkg/trait/kamelets.go | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index 05f734f..1b3c9dc 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -185,13 +185,20 @@ func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet v1alpha1.Kame
 		if err != nil {
 			return err
 		}
+
+		propertyNames := make([]string, 0, len(kamelet.Status.Properties))
+		for _, p := range kamelet.Status.Properties {
+			propertyNames = append(propertyNames, p.Name)
+		}
+
 		flowSource := v1.SourceSpec{
 			DataSpec: v1.DataSpec{
 				Name:    fmt.Sprintf("%s.yaml", kamelet.Name),
 				Content: string(flowData),
 			},
-			Language: v1.LanguageYaml,
-			Type:     v1.SourceTypeTemplate,
+			Language:      v1.LanguageYaml,
+			Type:          v1.SourceTypeTemplate,
+			PropertyNames: propertyNames,
 		}
 		flowSource, err = integrationSourceFromKameletSource(e, kamelet, flowSource, fmt.Sprintf("%s-kamelet-%s-flow", e.Integration.Name, kamelet.Name))
 		if err != nil {


[camel-k] 16/21: fix #1676: add kamelet binding resource

Posted by nf...@apache.org.
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 <ni...@gmail.com>
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)
+		})
+	}
+}


[camel-k] 19/21: Fix #1574: update runtime

Posted by nf...@apache.org.
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 279cfb975422019fd63a56da9c9cca56ce9bf0a2
Author: nicolaferraro <ni...@gmail.com>
AuthorDate: Tue Sep 15 17:53:39 2020 +0200

    Fix #1574: update runtime
---
 deploy/camel-catalog-1.5.1-SNAPSHOT-main.yaml    |   20 +-
 deploy/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml | 2159 +++++++++++++++++-----
 deploy/resources.go                              |   10 +-
 3 files changed, 1745 insertions(+), 444 deletions(-)

diff --git a/deploy/camel-catalog-1.5.1-SNAPSHOT-main.yaml b/deploy/camel-catalog-1.5.1-SNAPSHOT-main.yaml
index 405b36f..c4cd500 100644
--- a/deploy/camel-catalog-1.5.1-SNAPSHOT-main.yaml
+++ b/deploy/camel-catalog-1.5.1-SNAPSHOT-main.yaml
@@ -21,8 +21,8 @@ metadata:
   name: camel-catalog-1.5.1-snapshot-main
   labels:
     app: camel-k
-    camel.apache.org/catalog.version: 3.5.0-SNAPSHOT
-    camel.apache.org/catalog.loader.version: 3.5.0-SNAPSHOT
+    camel.apache.org/catalog.version: 3.5.0
+    camel.apache.org/catalog.loader.version: 3.5.0
     camel.apache.org/runtime.version: 1.5.1-SNAPSHOT
     camel.apache.org/runtime.provider: main
 spec:
@@ -31,9 +31,9 @@ spec:
     provider: main
     applicationClass: org.apache.camel.k.main.Application
     metadata:
-      camel.version: 3.5.0-SNAPSHOT
-      quarkus.version: 1.7.0.Final
-      camel-quarkus.version: 1.0.0
+      camel.version: 3.5.0
+      quarkus.version: 1.8.0.Final
+      camel-quarkus.version: 1.1.0
     dependencies:
     - groupId: org.apache.camel.k
       artifactId: camel-k-runtime-main
@@ -3235,6 +3235,16 @@ spec:
         artifactId: camel-knative
       - groupId: org.apache.camel.k
         artifactId: camel-knative-http
+    camel-kamelet:
+      groupId: org.apache.camel.k
+      artifactId: camel-kamelet
+      schemes:
+      - id: kamelet
+        http: true
+        passive: false
+      dependencies:
+      - groupId: org.apache.camel.k
+        artifactId: camel-kamelet
   loaders:
     yaml:
       groupId: org.apache.camel.k
diff --git a/deploy/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml b/deploy/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml
index db61e37..c180043 100644
--- a/deploy/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml
+++ b/deploy/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml
@@ -21,8 +21,8 @@ metadata:
   name: camel-catalog-1.5.1-snapshot-quarkus
   labels:
     app: camel-k
-    camel.apache.org/catalog.version: 3.5.0-SNAPSHOT
-    camel.apache.org/catalog.loader.version: 3.5.0-SNAPSHOT
+    camel.apache.org/catalog.version: 3.5.0
+    camel.apache.org/catalog.loader.version: 3.5.0
     camel.apache.org/runtime.version: 1.5.1-SNAPSHOT
     camel.apache.org/runtime.provider: quarkus
 spec:
@@ -31,9 +31,9 @@ spec:
     provider: quarkus
     applicationClass: io.quarkus.runner.GeneratedMain
     metadata:
-      camel.version: 3.5.0-SNAPSHOT
-      quarkus.version: 1.7.0.Final
-      camel-quarkus.version: 1.0.0
+      camel.version: 3.5.0
+      quarkus.version: 1.8.0.Final
+      camel-quarkus.version: 1.1.0
     dependencies:
     - groupId: org.apache.camel.k
       artifactId: camel-k-runtime-quarkus
@@ -65,15 +65,6 @@ spec:
         - groupId: org.apache.camel.quarkus
           artifactId: camel-quarkus-opentracing
   artifacts:
-    camel-quarkus-kudu:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-kudu
-      schemes:
-      - id: kudu
-        http: false
-        passive: false
-      javaTypes:
-      - org.apache.camel.component.kudu.KuduComponent
     camel-quarkus-aws2-ses:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-aws2-ses
@@ -83,24 +74,27 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.aws2.ses.Ses2Component
-    camel-quarkus-rest-openapi:
+    camel-quarkus-thrift:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-rest-openapi
+      artifactId: camel-quarkus-thrift
       schemes:
-      - id: rest-openapi
+      - id: thrift
         http: false
         passive: false
+      dataformats:
+      - thrift
       javaTypes:
-      - org.apache.camel.component.rest.openapi.RestOpenApiComponent
-    camel-quarkus-file:
+      - org.apache.camel.component.thrift.ThriftComponent
+      - org.apache.camel.dataformat.thrift.ThriftDataFormat
+    camel-quarkus-chunk:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-file
+      artifactId: camel-quarkus-chunk
       schemes:
-      - id: file
+      - id: chunk
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.file.FileComponent
+      - org.apache.camel.component.chunk.ChunkComponent
     camel-quarkus-aws2-s3:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-aws2-s3
@@ -110,13 +104,31 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.aws2.s3.AWS2S3Component
-    camel-quarkus-xpath:
+    camel-quarkus-jclouds:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-xpath
-      languages:
-      - xpath
+      artifactId: camel-quarkus-jclouds
+      schemes:
+      - id: jclouds
+        http: false
+        passive: false
       javaTypes:
-      - org.apache.camel.language.xpath.XPathLanguage
+      - org.apache.camel.component.jclouds.JcloudsComponent
+    camel-quarkus-twilio:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-twilio
+      schemes:
+      - id: twilio
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.twilio.TwilioComponent
+    camel-quarkus-beanio:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-beanio
+      dataformats:
+      - beanio
+      javaTypes:
+      - org.apache.camel.dataformat.beanio.BeanIODataFormat
     camel-quarkus-aws2-translate:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-aws2-translate
@@ -126,24 +138,54 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.aws2.translate.Translate2Component
-    camel-quarkus-influxdb:
+    camel-quarkus-zendesk:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-influxdb
+      artifactId: camel-quarkus-zendesk
       schemes:
-      - id: influxdb
+      - id: zendesk
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.influxdb.InfluxDbComponent
-    camel-quarkus-mock:
+      - org.apache.camel.component.zendesk.ZendeskComponent
+    camel-quarkus-xchange:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-mock
+      artifactId: camel-quarkus-xchange
       schemes:
-      - id: mock
+      - id: xchange
         http: false
-        passive: true
+        passive: false
       javaTypes:
-      - org.apache.camel.component.mock.MockComponent
+      - org.apache.camel.component.xchange.XChangeComponent
+    camel-quarkus-chatscript:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-chatscript
+      schemes:
+      - id: chatscript
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.chatscript.ChatScriptComponent
+    camel-quarkus-saxon:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-saxon
+      schemes:
+      - id: xquery
+        http: false
+        passive: false
+      languages:
+      - xquery
+      javaTypes:
+      - org.apache.camel.component.xquery.XQueryComponent
+      - org.apache.camel.language.xquery.XQueryLanguage
+    camel-quarkus-influxdb:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-influxdb
+      schemes:
+      - id: influxdb
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.influxdb.InfluxDbComponent
     camel-quarkus-kubernetes:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-kubernetes
@@ -234,13 +276,13 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.debezium.DebeziumPostgresComponent
-    camel-quarkus-soap:
+    camel-quarkus-cbor:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-soap
+      artifactId: camel-quarkus-cbor
       dataformats:
-      - soapjaxb
+      - cbor
       javaTypes:
-      - org.apache.camel.dataformat.soap.SoapJaxbDataFormat
+      - org.apache.camel.component.cbor.CBORDataFormat
     camel-quarkus-tika:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-tika
@@ -250,33 +292,1294 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.tika.TikaComponent
-    camel-quarkus-jolt:
+    camel-quarkus-cron:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-jolt
+      artifactId: camel-quarkus-cron
       schemes:
-      - id: jolt
+      - id: cron
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.jolt.JoltComponent
-    camel-quarkus-validator:
+      - org.apache.camel.component.cron.CronComponent
+    camel-quarkus-aws2-iam:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-validator
+      artifactId: camel-quarkus-aws2-iam
       schemes:
-      - id: validator
+      - id: aws2-iam
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.aws2.iam.IAM2Component
+    camel-quarkus-vertx-websocket:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-vertx-websocket
+      schemes:
+      - id: vertx-websocket
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.vertx.websocket.VertxWebsocketComponent
+    camel-quarkus-netty:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-netty
+      schemes:
+      - id: netty
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.netty.NettyComponent
+    camel-quarkus-drill:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-drill
+      schemes:
+      - id: drill
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.drill.DrillComponent
+    camel-quarkus-xmlsecurity:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-xmlsecurity
+      schemes:
+      - id: xmlsecurity-sign
+        http: false
+        passive: false
+      - id: xmlsecurity-verify
+        http: false
+        passive: false
+      dataformats:
+      - secureXML
+      javaTypes:
+      - org.apache.camel.component.xmlsecurity.XmlSignerComponent
+      - org.apache.camel.component.xmlsecurity.XmlVerifierComponent
+      - org.apache.camel.dataformat.xmlsecurity.XMLSecurityDataFormat
+    camel-quarkus-pulsar:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-pulsar
+      schemes:
+      - id: pulsar
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.pulsar.PulsarComponent
+    camel-quarkus-braintree:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-braintree
+      schemes:
+      - id: braintree
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.braintree.BraintreeComponent
+    camel-quarkus-weka:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-weka
+      schemes:
+      - id: weka
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.weka.WekaComponent
+    camel-quarkus-guava-eventbus:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-guava-eventbus
+      schemes:
+      - id: guava-eventbus
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.guava.eventbus.GuavaEventBusComponent
+    camel-quarkus-rss:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-rss
+      schemes:
+      - id: rss
+        http: false
+        passive: false
+      dataformats:
+      - rss
+      javaTypes:
+      - org.apache.camel.component.rss.RssComponent
+      - org.apache.camel.dataformat.rss.RssDataFormat
+    camel-quarkus-reactive-streams:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-reactive-streams
+      schemes:
+      - id: reactive-streams
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.reactive.streams.ReactiveStreamsComponent
+    camel-quarkus-exec:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-exec
+      schemes:
+      - id: exec
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.exec.ExecComponent
+    camel-quarkus-jslt:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-jslt
+      schemes:
+      - id: jslt
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.jslt.JsltComponent
+    camel-quarkus-irc:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-irc
+      schemes:
+      - id: irc
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.irc.IrcComponent
+    camel-quarkus-rabbitmq:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-rabbitmq
+      schemes:
+      - id: rabbitmq
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.rabbitmq.RabbitMQComponent
+    camel-quarkus-ldif:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-ldif
+      schemes:
+      - id: ldif
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.ldif.LdifComponent
+    camel-quarkus-jcr:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-jcr
+      schemes:
+      - id: jcr
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.jcr.JcrComponent
+    camel-quarkus-corda:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-corda
+      schemes:
+      - id: corda
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.corda.CordaComponent
+    camel-quarkus-stub:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-stub
+      schemes:
+      - id: stub
         http: false
         passive: true
       javaTypes:
-      - org.apache.camel.component.validator.ValidatorComponent
-    camel-quarkus-cron:
+      - org.apache.camel.component.stub.StubComponent
+    camel-quarkus-caffeine:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-cron
+      artifactId: camel-quarkus-caffeine
       schemes:
-      - id: cron
+      - id: caffeine-cache
+        http: false
+        passive: false
+      - id: caffeine-loadcache
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.cron.CronComponent
+      - org.apache.camel.component.caffeine.cache.CaffeineCacheComponent
+      - org.apache.camel.component.caffeine.load.CaffeineLoadCacheComponent
+    camel-quarkus-bonita:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-bonita
+      schemes:
+      - id: bonita
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.bonita.BonitaComponent
+    camel-quarkus-aws2-sts:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-aws2-sts
+      schemes:
+      - id: aws2-sts
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.aws2.sts.STS2Component
+    camel-quarkus-vertx:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-vertx
+      schemes:
+      - id: vertx
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.vertx.VertxComponent
+    camel-quarkus-ganglia:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-ganglia
+      schemes:
+      - id: ganglia
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.ganglia.GangliaComponent
+    camel-quarkus-groovy:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-groovy
+      languages:
+      - groovy
+      javaTypes:
+      - org.apache.camel.language.groovy.GroovyLanguage
+    camel-quarkus-google-calendar:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-google-calendar
+      schemes:
+      - id: google-calendar
+        http: false
+        passive: false
+      - id: google-calendar-stream
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.google.calendar.GoogleCalendarComponent
+      - org.apache.camel.component.google.calendar.stream.GoogleCalendarStreamComponent
+    camel-quarkus-azure:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-azure
+      schemes:
+      - id: azure-blob
+        http: false
+        passive: false
+      - id: azure-queue
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.azure.blob.BlobServiceComponent
+      - org.apache.camel.component.azure.queue.QueueServiceComponent
+    camel-quarkus-scheduler:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-scheduler
+      schemes:
+      - id: scheduler
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.scheduler.SchedulerComponent
+    camel-quarkus-pg-replication-slot:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-pg-replication-slot
+      schemes:
+      - id: pg-replication-slot
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.pg.replication.slot.PgReplicationSlotComponent
+    camel-quarkus-paho:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-paho
+      schemes:
+      - id: paho
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.paho.PahoComponent
+    camel-quarkus-dozer:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-dozer
+      schemes:
+      - id: dozer
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.dozer.DozerComponent
+    camel-quarkus-jgroups:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-jgroups
+      schemes:
+      - id: jgroups
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.jgroups.JGroupsComponent
+    camel-quarkus-snakeyaml:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-snakeyaml
+      dataformats:
+      - yaml-snakeyaml
+      javaTypes:
+      - org.apache.camel.component.snakeyaml.SnakeYAMLDataFormat
+    camel-quarkus-vm:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-vm
+      schemes:
+      - id: vm
+        http: false
+        passive: true
+      javaTypes:
+      - org.apache.camel.component.vm.VmComponent
+    camel-quarkus-hdfs:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-hdfs
+      schemes:
+      - id: hdfs
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.hdfs.HdfsComponent
+    camel-quarkus-aws2-cw:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-aws2-cw
+      schemes:
+      - id: aws2-cw
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.aws2.cw.Cw2Component
+    camel-quarkus-atomix:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-atomix
+      schemes:
+      - id: atomix-map
+        http: false
+        passive: false
+      - id: atomix-messaging
+        http: false
+        passive: false
+      - id: atomix-multimap
+        http: false
+        passive: false
+      - id: atomix-queue
+        http: false
+        passive: false
+      - id: atomix-set
+        http: false
+        passive: false
+      - id: atomix-value
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.atomix.client.map.AtomixMapComponent
+      - org.apache.camel.component.atomix.client.messaging.AtomixMessagingComponent
+      - org.apache.camel.component.atomix.client.multimap.AtomixMultiMapComponent
+      - org.apache.camel.component.atomix.client.queue.AtomixQueueComponent
+      - org.apache.camel.component.atomix.client.set.AtomixSetComponent
+      - org.apache.camel.component.atomix.client.value.AtomixValueComponent
+    camel-quarkus-olingo4:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-olingo4
+      schemes:
+      - id: olingo4
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.olingo4.Olingo4Component
+    camel-quarkus-as2:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-as2
+      schemes:
+      - id: as2
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.as2.AS2Component
+    camel-quarkus-github:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-github
+      schemes:
+      - id: github
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.github.GitHubComponent
+    camel-quarkus-digitalocean:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-digitalocean
+      schemes:
+      - id: digitalocean
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.digitalocean.DigitalOceanComponent
+    camel-quarkus-ical:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-ical
+      dataformats:
+      - ical
+      javaTypes:
+      - org.apache.camel.component.ical.ICalDataFormat
+    camel-quarkus-optaplanner:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-optaplanner
+      schemes:
+      - id: optaplanner
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.optaplanner.OptaPlannerComponent
+    camel-quarkus-syslog:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-syslog
+      dataformats:
+      - syslog
+      javaTypes:
+      - org.apache.camel.component.syslog.SyslogDataFormat
+    camel-quarkus-quickfix:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-quickfix
+      schemes:
+      - id: quickfix
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.quickfixj.QuickfixjComponent
+    camel-quarkus-lucene:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-lucene
+      schemes:
+      - id: lucene
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.lucene.LuceneComponent
+    camel-quarkus-ahc-ws:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-ahc-ws
+      schemes:
+      - id: ahc-ws
+        http: true
+        passive: false
+      - id: ahc-wss
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.ahc.ws.WsComponent
+    camel-quarkus-nitrite:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-nitrite
+      schemes:
+      - id: nitrite
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.nitrite.NitriteComponent
+    camel-quarkus-websocket-jsr356:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-websocket-jsr356
+      schemes:
+      - id: websocket-jsr356
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.websocket.jsr356.JSR356WebSocketComponent
+    camel-quarkus-splunk:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-splunk
+      schemes:
+      - id: splunk
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.splunk.SplunkComponent
+    camel-quarkus-dropbox:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-dropbox
+      schemes:
+      - id: dropbox
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.dropbox.DropboxComponent
+    camel-quarkus-aws-kinesis:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-aws-kinesis
+      schemes:
+      - id: aws-kinesis
+        http: false
+        passive: false
+      - id: aws-kinesis-firehose
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.aws.kinesis.KinesisComponent
+      - org.apache.camel.component.aws.firehose.KinesisFirehoseComponent
+    camel-quarkus-aws2-kinesis:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-aws2-kinesis
+      schemes:
+      - id: aws2-kinesis
+        http: false
+        passive: false
+      - id: aws2-kinesis-firehose
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.aws2.kinesis.Kinesis2Component
+      - org.apache.camel.component.aws2.firehose.KinesisFirehose2Component
+    camel-quarkus-jgroups-raft:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-jgroups-raft
+      schemes:
+      - id: jgroups-raft
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.jgroups.raft.JGroupsRaftComponent
+    camel-quarkus-facebook:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-facebook
+      schemes:
+      - id: facebook
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.facebook.FacebookComponent
+    camel-quarkus-aws-kms:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-aws-kms
+      schemes:
+      - id: aws-kms
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.aws.kms.KMSComponent
+    camel-quarkus-solr:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-solr
+      schemes:
+      - id: solr
+        http: false
+        passive: false
+      - id: solrs
+        http: false
+        passive: false
+      - id: solrCloud
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.solr.SolrComponent
+    camel-quarkus-timer:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-timer
+      schemes:
+      - id: timer
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.timer.TimerComponent
+    camel-quarkus-aws-ec2:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-aws-ec2
+      schemes:
+      - id: aws-ec2
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.aws.ec2.EC2Component
+    camel-quarkus-zip-deflater:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-zip-deflater
+      dataformats:
+      - gzipdeflater
+      - zipdeflater
+      javaTypes:
+      - org.apache.camel.dataformat.deflater.GzipDeflaterDataFormat
+      - org.apache.camel.dataformat.deflater.ZipDeflaterDataFormat
+    camel-quarkus-jsonpath:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-jsonpath
+      languages:
+      - jsonpath
+      javaTypes:
+      - org.apache.camel.jsonpath.JsonPathLanguage
+    camel-quarkus-zookeeper-master:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-zookeeper-master
+      schemes:
+      - id: zookeeper-master
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.zookeepermaster.MasterComponent
+    camel-quarkus-pdf:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-pdf
+      schemes:
+      - id: pdf
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.pdf.PdfComponent
+    camel-quarkus-yammer:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-yammer
+      schemes:
+      - id: yammer
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.yammer.YammerComponent
+    camel-quarkus-jackson:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-jackson
+      dataformats:
+      - json-jackson
+      javaTypes:
+      - org.apache.camel.component.jackson.JacksonDataFormat
+    camel-quarkus-aws-sns:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-aws-sns
+      schemes:
+      - id: aws-sns
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.aws.sns.SnsComponent
+    camel-quarkus-disruptor:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-disruptor
+      schemes:
+      - id: disruptor
+        http: false
+        passive: false
+      - id: disruptor-vm
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.disruptor.DisruptorComponent
+      - org.apache.camel.component.disruptor.vm.DisruptorVmComponent
+    camel-quarkus-printer:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-printer
+      schemes:
+      - id: lpr
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.printer.PrinterComponent
+    camel-quarkus-aws2-athena:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-aws2-athena
+      schemes:
+      - id: aws2-athena
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.aws2.athena.Athena2Component
+    camel-quarkus-zipfile:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-zipfile
+      dataformats:
+      - zipfile
+      javaTypes:
+      - org.apache.camel.dataformat.zipfile.ZipFileDataFormat
+    camel-quarkus-grok:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-grok
+      dataformats:
+      - grok
+      javaTypes:
+      - org.apache.camel.component.grok.GrokDataFormat
+    camel-quarkus-servicenow:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-servicenow
+      schemes:
+      - id: servicenow
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.servicenow.ServiceNowComponent
+    camel-quarkus-mybatis:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-mybatis
+      schemes:
+      - id: mybatis
+        http: false
+        passive: false
+      - id: mybatis-bean
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.mybatis.MyBatisComponent
+      - org.apache.camel.component.mybatis.MyBatisBeanComponent
+    camel-quarkus-milo:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-milo
+      schemes:
+      - id: milo-client
+        http: false
+        passive: false
+      - id: milo-server
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.milo.client.MiloClientComponent
+      - org.apache.camel.component.milo.server.MiloServerComponent
+    camel-quarkus-grpc:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-grpc
+      schemes:
+      - id: grpc
+        http: true
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.grpc.GrpcComponent
+    camel-quarkus-iota:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-iota
+      schemes:
+      - id: iota
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.iota.IOTAComponent
+    camel-quarkus-mvel:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-mvel
+      schemes:
+      - id: mvel
+        http: false
+        passive: false
+      languages:
+      - mvel
+      javaTypes:
+      - org.apache.camel.component.mvel.MvelComponent
+      - org.apache.camel.language.mvel.MvelLanguage
+    camel-quarkus-sip:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-sip
+      schemes:
+      - id: sip
+        http: false
+        passive: false
+      - id: sips
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.sip.SipComponent
+    camel-quarkus-velocity:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-velocity
+      schemes:
+      - id: velocity
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.velocity.VelocityComponent
+    camel-quarkus-consul:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-consul
+      schemes:
+      - id: consul
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.consul.ConsulComponent
+    camel-quarkus-google-sheets:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-google-sheets
+      schemes:
+      - id: google-sheets
+        http: false
+        passive: false
+      - id: google-sheets-stream
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.google.sheets.GoogleSheetsComponent
+      - org.apache.camel.component.google.sheets.stream.GoogleSheetsStreamComponent
+    camel-quarkus-slack:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-slack
+      schemes:
+      - id: slack
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.slack.SlackComponent
+    camel-quarkus-sjms2:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-sjms2
+      schemes:
+      - id: sjms2
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.sjms2.Sjms2Component
+    camel-quarkus-aws-ecs:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-aws-ecs
+      schemes:
+      - id: aws-ecs
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.aws.ecs.ECSComponent
+    camel-quarkus-apns:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-apns
+      schemes:
+      - id: apns
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.apns.ApnsComponent
+    camel-quarkus-sjms:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-sjms
+      schemes:
+      - id: sjms
+        http: false
+        passive: false
+      - id: sjms-batch
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.sjms.SjmsComponent
+      - org.apache.camel.component.sjms.batch.SjmsBatchComponent
+    camel-quarkus-freemarker:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-freemarker
+      schemes:
+      - id: freemarker
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.freemarker.FreemarkerComponent
+    camel-quarkus-couchbase:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-couchbase
+      schemes:
+      - id: couchbase
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.couchbase.CouchbaseComponent
+    camel-quarkus-pubnub:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-pubnub
+      schemes:
+      - id: pubnub
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.pubnub.PubNubComponent
+    camel-quarkus-bean-validator:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-bean-validator
+      schemes:
+      - id: bean-validator
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.bean.validator.BeanValidatorComponent
+    camel-quarkus-ipfs:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-ipfs
+      schemes:
+      - id: ipfs
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.ipfs.IPFSComponent
+    camel-quarkus-fop:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-fop
+      schemes:
+      - id: fop
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.fop.FopComponent
+    camel-quarkus-debezium-sqlserver:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-debezium-sqlserver
+      schemes:
+      - id: debezium-sqlserver
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.debezium.DebeziumSqlserverComponent
+    camel-quarkus-seda:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-seda
+      schemes:
+      - id: seda
+        http: false
+        passive: true
+      javaTypes:
+      - org.apache.camel.component.seda.SedaComponent
+    camel-quarkus-aws2-eks:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-aws2-eks
+      schemes:
+      - id: aws2-eks
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.aws2.eks.EKS2Component
+    camel-quarkus-zookeeper:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-zookeeper
+      schemes:
+      - id: zookeeper
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.zookeeper.ZooKeeperComponent
+    camel-quarkus-twitter:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-twitter
+      schemes:
+      - id: twitter-directmessage
+        http: false
+        passive: false
+      - id: twitter-search
+        http: false
+        passive: false
+      - id: twitter-timeline
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.twitter.directmessage.TwitterDirectMessageComponent
+      - org.apache.camel.component.twitter.search.TwitterSearchComponent
+      - org.apache.camel.component.twitter.timeline.TwitterTimelineComponent
+    camel-quarkus-schematron:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-schematron
+      schemes:
+      - id: schematron
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.schematron.SchematronComponent
+    camel-quarkus-workday:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-workday
+      schemes:
+      - id: workday
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.workday.WorkdayComponent
+    camel-quarkus-microprofile-metrics:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-microprofile-metrics
+      schemes:
+      - id: microprofile-metrics
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.microprofile.metrics.MicroProfileMetricsComponent
+    camel-quarkus-infinispan:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-infinispan
+      schemes:
+      - id: infinispan
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.infinispan.InfinispanComponent
+    camel-quarkus-avro-rpc:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-avro-rpc
+      schemes:
+      - id: avro
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.avro.AvroComponent
+    camel-quarkus-telegram:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-telegram
+      schemes:
+      - id: telegram
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.telegram.TelegramComponent
+    camel-quarkus-ref:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-ref
+      schemes:
+      - id: ref
+        http: false
+        passive: true
+      javaTypes:
+      - org.apache.camel.component.ref.RefComponent
+    camel-quarkus-stax:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-stax
+      schemes:
+      - id: stax
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.stax.StAXComponent
+    camel-quarkus-hazelcast:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-hazelcast
+      schemes:
+      - id: hazelcast-atomicvalue
+        http: false
+        passive: false
+      - id: hazelcast-instance
+        http: false
+        passive: false
+      - id: hazelcast-list
+        http: false
+        passive: false
+      - id: hazelcast-map
+        http: false
+        passive: false
+      - id: hazelcast-multimap
+        http: false
+        passive: false
+      - id: hazelcast-queue
+        http: false
+        passive: false
+      - id: hazelcast-replicatedmap
+        http: false
+        passive: false
+      - id: hazelcast-ringbuffer
+        http: false
+        passive: false
+      - id: hazelcast-seda
+        http: false
+        passive: false
+      - id: hazelcast-set
+        http: false
+        passive: false
+      - id: hazelcast-topic
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.hazelcast.atomicnumber.HazelcastAtomicnumberComponent
+      - org.apache.camel.component.hazelcast.instance.HazelcastInstanceComponent
+      - org.apache.camel.component.hazelcast.list.HazelcastListComponent
+      - org.apache.camel.component.hazelcast.map.HazelcastMapComponent
+      - org.apache.camel.component.hazelcast.multimap.HazelcastMultimapComponent
+      - org.apache.camel.component.hazelcast.queue.HazelcastQueueComponent
+      - org.apache.camel.component.hazelcast.replicatedmap.HazelcastReplicatedmapComponent
+      - org.apache.camel.component.hazelcast.ringbuffer.HazelcastRingbufferComponent
+      - org.apache.camel.component.hazelcast.seda.HazelcastSedaComponent
+      - org.apache.camel.component.hazelcast.set.HazelcastSetComponent
+      - org.apache.camel.component.hazelcast.topic.HazelcastTopicComponent
+    camel-quarkus-lzf:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-lzf
+      dataformats:
+      - lzf
+      javaTypes:
+      - org.apache.camel.dataformat.lzf.LZFDataFormat
+    camel-quarkus-djl:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-djl
+      schemes:
+      - id: djl
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.djl.DJLComponent
+    camel-quarkus-couchdb:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-couchdb
+      schemes:
+      - id: couchdb
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.couchdb.CouchDbComponent
+    camel-quarkus-jaxb:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-jaxb
+      dataformats:
+      - jaxb
+      javaTypes:
+      - org.apache.camel.converter.jaxb.JaxbDataFormat
+    camel-quarkus-iec60870:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-iec60870
+      schemes:
+      - id: iec60870-client
+        http: false
+        passive: false
+      - id: iec60870-server
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.iec60870.client.ClientComponent
+      - org.apache.camel.component.iec60870.server.ServerComponent
+    camel-quarkus-aws-sqs:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-aws-sqs
+      schemes:
+      - id: aws-sqs
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.aws.sqs.SqsComponent
+    camel-quarkus-barcode:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-barcode
+      dataformats:
+      - barcode
+      javaTypes:
+      - org.apache.camel.dataformat.barcode.BarcodeDataFormat
+    camel-quarkus-kudu:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-kudu
+      schemes:
+      - id: kudu
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.kudu.KuduComponent
+    camel-quarkus-rest-openapi:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-rest-openapi
+      schemes:
+      - id: rest-openapi
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.rest.openapi.RestOpenApiComponent
+    camel-quarkus-asterisk:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-asterisk
+      schemes:
+      - id: asterisk
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.asterisk.AsteriskComponent
+    camel-quarkus-file:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-file
+      schemes:
+      - id: file
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.file.FileComponent
+    camel-quarkus-master:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-master
+      schemes:
+      - id: master
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.master.MasterComponent
+    camel-quarkus-browse:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-browse
+      schemes:
+      - id: browse
+        http: false
+        passive: true
+      javaTypes:
+      - org.apache.camel.component.browse.BrowseComponent
+    camel-quarkus-xpath:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-xpath
+      languages:
+      - xpath
+      javaTypes:
+      - org.apache.camel.language.xpath.XPathLanguage
+    camel-quarkus-robotframework:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-robotframework
+      schemes:
+      - id: robotframework
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.robotframework.RobotFrameworkComponent
+    camel-quarkus-nats:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-nats
+      schemes:
+      - id: nats
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.nats.NatsComponent
+    camel-quarkus-stringtemplate:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-stringtemplate
+      schemes:
+      - id: string-template
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.stringtemplate.StringTemplateComponent
+    camel-quarkus-geocoder:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-geocoder
+      schemes:
+      - id: geocoder
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.geocoder.GeoCoderComponent
+    camel-quarkus-mock:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-mock
+      schemes:
+      - id: mock
+        http: false
+        passive: true
+      javaTypes:
+      - org.apache.camel.component.mock.MockComponent
+    camel-quarkus-soap:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-soap
+      dataformats:
+      - soapjaxb
+      javaTypes:
+      - org.apache.camel.dataformat.soap.SoapJaxbDataFormat
+    camel-quarkus-wordpress:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-wordpress
+      schemes:
+      - id: wordpress
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.wordpress.WordpressComponent
+    camel-quarkus-jsonapi:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-jsonapi
+      dataformats:
+      - jsonApi
+      javaTypes:
+      - org.apache.camel.component.jsonapi.JsonApiDataFormat
+    camel-quarkus-jolt:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-jolt
+      schemes:
+      - id: jolt
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.jolt.JoltComponent
+    camel-quarkus-validator:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-validator
+      schemes:
+      - id: validator
+        http: false
+        passive: true
+      javaTypes:
+      - org.apache.camel.component.validator.ValidatorComponent
     camel-quarkus-sap-netweaver:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-sap-netweaver
@@ -286,15 +1589,6 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.sap.netweaver.NetWeaverComponent
-    camel-quarkus-aws2-iam:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-aws2-iam
-      schemes:
-      - id: aws2-iam
-        http: false
-        passive: false
-      javaTypes:
-      - org.apache.camel.component.aws2.iam.IAM2Component
     camel-quarkus-aws2-ec2:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-aws2-ec2
@@ -329,15 +1623,6 @@ spec:
       - json-johnzon
       javaTypes:
       - org.apache.camel.component.johnzon.JohnzonDataFormat
-    camel-quarkus-netty:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-netty
-      schemes:
-      - id: netty
-        http: false
-        passive: false
-      javaTypes:
-      - org.apache.camel.component.netty.NettyComponent
     camel-quarkus-google-bigquery:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-google-bigquery
@@ -351,33 +1636,27 @@ spec:
       javaTypes:
       - org.apache.camel.component.google.bigquery.GoogleBigQueryComponent
       - org.apache.camel.component.google.bigquery.sql.GoogleBigQuerySQLComponent
-    camel-quarkus-salesforce:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-salesforce
-      schemes:
-      - id: salesforce
-        http: false
-        passive: false
-      javaTypes:
-      - org.apache.camel.component.salesforce.SalesforceComponent
-    camel-quarkus-braintree:
+    camel-quarkus-flatpack:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-braintree
+      artifactId: camel-quarkus-flatpack
       schemes:
-      - id: braintree
+      - id: flatpack
         http: false
         passive: false
+      dataformats:
+      - flatpack
       javaTypes:
-      - org.apache.camel.component.braintree.BraintreeComponent
-    camel-quarkus-reactive-streams:
+      - org.apache.camel.component.flatpack.FlatpackComponent
+      - org.apache.camel.dataformat.flatpack.FlatpackDataFormat
+    camel-quarkus-salesforce:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-reactive-streams
+      artifactId: camel-quarkus-salesforce
       schemes:
-      - id: reactive-streams
+      - id: salesforce
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.reactive.streams.ReactiveStreamsComponent
+      - org.apache.camel.component.salesforce.SalesforceComponent
     camel-quarkus-core:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-core
@@ -397,15 +1676,6 @@ spec:
       - org.apache.camel.language.ref.RefLanguage
       - org.apache.camel.language.simple.SimpleLanguage
       - org.apache.camel.language.tokenizer.TokenizeLanguage
-    camel-quarkus-exec:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-exec
-      schemes:
-      - id: exec
-        http: false
-        passive: false
-      javaTypes:
-      - org.apache.camel.component.exec.ExecComponent
     camel-quarkus-ognl:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-ognl
@@ -422,15 +1692,24 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.netty.http.NettyHttpComponent
-    camel-quarkus-rabbitmq:
+    camel-quarkus-coap:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-rabbitmq
+      artifactId: camel-quarkus-coap
       schemes:
-      - id: rabbitmq
+      - id: coap
+        http: false
+        passive: false
+      - id: coaps
+        http: false
+        passive: false
+      - id: coap+tcp
+        http: false
+        passive: false
+      - id: coaps+tcp
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.rabbitmq.RabbitMQComponent
+      - org.apache.camel.coap.CoAPComponent
     camel-quarkus-stream:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-stream
@@ -456,15 +1735,6 @@ spec:
       - tarfile
       javaTypes:
       - org.apache.camel.dataformat.tarfile.TarFileDataFormat
-    camel-quarkus-vertx:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-vertx
-      schemes:
-      - id: vertx
-        http: false
-        passive: false
-      javaTypes:
-      - org.apache.camel.component.vertx.VertxComponent
     camel-quarkus-jira:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-jira
@@ -500,39 +1770,42 @@ spec:
       - org.apache.camel.component.file.remote.FtpComponent
       - org.apache.camel.component.file.remote.FtpsComponent
       - org.apache.camel.component.file.remote.SftpComponent
-    camel-quarkus-groovy:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-groovy
-      languages:
-      - groovy
-      javaTypes:
-      - org.apache.camel.language.groovy.GroovyLanguage
-    camel-quarkus-google-calendar:
+    camel-quarkus-saga:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-google-calendar
+      artifactId: camel-quarkus-saga
       schemes:
-      - id: google-calendar
+      - id: saga
         http: false
         passive: false
-      - id: google-calendar-stream
+      javaTypes:
+      - org.apache.camel.component.saga.SagaComponent
+    camel-quarkus-hipchat:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-hipchat
+      schemes:
+      - id: hipchat
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.google.calendar.GoogleCalendarComponent
-      - org.apache.camel.component.google.calendar.stream.GoogleCalendarStreamComponent
-    camel-quarkus-azure:
+      - org.apache.camel.component.hipchat.HipchatComponent
+    camel-quarkus-ldap:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-azure
+      artifactId: camel-quarkus-ldap
       schemes:
-      - id: azure-blob
+      - id: ldap
         http: false
         passive: false
-      - id: azure-queue
+      javaTypes:
+      - org.apache.camel.component.ldap.LdapComponent
+    camel-quarkus-arangodb:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-arangodb
+      schemes:
+      - id: arangodb
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.azure.blob.BlobServiceComponent
-      - org.apache.camel.component.azure.queue.QueueServiceComponent
+      - org.apache.camel.component.arangodb.ArangoDbComponent
     camel-quarkus-aws-lambda:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-aws-lambda
@@ -542,15 +1815,6 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.aws.lambda.LambdaComponent
-    camel-quarkus-scheduler:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-scheduler
-      schemes:
-      - id: scheduler
-        http: false
-        passive: false
-      javaTypes:
-      - org.apache.camel.component.scheduler.SchedulerComponent
     camel-quarkus-platform-http:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-platform-http
@@ -569,24 +1833,6 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.xslt.XsltComponent
-    camel-quarkus-paho:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-paho
-      schemes:
-      - id: paho
-        http: false
-        passive: false
-      javaTypes:
-      - org.apache.camel.component.paho.PahoComponent
-    camel-quarkus-dozer:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-dozer
-      schemes:
-      - id: dozer
-        http: false
-        passive: false
-      javaTypes:
-      - org.apache.camel.component.dozer.DozerComponent
     camel-quarkus-bean:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-bean
@@ -646,31 +1892,6 @@ spec:
       javaTypes:
       - org.apache.camel.component.mail.MailComponent
       - org.apache.camel.dataformat.mime.multipart.MimeMultipartDataFormat
-    camel-quarkus-snakeyaml:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-snakeyaml
-      dataformats:
-      - yaml-snakeyaml
-      javaTypes:
-      - org.apache.camel.component.snakeyaml.SnakeYAMLDataFormat
-    camel-quarkus-vm:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-vm
-      schemes:
-      - id: vm
-        http: false
-        passive: true
-      javaTypes:
-      - org.apache.camel.component.vm.VmComponent
-    camel-quarkus-aws2-cw:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-aws2-cw
-      schemes:
-      - id: aws2-cw
-        http: false
-        passive: false
-      javaTypes:
-      - org.apache.camel.component.aws2.cw.Cw2Component
     camel-quarkus-gson:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-gson
@@ -687,24 +1908,33 @@ spec:
         passive: true
       javaTypes:
       - org.apache.camel.component.log.LogComponent
-    camel-quarkus-olingo4:
+    camel-quarkus-xmpp:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-olingo4
+      artifactId: camel-quarkus-xmpp
       schemes:
-      - id: olingo4
+      - id: xmpp
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.olingo4.Olingo4Component
-    camel-quarkus-github:
+      - org.apache.camel.component.xmpp.XmppComponent
+    camel-quarkus-jt400:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-github
+      artifactId: camel-quarkus-jt400
       schemes:
-      - id: github
+      - id: jt400
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.github.GitHubComponent
+      - org.apache.camel.component.jt400.Jt400Component
+    camel-quarkus-nsq:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-nsq
+      schemes:
+      - id: nsq
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.nsq.NsqComponent
     camel-quarkus-google-drive:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-google-drive
@@ -723,13 +1953,15 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.aws.sdb.SdbComponent
-    camel-quarkus-ical:
+    camel-quarkus-vertx-http:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-ical
-      dataformats:
-      - ical
+      artifactId: camel-quarkus-vertx-http
+      schemes:
+      - id: vertx-http
+        http: false
+        passive: false
       javaTypes:
-      - org.apache.camel.component.ical.ICalDataFormat
+      - org.apache.camel.component.vertx.http.VertxHttpComponent
     camel-quarkus-mongodb:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-mongodb
@@ -757,6 +1989,27 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.file.watch.FileWatchComponent
+    camel-quarkus-smpp:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-smpp
+      schemes:
+      - id: smpp
+        http: false
+        passive: false
+      - id: smpps
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.smpp.SmppComponent
+    camel-quarkus-pgevent:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-pgevent
+      schemes:
+      - id: pgevent
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.pgevent.PgEventComponent
     camel-quarkus-rest:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-rest
@@ -770,18 +2023,15 @@ spec:
       javaTypes:
       - org.apache.camel.component.rest.RestComponent
       - org.apache.camel.component.rest.RestApiComponent
-    camel-quarkus-ahc-ws:
+    camel-quarkus-cm-sms:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-ahc-ws
+      artifactId: camel-quarkus-cm-sms
       schemes:
-      - id: ahc-ws
-        http: true
-        passive: false
-      - id: ahc-wss
+      - id: cm-sms
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.ahc.ws.WsComponent
+      - org.apache.camel.component.cm.CMComponent
     camel-quarkus-ahc:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-ahc
@@ -800,46 +2050,66 @@ spec:
         passive: true
       javaTypes:
       - org.apache.camel.component.controlbus.ControlBusComponent
-    camel-quarkus-direct:
+    camel-quarkus-azure-storage-blob:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-direct
+      artifactId: camel-quarkus-azure-storage-blob
       schemes:
-      - id: direct
+      - id: azure-storage-blob
         http: false
-        passive: true
+        passive: false
       javaTypes:
-      - org.apache.camel.component.direct.DirectComponent
-    camel-quarkus-nitrite:
+      - org.apache.camel.component.azure.storage.blob.BlobComponent
+    camel-quarkus-ignite:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-nitrite
+      artifactId: camel-quarkus-ignite
       schemes:
-      - id: nitrite
+      - id: ignite-cache
+        http: false
+        passive: false
+      - id: ignite-compute
+        http: false
+        passive: false
+      - id: ignite-events
+        http: false
+        passive: false
+      - id: ignite-idgen
+        http: false
+        passive: false
+      - id: ignite-messaging
+        http: false
+        passive: false
+      - id: ignite-queue
+        http: false
+        passive: false
+      - id: ignite-set
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.nitrite.NitriteComponent
-    camel-quarkus-websocket-jsr356:
+      - org.apache.camel.component.ignite.cache.IgniteCacheComponent
+      - org.apache.camel.component.ignite.compute.IgniteComputeComponent
+      - org.apache.camel.component.ignite.events.IgniteEventsComponent
+      - org.apache.camel.component.ignite.idgen.IgniteIdGenComponent
+      - org.apache.camel.component.ignite.messaging.IgniteMessagingComponent
+      - org.apache.camel.component.ignite.queue.IgniteQueueComponent
+      - org.apache.camel.component.ignite.set.IgniteSetComponent
+    camel-quarkus-direct:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-websocket-jsr356
+      artifactId: camel-quarkus-direct
       schemes:
-      - id: websocket-jsr356
+      - id: direct
         http: false
-        passive: false
+        passive: true
       javaTypes:
-      - org.apache.camel.websocket.jsr356.JSR356WebSocketComponent
-    camel-quarkus-aws-kinesis:
+      - org.apache.camel.component.direct.DirectComponent
+    camel-quarkus-splunk-hec:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-aws-kinesis
+      artifactId: camel-quarkus-splunk-hec
       schemes:
-      - id: aws-kinesis
-        http: false
-        passive: false
-      - id: aws-kinesis-firehose
+      - id: splunk-hec
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.aws.kinesis.KinesisComponent
-      - org.apache.camel.component.aws.firehose.KinesisFirehoseComponent
+      - org.apache.camel.component.splunkhec.SplunkHECComponent
     camel-quarkus-elasticsearch-rest:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-elasticsearch-rest
@@ -849,49 +2119,44 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.elasticsearch.ElasticsearchComponent
-    camel-quarkus-aws-kms:
+    camel-quarkus-jooq:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-aws-kms
+      artifactId: camel-quarkus-jooq
       schemes:
-      - id: aws-kms
+      - id: jooq
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.aws.kms.KMSComponent
-    camel-quarkus-timer:
+      - org.apache.camel.component.jooq.JooqComponent
+    camel-quarkus-stomp:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-timer
+      artifactId: camel-quarkus-stomp
       schemes:
-      - id: timer
+      - id: stomp
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.timer.TimerComponent
-    camel-quarkus-aws-ec2:
+      - org.apache.camel.component.stomp.StompComponent
+    camel-quarkus-dns:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-aws-ec2
+      artifactId: camel-quarkus-dns
       schemes:
-      - id: aws-ec2
+      - id: dns
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.aws.ec2.EC2Component
-    camel-quarkus-zip-deflater:
+      - org.apache.camel.component.dns.DnsComponent
+    camel-quarkus-univocity-parsers:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-zip-deflater
+      artifactId: camel-quarkus-univocity-parsers
       dataformats:
-      - gzipdeflater
-      - zipdeflater
-      javaTypes:
-      - org.apache.camel.dataformat.deflater.GzipDeflaterDataFormat
-      - org.apache.camel.dataformat.deflater.ZipDeflaterDataFormat
-    camel-quarkus-jsonpath:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-jsonpath
-      languages:
-      - jsonpath
+      - univocity-csv
+      - univocity-fixed
+      - univocity-tsv
       javaTypes:
-      - org.apache.camel.jsonpath.JsonPathLanguage
+      - org.apache.camel.dataformat.univocity.UniVocityCsvDataFormat
+      - org.apache.camel.dataformat.univocity.UniVocityFixedWidthDataFormat
+      - org.apache.camel.dataformat.univocity.UniVocityTsvDataFormat
     camel-quarkus-google-mail:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-google-mail
@@ -932,15 +2197,22 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.jdbc.JdbcComponent
-    camel-quarkus-pdf:
+    camel-quarkus-fastjson:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-pdf
+      artifactId: camel-quarkus-fastjson
+      dataformats:
+      - json-fastjson
+      javaTypes:
+      - org.apache.camel.component.fastjson.FastjsonDataFormat
+    camel-quarkus-xslt-saxon:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-xslt-saxon
       schemes:
-      - id: pdf
+      - id: xslt-saxon
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.pdf.PdfComponent
+      - org.apache.camel.component.xslt.saxon.XsltSaxonComponent
     camel-quarkus-bindy:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-bindy
@@ -952,6 +2224,20 @@ spec:
       - org.apache.camel.dataformat.bindy.csv.BindyCsvDataFormat
       - org.apache.camel.dataformat.bindy.fixed.BindyFixedLengthDataFormat
       - org.apache.camel.dataformat.bindy.kvp.BindyKeyValuePairDataFormat
+    camel-quarkus-crypto:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-crypto
+      schemes:
+      - id: crypto
+        http: false
+        passive: false
+      dataformats:
+      - crypto
+      - pgp
+      javaTypes:
+      - org.apache.camel.component.crypto.DigitalSignatureComponent
+      - org.apache.camel.converter.crypto.CryptoDataFormat
+      - org.apache.camel.converter.crypto.PGPDataFormat
     camel-quarkus-tagsoup:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-tagsoup
@@ -979,13 +2265,6 @@ spec:
       javaTypes:
       - org.apache.camel.component.aws2.ddb.Ddb2Component
       - org.apache.camel.component.aws2.ddbstream.Ddb2StreamComponent
-    camel-quarkus-jackson:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-jackson
-      dataformats:
-      - json-jackson
-      javaTypes:
-      - org.apache.camel.component.jackson.JacksonDataFormat
     camel-quarkus-csv:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-csv
@@ -993,15 +2272,6 @@ spec:
       - csv
       javaTypes:
       - org.apache.camel.dataformat.csv.CsvDataFormat
-    camel-quarkus-aws-sns:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-aws-sns
-      schemes:
-      - id: aws-sns
-        http: false
-        passive: false
-      javaTypes:
-      - org.apache.camel.component.aws.sns.SnsComponent
     camel-quarkus-debezium-mongodb:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-debezium-mongodb
@@ -1011,24 +2281,24 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.debezium.DebeziumMongodbComponent
-    camel-quarkus-aws2-sqs:
+    camel-quarkus-xj:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-aws2-sqs
+      artifactId: camel-quarkus-xj
       schemes:
-      - id: aws2-sqs
+      - id: xj
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.aws2.sqs.Sqs2Component
-    camel-quarkus-aws2-athena:
+      - org.apache.camel.component.xj.XJComponent
+    camel-quarkus-aws2-sqs:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-aws2-athena
+      artifactId: camel-quarkus-aws2-sqs
       schemes:
-      - id: aws2-athena
+      - id: aws2-sqs
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.aws2.athena.Athena2Component
+      - org.apache.camel.component.aws2.sqs.Sqs2Component
     camel-quarkus-cassandraql:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-cassandraql
@@ -1038,20 +2308,15 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.cassandra.CassandraComponent
-    camel-quarkus-zipfile:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-zipfile
-      dataformats:
-      - zipfile
-      javaTypes:
-      - org.apache.camel.dataformat.zipfile.ZipFileDataFormat
-    camel-quarkus-grok:
+    camel-quarkus-ssh:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-grok
-      dataformats:
-      - grok
+      artifactId: camel-quarkus-ssh
+      schemes:
+      - id: ssh
+        http: false
+        passive: false
       javaTypes:
-      - org.apache.camel.component.grok.GrokDataFormat
+      - org.apache.camel.component.ssh.SshComponent
     camel-quarkus-servlet:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-servlet
@@ -1061,15 +2326,15 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.servlet.ServletComponent
-    camel-quarkus-servicenow:
+    camel-quarkus-cmis:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-servicenow
+      artifactId: camel-quarkus-cmis
       schemes:
-      - id: servicenow
+      - id: cmis
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.servicenow.ServiceNowComponent
+      - org.apache.camel.component.cmis.CMISComponent
     camel-quarkus-json-validator:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-json-validator
@@ -1079,15 +2344,15 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.jsonvalidator.JsonValidatorComponent
-    camel-quarkus-grpc:
+    camel-quarkus-git:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-grpc
+      artifactId: camel-quarkus-git
       schemes:
-      - id: grpc
-        http: true
+      - id: git
+        http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.grpc.GrpcComponent
+      - org.apache.camel.component.git.GitComponent
     camel-quarkus-aws-eks:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-aws-eks
@@ -1106,6 +2371,15 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.aws.swf.SWFComponent
+    camel-quarkus-web3j:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-web3j
+      schemes:
+      - id: web3j
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.web3j.Web3jComponent
     camel-quarkus-openstack:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-openstack
@@ -1144,55 +2418,54 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.jpa.JpaComponent
-    camel-quarkus-consul:
+    camel-quarkus-cometd:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-consul
+      artifactId: camel-quarkus-cometd
       schemes:
-      - id: consul
+      - id: cometd
+        http: false
+        passive: false
+      - id: cometds
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.consul.ConsulComponent
-    camel-quarkus-google-sheets:
+      - org.apache.camel.component.cometd.CometdComponent
+    camel-quarkus-atmos:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-google-sheets
+      artifactId: camel-quarkus-atmos
       schemes:
-      - id: google-sheets
-        http: false
-        passive: false
-      - id: google-sheets-stream
+      - id: atmos
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.google.sheets.GoogleSheetsComponent
-      - org.apache.camel.component.google.sheets.stream.GoogleSheetsStreamComponent
-    camel-quarkus-slack:
+      - org.apache.camel.component.atmos.AtmosComponent
+    camel-quarkus-nagios:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-slack
+      artifactId: camel-quarkus-nagios
       schemes:
-      - id: slack
+      - id: nagios
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.slack.SlackComponent
-    camel-quarkus-sjms2:
+      - org.apache.camel.component.nagios.NagiosComponent
+    camel-quarkus-language:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-sjms2
+      artifactId: camel-quarkus-language
       schemes:
-      - id: sjms2
+      - id: language
         http: false
-        passive: false
+        passive: true
       javaTypes:
-      - org.apache.camel.component.sjms2.Sjms2Component
-    camel-quarkus-aws-ecs:
+      - org.apache.camel.component.language.LanguageComponent
+    camel-quarkus-snmp:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-aws-ecs
+      artifactId: camel-quarkus-snmp
       schemes:
-      - id: aws-ecs
+      - id: snmp
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.aws.ecs.ECSComponent
+      - org.apache.camel.component.snmp.SnmpComponent
     camel-quarkus-google-pubsub:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-google-pubsub
@@ -1202,19 +2475,31 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.google.pubsub.GooglePubsubComponent
-    camel-quarkus-sjms:
+    camel-quarkus-elsql:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-sjms
+      artifactId: camel-quarkus-elsql
       schemes:
-      - id: sjms
+      - id: elsql
         http: false
         passive: false
-      - id: sjms-batch
+      javaTypes:
+      - org.apache.camel.component.elsql.ElsqlComponent
+    camel-quarkus-jing:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-jing
+      schemes:
+      - id: jing
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.sjms.SjmsComponent
-      - org.apache.camel.component.sjms.batch.SjmsBatchComponent
+      - org.apache.camel.component.validator.jing.JingComponent
+    camel-quarkus-asn1:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-asn1
+      dataformats:
+      - asn1
+      javaTypes:
+      - org.apache.camel.dataformat.asn1.ASN1DataFormat
     camel-quarkus-avro:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-avro
@@ -1222,24 +2507,16 @@ spec:
       - avro
       javaTypes:
       - org.apache.camel.dataformat.avro.AvroDataFormat
-    camel-quarkus-couchbase:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-couchbase
-      schemes:
-      - id: couchbase
-        http: false
-        passive: false
-      javaTypes:
-      - org.apache.camel.component.couchbase.CouchbaseComponent
-    camel-quarkus-pubnub:
+    camel-quarkus-hl7:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-pubnub
-      schemes:
-      - id: pubnub
-        http: false
-        passive: false
+      artifactId: camel-quarkus-hl7
+      languages:
+      - hl7terser
+      dataformats:
+      - hl7
       javaTypes:
-      - org.apache.camel.component.pubnub.PubNubComponent
+      - org.apache.camel.component.hl7.Hl7TerserLanguage
+      - org.apache.camel.component.hl7.HL7DataFormat
     camel-quarkus-mustache:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-mustache
@@ -1249,15 +2526,15 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.mustache.MustacheComponent
-    camel-quarkus-bean-validator:
+    camel-quarkus-jbpm:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-bean-validator
+      artifactId: camel-quarkus-jbpm
       schemes:
-      - id: bean-validator
+      - id: jbpm
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.bean.validator.BeanValidatorComponent
+      - org.apache.camel.component.jbpm.JBPMComponent
     camel-quarkus-kafka:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-kafka
@@ -1267,24 +2544,6 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.kafka.KafkaComponent
-    camel-quarkus-debezium-sqlserver:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-debezium-sqlserver
-      schemes:
-      - id: debezium-sqlserver
-        http: false
-        passive: false
-      javaTypes:
-      - org.apache.camel.component.debezium.DebeziumSqlserverComponent
-    camel-quarkus-seda:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-seda
-      schemes:
-      - id: seda
-        http: false
-        passive: true
-      javaTypes:
-      - org.apache.camel.component.seda.SedaComponent
     camel-quarkus-graphql:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-graphql
@@ -1294,32 +2553,15 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.graphql.GraphqlComponent
-    camel-quarkus-aws2-eks:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-aws2-eks
-      schemes:
-      - id: aws2-eks
-        http: false
-        passive: false
-      javaTypes:
-      - org.apache.camel.component.aws2.eks.EKS2Component
-    camel-quarkus-twitter:
+    camel-quarkus-flink:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-twitter
+      artifactId: camel-quarkus-flink
       schemes:
-      - id: twitter-directmessage
-        http: false
-        passive: false
-      - id: twitter-search
-        http: false
-        passive: false
-      - id: twitter-timeline
+      - id: flink
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.twitter.directmessage.TwitterDirectMessageComponent
-      - org.apache.camel.component.twitter.search.TwitterSearchComponent
-      - org.apache.camel.component.twitter.timeline.TwitterTimelineComponent
+      - org.apache.camel.component.flink.FlinkComponent
     camel-quarkus-sql:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-sql
@@ -1333,6 +2575,15 @@ spec:
       javaTypes:
       - org.apache.camel.component.sql.SqlComponent
       - org.apache.camel.component.sql.stored.SqlStoredComponent
+    camel-quarkus-beanstalk:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-beanstalk
+      schemes:
+      - id: beanstalk
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.beanstalk.BeanstalkComponent
     camel-quarkus-aws2-ecs:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-aws2-ecs
@@ -1342,6 +2593,15 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.aws2.ecs.ECS2Component
+    camel-quarkus-weather:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-weather
+      schemes:
+      - id: weather
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.weather.WeatherComponent
     camel-quarkus-box:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-box
@@ -1367,60 +2627,68 @@ spec:
       - xtokenize
       javaTypes:
       - org.apache.camel.language.xtokenizer.XMLTokenizeLanguage
-    camel-quarkus-microprofile-metrics:
+    camel-quarkus-aws2-lambda:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-microprofile-metrics
+      artifactId: camel-quarkus-aws2-lambda
       schemes:
-      - id: microprofile-metrics
+      - id: aws2-lambda
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.microprofile.metrics.MicroProfileMetricsComponent
-    camel-quarkus-infinispan:
+      - org.apache.camel.component.aws2.lambda.Lambda2Component
+    camel-quarkus-soroush:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-infinispan
+      artifactId: camel-quarkus-soroush
       schemes:
-      - id: infinispan
+      - id: soroush
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.infinispan.InfinispanComponent
-    camel-quarkus-avro-rpc:
+      - org.apache.camel.component.soroushbot.component.SoroushBotComponent
+    camel-quarkus-msv:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-avro-rpc
+      artifactId: camel-quarkus-msv
       schemes:
-      - id: avro
+      - id: msv
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.avro.AvroComponent
-    camel-quarkus-telegram:
+      - org.apache.camel.component.validator.msv.MsvComponent
+    camel-quarkus-jms:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-telegram
+      artifactId: camel-quarkus-jms
       schemes:
-      - id: telegram
+      - id: jms
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.telegram.TelegramComponent
-    camel-quarkus-ref:
+      - org.apache.camel.component.jms.JmsComponent
+    camel-quarkus-atom:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-ref
+      artifactId: camel-quarkus-atom
       schemes:
-      - id: ref
+      - id: atom
         http: false
-        passive: true
+        passive: false
       javaTypes:
-      - org.apache.camel.component.ref.RefComponent
-    camel-quarkus-jms:
+      - org.apache.camel.component.atom.AtomComponent
+    camel-quarkus-etcd:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-jms
+      artifactId: camel-quarkus-etcd
       schemes:
-      - id: jms
+      - id: etcd-keys
+        http: false
+        passive: false
+      - id: etcd-stats
+        http: false
+        passive: false
+      - id: etcd-watch
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.jms.JmsComponent
+      - org.apache.camel.component.etcd.EtcdKeysComponent
+      - org.apache.camel.component.etcd.EtcdStatsComponent
+      - org.apache.camel.component.etcd.EtcdWatchComponent
     camel-quarkus-aws2-sns:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-aws2-sns
@@ -1439,6 +2707,15 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.aws2.msk.MSK2Component
+    camel-quarkus-lumberjack:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-lumberjack
+      schemes:
+      - id: lumberjack
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.lumberjack.LumberjackComponent
     camel-quarkus-base64:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-base64
@@ -1446,13 +2723,15 @@ spec:
       - base64
       javaTypes:
       - org.apache.camel.dataformat.base64.Base64DataFormat
-    camel-quarkus-lzf:
+    camel-quarkus-ehcache:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-lzf
-      dataformats:
-      - lzf
+      artifactId: camel-quarkus-ehcache
+      schemes:
+      - id: ehcache
+        http: false
+        passive: false
       javaTypes:
-      - org.apache.camel.dataformat.lzf.LZFDataFormat
+      - org.apache.camel.component.ehcache.EhcacheComponent
     camel-quarkus-fhir:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-fhir
@@ -1476,6 +2755,15 @@ spec:
         passive: true
       javaTypes:
       - org.apache.camel.component.dataformat.DataFormatComponent
+    camel-quarkus-jsch:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-jsch
+      schemes:
+      - id: scp
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.scp.ScpComponent
     camel-quarkus-quartz:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-quartz
@@ -1485,22 +2773,24 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.quartz.QuartzComponent
-    camel-quarkus-couchdb:
+    camel-quarkus-mllp:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-couchdb
+      artifactId: camel-quarkus-mllp
       schemes:
-      - id: couchdb
+      - id: mllp
         http: false
         passive: false
       javaTypes:
-      - org.apache.camel.component.couchdb.CouchDbComponent
-    camel-quarkus-jaxb:
+      - org.apache.camel.component.mllp.MllpComponent
+    camel-quarkus-azure-storage-queue:
       groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-jaxb
-      dataformats:
-      - jaxb
+      artifactId: camel-quarkus-azure-storage-queue
+      schemes:
+      - id: azure-storage-queue
+        http: false
+        passive: false
       javaTypes:
-      - org.apache.camel.converter.jaxb.JaxbDataFormat
+      - org.apache.camel.component.azure.storage.queue.QueueComponent
     camel-quarkus-xstream:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-xstream
@@ -1510,15 +2800,6 @@ spec:
       javaTypes:
       - org.apache.camel.dataformat.xstream.JsonDataFormat
       - org.apache.camel.dataformat.xstream.XStreamDataFormat
-    camel-quarkus-aws-sqs:
-      groupId: org.apache.camel.quarkus
-      artifactId: camel-quarkus-aws-sqs
-      schemes:
-      - id: aws-sqs
-        http: false
-        passive: false
-      javaTypes:
-      - org.apache.camel.component.aws.sqs.SqsComponent
     camel-k-loader-yaml:
       groupId: org.apache.camel.k
       artifactId: camel-k-loader-yaml
@@ -1570,6 +2851,16 @@ spec:
       dependencies:
       - groupId: org.apache.camel.k
         artifactId: camel-k-quarkus-knative
+    camel-kamelet:
+      groupId: org.apache.camel.k
+      artifactId: camel-kamelet
+      schemes:
+      - id: kamelet
+        http: true
+        passive: false
+      dependencies:
+      - groupId: org.apache.camel.k
+        artifactId: camel-k-quarkus-kamelet
   loaders:
     yaml:
       groupId: org.apache.camel.k
diff --git a/deploy/resources.go b/deploy/resources.go
index 2950584..d326415 100644
--- a/deploy/resources.go
+++ b/deploy/resources.go
@@ -91,16 +91,16 @@ var assets = func() http.FileSystem {
 		"/camel-catalog-1.5.1-SNAPSHOT-main.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "camel-catalog-1.5.1-SNAPSHOT-main.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 91183,
+			uncompressedSize: 91408,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x7d\x5b\x77\xdb\x38\xb2\xee\x7b\x7e\x05\xd7\xe4\x65\xef\x75\x46\x35\xdd\xce\xcc\xf4\xd9\x7d\x9e\x6c\x39\x4e\xec\xd8\x8e\x3b\xf4\x24\x99\x79\xe9\x05\x91\x90\x04\x8b\x24\x68\x00\x92\x65\xff\xfa\xb3\x70\xe1\x55\x10\x24\x12\x86\xd7\xf6\x83\x49\x11\x55\x5f\xb1\x08\x12\x97\x42\xa1\xea\x7d\x34\x79\xbd\xbf\x77\xef\xa3\x6b\x92\xe0\x82\xe3\x34\x12\x34\x12\x4b\x1c\x9d\x96\x28\x59\xe2\x28\xa6\x73\xf1\x84\x18\x8e\x2e\xe8\xba\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\xbd\x5b\x77\xdb\x38\xb2\x2f\xfe\x9e\x4f\xc1\x35\x79\xd9\x7b\xfd\x47\x35\xdd\xce\xcc\xf4\xde\xfd\x7f\xb2\xe5\x38\xb1\x63\x3b\xee\xd0\x93\x64\xe6\xa5\x17\x44\x42\x12\x2c\x92\xa0\x01\x48\x96\xfd\xe9\xcf\xc2\x85\x57\x41\x90\x48\x18\x3e\xeb\xf8\xc1\xa4\x88\xaa\x5f\xb1\x08\x12\x97\x42\xa1\xea\x7d\x34\x79\xbd\xbf\x77\xef\xa3\x6b\x92\xe0\x82\xe3\x34\x12\x34\x12\x4b\x1c\x9d\x96\x28\x59\xe2\x28\xa6\x73\xf1\x84\x18\x8e\x2e\x [...]
 		},
 		"/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 49504,
+			uncompressedSize: 87866,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x7d\x5d\x77\xdb\xaa\xd2\xff\x7d\x3e\x85\x56\x73\x73\xce\x5a\x5b\xec\x7d\xd2\xff\xde\xff\xb5\xfa\x5c\x25\x69\xd3\x26\x6d\x5e\x5a\xe7\xb4\xdd\xfb\xa6\x0b\x4b\xd8\x26\x96\x40\x01\x64\x3b\xf9\xf4\xcf\x02\x21\x4b\xb2\x95\xd1\x4b\xc0\x4f\x2e\x22\x59\x0c\xbf\x81\x01\xc1\x68\x98\x81\xe3\x20\x74\xf7\x77\x74\x1c\x7c\xa1\x11\x61\x92\xc4\x81\xe2\x81\x5a\x90\xe0\x34\xc3\xd1\x82\x04\x13\x3e\x53\x6b\x2c\x48\x70\xc1\x73\x16\x63\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x7d\x5d\x57\xdc\x38\xd2\xff\x7d\x3e\x85\xcf\xe4\xe6\x79\xce\x7f\xad\x9d\x21\xbb\x3b\x7b\xe6\x7f\x05\x4d\x48\x20\x40\x48\xcc\x26\xd9\xbd\x99\xa3\xb6\xd5\xdd\xa2\x6d\xcb\x48\xea\x06\xf2\xe9\x9f\xa3\x17\xbf\xb6\x29\xbf\x20\xb1\x5c\x60\xbb\x55\xfa\x95\x55\x92\xa5\x52\xa9\x54\x7a\x1b\x84\xee\xfe\xde\xbc\x0d\x2e\x69\x4c\x72\x41\x92\x40\xb2\x40\x6e\x48\x70\x5c\xe0\x78\x43\x82\x88\xad\xe4\x03\xe6\x24\x38\x63\xbb\x3c\xc1\x [...]
 		},
 		"/cr-example.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "cr-example.yaml",
@@ -163,7 +163,7 @@ var assets = func() http.FileSystem {
 			modTime:          time.Time{},
 			uncompressedSize: 2148,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xbc\x54\xc1\x6e\xe3\x36\x10\xbd\xeb\x2b\x1e\xac\xcb\x2e\x10\xdb\x9b\x1e\xd5\x93\x9a\x38\x88\xd1\x54\x32\x2c\x6f\x83\x3d\x15\x13\x6a\x24\x11\xa1\x48\x95\xa4\xa2\xd5\xdf\x17\x94\xed\xc4\xce\x66\xd3\x1e\x82\xf2\x64\x73\x66\xde\xbc\x37\x6f\xc4\x18\xf3\x8f\x3b\x51\x8c\x3b\x29\x58\x3b\x2e\xe1\x0d\x7c\xc3\x48\x3b\x12\x0d\xa3\x30\x95\x1f\xc8\x32\x6e\x4c\xaf\x4b\xf2\xd2\x68\x7c\x4a\x8b\x9b\xcf\xe8\x75\xc9\x16\x46\x33\x8c\x45\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xbc\x54\x41\x6f\xe3\x36\x13\xbd\xeb\x57\x3c\x58\x97\x5d\x20\xb6\x37\x7b\xd4\x77\xd2\x97\x38\x88\xd1\x54\x32\x2c\x6f\x83\x3d\x15\x13\x6a\x24\x11\xa1\x48\x95\xa4\xa2\xd5\xbf\x2f\x28\xdb\x89\x9d\xcd\xa6\x3d\x04\xe5\xc9\xe6\xcc\xbc\x79\x6f\xde\x88\x31\xe6\x1f\x77\xa2\x18\x77\x52\xb0\x76\x5c\xc2\x1b\xf8\x86\x91\x76\x24\x1a\x46\x61\x2a\x3f\x90\x65\xdc\x98\x5e\x97\xe4\xa5\xd1\xf8\x94\x16\x37\x9f\xd1\xeb\x92\x2d\x8c\x66\x18\x [...]
 		},
 		"/operator-role-binding-events.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "operator-role-binding-events.yaml",


[camel-k] 01/21: kamelets: initial structure

Posted by nf...@apache.org.
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 7e4d6619da416c1e8c20e476055c33d2b14b1725
Author: Nicola Ferraro <ni...@gmail.com>
AuthorDate: Tue Jun 23 11:19:01 2020 +0200

    kamelets: initial structure
---
 .../csv-config.yaml => crd-kamelet.yaml}           |  38 +++--
 ...el-k.v1.1.0-snapshot.clusterserviceversion.yaml |   5 +
 .../kamelets.camel.apache.org.crd.yaml}            |  38 +++--
 deploy/olm-catalog/csv-config.yaml                 |   1 +
 .../camel-k/crds/crd-kamelet.yaml                  |  38 +++--
 pkg/apis/addtoscheme_camel_v1alpha1.go             |  27 +++
 pkg/apis/camel/v1alpha1/kamelet_types.go           | 105 ++++++++++++
 pkg/apis/camel/v1alpha1/kamelet_types_support.go   |  46 +++++
 pkg/apis/camel/v1alpha1/register.go                |  55 ++++++
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go   | 102 +++++++++++
 pkg/controller/kamelet/action.go                   |  54 ++++++
 pkg/controller/kamelet/initialize.go               |  46 +++++
 pkg/controller/kamelet/kamelet_controller.go       | 187 +++++++++++++++++++++
 pkg/controller/kamelet/log.go                      |  23 +++
 pkg/event/manager.go                               |  37 ++++
 pkg/install/cluster.go                             |  39 +++--
 pkg/util/log/log.go                                |  11 ++
 17 files changed, 808 insertions(+), 44 deletions(-)

diff --git a/deploy/olm-catalog/csv-config.yaml b/deploy/crd-kamelet.yaml
similarity index 62%
copy from deploy/olm-catalog/csv-config.yaml
copy to deploy/crd-kamelet.yaml
index 3075a7a..7d36aab 100644
--- a/deploy/olm-catalog/csv-config.yaml
+++ b/deploy/crd-kamelet.yaml
@@ -15,13 +15,31 @@
 # limitations under the License.
 # ---------------------------------------------------------------------------
 
-operator-path: deploy/operator-deployment.yaml
-crd-cr-paths:
-  - deploy/crd-build.yaml
-  - deploy/crd-camel-catalog.yaml
-  - deploy/crd-integration.yaml
-  - deploy/crd-integration-kit.yaml
-  - deploy/crd-integration-platform.yaml
-role-paths:
-  - deploy/operator-role-olm.yaml
-  - deploy/operator-role-olm-cluster.yaml
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+  name: kamelets.camel.apache.org
+  labels:
+    app: "camel-k"
+spec:
+  group: camel.apache.org
+  scope: Namespaced
+  version: v1alpha1
+  versions:
+  - name: v1alpha1
+    served: true
+    storage: true
+  subresources:
+    status: {}
+  names:
+    kind: Kamelet
+    listKind: KameletList
+    plural: kamelets
+    singular: kamelet
+    shortNames:
+    - kl
+  additionalPrinterColumns:
+  - name: Phase
+    type: string
+    description: The Kamelet phase
+    JSONPath: .status.phase
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-snapshot/camel-k.v1.1.0-snapshot.clusterserviceversion.yaml
index d761fee..4cc2a53 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-snapshot/camel-k.v1.1.0-snapshot.clusterserviceversion.yaml
@@ -122,6 +122,11 @@ spec:
       kind: IntegrationPlatform
       name: integrationplatforms.camel.apache.org
       version: v1
+    - description: A Camel K Kamelet resource
+      displayName: Kamelet
+      kind: Kamelet
+      name: kamelets.camel.apache.org
+      version: v1alpha1
   description: |
     Apache Camel K
     ==============
diff --git a/deploy/olm-catalog/csv-config.yaml b/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/kamelets.camel.apache.org.crd.yaml
similarity index 62%
copy from deploy/olm-catalog/csv-config.yaml
copy to deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/kamelets.camel.apache.org.crd.yaml
index 3075a7a..7d36aab 100644
--- a/deploy/olm-catalog/csv-config.yaml
+++ b/deploy/olm-catalog/camel-k-dev/1.1.0-snapshot/kamelets.camel.apache.org.crd.yaml
@@ -15,13 +15,31 @@
 # limitations under the License.
 # ---------------------------------------------------------------------------
 
-operator-path: deploy/operator-deployment.yaml
-crd-cr-paths:
-  - deploy/crd-build.yaml
-  - deploy/crd-camel-catalog.yaml
-  - deploy/crd-integration.yaml
-  - deploy/crd-integration-kit.yaml
-  - deploy/crd-integration-platform.yaml
-role-paths:
-  - deploy/operator-role-olm.yaml
-  - deploy/operator-role-olm-cluster.yaml
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+  name: kamelets.camel.apache.org
+  labels:
+    app: "camel-k"
+spec:
+  group: camel.apache.org
+  scope: Namespaced
+  version: v1alpha1
+  versions:
+  - name: v1alpha1
+    served: true
+    storage: true
+  subresources:
+    status: {}
+  names:
+    kind: Kamelet
+    listKind: KameletList
+    plural: kamelets
+    singular: kamelet
+    shortNames:
+    - kl
+  additionalPrinterColumns:
+  - name: Phase
+    type: string
+    description: The Kamelet phase
+    JSONPath: .status.phase
diff --git a/deploy/olm-catalog/csv-config.yaml b/deploy/olm-catalog/csv-config.yaml
index 3075a7a..a5e2dd2 100644
--- a/deploy/olm-catalog/csv-config.yaml
+++ b/deploy/olm-catalog/csv-config.yaml
@@ -22,6 +22,7 @@ crd-cr-paths:
   - deploy/crd-integration.yaml
   - deploy/crd-integration-kit.yaml
   - deploy/crd-integration-platform.yaml
+  - deploy/crd-kamelet.yaml
 role-paths:
   - deploy/operator-role-olm.yaml
   - deploy/operator-role-olm-cluster.yaml
diff --git a/deploy/olm-catalog/csv-config.yaml b/helm/camel-k/crds/crd-kamelet.yaml
similarity index 62%
copy from deploy/olm-catalog/csv-config.yaml
copy to helm/camel-k/crds/crd-kamelet.yaml
index 3075a7a..7d36aab 100644
--- a/deploy/olm-catalog/csv-config.yaml
+++ b/helm/camel-k/crds/crd-kamelet.yaml
@@ -15,13 +15,31 @@
 # limitations under the License.
 # ---------------------------------------------------------------------------
 
-operator-path: deploy/operator-deployment.yaml
-crd-cr-paths:
-  - deploy/crd-build.yaml
-  - deploy/crd-camel-catalog.yaml
-  - deploy/crd-integration.yaml
-  - deploy/crd-integration-kit.yaml
-  - deploy/crd-integration-platform.yaml
-role-paths:
-  - deploy/operator-role-olm.yaml
-  - deploy/operator-role-olm-cluster.yaml
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+  name: kamelets.camel.apache.org
+  labels:
+    app: "camel-k"
+spec:
+  group: camel.apache.org
+  scope: Namespaced
+  version: v1alpha1
+  versions:
+  - name: v1alpha1
+    served: true
+    storage: true
+  subresources:
+    status: {}
+  names:
+    kind: Kamelet
+    listKind: KameletList
+    plural: kamelets
+    singular: kamelet
+    shortNames:
+    - kl
+  additionalPrinterColumns:
+  - name: Phase
+    type: string
+    description: The Kamelet phase
+    JSONPath: .status.phase
diff --git a/pkg/apis/addtoscheme_camel_v1alpha1.go b/pkg/apis/addtoscheme_camel_v1alpha1.go
new file mode 100644
index 0000000..001d778
--- /dev/null
+++ b/pkg/apis/addtoscheme_camel_v1alpha1.go
@@ -0,0 +1,27 @@
+/*
+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 apis
+
+import (
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+)
+
+func init() {
+	// Register the types with the Scheme so the components can map objects to GroupVersionKinds and back
+	AddToSchemes = append(AddToSchemes, v1alpha1.SchemeBuilder.AddToScheme)
+}
diff --git a/pkg/apis/camel/v1alpha1/kamelet_types.go b/pkg/apis/camel/v1alpha1/kamelet_types.go
new file mode 100644
index 0000000..ed99b66
--- /dev/null
+++ b/pkg/apis/camel/v1alpha1/kamelet_types.go
@@ -0,0 +1,105 @@
+package v1alpha1
+
+import (
+	camelv1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+	openapi "github.com/go-openapi/spec"
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// KameletSpec defines the desired state of Kamelet
+type KameletSpec struct {
+	Info          KameletInfo         `json:"info,omitempty"`
+	Parameters    []KameletParameter  `json:"parameters,omitempty"`
+	Authorization AuthorizationSpec   `json:"authorization,omitempty"`
+	Sources       *camelv1.SourceSpec `json:"sources,omitempty"`
+	Flow          *camelv1.Flow       `json:"flow,omitempty"`
+	Dependencies  []string            `json:"dependencies,omitempty"`
+}
+
+type KameletInfo struct {
+	DisplayName string      `json:"displayName,omitempty"`
+	Description string      `json:"description,omitempty"`
+	Group       string      `json:"group,omitempty"`
+	Icon        KameletIcon `json:"icon,omitempty"`
+}
+
+type KameletIcon struct {
+	Data      string `json:"data,omitempty"`
+	MediaType string `json:"mediaType,omitempty"`
+}
+
+type KameletParameter struct {
+	Name        string            `json:"name,omitempty"`
+	Required    bool              `json:"required,omitempty"`
+	Description string            `json:"description,omitempty"`
+	Annotations map[string]string `json:"annotations,omitempty"`
+	Schema      *openapi.Schema   `json:"schema,omitempty"`
+}
+
+// AuthorizationSpec is TODO (oauth information)
+type AuthorizationSpec struct {
+}
+
+// KameletStatus defines the observed state of Kamelet
+type KameletStatus struct {
+	Phase      KameletPhase       `json:"phase,omitempty"`
+	Conditions []KameletCondition `json:"conditions,omitempty"`
+}
+
+// KameletCondition describes the state of a resource at a certain point.
+type KameletCondition struct {
+	// Type of kamelet condition.
+	Type KameletConditionType `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 KameletConditionType string
+
+const (
+	// KameletConditionReady --
+	KameletConditionReady KameletConditionType = "Ready"
+)
+
+type KameletPhase string
+
+const (
+	// KameletKind --
+	KameletKind string = "Kamelet"
+
+	// KameletPhaseNone --
+	KameletPhaseNone KameletPhase = ""
+	// KameletPhaseReady --
+	KameletPhaseReady KameletPhase = "Ready"
+)
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// Kamelet is the Schema for the kamelets API
+// +kubebuilder:subresource:status
+// +kubebuilder:resource:path=kamelets,scope=Namespaced
+type Kamelet struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	Spec   KameletSpec   `json:"spec,omitempty"`
+	Status KameletStatus `json:"status,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// KameletList contains a list of Kamelet
+type KameletList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []Kamelet `json:"items"`
+}
diff --git a/pkg/apis/camel/v1alpha1/kamelet_types_support.go b/pkg/apis/camel/v1alpha1/kamelet_types_support.go
new file mode 100644
index 0000000..eb18093
--- /dev/null
+++ b/pkg/apis/camel/v1alpha1/kamelet_types_support.go
@@ -0,0 +1,46 @@
+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 *KameletStatus) 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 KameletCondition) GetType() string {
+	return string(c.Type)
+}
+
+// GetStatus --
+func (c KameletCondition) GetStatus() corev1.ConditionStatus {
+	return c.Status
+}
+
+// GetLastUpdateTime --
+func (c KameletCondition) GetLastUpdateTime() metav1.Time {
+	return c.LastUpdateTime
+}
+
+// GetLastTransitionTime --
+func (c KameletCondition) GetLastTransitionTime() metav1.Time {
+	return c.LastTransitionTime
+}
+
+// GetReason --
+func (c KameletCondition) GetReason() string {
+	return c.Reason
+}
+
+// GetMessage --
+func (c KameletCondition) GetMessage() string {
+	return c.Message
+}
diff --git a/pkg/apis/camel/v1alpha1/register.go b/pkg/apis/camel/v1alpha1/register.go
new file mode 100644
index 0000000..5bafade
--- /dev/null
+++ b/pkg/apis/camel/v1alpha1/register.go
@@ -0,0 +1,55 @@
+/*
+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.
+*/
+
+// NOTE: Boilerplate only.  Ignore this file.
+
+// Package v1alpha1 contains Camel unstable API Schema definitions
+// +k8s:deepcopy-gen=package,register
+// +groupName=camel.apache.org
+package v1alpha1
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+)
+
+var (
+	// SchemeGroupVersion is group version used to register these objects
+	SchemeGroupVersion = schema.GroupVersion{Group: "camel.apache.org", Version: "v1alpha1"}
+
+	// SchemeBuilder is used to add go types to the GroupVersionKind scheme
+	SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
+
+	// AddToScheme is a shortcut to SchemeBuilder.AddToScheme
+	AddToScheme = SchemeBuilder.AddToScheme
+)
+
+// Resource takes an unqualified resource and returns a Group qualified GroupResource
+func Resource(resource string) schema.GroupResource {
+	return SchemeGroupVersion.WithResource(resource).GroupResource()
+}
+
+// Adds the list of known types to Scheme.
+func addKnownTypes(scheme *runtime.Scheme) error {
+	scheme.AddKnownTypes(SchemeGroupVersion,
+		&Kamelet{},
+		&KameletList{},
+	)
+	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
new file mode 100644
index 0000000..8c7d0d7
--- /dev/null
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -0,0 +1,102 @@
+// +build !ignore_autogenerated
+
+// Code generated by operator-sdk. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Kamelet) DeepCopyInto(out *Kamelet) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	out.Spec = in.Spec
+	out.Status = in.Status
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Kamelet.
+func (in *Kamelet) DeepCopy() *Kamelet {
+	if in == nil {
+		return nil
+	}
+	out := new(Kamelet)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *Kamelet) 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 *KameletList) DeepCopyInto(out *KameletList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]Kamelet, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KameletList.
+func (in *KameletList) DeepCopy() *KameletList {
+	if in == nil {
+		return nil
+	}
+	out := new(KameletList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *KameletList) 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 *KameletSpec) DeepCopyInto(out *KameletSpec) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KameletSpec.
+func (in *KameletSpec) DeepCopy() *KameletSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(KameletSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *KameletStatus) DeepCopyInto(out *KameletStatus) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KameletStatus.
+func (in *KameletStatus) DeepCopy() *KameletStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(KameletStatus)
+	in.DeepCopyInto(out)
+	return out
+}
diff --git a/pkg/controller/kamelet/action.go b/pkg/controller/kamelet/action.go
new file mode 100644
index 0000000..7f07717
--- /dev/null
+++ b/pkg/controller/kamelet/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 kamelet
+
+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 kamelet
+	CanHandle(kamelet *v1alpha1.Kamelet) bool
+
+	// executes the handling function
+	Handle(ctx context.Context, kamelet *v1alpha1.Kamelet) (*v1alpha1.Kamelet, 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/kamelet/initialize.go b/pkg/controller/kamelet/initialize.go
new file mode 100644
index 0000000..e1f4360
--- /dev/null
+++ b/pkg/controller/kamelet/initialize.go
@@ -0,0 +1,46 @@
+/*
+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 kamelet
+
+import (
+	"context"
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+)
+
+// NewInitializeAction returns a action that initializes the kamelet 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(kamelet *v1alpha1.Kamelet) bool {
+	return kamelet.Status.Phase == v1alpha1.KameletPhaseNone
+}
+
+func (action *initializeAction) Handle(ctx context.Context, kamelet *v1alpha1.Kamelet) (*v1alpha1.Kamelet, error) {
+	target := kamelet.DeepCopy()
+	target.Status.Phase = v1alpha1.KameletPhaseReady
+	return target, nil
+}
diff --git a/pkg/controller/kamelet/kamelet_controller.go b/pkg/controller/kamelet/kamelet_controller.go
new file mode 100644
index 0000000..048cf22
--- /dev/null
+++ b/pkg/controller/kamelet/kamelet_controller.go
@@ -0,0 +1,187 @@
+/*
+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 kamelet
+
+import (
+	"context"
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"time"
+
+	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"
+
+	"github.com/apache/camel-k/pkg/client"
+)
+
+// Add creates a new Kamelet 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 &ReconcileKamelet{
+		client:   c,
+		scheme:   mgr.GetScheme(),
+		recorder: mgr.GetEventRecorderFor("camel-k-kamelet-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-controller", mgr, controller.Options{Reconciler: r})
+	if err != nil {
+		return err
+	}
+
+	// Watch for changes to primary resource Kamelet
+	err = c.Watch(&source.Kind{Type: &v1alpha1.Kamelet{}}, &handler.EnqueueRequestForObject{}, predicate.Funcs{
+		UpdateFunc: func(e event.UpdateEvent) bool {
+			oldKamelet := e.ObjectOld.(*v1alpha1.Kamelet)
+			newKamelet := e.ObjectNew.(*v1alpha1.Kamelet)
+			// Ignore updates to the kamelet status in which case metadata.Generation
+			// does not change, or except when the kamelet phase changes as it's used
+			// to transition from one phase to another
+			return oldKamelet.Generation != newKamelet.Generation ||
+				oldKamelet.Status.Phase != newKamelet.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 = &ReconcileKamelet{}
+
+// ReconcileKamelet reconciles a Kamelet object
+type ReconcileKamelet 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 Kamelet object and makes changes based
+// on the state read and what is in the Kamelet.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 *ReconcileKamelet) Reconcile(request reconcile.Request) (reconcile.Result, error) {
+	rlog := Log.WithValues("request-namespace", request.Namespace, "request-name", request.Name)
+	rlog.Info("Reconciling Kamelet")
+
+	ctx := context.TODO()
+
+	// Fetch the Kamelet instance
+	var instance v1alpha1.Kamelet
+
+	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(),
+	}
+
+	var targetPhase v1alpha1.KameletPhase
+	var err error
+
+	target := instance.DeepCopy()
+	targetLog := rlog.ForKamelet(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.NotifyKameletError(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.NotifyKameletError(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.NotifyKameletUpdated(ctx, r.client, r.recorder, &instance, target)
+			break
+		}
+	}
+
+	if targetPhase == v1alpha1.KameletPhaseReady {
+		return reconcile.Result{}, nil
+	}
+
+	// Requeue
+	return reconcile.Result{
+		RequeueAfter: 5 * time.Second,
+	}, nil
+}
diff --git a/pkg/controller/kamelet/log.go b/pkg/controller/kamelet/log.go
new file mode 100644
index 0000000..2df12a4
--- /dev/null
+++ b/pkg/controller/kamelet/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 kamelet
+
+import "github.com/apache/camel-k/pkg/util/log"
+
+// Log --
+var Log = log.Log.WithName("controller").WithName("kamelet")
diff --git a/pkg/event/manager.go b/pkg/event/manager.go
index 43d1051..93e27f9 100644
--- a/pkg/event/manager.go
+++ b/pkg/event/manager.go
@@ -20,6 +20,7 @@ package event
 import (
 	"context"
 	"fmt"
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	"github.com/apache/camel-k/pkg/client"
@@ -60,6 +61,13 @@ const (
 	// ReasonBuildError --
 	ReasonBuildError = "BuildError"
 
+	// ReasonKameletError --
+	ReasonKameletError = "KameletError"
+	// ReasonKameletConditionChanged --
+	ReasonKameletConditionChanged = "KameletConditionChanged"
+	// ReasonKameletPhaseUpdated --
+	ReasonKameletPhaseUpdated = "KameletPhaseUpdated"
+
 	// ReasonRelatedObjectChanged --
 	ReasonRelatedObjectChanged = "ReasonRelatedObjectChanged"
 )
@@ -151,6 +159,35 @@ func NotifyIntegrationPlatformError(ctx context.Context, c client.Client, record
 	recorder.Eventf(p, corev1.EventTypeWarning, ReasonIntegrationPlatformError, "Cannot reconcile Integration Platform %s: %v", p.Name, err)
 }
 
+// NotifyKameletUpdated automatically generates events when a Kamelet changes
+func NotifyKameletUpdated(ctx context.Context, c client.Client, recorder record.EventRecorder, old, new *v1alpha1.Kamelet) {
+	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.KameletPhaseNone {
+		notifyIfConditionUpdated(recorder, new, oldConditions, new.Status.GetConditions(), "Kamelet", new.Name, ReasonKameletConditionChanged)
+	}
+	notifyIfPhaseUpdated(ctx, c, recorder, new, oldPhase, string(new.Status.Phase), "Kamelet", new.Name, ReasonKameletPhaseUpdated, "")
+}
+
+// NotifyKameletError automatically generates error events when the kamelet reconcile cycle phase has an error
+func NotifyKameletError(ctx context.Context, c client.Client, recorder record.EventRecorder, old, new *v1alpha1.Kamelet, err error) {
+	k := old
+	if new != nil {
+		k = new
+	}
+	if k == nil {
+		return
+	}
+	recorder.Eventf(k, corev1.EventTypeWarning, ReasonKameletError, "Cannot reconcile Kamelet %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 9b67062..ae55328 100644
--- a/pkg/install/cluster.go
+++ b/pkg/install/cluster.go
@@ -20,6 +20,7 @@ package install
 import (
 	"context"
 	"errors"
+	"fmt"
 	"strconv"
 	"time"
 
@@ -45,27 +46,32 @@ func SetupClusterWideResourcesOrCollect(ctx context.Context, clientProvider clie
 	}
 
 	// Install CRD for Integration Platform (if needed)
-	if err := installCRD(ctx, c, "IntegrationPlatform", "crd-integration-platform.yaml", collection); err != nil {
+	if err := installCRD(ctx, c, "IntegrationPlatform", "v1", "crd-integration-platform.yaml", collection); err != nil {
 		return err
 	}
 
 	// Install CRD for Integration Kit (if needed)
-	if err := installCRD(ctx, c, "IntegrationKit", "crd-integration-kit.yaml", collection); err != nil {
+	if err := installCRD(ctx, c, "IntegrationKit", "v1", "crd-integration-kit.yaml", collection); err != nil {
 		return err
 	}
 
 	// Install CRD for Integration (if needed)
-	if err := installCRD(ctx, c, "Integration", "crd-integration.yaml", collection); err != nil {
+	if err := installCRD(ctx, c, "Integration", "v1", "crd-integration.yaml", collection); err != nil {
 		return err
 	}
 
 	// Install CRD for Camel Catalog (if needed)
-	if err := installCRD(ctx, c, "CamelCatalog", "crd-camel-catalog.yaml", collection); err != nil {
+	if err := installCRD(ctx, c, "CamelCatalog", "v1", "crd-camel-catalog.yaml", collection); err != nil {
 		return err
 	}
 
 	// Install CRD for Build (if needed)
-	if err := installCRD(ctx, c, "Build", "crd-build.yaml", collection); err != nil {
+	if err := installCRD(ctx, c, "Build", "v1", "crd-build.yaml", collection); err != nil {
+		return err
+	}
+
+	// Install CRD for Kamelet (if needed)
+	if err := installCRD(ctx, c, "Kamelet", "v1alpha1", "crd-kamelet.yaml", collection); err != nil {
 		return err
 	}
 
@@ -120,32 +126,37 @@ func WaitForAllCRDInstallation(ctx context.Context, clientProvider client.Provid
 
 // AreAllCRDInstalled check if all the required CRDs are installed
 func AreAllCRDInstalled(ctx context.Context, c client.Client) (bool, error) {
-	if ok, err := IsCRDInstalled(ctx, c, "IntegrationPlatform"); err != nil {
+	if ok, err := IsCRDInstalled(ctx, c, "IntegrationPlatform", "v1"); err != nil {
+		return ok, err
+	} else if !ok {
+		return false, nil
+	}
+	if ok, err := IsCRDInstalled(ctx, c, "IntegrationKit", "v1"); err != nil {
 		return ok, err
 	} else if !ok {
 		return false, nil
 	}
-	if ok, err := IsCRDInstalled(ctx, c, "IntegrationKit"); err != nil {
+	if ok, err := IsCRDInstalled(ctx, c, "Integration", "v1"); err != nil {
 		return ok, err
 	} else if !ok {
 		return false, nil
 	}
-	if ok, err := IsCRDInstalled(ctx, c, "Integration"); err != nil {
+	if ok, err := IsCRDInstalled(ctx, c, "CamelCatalog", "v1"); err != nil {
 		return ok, err
 	} else if !ok {
 		return false, nil
 	}
-	if ok, err := IsCRDInstalled(ctx, c, "CamelCatalog"); err != nil {
+	if ok, err := IsCRDInstalled(ctx, c, "Build", "v1"); err != nil {
 		return ok, err
 	} else if !ok {
 		return false, nil
 	}
-	return IsCRDInstalled(ctx, c, "Build")
+	return IsCRDInstalled(ctx, c, "Kamelet", "v1alpha1")
 }
 
 // IsCRDInstalled check if the given CRD kind is installed
-func IsCRDInstalled(ctx context.Context, c client.Client, kind string) (bool, error) {
-	lst, err := c.Discovery().ServerResourcesForGroupVersion("camel.apache.org/v1")
+func IsCRDInstalled(ctx context.Context, c client.Client, kind string, version string) (bool, error) {
+	lst, err := c.Discovery().ServerResourcesForGroupVersion(fmt.Sprintf("camel.apache.org/%s", version))
 	if err != nil && k8serrors.IsNotFound(err) {
 		return false, nil
 	} else if err != nil {
@@ -159,7 +170,7 @@ func IsCRDInstalled(ctx context.Context, c client.Client, kind string) (bool, er
 	return false, nil
 }
 
-func installCRD(ctx context.Context, c client.Client, kind string, resourceName string, collection *kubernetes.Collection) error {
+func installCRD(ctx context.Context, c client.Client, kind string, version string, resourceName string, collection *kubernetes.Collection) error {
 	crd := deploy.Resource(resourceName)
 	if collection != nil {
 		unstr, err := kubernetes.LoadRawResourceFromYaml(string(crd))
@@ -171,7 +182,7 @@ func installCRD(ctx context.Context, c client.Client, kind string, resourceName
 	}
 
 	// Installing Integration CRD
-	installed, err := IsCRDInstalled(ctx, c, kind)
+	installed, err := IsCRDInstalled(ctx, c, kind, version)
 	if err != nil {
 		return err
 	}
diff --git a/pkg/util/log/log.go b/pkg/util/log/log.go
index 8287561..7ac3573 100644
--- a/pkg/util/log/log.go
+++ b/pkg/util/log/log.go
@@ -19,6 +19,7 @@ package log
 
 import (
 	"fmt"
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	"github.com/go-logr/logr"
@@ -128,6 +129,16 @@ func (l Logger) ForIntegrationPlatform(target *v1.IntegrationPlatform) Logger {
 	)
 }
 
+// ForIntegrationPlatform --
+func (l Logger) ForKamelet(target *v1alpha1.Kamelet) Logger {
+	return l.WithValues(
+		"api-version", target.APIVersion,
+		"kind", target.Kind,
+		"ns", target.Namespace,
+		"name", target.Name,
+	)
+}
+
 // ***********************************
 //
 // Helpers


[camel-k] 07/21: kamelet: fix icon definition

Posted by nf...@apache.org.
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 cf92c4f9284611a2fde4d3a353c9493b3b0c4423
Author: Nicola Ferraro <ni...@gmail.com>
AuthorDate: Thu Jun 25 15:21:56 2020 +0200

    kamelet: fix icon definition
---
 examples/kamelets/timer.kamelet.yaml     | 4 +++-
 pkg/apis/camel/v1alpha1/kamelet_types.go | 2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/examples/kamelets/timer.kamelet.yaml b/examples/kamelets/timer.kamelet.yaml
index 91848d0..0dd7f92 100644
--- a/examples/kamelets/timer.kamelet.yaml
+++ b/examples/kamelets/timer.kamelet.yaml
@@ -2,10 +2,12 @@ apiVersion: camel.apache.org/v1alpha1
 kind: Kamelet
 metadata:
   name: timer
+  annotations:
+    camel.apache.org/kamelet.icon: timer
 spec:
   definition:
     title: "Timer"
-    description: "Produces produces periodic events with a custom payload"
+    description: "Produces periodic events with a custom payload"
     required:
       - message
     properties:
diff --git a/pkg/apis/camel/v1alpha1/kamelet_types.go b/pkg/apis/camel/v1alpha1/kamelet_types.go
index a8e67fa..34594b2 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_types.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_types.go
@@ -24,7 +24,7 @@ import (
 )
 
 const (
-	AnnotationIcon = "camel.apache.org/icon"
+	AnnotationIcon = "camel.apache.org/kamelet.icon"
 )
 
 // KameletSpec defines the desired state of Kamelet


[camel-k] 21/21: Fix #1574: fix naming convention for property-defined sources

Posted by nf...@apache.org.
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 931b7612cea9b60632b7c8ea1cd417f081b2b11f
Author: nicolaferraro <ni...@gmail.com>
AuthorDate: Thu Sep 17 10:27:07 2020 +0200

    Fix #1574: fix naming convention for property-defined sources
---
 deploy/camel-catalog-1.5.1-SNAPSHOT-main.yaml    | 4 ++++
 deploy/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml | 4 ++++
 deploy/resources.go                              | 8 ++++----
 pkg/trait/knative_service_test.go                | 2 +-
 pkg/trait/trait_types.go                         | 6 +++---
 5 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/deploy/camel-catalog-1.5.1-SNAPSHOT-main.yaml b/deploy/camel-catalog-1.5.1-SNAPSHOT-main.yaml
index c4cd500..4604b99 100644
--- a/deploy/camel-catalog-1.5.1-SNAPSHOT-main.yaml
+++ b/deploy/camel-catalog-1.5.1-SNAPSHOT-main.yaml
@@ -64,6 +64,10 @@ spec:
         dependencies:
         - groupId: org.apache.camel.k
           artifactId: camel-k-runtime-tracing
+      master:
+        dependencies:
+        - groupId: org.apache.camel.k
+          artifactId: camel-k-runtime-master
   artifacts:
     camel-zipfile:
       groupId: org.apache.camel
diff --git a/deploy/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml b/deploy/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml
index c180043..6a4b50a 100644
--- a/deploy/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml
+++ b/deploy/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml
@@ -64,6 +64,10 @@ spec:
         dependencies:
         - groupId: org.apache.camel.quarkus
           artifactId: camel-quarkus-opentracing
+      master:
+        dependencies:
+        - groupId: org.apache.camel.quarkus
+          artifactId: camel-quarkus-master
   artifacts:
     camel-quarkus-aws2-ses:
       groupId: org.apache.camel.quarkus
diff --git a/deploy/resources.go b/deploy/resources.go
index d326415..71d31a1 100644
--- a/deploy/resources.go
+++ b/deploy/resources.go
@@ -91,16 +91,16 @@ var assets = func() http.FileSystem {
 		"/camel-catalog-1.5.1-SNAPSHOT-main.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "camel-catalog-1.5.1-SNAPSHOT-main.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 91408,
+			uncompressedSize: 91527,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\xbd\x5b\x77\xdb\x38\xb2\x2f\xfe\x9e\x4f\xc1\x35\x79\xd9\x7b\xfd\x47\x35\xdd\xce\xcc\xf4\xde\xfd\x7f\xb2\xe5\x38\xb1\x63\x3b\xee\xd0\x93\x64\xe6\xa5\x17\x44\x42\x12\x2c\x92\xa0\x01\x48\x96\xfd\xe9\xcf\xc2\x85\x57\x41\x90\x48\x18\x3e\xeb\xf8\xc1\xa4\x88\xaa\x5f\xb1\x08\x12\x97\x42\xa1\xea\x7d\x34\x79\xbd\xbf\x77\xef\xa3\x6b\x92\xe0\x82\xe3\x34\x12\x34\x12\x4b\x1c\x9d\x96\x28\x59\xe2\x28\xa6\x73\xf1\x84\x18\x8e\x2e\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\xbd\x5b\x77\xdb\x38\xb2\x2f\xfe\x9e\x4f\xc1\x35\x79\xd9\x7b\xfd\x47\x98\x6e\x67\x66\x7a\xef\xfe\x3f\xd9\x72\x9c\xd8\xb1\x1d\x77\xe8\x49\x32\xf3\xd2\x0b\x22\x21\x09\x16\x49\xd0\x00\x24\xcb\xfe\xf4\x67\xe1\xc2\xab\x20\x48\x64\x19\x3e\xeb\xf8\xc1\xa4\x88\xaa\x5f\xb1\x08\x12\x97\x42\xa1\xea\x7d\x34\x79\xbd\xbf\x77\xef\xa3\x6b\x9a\x90\x42\x90\x34\x92\x2c\x92\x4b\x12\x9d\x96\x38\x59\x92\x28\x66\x73\xf9\x84\x39\x89\x2e\x [...]
 		},
 		"/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 87866,
+			uncompressedSize: 87989,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x7d\x5d\x57\xdc\x38\xd2\xff\x7d\x3e\x85\xcf\xe4\xe6\x79\xce\x7f\xad\x9d\x21\xbb\x3b\x7b\xe6\x7f\x05\x4d\x48\x20\x40\x48\xcc\x26\xd9\xbd\x99\xa3\xb6\xd5\xdd\xa2\x6d\xcb\x48\xea\x06\xf2\xe9\x9f\xa3\x17\xbf\xb6\x29\xbf\x20\xb1\x5c\x60\xbb\x55\xfa\x95\x55\x92\xa5\x52\xa9\x54\x7a\x1b\x84\xee\xfe\xde\xbc\x0d\x2e\x69\x4c\x72\x41\x92\x40\xb2\x40\x6e\x48\x70\x5c\xe0\x78\x43\x82\x88\xad\xe4\x03\xe6\x24\x38\x63\xbb\x3c\xc1\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x7d\x5d\x57\xdc\x38\xd2\xff\x7d\x3e\x85\xcf\xe4\xe6\x79\xce\x7f\xad\x9d\x21\xbb\x3b\x7b\xe6\x7f\x05\x4d\x48\x20\x40\x48\xcc\x26\xd9\xbd\x99\xa3\xb6\xd5\xdd\xa2\x6d\xcb\x48\xea\x06\xf2\xe9\x9f\xa3\x17\xbf\xb6\x29\xbf\x20\xb1\x5c\x60\xbb\x55\xfa\x95\x55\x92\xa5\x52\xa9\x54\x7a\x1b\x84\xee\xfe\xde\xbc\x0d\x2e\x69\x4c\x72\x41\x92\x40\xb2\x40\x6e\x48\x70\x5c\xe0\x78\x43\x82\x88\xad\xe4\x03\xe6\x24\x38\x63\xbb\x3c\xc1\x [...]
 		},
 		"/cr-example.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "cr-example.yaml",
diff --git a/pkg/trait/knative_service_test.go b/pkg/trait/knative_service_test.go
index 731eec9..5b73d4e 100644
--- a/pkg/trait/knative_service_test.go
+++ b/pkg/trait/knative_service_test.go
@@ -174,7 +174,7 @@ func TestKnativeService(t *testing.T) {
 
 	assert.Equal(t, "file:/etc/camel/sources/i-source-000/routes.js", environment.ApplicationProperties["camel.k.sources[0].location"])
 	assert.Equal(t, "js", environment.ApplicationProperties["camel.k.sources[0].language"])
-	assert.Equal(t, "true", environment.ApplicationProperties["camel.k.sources[0].compression"])
+	assert.Equal(t, "true", environment.ApplicationProperties["camel.k.sources[0].compressed"])
 	test.EnvVarHasValue(t, spec.Containers[0].Env, "CAMEL_K_CONF", "/etc/camel/conf/application.properties")
 	test.EnvVarHasValue(t, spec.Containers[0].Env, "CAMEL_K_CONF_D", "/etc/camel/conf.d")
 }
diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go
index 3d38531..8343fb9 100644
--- a/pkg/trait/trait_types.go
+++ b/pkg/trait/trait_types.go
@@ -508,7 +508,7 @@ func (e *Environment) AddSourcesProperties() {
 			e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].loader", i)] = string(s.Loader)
 		}
 		if s.Compression {
-			e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].compression", i)] = "true"
+			e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].compressed", i)] = "true"
 		}
 
 		interceptors := make([]string, 0, len(s.Interceptors))
@@ -518,8 +518,8 @@ func (e *Environment) AddSourcesProperties() {
 		if e.Interceptors != nil {
 			interceptors = append(interceptors, e.Interceptors...)
 		}
-		if len(interceptors) > 0 {
-			e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].interceptors", i)] = strings.Join(interceptors, ",")
+		for intID, interceptor := range interceptors {
+			e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].interceptors[%d]", i, intID)] = interceptor
 		}
 	}
 }


[camel-k] 03/21: kamelets: improving kamelet format

Posted by nf...@apache.org.
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 f1533fe73a9429b3251a12904bf298d7d2d2b1d9
Author: Nicola Ferraro <ni...@gmail.com>
AuthorDate: Tue Jun 23 21:26:41 2020 +0200

    kamelets: improving kamelet format
---
 examples/kamelets/timer.kamelet.yaml             |  24 +-
 pkg/apis/camel/group.go                          |   6 +
 pkg/apis/camel/v1alpha1/doc.go                   |   4 +
 pkg/apis/camel/v1alpha1/jsonschema_types.go      | 260 +++++++++++++++
 pkg/apis/camel/v1alpha1/kamelet_types.go         |  71 ++--
 pkg/apis/camel/v1alpha1/kamelet_types_support.go |  17 +
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go | 407 ++++++++++++++++++++++-
 pkg/controller/add_kamelet.go                    |  26 ++
 8 files changed, 768 insertions(+), 47 deletions(-)

diff --git a/examples/kamelets/timer.kamelet.yaml b/examples/kamelets/timer.kamelet.yaml
index 9a2ec5d..91848d0 100644
--- a/examples/kamelets/timer.kamelet.yaml
+++ b/examples/kamelets/timer.kamelet.yaml
@@ -3,17 +3,21 @@ kind: Kamelet
 metadata:
   name: timer
 spec:
-  displayName: "Timer"
-  description: "Produces produces periodic events with a custom payload"
-  parameters:
-    - name: message
-      description: The message to generate
-      schema:
+  definition:
+    title: "Timer"
+    description: "Produces produces periodic events with a custom payload"
+    required:
+      - message
+    properties:
+      message:
+        title: Message
+        description: The message to generate
         type: string
-  produces:
-    type: text.types.camel.apache.org
-    schema:
-      content:
+  types:
+    out:
+      mediaType: application/json
+      schema:
+        id: text.camel.apache.org
         type: string
   flow:
     from:
diff --git a/pkg/apis/camel/group.go b/pkg/apis/camel/group.go
new file mode 100644
index 0000000..90958df
--- /dev/null
+++ b/pkg/apis/camel/group.go
@@ -0,0 +1,6 @@
+// Package camel contains camel API versions.
+//
+// This file ensures Go source parsers acknowledge the camel package
+// and any child packages. It can be removed if any other Go source files are
+// added to this package.
+package camel
diff --git a/pkg/apis/camel/v1alpha1/doc.go b/pkg/apis/camel/v1alpha1/doc.go
new file mode 100644
index 0000000..102912e
--- /dev/null
+++ b/pkg/apis/camel/v1alpha1/doc.go
@@ -0,0 +1,4 @@
+// Package v1alpha1 contains API Schema definitions for the camel v1alpha1 API group
+// +k8s:deepcopy-gen=package,register
+// +groupName=camel.apache.org
+package v1alpha1
diff --git a/pkg/apis/camel/v1alpha1/jsonschema_types.go b/pkg/apis/camel/v1alpha1/jsonschema_types.go
new file mode 100644
index 0000000..6ebdf1e
--- /dev/null
+++ b/pkg/apis/camel/v1alpha1/jsonschema_types.go
@@ -0,0 +1,260 @@
+/*
+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.
+*/
+
+// NOTE: this file has been originally copied from https://github.com/kubernetes/apiextensions-apiserver/blob/33bb2d8b009bae408e40818a93877459efeb4cb1/pkg/apis/apiextensions/v1/types_jsonschema.go
+
+package v1alpha1
+
+// JSONSchemaProps is a JSON-Schema following Specification Draft 4 (http://json-schema.org/).
+type JSONSchemaProps struct {
+	ID          string        `json:"id,omitempty" protobuf:"bytes,1,opt,name=id"`
+	Schema      JSONSchemaURL `json:"$schema,omitempty" protobuf:"bytes,2,opt,name=schema"`
+	Ref         *string       `json:"$ref,omitempty" protobuf:"bytes,3,opt,name=ref"`
+	Description string        `json:"description,omitempty" protobuf:"bytes,4,opt,name=description"`
+	Type        string        `json:"type,omitempty" protobuf:"bytes,5,opt,name=type"`
+
+	// format is an OpenAPI v3 format string. Unknown formats are ignored. The following formats are validated:
+	//
+	// - bsonobjectid: a bson object ID, i.e. a 24 characters hex string
+	// - uri: an URI as parsed by Golang net/url.ParseRequestURI
+	// - email: an email address as parsed by Golang net/mail.ParseAddress
+	// - hostname: a valid representation for an Internet host name, as defined by RFC 1034, section 3.1 [RFC1034].
+	// - ipv4: an IPv4 IP as parsed by Golang net.ParseIP
+	// - ipv6: an IPv6 IP as parsed by Golang net.ParseIP
+	// - cidr: a CIDR as parsed by Golang net.ParseCIDR
+	// - mac: a MAC address as parsed by Golang net.ParseMAC
+	// - uuid: an UUID that allows uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$
+	// - uuid3: an UUID3 that allows uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$
+	// - uuid4: an UUID4 that allows uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
+	// - uuid5: an UUID5 that allows uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
+	// - isbn: an ISBN10 or ISBN13 number string like "0321751043" or "978-0321751041"
+	// - isbn10: an ISBN10 number string like "0321751043"
+	// - isbn13: an ISBN13 number string like "978-0321751041"
+	// - creditcard: a credit card number defined by the regex ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11})$ with any non digit characters mixed in
+	// - ssn: a U.S. social security number following the regex ^\\d{3}[- ]?\\d{2}[- ]?\\d{4}$
+	// - hexcolor: an hexadecimal color code like "#FFFFFF: following the regex ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
+	// - rgbcolor: an RGB color code like rgb like "rgb(255,255,2559"
+	// - byte: base64 encoded binary data
+	// - password: any kind of string
+	// - date: a date string like "2006-01-02" as defined by full-date in RFC3339
+	// - duration: a duration string like "22 ns" as parsed by Golang time.ParseDuration or compatible with Scala duration format
+	// - datetime: a date time string like "2014-12-15T19:30:20.000Z" as defined by date-time in RFC3339.
+	Format string `json:"format,omitempty" protobuf:"bytes,6,opt,name=format"`
+
+	Title string `json:"title,omitempty" protobuf:"bytes,7,opt,name=title"`
+	// default is a default value for undefined object fields.
+	// Defaulting is a beta feature under the CustomResourceDefaulting feature gate.
+	// Defaulting requires spec.preserveUnknownFields to be false.
+	Default              *JSON                      `json:"default,omitempty" protobuf:"bytes,8,opt,name=default"`
+	Maximum              *float64                   `json:"maximum,omitempty" protobuf:"bytes,9,opt,name=maximum"`
+	ExclusiveMaximum     bool                       `json:"exclusiveMaximum,omitempty" protobuf:"bytes,10,opt,name=exclusiveMaximum"`
+	Minimum              *float64                   `json:"minimum,omitempty" protobuf:"bytes,11,opt,name=minimum"`
+	ExclusiveMinimum     bool                       `json:"exclusiveMinimum,omitempty" protobuf:"bytes,12,opt,name=exclusiveMinimum"`
+	MaxLength            *int64                     `json:"maxLength,omitempty" protobuf:"bytes,13,opt,name=maxLength"`
+	MinLength            *int64                     `json:"minLength,omitempty" protobuf:"bytes,14,opt,name=minLength"`
+	Pattern              string                     `json:"pattern,omitempty" protobuf:"bytes,15,opt,name=pattern"`
+	MaxItems             *int64                     `json:"maxItems,omitempty" protobuf:"bytes,16,opt,name=maxItems"`
+	MinItems             *int64                     `json:"minItems,omitempty" protobuf:"bytes,17,opt,name=minItems"`
+	UniqueItems          bool                       `json:"uniqueItems,omitempty" protobuf:"bytes,18,opt,name=uniqueItems"`
+	MultipleOf           *float64                   `json:"multipleOf,omitempty" protobuf:"bytes,19,opt,name=multipleOf"`
+	Enum                 []JSON                     `json:"enum,omitempty" protobuf:"bytes,20,rep,name=enum"`
+	MaxProperties        *int64                     `json:"maxProperties,omitempty" protobuf:"bytes,21,opt,name=maxProperties"`
+	MinProperties        *int64                     `json:"minProperties,omitempty" protobuf:"bytes,22,opt,name=minProperties"`
+	Required             []string                   `json:"required,omitempty" protobuf:"bytes,23,rep,name=required"`
+	Items                *JSONSchemaPropsOrArray    `json:"items,omitempty" protobuf:"bytes,24,opt,name=items"`
+	AllOf                []JSONSchemaProps          `json:"allOf,omitempty" protobuf:"bytes,25,rep,name=allOf"`
+	OneOf                []JSONSchemaProps          `json:"oneOf,omitempty" protobuf:"bytes,26,rep,name=oneOf"`
+	AnyOf                []JSONSchemaProps          `json:"anyOf,omitempty" protobuf:"bytes,27,rep,name=anyOf"`
+	Not                  *JSONSchemaProps           `json:"not,omitempty" protobuf:"bytes,28,opt,name=not"`
+	Properties           map[string]JSONSchemaProps `json:"properties,omitempty" protobuf:"bytes,29,rep,name=properties"`
+	AdditionalProperties *JSONSchemaPropsOrBool     `json:"additionalProperties,omitempty" protobuf:"bytes,30,opt,name=additionalProperties"`
+	PatternProperties    map[string]JSONSchemaProps `json:"patternProperties,omitempty" protobuf:"bytes,31,rep,name=patternProperties"`
+	Dependencies         JSONSchemaDependencies     `json:"dependencies,omitempty" protobuf:"bytes,32,opt,name=dependencies"`
+	AdditionalItems      *JSONSchemaPropsOrBool     `json:"additionalItems,omitempty" protobuf:"bytes,33,opt,name=additionalItems"`
+	Definitions          JSONSchemaDefinitions      `json:"definitions,omitempty" protobuf:"bytes,34,opt,name=definitions"`
+	ExternalDocs         *ExternalDocumentation     `json:"externalDocs,omitempty" protobuf:"bytes,35,opt,name=externalDocs"`
+	Example              *JSON                      `json:"example,omitempty" protobuf:"bytes,36,opt,name=example"`
+	Nullable             bool                       `json:"nullable,omitempty" protobuf:"bytes,37,opt,name=nullable"`
+
+	// x-kubernetes-preserve-unknown-fields stops the API server
+	// decoding step from pruning fields which are not specified
+	// in the validation schema. This affects fields recursively,
+	// but switches back to normal pruning behaviour if nested
+	// properties or additionalProperties are specified in the schema.
+	// This can either be true or undefined. False is forbidden.
+	XPreserveUnknownFields *bool `json:"x-kubernetes-preserve-unknown-fields,omitempty" protobuf:"bytes,38,opt,name=xKubernetesPreserveUnknownFields"`
+
+	// x-kubernetes-embedded-resource defines that the value is an
+	// embedded Kubernetes runtime.Object, with TypeMeta and
+	// ObjectMeta. The type must be object. It is allowed to further
+	// restrict the embedded object. kind, apiVersion and metadata
+	// are validated automatically. x-kubernetes-preserve-unknown-fields
+	// is allowed to be true, but does not have to be if the object
+	// is fully specified (up to kind, apiVersion, metadata).
+	XEmbeddedResource bool `json:"x-kubernetes-embedded-resource,omitempty" protobuf:"bytes,39,opt,name=xKubernetesEmbeddedResource"`
+
+	// x-kubernetes-int-or-string specifies that this value is
+	// either an integer or a string. If this is true, an empty
+	// type is allowed and type as child of anyOf is permitted
+	// if following one of the following patterns:
+	//
+	// 1) anyOf:
+	//    - type: integer
+	//    - type: string
+	// 2) allOf:
+	//    - anyOf:
+	//      - type: integer
+	//      - type: string
+	//    - ... zero or more
+	XIntOrString bool `json:"x-kubernetes-int-or-string,omitempty" protobuf:"bytes,40,opt,name=xKubernetesIntOrString"`
+
+	// x-kubernetes-list-map-keys annotates an array with the x-kubernetes-list-type `map` by specifying the keys used
+	// as the index of the map.
+	//
+	// This tag MUST only be used on lists that have the "x-kubernetes-list-type"
+	// extension set to "map". Also, the values specified for this attribute must
+	// be a scalar typed field of the child structure (no nesting is supported).
+	//
+	// The properties specified must either be required or have a default value,
+	// to ensure those properties are present for all list items.
+	//
+	// +optional
+	XListMapKeys []string `json:"x-kubernetes-list-map-keys,omitempty" protobuf:"bytes,41,rep,name=xKubernetesListMapKeys"`
+
+	// x-kubernetes-list-type annotates an array to further describe its topology.
+	// This extension must only be used on lists and may have 3 possible values:
+	//
+	// 1) `atomic`: the list is treated as a single entity, like a scalar.
+	//      Atomic lists will be entirely replaced when updated. This extension
+	//      may be used on any type of list (struct, scalar, ...).
+	// 2) `set`:
+	//      Sets are lists that must not have multiple items with the same value. Each
+	//      value must be a scalar, an object with x-kubernetes-map-type `atomic` or an
+	//      array with x-kubernetes-list-type `atomic`.
+	// 3) `map`:
+	//      These lists are like maps in that their elements have a non-index key
+	//      used to identify them. Order is preserved upon merge. The map tag
+	//      must only be used on a list with elements of type object.
+	// Defaults to atomic for arrays.
+	// +optional
+	XListType *string `json:"x-kubernetes-list-type,omitempty" protobuf:"bytes,42,opt,name=xKubernetesListType"`
+
+	// x-kubernetes-map-type annotates an object to further describe its topology.
+	// This extension must only be used when type is object and may have 2 possible values:
+	//
+	// 1) `granular`:
+	//      These maps are actual maps (key-value pairs) and each fields are independent
+	//      from each other (they can each be manipulated by separate actors). This is
+	//      the default behaviour for all maps.
+	// 2) `atomic`: the list is treated as a single entity, like a scalar.
+	//      Atomic maps will be entirely replaced when updated.
+	// +optional
+	XMapType *string `json:"x-kubernetes-map-type,omitempty" protobuf:"bytes,43,opt,name=xKubernetesMapType"`
+}
+
+// JSON represents any valid JSON value.
+// These types are supported: bool, int64, float64, string, []interface{}, map[string]interface{} and nil.
+type JSON struct {
+	Raw []byte `protobuf:"bytes,1,opt,name=raw"`
+}
+
+// OpenAPISchemaType is used by the kube-openapi generator when constructing
+// the OpenAPI spec of this type.
+//
+// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
+func (_ JSON) OpenAPISchemaType() []string {
+	// TODO: return actual types when anyOf is supported
+	return nil
+}
+
+// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
+// the OpenAPI spec of this type.
+func (_ JSON) OpenAPISchemaFormat() string { return "" }
+
+// JSONSchemaURL represents a schema url.
+type JSONSchemaURL string
+
+// JSONSchemaPropsOrArray represents a value that can either be a JSONSchemaProps
+// or an array of JSONSchemaProps. Mainly here for serialization purposes.
+type JSONSchemaPropsOrArray struct {
+	Schema      *JSONSchemaProps  `protobuf:"bytes,1,opt,name=schema"`
+	JSONSchemas []JSONSchemaProps `protobuf:"bytes,2,rep,name=jSONSchemas"`
+}
+
+// OpenAPISchemaType is used by the kube-openapi generator when constructing
+// the OpenAPI spec of this type.
+//
+// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
+func (_ JSONSchemaPropsOrArray) OpenAPISchemaType() []string {
+	// TODO: return actual types when anyOf is supported
+	return nil
+}
+
+// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
+// the OpenAPI spec of this type.
+func (_ JSONSchemaPropsOrArray) OpenAPISchemaFormat() string { return "" }
+
+// JSONSchemaPropsOrBool represents JSONSchemaProps or a boolean value.
+// Defaults to true for the boolean property.
+type JSONSchemaPropsOrBool struct {
+	Allows bool             `protobuf:"varint,1,opt,name=allows"`
+	Schema *JSONSchemaProps `protobuf:"bytes,2,opt,name=schema"`
+}
+
+// OpenAPISchemaType is used by the kube-openapi generator when constructing
+// the OpenAPI spec of this type.
+//
+// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
+func (_ JSONSchemaPropsOrBool) OpenAPISchemaType() []string {
+	// TODO: return actual types when anyOf is supported
+	return nil
+}
+
+// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
+// the OpenAPI spec of this type.
+func (_ JSONSchemaPropsOrBool) OpenAPISchemaFormat() string { return "" }
+
+// JSONSchemaDependencies represent a dependencies property.
+type JSONSchemaDependencies map[string]JSONSchemaPropsOrStringArray
+
+// JSONSchemaPropsOrStringArray represents a JSONSchemaProps or a string array.
+type JSONSchemaPropsOrStringArray struct {
+	Schema   *JSONSchemaProps `protobuf:"bytes,1,opt,name=schema"`
+	Property []string         `protobuf:"bytes,2,rep,name=property"`
+}
+
+// OpenAPISchemaType is used by the kube-openapi generator when constructing
+// the OpenAPI spec of this type.
+//
+// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
+func (_ JSONSchemaPropsOrStringArray) OpenAPISchemaType() []string {
+	// TODO: return actual types when anyOf is supported
+	return nil
+}
+
+// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
+// the OpenAPI spec of this type.
+func (_ JSONSchemaPropsOrStringArray) OpenAPISchemaFormat() string { return "" }
+
+// JSONSchemaDefinitions contains the models explicitly defined in this spec.
+type JSONSchemaDefinitions map[string]JSONSchemaProps
+
+// ExternalDocumentation allows referencing an external resource for extended documentation.
+type ExternalDocumentation struct {
+	Description string `json:"description,omitempty" protobuf:"bytes,1,opt,name=description"`
+	URL         string `json:"url,omitempty" protobuf:"bytes,2,opt,name=url"`
+}
diff --git a/pkg/apis/camel/v1alpha1/kamelet_types.go b/pkg/apis/camel/v1alpha1/kamelet_types.go
index 190a71d..0855489 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_types.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_types.go
@@ -1,53 +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 v1alpha1
 
 import (
 	camelv1 "github.com/apache/camel-k/pkg/apis/camel/v1"
-	openapi "github.com/go-openapi/spec"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
+const (
+	AnnotationIcon = "camel.apache.org/icon"
+)
+
 // KameletSpec defines the desired state of Kamelet
 type KameletSpec struct {
-	Info          KameletInfo         `json:"info,omitempty"`
-	Parameters    []KameletParameter  `json:"parameters,omitempty"`
-	Authorization AuthorizationSpec   `json:"authorization,omitempty"`
-	Sources       *camelv1.SourceSpec `json:"sources,omitempty"`
-	Flow          *camelv1.Flow       `json:"flow,omitempty"`
-	Consumes      *EventType          `json:"consumes,omitempty"`
-	Produces      *EventType          `json:"produces,omitempty"`
-	Dependencies  []string            `json:"dependencies,omitempty"`
-}
-
-type EventType struct {
-	Type   string      `json:"type,omitempty"`
-	Schema *DataSchema `json:"schema,omitempty"`
+	Definition    JSONSchemaProps             `json:"definition,omitempty"`
+	Sources       *camelv1.SourceSpec         `json:"sources,omitempty"`
+	Flow          *camelv1.Flow               `json:"flow,omitempty"`
+	Authorization AuthorizationSpec           `json:"authorization,omitempty"`
+	Types         map[EventSlot]EventTypeSpec `json:"types,omitempty"`
+	Dependencies  []string                    `json:"dependencies,omitempty"`
 }
 
-type DataSchema struct {
-	Ref     *corev1.ObjectReference `json:"ref,omitempty"`
-	Content *openapi.Schema         `json:"schema,omitempty"`
+type EventTypeSpec struct {
+	MediaType string           `json:"mediaType,omitempty"`
+	Schema    *JSONSchemaProps `json:"schema,omitempty"`
 }
 
-type KameletInfo struct {
-	DisplayName string      `json:"displayName,omitempty"`
-	Description string      `json:"description,omitempty"`
-	Group       string      `json:"group,omitempty"`
-	Icon        KameletIcon `json:"icon,omitempty"`
-}
-
-type KameletIcon struct {
-	Data      string `json:"data,omitempty"`
-	MediaType string `json:"mediaType,omitempty"`
-}
+type EventSlot string
 
-type KameletParameter struct {
-	Name        string            `json:"name,omitempty"`
-	Required    bool              `json:"required,omitempty"`
-	Description string            `json:"description,omitempty"`
-	Annotations map[string]string `json:"annotations,omitempty"`
-	Schema      *openapi.Schema   `json:"schema,omitempty"`
-}
+const (
+	EventSlotIn    EventSlot = "in"
+	EventSlotOut   EventSlot = "out"
+	EventSlotError EventSlot = "error"
+)
 
 // AuthorizationSpec is TODO (oauth information)
 type AuthorizationSpec struct {
diff --git a/pkg/apis/camel/v1alpha1/kamelet_types_support.go b/pkg/apis/camel/v1alpha1/kamelet_types_support.go
index eb18093..b4f25c1 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_types_support.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_types_support.go
@@ -1,3 +1,20 @@
+/*
+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 (
diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index 8c7d0d7..b81d3ca 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -5,16 +5,371 @@
 package v1alpha1
 
 import (
+	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	runtime "k8s.io/apimachinery/pkg/runtime"
 )
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *AuthorizationSpec) DeepCopyInto(out *AuthorizationSpec) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationSpec.
+func (in *AuthorizationSpec) DeepCopy() *AuthorizationSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(AuthorizationSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ExternalDocumentation) DeepCopyInto(out *ExternalDocumentation) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalDocumentation.
+func (in *ExternalDocumentation) DeepCopy() *ExternalDocumentation {
+	if in == nil {
+		return nil
+	}
+	out := new(ExternalDocumentation)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *JSON) DeepCopyInto(out *JSON) {
+	*out = *in
+	if in.Raw != nil {
+		in, out := &in.Raw, &out.Raw
+		*out = make([]byte, len(*in))
+		copy(*out, *in)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSON.
+func (in *JSON) DeepCopy() *JSON {
+	if in == nil {
+		return nil
+	}
+	out := new(JSON)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in JSONSchemaDefinitions) DeepCopyInto(out *JSONSchemaDefinitions) {
+	{
+		in := &in
+		*out = make(JSONSchemaDefinitions, len(*in))
+		for key, val := range *in {
+			(*out)[key] = *val.DeepCopy()
+		}
+		return
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaDefinitions.
+func (in JSONSchemaDefinitions) DeepCopy() JSONSchemaDefinitions {
+	if in == nil {
+		return nil
+	}
+	out := new(JSONSchemaDefinitions)
+	in.DeepCopyInto(out)
+	return *out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in JSONSchemaDependencies) DeepCopyInto(out *JSONSchemaDependencies) {
+	{
+		in := &in
+		*out = make(JSONSchemaDependencies, len(*in))
+		for key, val := range *in {
+			(*out)[key] = *val.DeepCopy()
+		}
+		return
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaDependencies.
+func (in JSONSchemaDependencies) DeepCopy() JSONSchemaDependencies {
+	if in == nil {
+		return nil
+	}
+	out := new(JSONSchemaDependencies)
+	in.DeepCopyInto(out)
+	return *out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *JSONSchemaProps) DeepCopyInto(out *JSONSchemaProps) {
+	*out = *in
+	if in.Ref != nil {
+		in, out := &in.Ref, &out.Ref
+		*out = new(string)
+		**out = **in
+	}
+	if in.Default != nil {
+		in, out := &in.Default, &out.Default
+		*out = new(JSON)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Maximum != nil {
+		in, out := &in.Maximum, &out.Maximum
+		*out = new(float64)
+		**out = **in
+	}
+	if in.Minimum != nil {
+		in, out := &in.Minimum, &out.Minimum
+		*out = new(float64)
+		**out = **in
+	}
+	if in.MaxLength != nil {
+		in, out := &in.MaxLength, &out.MaxLength
+		*out = new(int64)
+		**out = **in
+	}
+	if in.MinLength != nil {
+		in, out := &in.MinLength, &out.MinLength
+		*out = new(int64)
+		**out = **in
+	}
+	if in.MaxItems != nil {
+		in, out := &in.MaxItems, &out.MaxItems
+		*out = new(int64)
+		**out = **in
+	}
+	if in.MinItems != nil {
+		in, out := &in.MinItems, &out.MinItems
+		*out = new(int64)
+		**out = **in
+	}
+	if in.MultipleOf != nil {
+		in, out := &in.MultipleOf, &out.MultipleOf
+		*out = new(float64)
+		**out = **in
+	}
+	if in.Enum != nil {
+		in, out := &in.Enum, &out.Enum
+		*out = make([]JSON, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.MaxProperties != nil {
+		in, out := &in.MaxProperties, &out.MaxProperties
+		*out = new(int64)
+		**out = **in
+	}
+	if in.MinProperties != nil {
+		in, out := &in.MinProperties, &out.MinProperties
+		*out = new(int64)
+		**out = **in
+	}
+	if in.Required != nil {
+		in, out := &in.Required, &out.Required
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = new(JSONSchemaPropsOrArray)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.AllOf != nil {
+		in, out := &in.AllOf, &out.AllOf
+		*out = make([]JSONSchemaProps, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.OneOf != nil {
+		in, out := &in.OneOf, &out.OneOf
+		*out = make([]JSONSchemaProps, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.AnyOf != nil {
+		in, out := &in.AnyOf, &out.AnyOf
+		*out = make([]JSONSchemaProps, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.Not != nil {
+		in, out := &in.Not, &out.Not
+		*out = new(JSONSchemaProps)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Properties != nil {
+		in, out := &in.Properties, &out.Properties
+		*out = make(map[string]JSONSchemaProps, len(*in))
+		for key, val := range *in {
+			(*out)[key] = *val.DeepCopy()
+		}
+	}
+	if in.AdditionalProperties != nil {
+		in, out := &in.AdditionalProperties, &out.AdditionalProperties
+		*out = new(JSONSchemaPropsOrBool)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.PatternProperties != nil {
+		in, out := &in.PatternProperties, &out.PatternProperties
+		*out = make(map[string]JSONSchemaProps, len(*in))
+		for key, val := range *in {
+			(*out)[key] = *val.DeepCopy()
+		}
+	}
+	if in.Dependencies != nil {
+		in, out := &in.Dependencies, &out.Dependencies
+		*out = make(JSONSchemaDependencies, len(*in))
+		for key, val := range *in {
+			(*out)[key] = *val.DeepCopy()
+		}
+	}
+	if in.AdditionalItems != nil {
+		in, out := &in.AdditionalItems, &out.AdditionalItems
+		*out = new(JSONSchemaPropsOrBool)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Definitions != nil {
+		in, out := &in.Definitions, &out.Definitions
+		*out = make(JSONSchemaDefinitions, len(*in))
+		for key, val := range *in {
+			(*out)[key] = *val.DeepCopy()
+		}
+	}
+	if in.ExternalDocs != nil {
+		in, out := &in.ExternalDocs, &out.ExternalDocs
+		*out = new(ExternalDocumentation)
+		**out = **in
+	}
+	if in.Example != nil {
+		in, out := &in.Example, &out.Example
+		*out = new(JSON)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.XPreserveUnknownFields != nil {
+		in, out := &in.XPreserveUnknownFields, &out.XPreserveUnknownFields
+		*out = new(bool)
+		**out = **in
+	}
+	if in.XListMapKeys != nil {
+		in, out := &in.XListMapKeys, &out.XListMapKeys
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	if in.XListType != nil {
+		in, out := &in.XListType, &out.XListType
+		*out = new(string)
+		**out = **in
+	}
+	if in.XMapType != nil {
+		in, out := &in.XMapType, &out.XMapType
+		*out = new(string)
+		**out = **in
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaProps.
+func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps {
+	if in == nil {
+		return nil
+	}
+	out := new(JSONSchemaProps)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *JSONSchemaPropsOrArray) DeepCopyInto(out *JSONSchemaPropsOrArray) {
+	*out = *in
+	if in.Schema != nil {
+		in, out := &in.Schema, &out.Schema
+		*out = new(JSONSchemaProps)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.JSONSchemas != nil {
+		in, out := &in.JSONSchemas, &out.JSONSchemas
+		*out = make([]JSONSchemaProps, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaPropsOrArray.
+func (in *JSONSchemaPropsOrArray) DeepCopy() *JSONSchemaPropsOrArray {
+	if in == nil {
+		return nil
+	}
+	out := new(JSONSchemaPropsOrArray)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *JSONSchemaPropsOrBool) DeepCopyInto(out *JSONSchemaPropsOrBool) {
+	*out = *in
+	if in.Schema != nil {
+		in, out := &in.Schema, &out.Schema
+		*out = new(JSONSchemaProps)
+		(*in).DeepCopyInto(*out)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaPropsOrBool.
+func (in *JSONSchemaPropsOrBool) DeepCopy() *JSONSchemaPropsOrBool {
+	if in == nil {
+		return nil
+	}
+	out := new(JSONSchemaPropsOrBool)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *JSONSchemaPropsOrStringArray) DeepCopyInto(out *JSONSchemaPropsOrStringArray) {
+	*out = *in
+	if in.Schema != nil {
+		in, out := &in.Schema, &out.Schema
+		*out = new(JSONSchemaProps)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Property != nil {
+		in, out := &in.Property, &out.Property
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaPropsOrStringArray.
+func (in *JSONSchemaPropsOrStringArray) DeepCopy() *JSONSchemaPropsOrStringArray {
+	if in == nil {
+		return nil
+	}
+	out := new(JSONSchemaPropsOrStringArray)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Kamelet) DeepCopyInto(out *Kamelet) {
 	*out = *in
 	out.TypeMeta = in.TypeMeta
 	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
-	out.Spec = in.Spec
-	out.Status = in.Status
+	in.Spec.DeepCopyInto(&out.Spec)
+	in.Status.DeepCopyInto(&out.Status)
 	return
 }
 
@@ -37,6 +392,24 @@ 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 *KameletCondition) DeepCopyInto(out *KameletCondition) {
+	*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 KameletCondition.
+func (in *KameletCondition) DeepCopy() *KameletCondition {
+	if in == nil {
+		return nil
+	}
+	out := new(KameletCondition)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *KameletList) DeepCopyInto(out *KameletList) {
 	*out = *in
 	out.TypeMeta = in.TypeMeta
@@ -72,6 +445,29 @@ func (in *KameletList) DeepCopyObject() runtime.Object {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *KameletSpec) DeepCopyInto(out *KameletSpec) {
 	*out = *in
+	in.Definition.DeepCopyInto(&out.Definition)
+	if in.Sources != nil {
+		in, out := &in.Sources, &out.Sources
+		*out = new(v1.SourceSpec)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Flow != nil {
+		in, out := &in.Flow, &out.Flow
+		*out = (*in).DeepCopy()
+	}
+	out.Authorization = in.Authorization
+	if in.Types != nil {
+		in, out := &in.Types, &out.Types
+		*out = make(map[string]JSONSchemaProps, len(*in))
+		for key, val := range *in {
+			(*out)[key] = *val.DeepCopy()
+		}
+	}
+	if in.Dependencies != nil {
+		in, out := &in.Dependencies, &out.Dependencies
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
 	return
 }
 
@@ -88,6 +484,13 @@ func (in *KameletSpec) DeepCopy() *KameletSpec {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *KameletStatus) DeepCopyInto(out *KameletStatus) {
 	*out = *in
+	if in.Conditions != nil {
+		in, out := &in.Conditions, &out.Conditions
+		*out = make([]KameletCondition, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
 	return
 }
 
diff --git a/pkg/controller/add_kamelet.go b/pkg/controller/add_kamelet.go
new file mode 100644
index 0000000..7818bcd
--- /dev/null
+++ b/pkg/controller/add_kamelet.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/kamelet"
+)
+
+func init() {
+	// AddToManagerFuncs is a list of functions to create controllers and add them to a manager.
+	AddToManagerFuncs = append(AddToManagerFuncs, kamelet.Add)
+}


[camel-k] 20/21: Fix #1574: fix waiting for CRD installation

Posted by nf...@apache.org.
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 4316b0378dca4fb8d1c585c0dd47bc17739fffc6
Author: nicolaferraro <ni...@gmail.com>
AuthorDate: Wed Sep 16 12:39:09 2020 +0200

    Fix #1574: fix waiting for CRD installation
---
 pkg/install/cluster.go | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/pkg/install/cluster.go b/pkg/install/cluster.go
index 8fdc902..7758b70 100644
--- a/pkg/install/cluster.go
+++ b/pkg/install/cluster.go
@@ -80,6 +80,11 @@ func SetupClusterWideResourcesOrCollect(ctx context.Context, clientProvider clie
 		return err
 	}
 
+	// Wait for all CRDs to be installed before proceeding
+	if err := WaitForAllCRDInstallation(ctx, clientProvider, 25*time.Second); err != nil {
+		return err
+	}
+
 	// Installing ClusterRole
 	clusterRoleInstalled, err := IsClusterRoleInstalled(ctx, c)
 	if err != nil {
@@ -98,11 +103,6 @@ func SetupClusterWideResourcesOrCollect(ctx context.Context, clientProvider clie
 		return err
 	}
 
-	// Wait for all CRDs to be installed before proceeding
-	if err := WaitForAllCRDInstallation(ctx, clientProvider, 25*time.Second); err != nil {
-		return err
-	}
-
 	return nil
 }
 
@@ -156,7 +156,12 @@ func AreAllCRDInstalled(ctx context.Context, c client.Client) (bool, error) {
 	} else if !ok {
 		return false, nil
 	}
-	return IsCRDInstalled(ctx, c, "Kamelet", "v1alpha1")
+	if ok, err := IsCRDInstalled(ctx, c, "Kamelet", "v1alpha1"); err != nil {
+		return ok, err
+	} else if !ok {
+		return false, nil
+	}
+	return IsCRDInstalled(ctx, c, "KameletBinding", "v1alpha1")
 }
 
 // IsCRDInstalled check if the given CRD kind is installed


[camel-k] 17/21: fix #1676: allow using non-string values in properties

Posted by nf...@apache.org.
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 86ce1cdf897f7b654891cc8c12b390a9e2c58ccb
Author: nicolaferraro <ni...@gmail.com>
AuthorDate: Tue Sep 1 17:27:38 2020 +0200

    fix #1676: allow using non-string values in properties
---
 deploy/resources.go                              | 14 +++++++++---
 e2e/yaks/kamelets/timer-source.yaml              |  2 +-
 pkg/apis/camel/v1alpha1/kamelet_binding_types.go | 10 +++++++-
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go | 29 ++++++++++++++++++------
 pkg/controller/kameletbinding/initialize.go      | 16 ++++++++++++-
 5 files changed, 58 insertions(+), 13 deletions(-)

diff --git a/deploy/resources.go b/deploy/resources.go
index a07493e..2950584 100644
--- a/deploy/resources.go
+++ b/deploy/resources.go
@@ -144,8 +144,15 @@ 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 [...]
 		},
-		"/kamelets.camel.apache.org.crd.yaml": &vfsgen۰CompressedFileInfo{
-			name:             "kamelets.camel.apache.org.crd.yaml",
+		"/crd-kamelet-binding.yaml": &vfsgen۰CompressedFileInfo{
+			name:             "crd-kamelet-binding.yaml",
+			modTime:          time.Time{},
+			uncompressedSize: 1541,
+
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x54\xcd\x6e\xe3\x36\x10\xbe\xeb\x29\x3e\x58\x97\x5d\x20\x96\x9b\x9e\x0a\xf5\xe4\xf5\x26\xa8\x9b\x40\x0e\x22\x6f\x17\x7b\x1c\x4b\x63\x69\x60\x8a\x64\x49\xca\x8e\x51\xf4\xdd\x0b\x4a\x72\xe2\x74\xf7\xb8\xba\x89\xf3\xf7\xfd\x0c\x99\x62\xfe\xf3\xbe\x24\xc5\xa3\x54\xac\x3d\xd7\x08\x06\xa1\x65\x2c\x2d\x55\x2d\xa3\x34\xfb\x70\x22\xc7\xb8\x37\xbd\xae\x29\x88\xd1\xf8\xb0\x2c\xef\x3f\xa2\xd7\x35\x3b\x18\xcd\x30\x0e\x9d\x71\x [...]
+		},
+		"/crd-kamelet.yaml": &vfsgen۰CompressedFileInfo{
+			name:             "crd-kamelet.yaml",
 			modTime:          time.Time{},
 			uncompressedSize: 1498,
 
@@ -387,7 +394,8 @@ 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["/kamelets.camel.apache.org.crd.yaml"].(os.FileInfo),
+		fs["/crd-kamelet-binding.yaml"].(os.FileInfo),
+		fs["/crd-kamelet.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/timer-source.yaml b/e2e/yaks/kamelets/timer-source.yaml
index 35bfe52..0b48886 100644
--- a/e2e/yaks/kamelets/timer-source.yaml
+++ b/e2e/yaks/kamelets/timer-source.yaml
@@ -10,7 +10,7 @@ spec:
       name: timer
     properties:
       message: Hello Kamelets
-      period: "1000"
+      period: 1000
   sink:
     ref:
       kind: InMemoryChannel
diff --git a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
index 844f5f0..64702c2 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
@@ -18,6 +18,8 @@ limitations under the License.
 package v1alpha1
 
 import (
+	"encoding/json"
+
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -40,7 +42,13 @@ type Endpoint struct {
 	// 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"`
+	Properties EndpointProperties `json:"properties,omitempty"`
+}
+
+// EndpointProperties is a key/value struct represented as JSON raw to allow numeric/boolean values
+// +kubebuilder:validation:Type=object
+type EndpointProperties struct {
+	json.RawMessage `json:",inline"`
 }
 
 // KameletBindingStatus --
diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index 32596ba..fe54781 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -41,13 +41,7 @@ func (in *Endpoint) DeepCopyInto(out *Endpoint) {
 		*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
-		}
-	}
+	in.Properties.DeepCopyInto(&out.Properties)
 	return
 }
 
@@ -62,6 +56,27 @@ func (in *Endpoint) DeepCopy() *Endpoint {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *EndpointProperties) DeepCopyInto(out *EndpointProperties) {
+	*out = *in
+	if in.RawMessage != nil {
+		in, out := &in.RawMessage, &out.RawMessage
+		*out = make(json.RawMessage, len(*in))
+		copy(*out, *in)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointProperties.
+func (in *EndpointProperties) DeepCopy() *EndpointProperties {
+	if in == nil {
+		return nil
+	}
+	out := new(EndpointProperties)
+	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 {
diff --git a/pkg/controller/kameletbinding/initialize.go b/pkg/controller/kameletbinding/initialize.go
index dd43839..d047ae6 100644
--- a/pkg/controller/kameletbinding/initialize.go
+++ b/pkg/controller/kameletbinding/initialize.go
@@ -119,7 +119,21 @@ func getEndpointURI(e v1alpha1.Endpoint) (string, error) {
 	if err != nil {
 		return baseURI, err
 	}
-	return uri.AppendParameters(baseURI, e.Properties), nil
+
+	// 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) {


[camel-k] 15/21: Fix #1574: add e2e test for Kamelets

Posted by nf...@apache.org.
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 7e32e9445b297b8b9f6b23f73f2d4382dc261075
Author: nicolaferraro <ni...@gmail.com>
AuthorDate: Wed Aug 19 16:42:58 2020 +0200

    Fix #1574: add e2e test for Kamelets
---
 e2e/yaks/kamelets/kamelet.feature    |  5 +++++
 e2e/yaks/kamelets/timer.kamelet.yaml | 37 ++++++++++++++++++++++++++++++++++++
 e2e/yaks/kamelets/usage.groovy       | 21 ++++++++++++++++++++
 e2e/yaks/kamelets/yaks-config.yaml   | 28 +++++++++++++++++++++++++++
 4 files changed, 91 insertions(+)

diff --git a/e2e/yaks/kamelets/kamelet.feature b/e2e/yaks/kamelets/kamelet.feature
new file mode 100644
index 0000000..3f9e170
--- /dev/null
+++ b/e2e/yaks/kamelets/kamelet.feature
@@ -0,0 +1,5 @@
+Feature: Camel K can run Kamelets
+
+  Scenario: Running integration using a simple Kamelet
+    Given integration usage is running
+    Then integration usage should print Hello Kamelets
diff --git a/e2e/yaks/kamelets/timer.kamelet.yaml b/e2e/yaks/kamelets/timer.kamelet.yaml
new file mode 100644
index 0000000..554e15b
--- /dev/null
+++ b/e2e/yaks/kamelets/timer.kamelet.yaml
@@ -0,0 +1,37 @@
+apiVersion: camel.apache.org/v1alpha1
+kind: Kamelet
+metadata:
+  name: timer
+  annotations:
+    camel.apache.org/kamelet.icon: timer
+spec:
+  definition:
+    title: "Timer"
+    description: "Produces periodic events with a custom payload"
+    required:
+      - message
+    properties:
+      period:
+        title: Period
+        description: The time interval between two events
+        type: integer
+        default: 1000
+      message:
+        title: Message
+        description: The message to generate
+        type: string
+  types:
+    out:
+      mediaType: application/json
+      schema:
+        id: text.camel.apache.org
+        type: string
+  flow:
+    from:
+      uri: timer:tick
+      parameters:
+        period: "{{period}}"
+      steps:
+        - set-body:
+            constant: "{{message}}"
+        - to: "direct:{{routeId}}"
diff --git a/e2e/yaks/kamelets/usage.groovy b/e2e/yaks/kamelets/usage.groovy
new file mode 100755
index 0000000..d4c5de8
--- /dev/null
+++ b/e2e/yaks/kamelets/usage.groovy
@@ -0,0 +1,21 @@
+// camel-k: language=groovy dependency=mvn:org.apache.camel.k:camel-kamelet:1.5.1-SNAPSHOT
+
+/*
+ * 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.
+ */
+
+from('kamelet:timer?message=Hello+Kamelets&period=1000')
+    .log('${body}')
diff --git a/e2e/yaks/kamelets/yaks-config.yaml b/e2e/yaks/kamelets/yaks-config.yaml
new file mode 100644
index 0000000..1df07fc
--- /dev/null
+++ b/e2e/yaks/kamelets/yaks-config.yaml
@@ -0,0 +1,28 @@
+# ---------------------------------------------------------------------------
+# 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.
+# ---------------------------------------------------------------------------
+
+config:
+  namespace:
+    temporary: true
+pre:
+- name: installation
+  run: |
+    kamel install -n $YAKS_NAMESPACE
+
+    kubectl apply -f timer.kamelet.yaml -n $YAKS_NAMESPACE
+
+    kamel run usage.groovy -w -n $YAKS_NAMESPACE


[camel-k] 08/21: kamelets: support automatic configuration

Posted by nf...@apache.org.
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 69a6947eb28c8c24425f347df8006ef626acd43b
Author: Nicola Ferraro <ni...@gmail.com>
AuthorDate: Fri Jul 3 11:45:05 2020 +0200

    kamelets: support automatic configuration
---
 pkg/apis/camel/v1/integration_types_support.go |  16 +++
 pkg/trait/kamelets.go                          |  94 ++++++++++++++--
 pkg/trait/kamelets_test.go                     | 150 ++++++++++++++++++++++++-
 pkg/util/test/client.go                        |  19 +++-
 4 files changed, 264 insertions(+), 15 deletions(-)

diff --git a/pkg/apis/camel/v1/integration_types_support.go b/pkg/apis/camel/v1/integration_types_support.go
index dd848f0..2e807d3 100644
--- a/pkg/apis/camel/v1/integration_types_support.go
+++ b/pkg/apis/camel/v1/integration_types_support.go
@@ -156,6 +156,22 @@ func (in *IntegrationStatus) AddOrReplaceGeneratedSources(sources ...SourceSpec)
 	in.GeneratedSources = append(in.GeneratedSources, newSources...)
 }
 
+// AddConfigurationsIfMissing --
+func (in *IntegrationStatus) AddConfigurationsIfMissing(configurations ...ConfigurationSpec) {
+	for _, config := range configurations {
+		alreadyPresent := false
+		for _, r := range in.Configuration {
+			if r.Type == config.Type && r.Value == config.Value {
+				alreadyPresent = true
+				break
+			}
+		}
+		if !alreadyPresent {
+			in.Configuration = append(in.Configuration, config)
+		}
+	}
+}
+
 // Configurations --
 func (in *IntegrationSpec) Configurations() []ConfigurationSpec {
 	if in == nil {
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index 55b61a2..2a98a3a 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -45,8 +45,25 @@ type kameletsTrait struct {
 	List string `property:"list"`
 }
 
+type configurationKey struct {
+	kamelet         string
+	configurationID string
+}
+
+func newConfigurationKey(kamelet, configurationID string) configurationKey {
+	return configurationKey{
+		kamelet:         kamelet,
+		configurationID: configurationID,
+	}
+}
+
+const (
+	kameletLabel              = "camel.apache.org/kamelet"
+	kameletConfigurationLabel = "camel.apache.org/kamelet.configuration"
+)
+
 var (
-	kameletNameRegexp = regexp.MustCompile("kamelet:(?://)?([a-z0-9-.]+)(?:$|[^a-z0-9-.].*)")
+	kameletNameRegexp = regexp.MustCompile("kamelet:(?://)?([a-z0-9-.]+(/[a-z0-9-.]+)?)(?:$|[^a-z0-9-.].*)")
 )
 
 func newKameletsTrait() Trait {
@@ -79,19 +96,21 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 
 	}
 
-	return len(t.getKamelets()) > 0, nil
+	return len(t.getKameletKeys()) > 0, nil
 }
 
 func (t *kameletsTrait) Apply(e *Environment) error {
 	if err := t.addKamelets(e); err != nil {
 		return err
 	}
-
+	if err := t.addConfigurationSecrets(e); err != nil {
+		return err
+	}
 	return nil
 }
 
 func (t *kameletsTrait) addKamelets(e *Environment) error {
-	for _, k := range t.getKamelets() {
+	for _, k := range t.getKameletKeys() {
 		var kamelet v1alpha1.Kamelet
 		key := client.ObjectKey{
 			Namespace: e.Integration.Namespace,
@@ -168,14 +187,75 @@ func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet v1alpha1.Kame
 	return nil
 }
 
-func (t *kameletsTrait) getKamelets() []string {
+func (t *kameletsTrait) addConfigurationSecrets(e *Environment) error {
+	for _, k := range t.getConfigurationKeys() {
+		var options = metav1.ListOptions{
+			LabelSelector: fmt.Sprintf("%s=%s", kameletLabel, k.kamelet),
+		}
+		if k.configurationID != "" {
+			options.LabelSelector = fmt.Sprintf("%s=%s,%s=%s", kameletLabel, k.kamelet, kameletConfigurationLabel, k.configurationID)
+		}
+		secrets, err := t.Client.CoreV1().Secrets(e.Integration.Namespace).List(options)
+		if err != nil {
+			return err
+		}
+
+		for _, item := range secrets.Items {
+			if item.Labels != nil && item.Labels[kameletConfigurationLabel] != k.configurationID {
+				continue
+			}
+
+			e.Integration.Status.AddConfigurationsIfMissing(v1.ConfigurationSpec{
+				Type:  "secret",
+				Value: item.Name,
+			})
+		}
+	}
+	return nil
+}
+
+func (t *kameletsTrait) getKameletKeys() []string {
 	answer := make([]string, 0)
 	for _, item := range strings.Split(t.List, ",") {
 		i := strings.Trim(item, " \t\"")
+		if strings.Contains(i, "/") {
+			i = strings.SplitN(i, "/", 2)[0]
+		}
 		if i != "" {
-			answer = append(answer, i)
+			util.StringSliceUniqueAdd(&answer, i)
+		}
+	}
+	sort.Strings(answer)
+	return answer
+}
+
+func (t *kameletsTrait) getConfigurationKeys() []configurationKey {
+	answer := make([]configurationKey, 0)
+	for _, item := range t.getKameletKeys() {
+		answer = append(answer, newConfigurationKey(item, ""))
+	}
+	for _, item := range strings.Split(t.List, ",") {
+		i := strings.Trim(item, " \t\"")
+		if strings.Contains(i, "/") {
+			parts := strings.SplitN(i, "/", 2)
+			newKey := newConfigurationKey(parts[0], parts[1])
+			alreadyPresent := false
+			for _, existing := range answer {
+				if existing == newKey {
+					alreadyPresent = true
+					break
+				}
+			}
+			if !alreadyPresent {
+				answer = append(answer, newKey)
+			}
 		}
 	}
+	sort.Slice(answer, func(i, j int) bool {
+		o1 := answer[i]
+		o2 := answer[j]
+		return o1.kamelet < o2.kamelet || (o1.kamelet == o2.kamelet && o1.configurationID < o2.configurationID)
+	})
 	return answer
 }
 
@@ -236,7 +316,7 @@ func integrationSourceFromKameletSource(e *Environment, kamelet v1alpha1.Kamelet
 func extractKamelets(uris []string) (kamelets []string) {
 	for _, uri := range uris {
 		matches := kameletNameRegexp.FindStringSubmatch(uri)
-		if len(matches) == 2 {
+		if len(matches) > 1 {
 			kamelets = append(kamelets, matches[1])
 		}
 	}
diff --git a/pkg/trait/kamelets_test.go b/pkg/trait/kamelets_test.go
index 500baba..4916046 100644
--- a/pkg/trait/kamelets_test.go
+++ b/pkg/trait/kamelets_test.go
@@ -64,7 +64,17 @@ func TestConfigurationWithKamelets(t *testing.T) {
 	enabled, err := trait.Configure(environment)
 	assert.NoError(t, err)
 	assert.True(t, enabled)
-	assert.Equal(t, []string{"c0", "c1", "c2", "complex-.-.-1a", "complex-.-.-1b", "complex-.-.-1c"}, trait.getKamelets())
+	assert.Equal(t, []string{"c0", "c1", "c2", "complex-.-.-1a", "complex-.-.-1b", "complex-.-.-1c"}, trait.getKameletKeys())
+	assert.Equal(t, []configurationKey{
+		newConfigurationKey("c0", ""),
+		newConfigurationKey("c1", ""),
+		newConfigurationKey("c2", ""),
+		newConfigurationKey("complex-.-.-1a", ""),
+		newConfigurationKey("complex-.-.-1b", ""),
+		newConfigurationKey("complex-.-.-1b", "a"),
+		newConfigurationKey("complex-.-.-1c", ""),
+		newConfigurationKey("complex-.-.-1c", "b"),
+	}, trait.getConfigurationKeys())
 }
 
 func TestKameletLookup(t *testing.T) {
@@ -93,7 +103,7 @@ func TestKameletLookup(t *testing.T) {
 	enabled, err := trait.Configure(environment)
 	assert.NoError(t, err)
 	assert.True(t, enabled)
-	assert.Equal(t, []string{"timer"}, trait.getKamelets())
+	assert.Equal(t, []string{"timer"}, trait.getKameletKeys())
 
 	err = trait.Apply(environment)
 	assert.NoError(t, err)
@@ -141,7 +151,7 @@ func TestKameletSecondarySourcesLookup(t *testing.T) {
 	enabled, err := trait.Configure(environment)
 	assert.NoError(t, err)
 	assert.True(t, enabled)
-	assert.Equal(t, []string{"timer"}, trait.getKamelets())
+	assert.Equal(t, []string{"timer"}, trait.getKameletKeys())
 
 	err = trait.Apply(environment)
 	assert.NoError(t, err)
@@ -191,7 +201,7 @@ func TestNonYAMLKameletLookup(t *testing.T) {
 	enabled, err := trait.Configure(environment)
 	assert.NoError(t, err)
 	assert.True(t, enabled)
-	assert.Equal(t, []string{"timer"}, trait.getKamelets())
+	assert.Equal(t, []string{"timer"}, trait.getKameletKeys())
 
 	err = trait.Apply(environment)
 	assert.NoError(t, err)
@@ -237,7 +247,7 @@ func TestErrorMultipleKameletSources(t *testing.T) {
 	enabled, err := trait.Configure(environment)
 	assert.NoError(t, err)
 	assert.True(t, enabled)
-	assert.Equal(t, []string{"timer"}, trait.getKamelets())
+	assert.Equal(t, []string{"timer"}, trait.getKameletKeys())
 
 	err = trait.Apply(environment)
 	assert.Error(t, err)
@@ -302,7 +312,7 @@ func TestMultipleKamelets(t *testing.T) {
 	enabled, err := trait.Configure(environment)
 	assert.NoError(t, err)
 	assert.True(t, enabled)
-	assert.Equal(t, []string{"logger", "timer"}, trait.getKamelets())
+	assert.Equal(t, []string{"logger", "timer"}, trait.getKameletKeys())
 
 	err = trait.Apply(environment)
 	assert.NoError(t, err)
@@ -337,6 +347,134 @@ func TestMultipleKamelets(t *testing.T) {
 	assert.Equal(t, []string{"camel:log", "camel:tbd", "camel:timer", "camel:xxx"}, environment.Integration.Status.Dependencies)
 }
 
+func TestKameletConfigLookup(t *testing.T) {
+	trait, environment := createKameletsTestEnvironment(`
+- from:
+    uri: kamelet:timer
+    steps:
+    - to: log:info
+`, &v1alpha1.Kamelet{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "test",
+			Name:      "timer",
+		},
+		Spec: v1alpha1.KameletSpec{
+			Flow: &v1.Flow{
+				"from": map[string]interface{}{
+					"uri": "timer:tick",
+				},
+			},
+			Dependencies: []string{
+				"camel:timer",
+				"camel:log",
+			},
+		},
+	}, &corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "test",
+			Name:      "my-secret",
+			Labels: map[string]string{
+				"camel.apache.org/kamelet": "timer",
+			},
+		},
+	}, &corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "test",
+			Name:      "my-secret2",
+			Labels: map[string]string{
+				"camel.apache.org/kamelet":               "timer",
+				"camel.apache.org/kamelet.configuration": "id2",
+			},
+		},
+	}, &corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "test",
+			Name:      "my-secret3",
+			Labels: map[string]string{
+				"camel.apache.org/kamelet": "timer",
+			},
+		},
+	})
+	enabled, err := trait.Configure(environment)
+	assert.NoError(t, err)
+	assert.True(t, enabled)
+	assert.Equal(t, []string{"timer"}, trait.getKameletKeys())
+	assert.Equal(t, []configurationKey{newConfigurationKey("timer", "")}, trait.getConfigurationKeys())
+
+	err = trait.Apply(environment)
+	assert.NoError(t, err)
+	assert.Len(t, environment.Integration.Status.Configuration, 2)
+	assert.Contains(t, environment.Integration.Status.Configuration, v1.ConfigurationSpec{Type: "secret", Value: "my-secret"})
+	assert.NotContains(t, environment.Integration.Status.Configuration, v1.ConfigurationSpec{Type: "secret", Value: "my-secret2"})
+	assert.Contains(t, environment.Integration.Status.Configuration, v1.ConfigurationSpec{Type: "secret", Value: "my-secret3"})
+}
+
+func TestKameletNamedConfigLookup(t *testing.T) {
+	trait, environment := createKameletsTestEnvironment(`
+- from:
+    uri: kamelet:timer/id2
+    steps:
+    - to: log:info
+`, &v1alpha1.Kamelet{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "test",
+			Name:      "timer",
+		},
+		Spec: v1alpha1.KameletSpec{
+			Flow: &v1.Flow{
+				"from": map[string]interface{}{
+					"uri": "timer:tick",
+				},
+			},
+			Dependencies: []string{
+				"camel:timer",
+				"camel:log",
+			},
+		},
+	}, &corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "test",
+			Name:      "my-secret",
+			Labels: map[string]string{
+				"camel.apache.org/kamelet": "timer",
+			},
+		},
+	}, &corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "test",
+			Name:      "my-secret2",
+			Labels: map[string]string{
+				"camel.apache.org/kamelet":               "timer",
+				"camel.apache.org/kamelet.configuration": "id2",
+			},
+		},
+	}, &corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "test",
+			Name:      "my-secret3",
+			Labels: map[string]string{
+				"camel.apache.org/kamelet":               "timer",
+				"camel.apache.org/kamelet.configuration": "id3",
+			},
+		},
+	})
+	enabled, err := trait.Configure(environment)
+	assert.NoError(t, err)
+	assert.True(t, enabled)
+	assert.Equal(t, []string{"timer"}, trait.getKameletKeys())
+	assert.Equal(t, []configurationKey{
+		newConfigurationKey("timer", ""),
+		newConfigurationKey("timer", "id2"),
+	}, trait.getConfigurationKeys())
+
+	err = trait.Apply(environment)
+	assert.NoError(t, err)
+	assert.Len(t, environment.Integration.Status.Configuration, 2)
+	assert.Contains(t, environment.Integration.Status.Configuration, v1.ConfigurationSpec{Type: "secret", Value: "my-secret"})
+	assert.Contains(t, environment.Integration.Status.Configuration, v1.ConfigurationSpec{Type: "secret", Value: "my-secret2"})
+	assert.NotContains(t, environment.Integration.Status.Configuration, v1.ConfigurationSpec{Type: "secret", Value: "my-secret3"})
+}
+
 func createKameletsTestEnvironment(flow string, objects ...runtime.Object) (*kameletsTrait, *Environment) {
 	catalog, _ := camel.DefaultCatalog()
 
diff --git a/pkg/util/test/client.go b/pkg/util/test/client.go
index d3df07b..b223f95 100644
--- a/pkg/util/test/client.go
+++ b/pkg/util/test/client.go
@@ -20,9 +20,9 @@ package test
 import (
 	"github.com/apache/camel-k/pkg/apis"
 	"github.com/apache/camel-k/pkg/client"
-
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/client-go/kubernetes"
+	fakeclientset "k8s.io/client-go/kubernetes/fake"
 	clientscheme "k8s.io/client-go/kubernetes/scheme"
 	"k8s.io/client-go/rest"
 
@@ -40,10 +40,25 @@ func NewFakeClient(initObjs ...runtime.Object) (client.Client, error) {
 	}
 
 	c := fake.NewFakeClientWithScheme(scheme, initObjs...)
+	filtered := make([]runtime.Object, 0, len(initObjs))
+	for _, o := range initObjs {
+		kinds, _, _ := scheme.ObjectKinds(o)
+		allow := true
+		for _, k := range kinds {
+			if k.Group == "camel.apache.org" {
+				allow = false
+				break
+			}
+		}
+		if allow {
+			filtered = append(filtered, o)
+		}
+	}
+	clientset := fakeclientset.NewSimpleClientset(filtered...)
 
 	return &FakeClient{
 		Client:    c,
-		Interface: nil,
+		Interface: clientset,
 	}, nil
 }
 


[camel-k] 14/21: Fix #1574: fix examples

Posted by nf...@apache.org.
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 5656cba7f17ca1838639e9390a0636706fb162f7
Author: nicolaferraro <ni...@gmail.com>
AuthorDate: Wed Aug 19 16:39:51 2020 +0200

    Fix #1574: fix examples
---
 deploy/camel-catalog-1.5.1-SNAPSHOT-main.yaml    | 82 ++++++++++++++++++++++--
 deploy/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml | 26 ++++++--
 deploy/resources.go                              |  8 +--
 examples/kamelets/fake-usage.groovy              | 21 ------
 examples/kamelets/timer.kamelet.yaml             | 11 +++-
 examples/kamelets/usage.groovy                   |  7 +-
 6 files changed, 115 insertions(+), 40 deletions(-)

diff --git a/deploy/camel-catalog-1.5.1-SNAPSHOT-main.yaml b/deploy/camel-catalog-1.5.1-SNAPSHOT-main.yaml
index 966d5e7..405b36f 100644
--- a/deploy/camel-catalog-1.5.1-SNAPSHOT-main.yaml
+++ b/deploy/camel-catalog-1.5.1-SNAPSHOT-main.yaml
@@ -21,8 +21,8 @@ metadata:
   name: camel-catalog-1.5.1-snapshot-main
   labels:
     app: camel-k
-    camel.apache.org/catalog.version: 3.4.0
-    camel.apache.org/catalog.loader.version: 3.4.0
+    camel.apache.org/catalog.version: 3.5.0-SNAPSHOT
+    camel.apache.org/catalog.loader.version: 3.5.0-SNAPSHOT
     camel.apache.org/runtime.version: 1.5.1-SNAPSHOT
     camel.apache.org/runtime.provider: main
 spec:
@@ -31,9 +31,9 @@ spec:
     provider: main
     applicationClass: org.apache.camel.k.main.Application
     metadata:
-      camel.version: 3.4.0
-      quarkus.version: 1.6.0.Final
-      camel-quarkus.version: 1.0.0-CR3
+      camel.version: 3.5.0-SNAPSHOT
+      quarkus.version: 1.7.0.Final
+      camel-quarkus.version: 1.0.0
     dependencies:
     - groupId: org.apache.camel.k
       artifactId: camel-k-runtime-main
@@ -94,6 +94,15 @@ spec:
       javaTypes:
       - org.apache.camel.component.azure.blob.BlobServiceComponent
       - org.apache.camel.component.azure.queue.QueueServiceComponent
+    camel-vertx-websocket:
+      groupId: org.apache.camel
+      artifactId: camel-vertx-websocket
+      schemes:
+      - id: vertx-websocket
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.vertx.websocket.VertxWebsocketComponent
     camel-seda:
       groupId: org.apache.camel
       artifactId: camel-seda
@@ -193,6 +202,15 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.sjms2.Sjms2Component
+    camel-vertx-http:
+      groupId: org.apache.camel
+      artifactId: camel-vertx-http
+      schemes:
+      - id: vertx-http
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.vertx.http.VertxHttpComponent
     camel-facebook:
       groupId: org.apache.camel
       artifactId: camel-facebook
@@ -299,6 +317,15 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.aws2.iam.IAM2Component
+    camel-jsonata:
+      groupId: org.apache.camel
+      artifactId: camel-jsonata
+      schemes:
+      - id: jsonata
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.jsonata.JsonataComponent
     camel-aws-eks:
       groupId: org.apache.camel
       artifactId: camel-aws-eks
@@ -595,6 +622,15 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.weka.WekaComponent
+    camel-azure-eventhubs:
+      groupId: org.apache.camel
+      artifactId: camel-azure-eventhubs
+      schemes:
+      - id: azure-eventhubs
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.azure.eventhubs.EventHubsComponent
     camel-jacksonxml:
       groupId: org.apache.camel
       artifactId: camel-jacksonxml
@@ -780,6 +816,15 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.salesforce.SalesforceComponent
+    camel-minio:
+      groupId: org.apache.camel
+      artifactId: camel-minio
+      schemes:
+      - id: minio
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.minio.MinioComponent
     camel-xj:
       groupId: org.apache.camel
       artifactId: camel-xj
@@ -1288,6 +1333,15 @@ spec:
         passive: false
       javaTypes:
       - org.apache.camel.component.guava.eventbus.GuavaEventBusComponent
+    camel-aws2-sts:
+      groupId: org.apache.camel
+      artifactId: camel-aws2-sts
+      schemes:
+      - id: aws2-sts
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.aws2.sts.STS2Component
     camel-msv:
       groupId: org.apache.camel
       artifactId: camel-msv
@@ -2200,6 +2254,15 @@ spec:
       - groovy
       javaTypes:
       - org.apache.camel.language.groovy.GroovyLanguage
+    camel-arangodb:
+      groupId: org.apache.camel
+      artifactId: camel-arangodb
+      schemes:
+      - id: arangodb
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.arangodb.ArangoDbComponent
     camel-saga:
       groupId: org.apache.camel
       artifactId: camel-saga
@@ -2794,6 +2857,15 @@ spec:
       - grok
       javaTypes:
       - org.apache.camel.component.grok.GrokDataFormat
+    camel-oaipmh:
+      groupId: org.apache.camel
+      artifactId: camel-oaipmh
+      schemes:
+      - id: oaipmh
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.oaipmh.component.OAIPMHComponent
     camel-mvel:
       groupId: org.apache.camel
       artifactId: camel-mvel
diff --git a/deploy/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml b/deploy/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml
index 7e18efe..db61e37 100644
--- a/deploy/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml
+++ b/deploy/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml
@@ -21,8 +21,8 @@ metadata:
   name: camel-catalog-1.5.1-snapshot-quarkus
   labels:
     app: camel-k
-    camel.apache.org/catalog.version: 3.4.0
-    camel.apache.org/catalog.loader.version: 3.4.0
+    camel.apache.org/catalog.version: 3.5.0-SNAPSHOT
+    camel.apache.org/catalog.loader.version: 3.5.0-SNAPSHOT
     camel.apache.org/runtime.version: 1.5.1-SNAPSHOT
     camel.apache.org/runtime.provider: quarkus
 spec:
@@ -31,9 +31,9 @@ spec:
     provider: quarkus
     applicationClass: io.quarkus.runner.GeneratedMain
     metadata:
-      camel.version: 3.4.0
-      quarkus.version: 1.6.0.Final
-      camel-quarkus.version: 1.0.0-CR3
+      camel.version: 3.5.0-SNAPSHOT
+      quarkus.version: 1.7.0.Final
+      camel-quarkus.version: 1.0.0
     dependencies:
     - groupId: org.apache.camel.k
       artifactId: camel-k-runtime-quarkus
@@ -1045,6 +1045,13 @@ spec:
       - zipfile
       javaTypes:
       - org.apache.camel.dataformat.zipfile.ZipFileDataFormat
+    camel-quarkus-grok:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-grok
+      dataformats:
+      - grok
+      javaTypes:
+      - org.apache.camel.component.grok.GrokDataFormat
     camel-quarkus-servlet:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-servlet
@@ -1128,6 +1135,15 @@ spec:
       - org.apache.camel.component.openstack.neutron.NeutronComponent
       - org.apache.camel.component.openstack.nova.NovaComponent
       - org.apache.camel.component.openstack.swift.SwiftComponent
+    camel-quarkus-jpa:
+      groupId: org.apache.camel.quarkus
+      artifactId: camel-quarkus-jpa
+      schemes:
+      - id: jpa
+        http: false
+        passive: false
+      javaTypes:
+      - org.apache.camel.component.jpa.JpaComponent
     camel-quarkus-consul:
       groupId: org.apache.camel.quarkus
       artifactId: camel-quarkus-consul
diff --git a/deploy/resources.go b/deploy/resources.go
index 673756d..1a944c4 100644
--- a/deploy/resources.go
+++ b/deploy/resources.go
@@ -91,16 +91,16 @@ var assets = func() http.FileSystem {
 		"/camel-catalog-1.5.1-SNAPSHOT-main.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "camel-catalog-1.5.1-SNAPSHOT-main.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 89178,
+			uncompressedSize: 91183,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x7d\x5b\x77\xdb\x38\xb2\xee\x7b\x7e\x05\xd7\xe4\x65\xef\x75\x86\x35\xdd\xce\xcc\xf4\xd9\x7d\x9e\x6c\x39\x4e\xec\xd8\x8e\x3b\xf2\x24\x99\x79\xe9\x05\x91\x90\x04\x8b\x24\x68\x00\x92\x65\xff\xfa\xb3\x70\xe1\x55\x10\x24\x12\x86\xd7\xf6\x83\x49\x11\x55\x5f\xb1\x08\x12\x97\x42\xa1\xea\x7d\x14\xbf\xde\xdf\xbb\xf7\xd1\x35\x49\x70\xc1\x71\x1a\x09\x1a\x89\x25\x8e\x4e\x4b\x94\x2c\x71\x34\xa5\x73\xf1\x84\x18\x8e\x2e\xe8\xba\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x7d\x5b\x77\xdb\x38\xb2\xee\x7b\x7e\x05\xd7\xe4\x65\xef\x75\x46\x35\xdd\xce\xcc\xf4\xd9\x7d\x9e\x6c\x39\x4e\xec\xd8\x8e\x3b\xf4\x24\x99\x79\xe9\x05\x91\x90\x04\x8b\x24\x68\x00\x92\x65\xff\xfa\xb3\x70\xe1\x55\x10\x24\x12\x86\xd7\xf6\x83\x49\x11\x55\x5f\xb1\x08\x12\x97\x42\xa1\xea\x7d\x34\x79\xbd\xbf\x77\xef\xa3\x6b\x92\xe0\x82\xe3\x34\x12\x34\x12\x4b\x1c\x9d\x96\x28\x59\xe2\x28\xa6\x73\xf1\x84\x18\x8e\x2e\xe8\xba\x [...]
 		},
 		"/camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "camel-catalog-1.5.1-SNAPSHOT-quarkus.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 49034,
+			uncompressedSize: 49504,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x7d\x5d\x77\xdb\xaa\xf2\xf7\x7d\x3e\x85\x56\x73\x73\xce\x5a\x5b\xec\x7d\xd2\xb3\xf7\x45\x9f\xab\x24\x6d\xda\xa4\x4d\x9a\xc6\x39\x6d\xf7\xbe\xe9\xc2\x12\xb6\x89\x25\x50\x00\xd9\x4e\x3e\xfd\xb3\x40\xc8\x92\x6c\x65\xf4\x12\xf0\x3f\x17\x91\x2c\x86\xdf\xc0\x80\x60\x34\xcc\xc0\x71\x10\xba\xfb\x3b\x3a\x0e\xbe\xd0\x88\x30\x49\xe2\x40\xf1\x40\x2d\x48\x70\x9a\xe1\x68\x41\x82\x09\x9f\xa9\x35\x16\x24\xb8\xe0\x39\x8b\xb1\xa2\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x7d\x5d\x77\xdb\xaa\xd2\xff\x7d\x3e\x85\x56\x73\x73\xce\x5a\x5b\xec\x7d\xd2\xff\xde\xff\xb5\xfa\x5c\x25\x69\xd3\x26\x6d\x5e\x5a\xe7\xb4\xdd\xfb\xa6\x0b\x4b\xd8\x26\x96\x40\x01\x64\x3b\xf9\xf4\xcf\x02\x21\x4b\xb2\x95\xd1\x4b\xc0\x4f\x2e\x22\x59\x0c\xbf\x81\x01\xc1\x68\x98\x81\xe3\x20\x74\xf7\x77\x74\x1c\x7c\xa1\x11\x61\x92\xc4\x81\xe2\x81\x5a\x90\xe0\x34\xc3\xd1\x82\x04\x13\x3e\x53\x6b\x2c\x48\x70\xc1\x73\x16\x63\x [...]
 		},
 		"/cr-example.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "cr-example.yaml",
diff --git a/examples/kamelets/fake-usage.groovy b/examples/kamelets/fake-usage.groovy
deleted file mode 100755
index bff523b..0000000
--- a/examples/kamelets/fake-usage.groovy
+++ /dev/null
@@ -1,21 +0,0 @@
-// camel-k: language=groovy trait=kamelets.list=timer
-/*
- * 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.
- */
-
-// The integration should contain the kamelet as source
-
-// Until the kamelet component is added in runtime
\ No newline at end of file
diff --git a/examples/kamelets/timer.kamelet.yaml b/examples/kamelets/timer.kamelet.yaml
index 0dd7f92..554e15b 100644
--- a/examples/kamelets/timer.kamelet.yaml
+++ b/examples/kamelets/timer.kamelet.yaml
@@ -11,6 +11,11 @@ spec:
     required:
       - message
     properties:
+      period:
+        title: Period
+        description: The time interval between two events
+        type: integer
+        default: 1000
       message:
         title: Message
         description: The message to generate
@@ -24,7 +29,9 @@ spec:
   flow:
     from:
       uri: timer:tick
+      parameters:
+        period: "{{period}}"
       steps:
         - set-body:
-            constant: "Hello [here there'll be the message] !!!"
-        - to: "log:info"
+            constant: "{{message}}"
+        - to: "direct:{{routeId}}"
diff --git a/examples/kamelets/usage.groovy b/examples/kamelets/usage.groovy
index 15090c9..d4c5de8 100755
--- a/examples/kamelets/usage.groovy
+++ b/examples/kamelets/usage.groovy
@@ -1,4 +1,5 @@
-// camel-k: language=groovy
+// camel-k: language=groovy dependency=mvn:org.apache.camel.k:camel-kamelet:1.5.1-SNAPSHOT
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -16,5 +17,5 @@
  * limitations under the License.
  */
 
-from('kamelet:timer')
-    .to('log:info')
+from('kamelet:timer?message=Hello+Kamelets&period=1000')
+    .log('${body}')


[camel-k] 11/21: kamelet: fix tests and lint

Posted by nf...@apache.org.
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 b9c2cbe0d20e507e87ab0df2df4ae72e009309ab
Author: Nicola Ferraro <ni...@gmail.com>
AuthorDate: Fri Jul 10 13:12:31 2020 +0200

    kamelet: fix tests and lint
---
 pkg/controller/kamelet/initialize.go         |  1 +
 pkg/controller/kamelet/kamelet_controller.go |  6 ++----
 pkg/event/manager.go                         |  2 +-
 pkg/trait/dependencies.go                    |  8 +++-----
 pkg/trait/kamelets.go                        | 15 +++++++++------
 pkg/trait/kamelets_test.go                   | 10 +++++++++-
 pkg/trait/knative_service_test.go            | 16 +++++++++-------
 pkg/trait/service_test.go                    | 24 ++++++++++++++++--------
 pkg/trait/trait_types.go                     |  2 +-
 pkg/util/kubernetes/resolver.go              |  3 ++-
 pkg/util/log/log.go                          |  2 +-
 11 files changed, 54 insertions(+), 35 deletions(-)

diff --git a/pkg/controller/kamelet/initialize.go b/pkg/controller/kamelet/initialize.go
index e1f4360..0b3f0aa 100644
--- a/pkg/controller/kamelet/initialize.go
+++ b/pkg/controller/kamelet/initialize.go
@@ -19,6 +19,7 @@ package kamelet
 
 import (
 	"context"
+
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 )
 
diff --git a/pkg/controller/kamelet/kamelet_controller.go b/pkg/controller/kamelet/kamelet_controller.go
index baad186..0522a59 100644
--- a/pkg/controller/kamelet/kamelet_controller.go
+++ b/pkg/controller/kamelet/kamelet_controller.go
@@ -19,14 +19,14 @@ package kamelet
 
 import (
 	"context"
-	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	"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"
@@ -35,8 +35,6 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/predicate"
 	"sigs.k8s.io/controller-runtime/pkg/reconcile"
 	"sigs.k8s.io/controller-runtime/pkg/source"
-
-	"github.com/apache/camel-k/pkg/client"
 )
 
 // Add creates a new Kamelet Controller and adds it to the Manager. The Manager will set fields on the Controller
diff --git a/pkg/event/manager.go b/pkg/event/manager.go
index 93e27f9..a2b2eb8 100644
--- a/pkg/event/manager.go
+++ b/pkg/event/manager.go
@@ -20,9 +20,9 @@ package event
 import (
 	"context"
 	"fmt"
-	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 
 	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/apache/camel-k/pkg/util/kubernetes"
 	"github.com/apache/camel-k/pkg/util/log"
diff --git a/pkg/trait/dependencies.go b/pkg/trait/dependencies.go
index 4a704b6..5fc0264 100644
--- a/pkg/trait/dependencies.go
+++ b/pkg/trait/dependencies.go
@@ -19,14 +19,12 @@ package trait
 
 import (
 	"fmt"
-	"github.com/apache/camel-k/pkg/util/kubernetes"
-
-	"github.com/apache/camel-k/pkg/metadata"
-
-	"github.com/scylladb/go-set/strset"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+	"github.com/apache/camel-k/pkg/metadata"
 	"github.com/apache/camel-k/pkg/util"
+	"github.com/apache/camel-k/pkg/util/kubernetes"
+	"github.com/scylladb/go-set/strset"
 )
 
 // The Dependencies trait is internally used to automatically add runtime dependencies based on the
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index 994ddcb..d1b3bef 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -20,8 +20,6 @@ package trait
 import (
 	"encoding/json"
 	"fmt"
-	"github.com/apache/camel-k/pkg/util/flow"
-	"github.com/apache/camel-k/pkg/util/kubernetes"
 	"regexp"
 	"sort"
 	"strconv"
@@ -32,6 +30,8 @@ import (
 	"github.com/apache/camel-k/pkg/metadata"
 	"github.com/apache/camel-k/pkg/util"
 	"github.com/apache/camel-k/pkg/util/digest"
+	"github.com/apache/camel-k/pkg/util/flow"
+	"github.com/apache/camel-k/pkg/util/kubernetes"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"sigs.k8s.io/controller-runtime/pkg/client"
@@ -61,6 +61,9 @@ func newConfigurationKey(kamelet, configurationID string) configurationKey {
 }
 
 const (
+	contentKey = "content"
+	schemaKey  = "schema"
+
 	kameletLabel              = "camel.apache.org/kamelet"
 	kameletConfigurationLabel = "camel.apache.org/kamelet.configuration"
 )
@@ -148,7 +151,7 @@ func (t *kameletsTrait) addKamelets(e *Environment) error {
 }
 
 func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet v1alpha1.Kamelet) error {
-	var sources []v1.SourceSpec
+	sources := make([]v1.SourceSpec, 0)
 
 	if kamelet.Spec.Flow != nil {
 
@@ -321,8 +324,8 @@ func integrationSourceFromKameletSource(e *Environment, kamelet v1alpha1.Kamelet
 			},
 		},
 		Data: map[string]string{
-			"content": source.Content,
-			"schema":  string(schema),
+			contentKey: source.Content,
+			schemaKey:  string(schema),
 		},
 	}
 
@@ -331,7 +334,7 @@ func integrationSourceFromKameletSource(e *Environment, kamelet v1alpha1.Kamelet
 	target := source.DeepCopy()
 	target.Content = ""
 	target.ContentRef = name
-	target.ContentKey = "content"
+	target.ContentKey = contentKey
 	return *target, nil
 }
 
diff --git a/pkg/trait/kamelets_test.go b/pkg/trait/kamelets_test.go
index d2a1321..4f37b1d 100644
--- a/pkg/trait/kamelets_test.go
+++ b/pkg/trait/kamelets_test.go
@@ -98,6 +98,7 @@ func TestKameletLookup(t *testing.T) {
 				"camel:log",
 			},
 		},
+		Status: v1alpha1.KameletStatus{Phase: v1alpha1.KameletPhaseReady},
 	})
 	enabled, err := trait.Configure(environment)
 	assert.NoError(t, err)
@@ -146,6 +147,7 @@ func TestKameletSecondarySourcesLookup(t *testing.T) {
 				},
 			},
 		},
+		Status: v1alpha1.KameletStatus{Phase: v1alpha1.KameletPhaseReady},
 	})
 	enabled, err := trait.Configure(environment)
 	assert.NoError(t, err)
@@ -196,6 +198,7 @@ func TestNonYAMLKameletLookup(t *testing.T) {
 				},
 			},
 		},
+		Status: v1alpha1.KameletStatus{Phase: v1alpha1.KameletPhaseReady},
 	})
 	enabled, err := trait.Configure(environment)
 	assert.NoError(t, err)
@@ -242,6 +245,7 @@ func TestErrorMultipleKameletSources(t *testing.T) {
 				},
 			}),
 		},
+		Status: v1alpha1.KameletStatus{Phase: v1alpha1.KameletPhaseReady},
 	})
 	enabled, err := trait.Configure(environment)
 	assert.NoError(t, err)
@@ -284,6 +288,7 @@ func TestMultipleKamelets(t *testing.T) {
 				"camel:xxx",
 			},
 		},
+		Status: v1alpha1.KameletStatus{Phase: v1alpha1.KameletPhaseReady},
 	}, &v1alpha1.Kamelet{
 		ObjectMeta: metav1.ObjectMeta{
 			Namespace: "test",
@@ -307,6 +312,7 @@ func TestMultipleKamelets(t *testing.T) {
 				"camel:tbd",
 			},
 		},
+		Status: v1alpha1.KameletStatus{Phase: v1alpha1.KameletPhaseReady},
 	})
 	enabled, err := trait.Configure(environment)
 	assert.NoError(t, err)
@@ -368,6 +374,7 @@ func TestKameletConfigLookup(t *testing.T) {
 				"camel:log",
 			},
 		},
+		Status: v1alpha1.KameletStatus{Phase: v1alpha1.KameletPhaseReady},
 	}, &corev1.Secret{
 		ObjectMeta: metav1.ObjectMeta{
 			Namespace: "test",
@@ -430,6 +437,7 @@ func TestKameletNamedConfigLookup(t *testing.T) {
 				"camel:log",
 			},
 		},
+		Status: v1alpha1.KameletStatus{Phase: v1alpha1.KameletPhaseReady},
 	}, &corev1.Secret{
 		ObjectMeta: metav1.ObjectMeta{
 			Namespace: "test",
@@ -516,6 +524,6 @@ func marshalOrFail(flow map[string]interface{}) *v1.Flow {
 	if err != nil {
 		panic(err)
 	}
-	f := v1.Flow{data}
+	f := v1.Flow{RawMessage: data}
 	return &f
 }
diff --git a/pkg/trait/knative_service_test.go b/pkg/trait/knative_service_test.go
index dcf0f65..9406d32 100644
--- a/pkg/trait/knative_service_test.go
+++ b/pkg/trait/knative_service_test.go
@@ -21,17 +21,16 @@ import (
 	"context"
 	"testing"
 
-	"github.com/stretchr/testify/assert"
-
-	corev1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	serving "knative.dev/serving/pkg/apis/serving/v1"
-
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	"github.com/apache/camel-k/pkg/util/camel"
 	"github.com/apache/camel-k/pkg/util/envvar"
+	"github.com/apache/camel-k/pkg/util/gzip"
 	"github.com/apache/camel-k/pkg/util/kubernetes"
 	"github.com/apache/camel-k/pkg/util/test"
+	"github.com/stretchr/testify/assert"
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	serving "knative.dev/serving/pkg/apis/serving/v1"
 )
 
 const (
@@ -45,6 +44,9 @@ func TestKnativeService(t *testing.T) {
 
 	traitCatalog := NewCatalog(context.TODO(), nil)
 
+	compressedRoute, err := gzip.CompressBase64([]byte(`from("undertow:test").log("hello")`))
+	assert.NoError(t, err)
+
 	environment := Environment{
 		CamelCatalog: catalog,
 		Catalog:      traitCatalog,
@@ -62,7 +64,7 @@ func TestKnativeService(t *testing.T) {
 					{
 						DataSpec: v1.DataSpec{
 							Name:        "routes.js",
-							Content:     `from("undertow:test").log("hello")`,
+							Content:     string(compressedRoute),
 							Compression: true,
 						},
 						Language: v1.LanguageJavaScript,
diff --git a/pkg/trait/service_test.go b/pkg/trait/service_test.go
index 61e5597..372dc2f 100644
--- a/pkg/trait/service_test.go
+++ b/pkg/trait/service_test.go
@@ -21,15 +21,14 @@ import (
 	"context"
 	"testing"
 
+	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+	"github.com/apache/camel-k/pkg/util/camel"
+	"github.com/apache/camel-k/pkg/util/gzip"
+	"github.com/apache/camel-k/pkg/util/kubernetes"
 	"github.com/stretchr/testify/assert"
-
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-
-	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
-	"github.com/apache/camel-k/pkg/util/camel"
-	"github.com/apache/camel-k/pkg/util/kubernetes"
 	"github.com/apache/camel-k/pkg/util/test"
 )
 
@@ -44,6 +43,9 @@ func TestServiceWithDefaults(t *testing.T) {
 
 	traitCatalog := NewCatalog(context.TODO(), nil)
 
+	compressedRoute, err := gzip.CompressBase64([]byte(`from("undertow:test").log("hello")`))
+	assert.NoError(t, err)
+
 	environment := Environment{
 		CamelCatalog: catalog,
 		Catalog:      traitCatalog,
@@ -61,7 +63,7 @@ func TestServiceWithDefaults(t *testing.T) {
 					{
 						DataSpec: v1.DataSpec{
 							Name:        "routes.js",
-							Content:     `from("undertow:test").log("hello")`,
+							Content:     string(compressedRoute),
 							Compression: true,
 						},
 						Language: v1.LanguageJavaScript,
@@ -130,6 +132,9 @@ func TestService(t *testing.T) {
 
 	traitCatalog := NewCatalog(context.TODO(), nil)
 
+	compressedRoute, err := gzip.CompressBase64([]byte(`from("undertow:test").log("hello")`))
+	assert.NoError(t, err)
+
 	environment := Environment{
 		CamelCatalog: catalog,
 		Catalog:      traitCatalog,
@@ -147,7 +152,7 @@ func TestService(t *testing.T) {
 					{
 						DataSpec: v1.DataSpec{
 							Name:        "routes.js",
-							Content:     `from("undertow:test").log("hello")`,
+							Content:     string(compressedRoute),
 							Compression: true,
 						},
 						Language: v1.LanguageJavaScript,
@@ -295,6 +300,9 @@ func TestServiceWithNodePort(t *testing.T) {
 
 	traitCatalog := NewCatalog(context.TODO(), nil)
 
+	compressedRoute, err := gzip.CompressBase64([]byte(`from("undertow:test").log("hello")`))
+	assert.NoError(t, err)
+
 	environment := Environment{
 		CamelCatalog: catalog,
 		Catalog:      traitCatalog,
@@ -312,7 +320,7 @@ func TestServiceWithNodePort(t *testing.T) {
 					{
 						DataSpec: v1.DataSpec{
 							Name:        "routes.js",
-							Content:     `from("undertow:test").log("hello")`,
+							Content:     string(compressedRoute),
 							Compression: true,
 						},
 						Language: v1.LanguageJavaScript,
diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go
index f1666f7..c397c2f 100644
--- a/pkg/trait/trait_types.go
+++ b/pkg/trait/trait_types.go
@@ -557,7 +557,7 @@ func (e *Environment) AddSourcesProperties() {
 				properties[fmt.Sprintf("camel.k.kamelets[%s].loader", kameletName)] = s.Loader
 			}
 			if s.Compression {
-				properties[fmt.Sprintf("camel.k.kamelets[%s].compression", kameletName)] = "true"
+				properties[fmt.Sprintf("camel.k.kamelets[%s].compression", kameletName)] = True
 			}
 
 			interceptors := make([]string, 0, len(s.Interceptors))
diff --git a/pkg/util/kubernetes/resolver.go b/pkg/util/kubernetes/resolver.go
index ae7621a..185c11b 100644
--- a/pkg/util/kubernetes/resolver.go
+++ b/pkg/util/kubernetes/resolver.go
@@ -23,6 +23,7 @@ import (
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	"github.com/apache/camel-k/pkg/util/gzip"
+	"github.com/pkg/errors"
 	corev1 "k8s.io/api/core/v1"
 	controller "sigs.k8s.io/controller-runtime/pkg/client"
 )
@@ -84,7 +85,7 @@ func Resolve(data *v1.DataSpec, mapLookup func(string) (*corev1.ConfigMap, error
 		var uncompressed []byte
 		var err error
 		if uncompressed, err = gzip.UncompressBase64(cnt); err != nil {
-			return err
+			return errors.Wrap(err, "error while uncompressing data")
 		}
 		data.Compression = false
 		data.Content = string(uncompressed)
diff --git a/pkg/util/log/log.go b/pkg/util/log/log.go
index 7ac3573..7d290f0 100644
--- a/pkg/util/log/log.go
+++ b/pkg/util/log/log.go
@@ -19,9 +19,9 @@ package log
 
 import (
 	"fmt"
-	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	"github.com/go-logr/logr"
 	logf "sigs.k8s.io/controller-runtime/pkg/log"
 )


[camel-k] 05/21: kamelets: adding mount paths and implement kamelets trait

Posted by nf...@apache.org.
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 69c2ecc6ad3100514b5c1eef258aaa596d460f89
Author: Nicola Ferraro <ni...@gmail.com>
AuthorDate: Wed Jun 24 12:54:55 2020 +0200

    kamelets: adding mount paths and implement kamelets trait
---
 pkg/apis/camel/v1alpha1/kamelet_types.go         |   2 +-
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go |   5 +-
 pkg/trait/kamelets.go                            | 112 +++++++++----
 pkg/trait/kamelets_test.go                       | 197 ++++++++++++++++++++++-
 pkg/trait/trait_test.go                          |   2 +-
 pkg/trait/trait_types.go                         |  17 +-
 6 files changed, 291 insertions(+), 44 deletions(-)

diff --git a/pkg/apis/camel/v1alpha1/kamelet_types.go b/pkg/apis/camel/v1alpha1/kamelet_types.go
index fa53584..a8e67fa 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_types.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_types.go
@@ -31,7 +31,7 @@ const (
 type KameletSpec struct {
 	Definition    JSONSchemaProps             `json:"definition,omitempty"`
 	Sources       []camelv1.SourceSpec        `json:"sources,omitempty"`
-	Flow          camelv1.Flow                `json:"flow,omitempty"`
+	Flow          *camelv1.Flow               `json:"flow,omitempty"`
 	Authorization AuthorizationSpec           `json:"authorization,omitempty"`
 	Types         map[EventSlot]EventTypeSpec `json:"types,omitempty"`
 	Dependencies  []string                    `json:"dependencies,omitempty"`
diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index 2f7512c..61e8aa0 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -474,7 +474,10 @@ func (in *KameletSpec) DeepCopyInto(out *KameletSpec) {
 			(*in)[i].DeepCopyInto(&(*out)[i])
 		}
 	}
-	in.Flow.DeepCopyInto(&out.Flow)
+	if in.Flow != nil {
+		in, out := &in.Flow, &out.Flow
+		*out = (*in).DeepCopy()
+	}
 	out.Authorization = in.Authorization
 	if in.Types != nil {
 		in, out := &in.Types, &out.Types
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index 4ba9d67..180985a 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -28,6 +28,7 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"regexp"
+	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sort"
 	"strconv"
 	"strings"
@@ -54,6 +55,11 @@ func newKameletsTrait() Trait {
 	}
 }
 
+// IsPlatformTrait overrides base class method
+func (t *kameletsTrait) IsPlatformTrait() bool {
+	return true
+}
+
 func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 	if t.Enabled != nil && !*t.Enabled {
 		return false, nil
@@ -73,47 +79,85 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 
 	}
 
-	return t.List != "", nil
+	return len(t.getKamelets()) > 0, nil
 }
 
 func (t *kameletsTrait) Apply(e *Environment) error {
-
+	if err := t.addKamelets(e); err != nil {
+		return err
+	}
 	return nil
 }
 
-// IsPlatformTrait overrides base class method
-func (t *kameletsTrait) IsPlatformTrait() bool {
-	return true
+func (t *kameletsTrait) addKamelets(e *Environment) error {
+	for _, k := range t.getKamelets() {
+		var kamelet v1alpha1.Kamelet
+		key := client.ObjectKey{
+			Namespace: e.Integration.Namespace,
+			Name:      k,
+		}
+		if err := t.Client.Get(t.Ctx, key, &kamelet); err != nil {
+			return err
+		}
+		if err := t.addKameletAsSource(e, kamelet); err != nil {
+			return err
+		}
+	}
+	return nil
 }
 
-func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet *v1alpha1.Kamelet) error {
+func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet v1alpha1.Kamelet) error {
 	var sources []v1.SourceSpec
 
-	flowData, err := flows.Marshal([]v1.Flow{kamelet.Spec.Flow})
-	if err != nil {
-		return err
-	}
-	flowSource := v1.SourceSpec{
-		DataSpec: v1.DataSpec{
-			Name:    "flow.yaml",
-			Content: string(flowData),
-		},
-		Language: v1.LanguageYaml,
-		Type:     v1.SourceTypeKamelet,
-	}
-	flowSource, err = integrationSourceFromKameletSource(e, kamelet, flowSource, fmt.Sprintf("%s-kamelet-%s-flow", e.Integration.Name, kamelet.Name))
-	if err != nil {
-		return err
+	if kamelet.Spec.Flow != nil {
+		flowData, err := flows.Marshal([]v1.Flow{*kamelet.Spec.Flow})
+		if err != nil {
+			return err
+		}
+		flowSource := v1.SourceSpec{
+			DataSpec: v1.DataSpec{
+				Name:    fmt.Sprintf("%s.yaml", kamelet.Name),
+				Content: string(flowData),
+			},
+			Language: v1.LanguageYaml,
+			Type:     v1.SourceTypeKamelet,
+		}
+		flowSource, err = integrationSourceFromKameletSource(e, kamelet, flowSource, fmt.Sprintf("%s-kamelet-%s-flow", e.Integration.Name, kamelet.Name))
+		if err != nil {
+			return err
+		}
+		sources = append(sources, flowSource)
 	}
-	sources = append(sources, flowSource)
 
 	for idx, s := range kamelet.Spec.Sources {
-		intSource, err := integrationSourceFromKameletSource(e, kamelet, s, fmt.Sprintf("%s-kamelet-%s-source-%03d", e.Integration.Name, kamelet.Name, idx))
+		intSource, err := integrationSourceFromKameletSource(e, kamelet, s, fmt.Sprintf("%s-kamelet-%s-%03d", e.Integration.Name, kamelet.Name, idx))
 		if err != nil {
 			return err
 		}
 		sources = append(sources, intSource)
 	}
+
+	kameletCounter := 0
+	for _, source := range sources {
+		if source.Type == v1.SourceTypeKamelet {
+			kameletCounter++
+		}
+		replaced := false
+		for idx, existing := range e.Integration.Status.GeneratedSources {
+			if existing.Name == source.Name {
+				replaced = true
+				e.Integration.Status.GeneratedSources[idx] = source
+			}
+		}
+		if !replaced {
+			e.Integration.Status.GeneratedSources = append(e.Integration.Status.GeneratedSources, source)
+		}
+	}
+
+	if kameletCounter > 1 {
+		return fmt.Errorf(`kamelet %s contains %d sources of type "kamelet": at most one is allowed`, kamelet.Name, kameletCounter)
+	}
+
 	return nil
 }
 
@@ -128,9 +172,15 @@ func (t *kameletsTrait) getKamelets() []string {
 	return answer
 }
 
-func integrationSourceFromKameletSource(e *Environment, kamelet *v1alpha1.Kamelet, source v1.SourceSpec, name string) (v1.SourceSpec, error) {
+func integrationSourceFromKameletSource(e *Environment, kamelet v1alpha1.Kamelet, source v1.SourceSpec, name string) (v1.SourceSpec, error) {
+	if source.Type == v1.SourceTypeKamelet {
+		// Kamelets must be named "<kamelet-name>.extension"
+		language := source.InferLanguage()
+		source.Name = fmt.Sprintf("%s.%s", kamelet.Name, string(language))
+	}
+
 	if source.DataSpec.ContentRef != "" {
-		return renameSource(kamelet, source), nil
+		return source, nil
 	}
 
 	// Create configmaps to avoid storing kamelet definitions in the integration CR
@@ -169,19 +219,11 @@ func integrationSourceFromKameletSource(e *Environment, kamelet *v1alpha1.Kamele
 
 	e.Resources.Add(&cm)
 
-	target := renameSource(kamelet, source)
+	target := source.DeepCopy()
 	target.Content = ""
 	target.ContentRef = name
 	target.ContentKey = "content"
-	return target, nil
-}
-
-func renameSource(kamelet *v1alpha1.Kamelet, source v1.SourceSpec) v1.SourceSpec {
-	target := source.DeepCopy()
-	if !strings.HasPrefix(target.Name, fmt.Sprintf("kamelet-%s-", kamelet.Name)) {
-		target.Name = fmt.Sprintf("kamelet-%s-%s", kamelet.Name, target.Name)
-	}
-	return *target
+	return *target, nil
 }
 
 func extractKamelets(uris []string) (kamelets []string) {
diff --git a/pkg/trait/kamelets_test.go b/pkg/trait/kamelets_test.go
index b7d4fe7..30585c3 100644
--- a/pkg/trait/kamelets_test.go
+++ b/pkg/trait/kamelets_test.go
@@ -19,6 +19,10 @@ package trait
 
 import (
 	"context"
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
 	"testing"
 
 	"github.com/apache/camel-k/pkg/util/camel"
@@ -30,7 +34,20 @@ import (
 	"github.com/apache/camel-k/pkg/util/test"
 )
 
-func TestKameletsFinding(t *testing.T) {
+func TestConfigurationNoKameletsUsed(t *testing.T) {
+	trait, environment := createKameletsTestEnvironment(`
+- from:
+    uri: timer:tick
+    steps:
+    - to: log:info
+`)
+	enabled, err := trait.Configure(environment)
+	assert.NoError(t, err)
+	assert.False(t, enabled)
+	assert.Equal(t, "", trait.List)
+}
+
+func TestConfigurationWithKamelets(t *testing.T) {
 	trait, environment := createKameletsTestEnvironment(`
 - from:
     uri: kamelet:c1
@@ -50,10 +67,180 @@ func TestKameletsFinding(t *testing.T) {
 	assert.Equal(t, []string{"c0", "c1", "c2", "complex-.-.-1a", "complex-.-.-1b", "complex-.-.-1c"}, trait.getKamelets())
 }
 
-func createKameletsTestEnvironment(flow string) (*kameletsTrait, *Environment) {
+func TestKameletLookup(t *testing.T) {
+	trait, environment := createKameletsTestEnvironment(`
+- from:
+    uri: kamelet:timer
+    steps:
+    - to: log:info
+`, &v1alpha1.Kamelet{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "test",
+			Name:      "timer",
+		},
+		Spec: v1alpha1.KameletSpec{
+			Flow: &v1.Flow{
+				"from": map[string]interface{}{
+					"uri": "timer:tick",
+				},
+			},
+		},
+	})
+	enabled, err := trait.Configure(environment)
+	assert.NoError(t, err)
+	assert.True(t, enabled)
+	assert.Equal(t, []string{"timer"}, trait.getKamelets())
+
+	err = trait.Apply(environment)
+	assert.NoError(t, err)
+	cm := environment.Resources.GetConfigMap(func(_ *corev1.ConfigMap) bool { return true })
+	assert.NotNil(t, cm)
+	assert.Equal(t, "it-kamelet-timer-flow", cm.Name)
+	assert.Equal(t, "test", cm.Namespace)
+
+	assert.Len(t, environment.Integration.Status.GeneratedSources, 1)
+	source := environment.Integration.Status.GeneratedSources[0]
+	assert.Equal(t, "timer.yaml", source.Name)
+	assert.Equal(t, "kamelet", string(source.Type))
+}
+
+func TestKameletSecondarySourcesLookup(t *testing.T) {
+	trait, environment := createKameletsTestEnvironment(`
+- from:
+    uri: kamelet:timer
+    steps:
+    - to: log:info
+`, &v1alpha1.Kamelet{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "test",
+			Name:      "timer",
+		},
+		Spec: v1alpha1.KameletSpec{
+			Flow: &v1.Flow{
+				"from": map[string]interface{}{
+					"uri": "timer:tick",
+				},
+			},
+			Sources: []v1.SourceSpec{
+				{
+					DataSpec: v1.DataSpec{
+						Name:    "support.groovy",
+						Content: "from('xxx:xxx').('to:log:info')",
+					},
+					Language: v1.LanguageGroovy,
+				},
+			},
+		},
+	})
+	enabled, err := trait.Configure(environment)
+	assert.NoError(t, err)
+	assert.True(t, enabled)
+	assert.Equal(t, []string{"timer"}, trait.getKamelets())
+
+	err = trait.Apply(environment)
+	assert.NoError(t, err)
+	cmFlow := environment.Resources.GetConfigMap(func(c *corev1.ConfigMap) bool { return c.Name == "it-kamelet-timer-flow" })
+	assert.NotNil(t, cmFlow)
+	cmRes := environment.Resources.GetConfigMap(func(c *corev1.ConfigMap) bool { return c.Name == "it-kamelet-timer-000" })
+	assert.NotNil(t, cmRes)
+
+	assert.Len(t, environment.Integration.Status.GeneratedSources, 2)
+
+	flowSource := environment.Integration.Status.GeneratedSources[0]
+	assert.Equal(t, "timer.yaml", flowSource.Name)
+	assert.Equal(t, "kamelet", string(flowSource.Type))
+	assert.Equal(t, "it-kamelet-timer-flow", flowSource.ContentRef)
+	assert.Equal(t, "content", flowSource.ContentKey)
+
+	supportSource := environment.Integration.Status.GeneratedSources[1]
+	assert.Equal(t, "support.groovy", supportSource.Name)
+	assert.Equal(t, "", string(supportSource.Type))
+	assert.Equal(t, "it-kamelet-timer-000", supportSource.ContentRef)
+	assert.Equal(t, "content", supportSource.ContentKey)
+}
+
+func TestNonYAMLKameletLookup(t *testing.T) {
+	trait, environment := createKameletsTestEnvironment(`
+- from:
+    uri: kamelet:timer
+    steps:
+    - to: log:info
+`, &v1alpha1.Kamelet{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "test",
+			Name:      "timer",
+		},
+		Spec: v1alpha1.KameletSpec{
+			Sources: []v1.SourceSpec{
+				{
+					DataSpec: v1.DataSpec{
+						Name:    "mykamelet.groovy",
+						Content: `from("timer").to("log:info")`,
+					},
+					Type: v1.SourceTypeKamelet,
+				},
+			},
+		},
+	})
+	enabled, err := trait.Configure(environment)
+	assert.NoError(t, err)
+	assert.True(t, enabled)
+	assert.Equal(t, []string{"timer"}, trait.getKamelets())
+
+	err = trait.Apply(environment)
+	assert.NoError(t, err)
+	cm := environment.Resources.GetConfigMap(func(_ *corev1.ConfigMap) bool { return true })
+	assert.NotNil(t, cm)
+	assert.Equal(t, "it-kamelet-timer-000", cm.Name)
+	assert.Equal(t, "test", cm.Namespace)
+
+	assert.Len(t, environment.Integration.Status.GeneratedSources, 1)
+	source := environment.Integration.Status.GeneratedSources[0]
+	assert.Equal(t, "timer.groovy", source.Name)
+	assert.Equal(t, "kamelet", string(source.Type))
+}
+
+func TestErrorMultipleKameletSources(t *testing.T) {
+	trait, environment := createKameletsTestEnvironment(`
+- from:
+    uri: kamelet:timer
+    steps:
+    - to: log:info
+`, &v1alpha1.Kamelet{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "test",
+			Name:      "timer",
+		},
+		Spec: v1alpha1.KameletSpec{
+			Sources: []v1.SourceSpec{
+				{
+					DataSpec: v1.DataSpec{
+						Name:    "mykamelet.groovy",
+						Content: `from("timer").to("log:info")`,
+					},
+					Type: v1.SourceTypeKamelet,
+				},
+			},
+			Flow: &v1.Flow{
+				"from": map[string]interface{}{
+					"uri": "timer:tick",
+				},
+			},
+		},
+	})
+	enabled, err := trait.Configure(environment)
+	assert.NoError(t, err)
+	assert.True(t, enabled)
+	assert.Equal(t, []string{"timer"}, trait.getKamelets())
+
+	err = trait.Apply(environment)
+	assert.Error(t, err)
+}
+
+func createKameletsTestEnvironment(flow string, objects ...runtime.Object) (*kameletsTrait, *Environment) {
 	catalog, _ := camel.DefaultCatalog()
 
-	client, _ := test.NewFakeClient()
+	client, _ := test.NewFakeClient(objects...)
 	trait := newKameletsTrait().(*kameletsTrait)
 	trait.Ctx = context.TODO()
 	trait.Client = client
@@ -62,6 +249,10 @@ func createKameletsTestEnvironment(flow string) (*kameletsTrait, *Environment) {
 		Catalog:      NewCatalog(context.TODO(), nil),
 		CamelCatalog: catalog,
 		Integration: &v1.Integration{
+			ObjectMeta: metav1.ObjectMeta{
+				Namespace: "test",
+				Name:      "it",
+			},
 			Spec: v1.IntegrationSpec{
 				Sources: []v1.SourceSpec{
 					{
diff --git a/pkg/trait/trait_test.go b/pkg/trait/trait_test.go
index d50bd91..bcf3519 100644
--- a/pkg/trait/trait_test.go
+++ b/pkg/trait/trait_test.go
@@ -382,7 +382,7 @@ func TestOnlySomeTraitsInfluenceBuild(t *testing.T) {
 
 func TestOnlySomeTraitsArePlatform(t *testing.T) {
 	c := NewTraitTestCatalog()
-	platformTraits := []string{"builder", "camel", "jvm", "container", "dependencies", "deployer", "deployment", "environment", "openapi", "owner", "platform"}
+	platformTraits := []string{"builder", "camel", "jvm", "container", "dependencies", "deployer", "deployment", "environment", "kamelets", "openapi", "owner", "platform"}
 
 	for _, trait := range c.allTraits() {
 		if trait.IsPlatformTrait() {
diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go
index babe121..e815469 100644
--- a/pkg/trait/trait_types.go
+++ b/pkg/trait/trait_types.go
@@ -54,6 +54,9 @@ var (
 	// SourcesMountPath --
 	SourcesMountPath = path.Join(BasePath, "sources")
 
+	// KameletsMountPath --
+	KameletsMountPath = path.Join(BasePath, "kamelets.d")
+
 	// ResourcesMountPath --
 	ResourcesMountPath = path.Join(BasePath, "resources")
 
@@ -527,12 +530,20 @@ func (e *Environment) ConfigureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]c
 
 	for i, s := range e.Integration.Sources() {
 		cmName := fmt.Sprintf("%s-source-%03d", e.Integration.Name, i)
+		if s.ContentRef != "" {
+			cmName = s.ContentRef
+		}
+
 		refName := fmt.Sprintf("i-source-%03d", i)
+		if s.Type == v1.SourceTypeKamelet {
+			refName = fmt.Sprintf("i-kamelet-source-%03d", i)
+		}
+
 		resName := strings.TrimPrefix(s.Name, "/")
-		resPath := path.Join(SourcesMountPath, refName)
 
-		if s.ContentRef != "" {
-			cmName = s.ContentRef
+		resPath := path.Join(SourcesMountPath, refName)
+		if s.Type == v1.SourceTypeKamelet {
+			resPath = KameletsMountPath
 		}
 
 		*vols = append(*vols, corev1.Volume{