You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2023/01/10 08:24:10 UTC

[camel-k] branch main updated (b5e208942 -> d1af7f9b6)

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

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


    from b5e208942 api: Generate apply configurations
     new acf77559f fix(#3844): Add service discovery for Kamelet data type converter
     new d1af7f9b6 fix(#3844): Add e2e test for data type converter service discovery

The 2 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:
 docs/modules/ROOT/partials/apis/camel-k-crds.adoc  |  34 +++++
 .../event-binding.yaml}                            |  25 ++--
 .../event-sink.kamelet.yaml}                       |  44 +++++--
 .../event-source.kamelet.yaml}                     |  50 +++++---
 .../kamelet-data-types/kamelet-data-types.feature  |  15 +++
 .../kamelet-data-types/log-action.kamelet.yaml     |  63 +++++++++
 .../yaks-config.yaml                               |  16 ++-
 pkg/apis/camel/v1/maven_types.go                   |   6 +
 pkg/apis/camel/v1/maven_types_support.go           |  62 ++++++++-
 pkg/apis/camel/v1/maven_types_support_test.go      | 142 +++++++++++++++++++++
 pkg/apis/camel/v1/zz_generated.deepcopy.go         |  43 +++++++
 pkg/builder/project_test.go                        |   4 +-
 pkg/builder/quarkus.go                             |  50 +++++---
 pkg/cmd/local/local.go                             |   2 +-
 pkg/util/camel/camel_dependencies.go               |  18 +--
 pkg/util/defaults/defaults.go                      |   2 +-
 pkg/util/maven/maven_project.go                    |   7 +-
 pkg/util/maven/maven_types.go                      |   8 +-
 18 files changed, 505 insertions(+), 86 deletions(-)
 copy e2e/yaks/common/{kamelet-steps/steps-binding.yaml => kamelet-data-types/event-binding.yaml} (81%)
 copy e2e/yaks/common/{kamelet-binding/logger-sink.kamelet.yaml => kamelet-data-types/event-sink.kamelet.yaml} (53%)
 copy e2e/yaks/common/{kamelet-binding/timer-source.kamelet.yaml => kamelet-data-types/event-source.kamelet.yaml} (55%)
 create mode 100644 e2e/yaks/common/kamelet-data-types/kamelet-data-types.feature
 create mode 100644 e2e/yaks/common/kamelet-data-types/log-action.kamelet.yaml
 copy e2e/yaks/common/{kamelet-beans => kamelet-data-types}/yaks-config.yaml (71%)
 create mode 100644 pkg/apis/camel/v1/maven_types_support_test.go


[camel-k] 02/02: fix(#3844): Add e2e test for data type converter service discovery

Posted by pc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit d1af7f9b69275c63b7151361037ebda00827f768
Author: Christoph Deppisch <cd...@redhat.com>
AuthorDate: Mon Jan 9 15:21:23 2023 +0100

    fix(#3844): Add e2e test for data type converter service discovery
    
    - Kameletes used in the test make use of DataTypeRegistry and classpath scan is disabled
    - Data type registry will then perform a lookup of the data types via service discovery mechanism
---
 .../common/kamelet-data-types/event-binding.yaml   | 41 ++++++++++++++
 .../kamelet-data-types/event-sink.kamelet.yaml     | 61 +++++++++++++++++++++
 .../kamelet-data-types/event-source.kamelet.yaml   | 62 +++++++++++++++++++++
 .../kamelet-data-types/kamelet-data-types.feature  | 15 ++++++
 .../kamelet-data-types/log-action.kamelet.yaml     | 63 ++++++++++++++++++++++
 .../common/kamelet-data-types/yaks-config.yaml     | 42 +++++++++++++++
 6 files changed, 284 insertions(+)

diff --git a/e2e/yaks/common/kamelet-data-types/event-binding.yaml b/e2e/yaks/common/kamelet-data-types/event-binding.yaml
new file mode 100644
index 000000000..42f1d6771
--- /dev/null
+++ b/e2e/yaks/common/kamelet-data-types/event-binding.yaml
@@ -0,0 +1,41 @@
+# ---------------------------------------------------------------------------
+# 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.
+# ---------------------------------------------------------------------------
+
+apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  name: event-binding
+spec:
+  source:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1alpha1
+      name: event-source
+    properties:
+      outputFormat: ${outputFormat}
+  steps:
+    - ref:
+        kind: Kamelet
+        apiVersion: camel.apache.org/v1alpha1
+        name: log-action
+  sink:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1alpha1
+      name: event-sink
+    properties:
+      inputFormat: ${inputFormat}
diff --git a/e2e/yaks/common/kamelet-data-types/event-sink.kamelet.yaml b/e2e/yaks/common/kamelet-data-types/event-sink.kamelet.yaml
new file mode 100644
index 000000000..94b254ecf
--- /dev/null
+++ b/e2e/yaks/common/kamelet-data-types/event-sink.kamelet.yaml
@@ -0,0 +1,61 @@
+# ---------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ---------------------------------------------------------------------------
+
+apiVersion: camel.apache.org/v1alpha1
+kind: Kamelet
+metadata:
+  name: event-sink
+  labels:
+    camel.apache.org/kamelet.type: "sink"
+spec:
+  definition:
+    title: "Event Sink"
+    description: "Handles incoming event with data type auto conversion"
+    required:
+      - inputFormat
+    properties:
+      inputFormat:
+        title: Input Format
+        description: The data type to convert incoming events to
+        type: string
+  dependencies:
+    - github:apache.camel-kamelets:camel-kamelets-utils:main-SNAPSHOT
+    - "camel:core"
+    - "camel:kamelet"
+  template:
+    beans:
+      - name: dataTypeRegistry
+        type: "#class:org.apache.camel.kamelets.utils.format.DefaultDataTypeRegistry"
+        property:
+          - key: classpathScan
+            value: false
+      - name: inputTypeProcessor
+        type: "#class:org.apache.camel.kamelets.utils.format.DataTypeProcessor"
+        property:
+          - key: scheme
+            value: 'camel'
+          - key: format
+            value: '{{inputFormat}}'
+          - key: registry
+            value: '#bean:{{dataTypeRegistry}}'
+    from:
+      uri: "kamelet:source"
+      steps:
+        - process:
+            ref: "{{inputTypeProcessor}}"
+        - to:
+            uri: "log:info"
diff --git a/e2e/yaks/common/kamelet-data-types/event-source.kamelet.yaml b/e2e/yaks/common/kamelet-data-types/event-source.kamelet.yaml
new file mode 100644
index 000000000..10cc5fcb2
--- /dev/null
+++ b/e2e/yaks/common/kamelet-data-types/event-source.kamelet.yaml
@@ -0,0 +1,62 @@
+# ---------------------------------------------------------------------------
+# 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.
+# ---------------------------------------------------------------------------
+
+apiVersion: camel.apache.org/v1alpha1
+kind: Kamelet
+metadata:
+  name: event-source
+  labels:
+    camel.apache.org/kamelet.type: "source"
+spec:
+  definition:
+    title: "Event Source"
+    description: "Produces events in given data type"
+    required:
+      - outputFormat
+    properties:
+      outputFormat:
+        title: Output Format
+        description: The data type of produced events
+        type: string
+  dependencies:
+    - github:apache.camel-kamelets:camel-kamelets-utils:main-SNAPSHOT
+    - "camel:core"
+    - "camel:kamelet"
+  template:
+    beans:
+      - name: dataTypeRegistry
+        type: "#class:org.apache.camel.kamelets.utils.format.DefaultDataTypeRegistry"
+        property:
+          - key: classpathScan
+            value: false
+      - name: outputTypeProcessor
+        type: "#class:org.apache.camel.kamelets.utils.format.DataTypeProcessor"
+        property:
+          - key: scheme
+            value: 'camel'
+          - key: format
+            value: '{{outputFormat}}'
+          - key: registry
+            value: '#bean:{{dataTypeRegistry}}'
+    from:
+      uri: timer:tick
+      steps:
+        - set-body:
+            constant: "Hello from Camel K!"
+        - process:
+            ref: "{{outputTypeProcessor}}"
+        - to: "kamelet:sink"
diff --git a/e2e/yaks/common/kamelet-data-types/kamelet-data-types.feature b/e2e/yaks/common/kamelet-data-types/kamelet-data-types.feature
new file mode 100644
index 000000000..a30ecc5d5
--- /dev/null
+++ b/e2e/yaks/common/kamelet-data-types/kamelet-data-types.feature
@@ -0,0 +1,15 @@
+Feature: Kamelets with data types
+
+  Background:
+    Given Camel K resource polling configuration
+      | maxAttempts          | 200  |
+      | delayBetweenAttempts | 4000 |
+
+  Scenario: Kamelet event data type conversion
+    Given variables
+    | outputFormat | binary |
+    | inputFormat  | string |
+    Given load KameletBinding event-binding.yaml
+    Given Camel K integration event-binding is running
+    Then Camel K integration event-binding should print BodyType: byte[], Body: Hello from Camel K!
+    Then Camel K integration event-binding should print BodyType: String, Body: Hello from Camel K!
diff --git a/e2e/yaks/common/kamelet-data-types/log-action.kamelet.yaml b/e2e/yaks/common/kamelet-data-types/log-action.kamelet.yaml
new file mode 100644
index 000000000..9461ee6ab
--- /dev/null
+++ b/e2e/yaks/common/kamelet-data-types/log-action.kamelet.yaml
@@ -0,0 +1,63 @@
+# ---------------------------------------------------------------------------
+# 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.
+# ---------------------------------------------------------------------------
+apiVersion: camel.apache.org/v1alpha1
+kind: Kamelet
+metadata:
+  name: log-action
+  annotations:
+    camel.apache.org/kamelet.support.level: "Stable"
+    camel.apache.org/catalog.version: "main-SNAPSHOT"
+    camel.apache.org/kamelet.icon: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE2LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodH [...]
+    camel.apache.org/provider: "Apache Software Foundation"
+    camel.apache.org/kamelet.group: "Logging"
+  labels:
+    camel.apache.org/kamelet.type: "action"
+spec:
+  definition:
+    title: "Log Action"
+    description: |-
+      Logs all data that flows between source and sink, useful for debugging purposes.
+    type: object
+    properties:
+      loggerName:
+        title: Logger Name
+        description: Name of the logging category to use
+        type: string
+        default: "log-action"
+      level:
+        title: Log Level
+        description: Logging level to use
+        type: string
+        default: "INFO"
+        x-descriptors:
+        - 'urn:alm:descriptor:com.tectonic.ui:select:TRACE'
+        - 'urn:alm:descriptor:com.tectonic.ui:select:DEBUG'
+        - 'urn:alm:descriptor:com.tectonic.ui:select:INFO'
+        - 'urn:alm:descriptor:com.tectonic.ui:select:WARN'
+        - 'urn:alm:descriptor:com.tectonic.ui:select:ERROR'
+        - 'urn:alm:descriptor:com.tectonic.ui:select:OFF'
+  dependencies:
+  - "camel:kamelet"
+  - "camel:log"
+  template:
+    from:
+      uri: "kamelet:source"
+      steps:
+      - to:
+          uri: "log:{{loggerName}}"
+          parameters:
+            level: "{{?level}}"
diff --git a/e2e/yaks/common/kamelet-data-types/yaks-config.yaml b/e2e/yaks/common/kamelet-data-types/yaks-config.yaml
new file mode 100644
index 000000000..c53dce8f2
--- /dev/null
+++ b/e2e/yaks/common/kamelet-data-types/yaks-config.yaml
@@ -0,0 +1,42 @@
+# ---------------------------------------------------------------------------
+# 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
+  runtime:
+    env:
+      - name: CITRUS_TYPE_CONVERTER
+        value: camel
+    settings:
+      loggers:
+        - name: INTEGRATION_STATUS
+          level: INFO
+        - name: INTEGRATION_LOGS
+          level: INFO
+    resources:
+      - event-binding.yaml
+pre:
+- name: installation
+  run: |
+    kubectl apply -f event-source.kamelet.yaml -n $YAKS_NAMESPACE
+    kubectl apply -f event-sink.kamelet.yaml -n $YAKS_NAMESPACE
+    kubectl apply -f log-action.kamelet.yaml -n $YAKS_NAMESPACE
+post:
+  - name: print dump
+    if: env:CI=true && failure()
+    run: yaks dump --includes app=camel-k


[camel-k] 01/02: fix(#3844): Add service discovery for Kamelet data type converter

Posted by pc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit acf77559fb63c2244d0b1959bc185fe7e39d083e
Author: Christoph Deppisch <cd...@redhat.com>
AuthorDate: Mon Jan 9 15:21:16 2023 +0100

    fix(#3844): Add service discovery for Kamelet data type converter
    
    - Enable service discovery for data type converter resources in order to enable factory finder mechanism when resolving data type implementations
    - Add proper quarkus-maven-plugin build time properties for quarkus.camel.* properties
    - Fixes the way camel-quarkus build time properties are set (set properties on the quarkus-maven-plugin instead of using generic Maven system properties)
    - Explicitly add quarkus.camel.service.discovery.include-patterns for data type converter resources in order to enable lazy loading of Kamelets data type implementations
    
    Relates to https://github.com/apache/camel-k/issues/1980
---
 docs/modules/ROOT/partials/apis/camel-k-crds.adoc |  34 ++++++
 pkg/apis/camel/v1/maven_types.go                  |   6 +
 pkg/apis/camel/v1/maven_types_support.go          |  62 +++++++++-
 pkg/apis/camel/v1/maven_types_support_test.go     | 142 ++++++++++++++++++++++
 pkg/apis/camel/v1/zz_generated.deepcopy.go        |  43 +++++++
 pkg/builder/project_test.go                       |   4 +-
 pkg/builder/quarkus.go                            |  50 +++++---
 pkg/cmd/local/local.go                            |   2 +-
 pkg/util/camel/camel_dependencies.go              |  18 +--
 pkg/util/defaults/defaults.go                     |   2 +-
 pkg/util/maven/maven_project.go                   |   7 +-
 pkg/util/maven/maven_types.go                     |   8 +-
 12 files changed, 341 insertions(+), 37 deletions(-)

diff --git a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
index 122776fcb..0db42b568 100644
--- a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
+++ b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
@@ -2423,6 +2423,12 @@ See https://maven.apache.org/ref/3.8.4/maven-embedder/cli.html.
 
 |===
 
+[#_camel_apache_org_v1_PluginProperties]
+=== PluginProperties(`map[string]github.com/apache/camel-k/pkg/apis/camel/v1.StringOrProperties` alias)
+
+
+
+
 [#_camel_apache_org_v1_PodSpec]
 === PodSpec
 
@@ -2547,6 +2553,7 @@ the specification
 *Appears on:*
 
 * <<#_camel_apache_org_v1_Server, Server>>
+* <<#_camel_apache_org_v1_StringOrProperties, StringOrProperties>>
 
 
 
@@ -3073,6 +3080,33 @@ SpectrumTask is used to configure Spectrum
 
 
 
+|===
+
+[#_camel_apache_org_v1_StringOrProperties]
+=== StringOrProperties
+
+
+
+[cols="2,2a",options="header"]
+|===
+|Field
+|Description
+
+|`-` +
+string
+|
+
+
+
+
+|`properties` +
+*xref:#_camel_apache_org_v1_Properties[Properties]*
+|
+
+
+
+
+
 |===
 
 [#_camel_apache_org_v1_Task]
diff --git a/pkg/apis/camel/v1/maven_types.go b/pkg/apis/camel/v1/maven_types.go
index 1d55cb3fd..378d7cfc4 100644
--- a/pkg/apis/camel/v1/maven_types.go
+++ b/pkg/apis/camel/v1/maven_types.go
@@ -96,4 +96,10 @@ type Server struct {
 	Configuration Properties `xml:"configuration,omitempty" json:"configuration,omitempty"`
 }
 
+type StringOrProperties struct {
+	Value      string     `xml:",chardata" json:"-"`
+	Properties Properties `xml:"properties,omitempty" json:"properties,omitempty"`
+}
+
 type Properties map[string]string
+type PluginProperties map[string]StringOrProperties
diff --git a/pkg/apis/camel/v1/maven_types_support.go b/pkg/apis/camel/v1/maven_types_support.go
index d4777bffc..5ba46f595 100644
--- a/pkg/apis/camel/v1/maven_types_support.go
+++ b/pkg/apis/camel/v1/maven_types_support.go
@@ -17,7 +17,9 @@ limitations under the License.
 
 package v1
 
-import "encoding/xml"
+import (
+	"encoding/xml"
+)
 
 func (in *MavenArtifact) GetDependencyID() string {
 	switch {
@@ -35,10 +37,14 @@ type propertiesEntry struct {
 
 func (m Properties) AddAll(properties map[string]string) {
 	for k, v := range properties {
-		m[k] = v
+		m.Add(k, v)
 	}
 }
 
+func (m Properties) Add(key string, value string) {
+	m[key] = value
+}
+
 func (m Properties) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
 	if len(m) == 0 {
 		return nil
@@ -57,3 +63,55 @@ func (m Properties) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
 
 	return e.EncodeToken(start.End())
 }
+
+func (m PluginProperties) AddAll(properties map[string]string) {
+	for k, v := range properties {
+		m.Add(k, v)
+	}
+}
+
+func (m PluginProperties) Add(key string, value string) {
+	m[key] = StringOrProperties{Value: value}
+}
+
+func (m PluginProperties) AddProperties(key string, properties map[string]string) {
+	m[key] = StringOrProperties{Properties: properties}
+}
+
+func (m PluginProperties) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+	if len(m) == 0 {
+		return nil
+	}
+
+	if err := e.EncodeToken(start); err != nil {
+		return err
+	}
+
+	for k, v := range m {
+		if v.Value != "" {
+			if err := e.Encode(propertiesEntry{XMLName: xml.Name{Local: k}, Value: v.Value}); err != nil {
+				return err
+			}
+		}
+
+		if len(v.Properties) > 0 {
+			nestedPropertyStart := xml.StartElement{Name: xml.Name{Local: k}}
+			if err := e.EncodeToken(nestedPropertyStart); err != nil {
+				return err
+			}
+
+			for key, value := range v.Properties {
+				if err := e.Encode(propertiesEntry{XMLName: xml.Name{Local: key}, Value: value}); err != nil {
+					return err
+				}
+			}
+
+			if err := e.EncodeToken(nestedPropertyStart.End()); err != nil {
+				return err
+			}
+
+		}
+	}
+
+	return e.EncodeToken(start.End())
+}
diff --git a/pkg/apis/camel/v1/maven_types_support_test.go b/pkg/apis/camel/v1/maven_types_support_test.go
new file mode 100644
index 000000000..979e6f7e5
--- /dev/null
+++ b/pkg/apis/camel/v1/maven_types_support_test.go
@@ -0,0 +1,142 @@
+/*
+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 v1
+
+import (
+	"bytes"
+	"encoding/xml"
+	"strings"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestMarshalEmptyProperties(t *testing.T) {
+	buf := new(bytes.Buffer)
+	e := xml.NewEncoder(buf)
+
+	err := Properties{}.MarshalXML(e, xml.StartElement{
+		Name: xml.Name{Local: "root"},
+	})
+
+	assert.NoError(t, err)
+
+	err = e.Flush()
+
+	assert.NoError(t, err)
+	assert.Equal(t, "", buf.String())
+}
+
+func TestMarshalProperties(t *testing.T) {
+	buf := new(bytes.Buffer)
+	e := xml.NewEncoder(buf)
+
+	properties := Properties{}
+	properties.Add("v1", "foo")
+	properties.Add("v2", "bar")
+
+	err := properties.MarshalXML(e, xml.StartElement{
+		Name: xml.Name{Local: "root"},
+	})
+
+	assert.NoError(t, err)
+
+	err = e.Flush()
+
+	assert.NoError(t, err)
+
+	result := buf.String()
+	assert.True(t, strings.HasPrefix(result, "<root>"))
+	assert.True(t, strings.HasSuffix(result, "</root>"))
+	assert.Contains(t, result, "<v1>foo</v1>")
+	assert.Contains(t, result, "<v2>bar</v2>")
+}
+
+func TestMarshalEmptyPluginProperties(t *testing.T) {
+	buf := new(bytes.Buffer)
+	e := xml.NewEncoder(buf)
+
+	err := PluginProperties{}.MarshalXML(e, xml.StartElement{
+		Name: xml.Name{Local: "root"},
+	})
+
+	assert.NoError(t, err)
+
+	err = e.Flush()
+
+	assert.NoError(t, err)
+	assert.Equal(t, "", buf.String())
+}
+
+func TestMarshalPluginProperties(t *testing.T) {
+	buf := new(bytes.Buffer)
+	e := xml.NewEncoder(buf)
+
+	properties := PluginProperties{}
+	properties.Add("v1", "foo")
+	properties.Add("v2", "bar")
+
+	err := properties.MarshalXML(e, xml.StartElement{
+		Name: xml.Name{Local: "root"},
+	})
+
+	assert.NoError(t, err)
+
+	err = e.Flush()
+
+	assert.NoError(t, err)
+
+	result := buf.String()
+	assert.True(t, strings.HasPrefix(result, "<root>"))
+	assert.True(t, strings.HasSuffix(result, "</root>"))
+	assert.Contains(t, result, "<v1>foo</v1>")
+	assert.Contains(t, result, "<v2>bar</v2>")
+}
+
+func TestMarshalPluginPropertiesWithNestedProps(t *testing.T) {
+	buf := new(bytes.Buffer)
+	e := xml.NewEncoder(buf)
+
+	properties := PluginProperties{}
+	properties.Add("v1", "foo")
+	properties.AddProperties("props", map[string]string{
+		"prop1": "foo",
+		"prop2": "baz",
+	})
+	properties.Add("v2", "bar")
+
+	err := properties.MarshalXML(e, xml.StartElement{
+		Name: xml.Name{Local: "root"},
+	})
+
+	assert.NoError(t, err)
+
+	err = e.Flush()
+
+	assert.NoError(t, err)
+
+	result := buf.String()
+	assert.True(t, strings.HasPrefix(result, "<root>"))
+	assert.True(t, strings.HasSuffix(result, "</root>"))
+	assert.Contains(t, result, "<v1>foo</v1>")
+	assert.Contains(t, result, "<props>")
+	assert.Contains(t, result, "</props>")
+	assert.Contains(t, result, "<prop1>foo</prop1>")
+	assert.Contains(t, result, "<prop2>baz</prop2>")
+	assert.Contains(t, result, "<v2>bar</v2>")
+}
diff --git a/pkg/apis/camel/v1/zz_generated.deepcopy.go b/pkg/apis/camel/v1/zz_generated.deepcopy.go
index 7aa25d965..a6082a6c2 100644
--- a/pkg/apis/camel/v1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1/zz_generated.deepcopy.go
@@ -1304,6 +1304,27 @@ func (in *MavenSpec) DeepCopy() *MavenSpec {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in PluginProperties) DeepCopyInto(out *PluginProperties) {
+	{
+		in := &in
+		*out = make(PluginProperties, len(*in))
+		for key, val := range *in {
+			(*out)[key] = *val.DeepCopy()
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PluginProperties.
+func (in PluginProperties) DeepCopy() PluginProperties {
+	if in == nil {
+		return nil
+	}
+	out := new(PluginProperties)
+	in.DeepCopyInto(out)
+	return *out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *PodSpec) DeepCopyInto(out *PodSpec) {
 	*out = *in
@@ -1623,6 +1644,28 @@ func (in *SpectrumTask) DeepCopy() *SpectrumTask {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *StringOrProperties) DeepCopyInto(out *StringOrProperties) {
+	*out = *in
+	if in.Properties != nil {
+		in, out := &in.Properties, &out.Properties
+		*out = make(Properties, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StringOrProperties.
+func (in *StringOrProperties) DeepCopy() *StringOrProperties {
+	if in == nil {
+		return nil
+	}
+	out := new(StringOrProperties)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Task) DeepCopyInto(out *Task) {
 	*out = *in
diff --git a/pkg/builder/project_test.go b/pkg/builder/project_test.go
index 15bd9f212..a529f058d 100644
--- a/pkg/builder/project_test.go
+++ b/pkg/builder/project_test.go
@@ -452,7 +452,7 @@ func TestInjectServersIntoDefaultMavenSettings(t *testing.T) {
 			ID:       "image-repository",
 			Username: "jpoth",
 			Password: "changeit",
-			Configuration: map[string]string{
+			Configuration: v1.Properties{
 				"allowInsecureRegistries": "false",
 			},
 		},
@@ -478,7 +478,7 @@ func TestInjectServersIntoCustomMavenSettings(t *testing.T) {
 			ID:       "image-repository",
 			Username: "jpoth",
 			Password: "changeit",
-			Configuration: map[string]string{
+			Configuration: v1.Properties{
 				"allowInsecureRegistries": "false",
 			},
 		},
diff --git a/pkg/builder/quarkus.go b/pkg/builder/quarkus.go
index f5ad3ef79..91d6bfa33 100644
--- a/pkg/builder/quarkus.go
+++ b/pkg/builder/quarkus.go
@@ -78,12 +78,9 @@ func loadCamelQuarkusCatalog(ctx *builderContext) error {
 
 func generateQuarkusProject(ctx *builderContext) error {
 	p := GenerateQuarkusProjectCommon(
-		ctx.Build.Runtime.Metadata["camel-quarkus.version"],
 		ctx.Build.Runtime.Version,
-		ctx.Build.Runtime.Metadata["quarkus.version"])
-
-	// Add all the properties from the build configuration
-	p.Properties.AddAll(ctx.Build.Maven.Properties)
+		ctx.Build.Runtime.Metadata["quarkus.version"],
+		ctx.Build.Maven.Properties)
 
 	// Add Maven build extensions
 	p.Build.Extensions = ctx.Build.Maven.Extension
@@ -96,23 +93,14 @@ func generateQuarkusProject(ctx *builderContext) error {
 	return nil
 }
 
-func GenerateQuarkusProjectCommon(camelQuarkusVersion string, runtimeVersion string, quarkusVersion string) maven.Project {
+func GenerateQuarkusProjectCommon(runtimeVersion string, quarkusVersion string, buildTimeProperties map[string]string) maven.Project {
 	p := maven.NewProjectWithGAV("org.apache.camel.k.integration", "camel-k-integration", defaults.Version)
 	p.DependencyManagement = &maven.DependencyManagement{Dependencies: make([]maven.Dependency, 0)}
 	p.Dependencies = make([]maven.Dependency, 0)
 	p.Build = &maven.Build{Plugins: make([]maven.Plugin, 0)}
 
-	// camel-quarkus does route discovery at startup, but we don't want
-	// this to happen as routes are loaded at runtime and looking for
-	// routes at build time may try to load camel-k-runtime routes builder
-	// proxies which in some case may fail.
-	p.Properties["quarkus.camel.routes-discovery.enabled"] = "false"
-
-	// disable quarkus banner
-	p.Properties["quarkus.banner.enabled"] = "false"
-
 	// set fast-jar packaging by default, since it gives some startup time improvements
-	p.Properties["quarkus.package.type"] = "fast-jar"
+	p.Properties.Add("quarkus.package.type", "fast-jar")
 
 	// DependencyManagement
 	p.DependencyManagement.Dependencies = append(p.DependencyManagement.Dependencies,
@@ -125,6 +113,34 @@ func GenerateQuarkusProjectCommon(camelQuarkusVersion string, runtimeVersion str
 		},
 	)
 
+	// Add all the properties from the build configuration
+	p.Properties.AddAll(buildTimeProperties)
+
+	// Quarkus build time properties
+	buildProperties := make(map[string]string)
+
+	// disable quarkus banner
+	buildProperties["quarkus.banner.enabled"] = "false"
+
+	// camel-quarkus does route discovery at startup, but we don't want
+	// this to happen as routes are loaded at runtime and looking for
+	// routes at build time may try to load camel-k-runtime routes builder
+	// proxies which in some case may fail.
+	buildProperties["quarkus.camel.routes-discovery.enabled"] = "false"
+
+	// required for Kamelets utils to resolve data type converters at runtime
+	buildProperties["quarkus.camel.service.discovery.include-patterns"] = "META-INF/services/org/apache/camel/datatype/converter/*"
+
+	// copy all user defined quarkus.camel build time properties to the quarkus-maven-plugin build properties
+	for key, value := range buildTimeProperties {
+		if strings.HasPrefix(key, "quarkus.camel.") {
+			buildProperties[key] = value
+		}
+	}
+
+	configuration := v1.PluginProperties{}
+	configuration.AddProperties("properties", buildProperties)
+
 	// Plugins
 	p.Build.Plugins = append(p.Build.Plugins,
 		maven.Plugin{
@@ -133,9 +149,11 @@ func GenerateQuarkusProjectCommon(camelQuarkusVersion string, runtimeVersion str
 			Version:    quarkusVersion,
 			Executions: []maven.Execution{
 				{
+					ID: "build-integration",
 					Goals: []string{
 						"build",
 					},
+					Configuration: configuration,
 				},
 			},
 		},
diff --git a/pkg/cmd/local/local.go b/pkg/cmd/local/local.go
index 0032e0eee..b1513a855 100644
--- a/pkg/cmd/local/local.go
+++ b/pkg/cmd/local/local.go
@@ -118,9 +118,9 @@ func getTopLevelDependencies(ctx context.Context, catalog *camel.RuntimeCatalog,
 
 func getTransitiveDependencies(ctx context.Context, catalog *camel.RuntimeCatalog, dependencies []string, repositories []string) ([]string, error) {
 	project := builder.GenerateQuarkusProjectCommon(
-		catalog.GetCamelQuarkusVersion(),
 		defaults.DefaultRuntimeVersion,
 		catalog.GetQuarkusVersion(),
+		make(map[string]string),
 	)
 
 	if err := camel.ManageIntegrationDependencies(&project, dependencies, catalog); err != nil {
diff --git a/pkg/util/camel/camel_dependencies.go b/pkg/util/camel/camel_dependencies.go
index 7ef91d326..a3b65b003 100644
--- a/pkg/util/camel/camel_dependencies.go
+++ b/pkg/util/camel/camel_dependencies.go
@@ -213,20 +213,22 @@ func addRegistryMavenDependency(project *maven.Project, dependency string) error
 	if isClasspath {
 		outputDirectory = "src/main/resources"
 	}
+
+	properties := v1.PluginProperties{}
+	properties.Add("outputDirectory", filepath.Join(outputDirectory, filepath.Dir(outputFileRelativePath)))
+	properties.Add("outputFileName", filepath.Base(outputFileRelativePath))
+	properties.Add("groupId", gav.GroupID)
+	properties.Add("artifactId", gav.ArtifactID)
+	properties.Add("version", gav.Version)
+	properties.Add("type", gav.Type)
+
 	exec := maven.Execution{
 		ID:    fmt.Sprint(len(plugin.Executions)),
 		Phase: "validate",
 		Goals: []string{
 			"artifact",
 		},
-		Configuration: map[string]string{
-			"outputDirectory": filepath.Join(outputDirectory, filepath.Dir(outputFileRelativePath)),
-			"outputFileName":  filepath.Base(outputFileRelativePath),
-			"groupId":         gav.GroupID,
-			"artifactId":      gav.ArtifactID,
-			"version":         gav.Version,
-			"type":            gav.Type,
-		},
+		Configuration: properties,
 	}
 	plugin.Executions = append(plugin.Executions, exec)
 
diff --git a/pkg/util/defaults/defaults.go b/pkg/util/defaults/defaults.go
index 3297388a4..f2a39043d 100644
--- a/pkg/util/defaults/defaults.go
+++ b/pkg/util/defaults/defaults.go
@@ -47,5 +47,5 @@ const (
 	installDefaultKamelets = true
 )
 
-//GitCommit must be provided during application build
+// GitCommit must be provided during application build
 var GitCommit string
diff --git a/pkg/util/maven/maven_project.go b/pkg/util/maven/maven_project.go
index f73eb0d01..9bb125d19 100644
--- a/pkg/util/maven/maven_project.go
+++ b/pkg/util/maven/maven_project.go
@@ -40,8 +40,9 @@ func NewProjectWithGAV(group string, artifact string, version string) Project {
 	p.GroupID = group
 	p.ArtifactID = artifact
 	p.Version = version
-	p.Properties = make(map[string]string)
-	p.Properties["project.build.sourceEncoding"] = "UTF-8"
+	p.Properties = v1.Properties{
+		"project.build.sourceEncoding": "UTF-8",
+	}
 
 	return p
 }
@@ -167,7 +168,7 @@ func NewDependency(groupID string, artifactID string, version string) Dependency
 // The repository can be customized by appending @param to the repository
 // URL, e.g.:
 //
-//     http://my-nexus:8081/repository/publicc@id=my-repo@snapshots
+//	http://my-nexus:8081/repository/publicc@id=my-repo@snapshots
 //
 // That enables snapshots and sets the repository id to `my-repo`.
 func NewRepository(repo string) v1.Repository {
diff --git a/pkg/util/maven/maven_types.go b/pkg/util/maven/maven_types.go
index b033a66b4..df8ed5d0a 100644
--- a/pkg/util/maven/maven_types.go
+++ b/pkg/util/maven/maven_types.go
@@ -45,10 +45,10 @@ type Plugin struct {
 }
 
 type Execution struct {
-	ID            string        `xml:"id,omitempty"`
-	Phase         string        `xml:"phase,omitempty"`
-	Goals         []string      `xml:"goals>goal,omitempty"`
-	Configuration v1.Properties `xml:"configuration,omitempty"`
+	ID            string              `xml:"id,omitempty"`
+	Phase         string              `xml:"phase,omitempty"`
+	Goals         []string            `xml:"goals>goal,omitempty"`
+	Configuration v1.PluginProperties `xml:"configuration,omitempty"`
 }
 
 // Settings models a Maven settings.