You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2021/12/07 13:51:51 UTC

[camel] branch main updated (1775fbd -> ccb89aa)

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

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


    from 1775fbd  Sync deps
     new 30b2fbc  CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file. WIP.
     new 65d9ed1  CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file. WIP.
     new a937b49  CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file. WIP.
     new 4ef0dc7  CAMEL-17288: camel-core - Route template parameters dash vs camel case keys and required
     new c2e6268  CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file. WIP.
     new dfae5bb  CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file. WIP.
     new f28834c  CAMEL-17282: RemoveHeader EIP remove deprecated headerName
     new ccb89aa  CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file.

The 8 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:
 .../org/apache/camel/RouteTemplateContext.java     |   8 +
 .../java/org/apache/camel/impl/DefaultModel.java   |  19 +-
 .../DeadLetterChannelBuilderConfigurer.java        | 145 ++++++
 .../DefaultErrorHandlerBuilderConfigurer.java      | 145 ++++++
 ...g.apache.camel.builder.DeadLetterChannelBuilder |   2 +
 ...apache.camel.builder.DefaultErrorHandlerBuilder |   2 +
 .../camel/builder/DeadLetterChannelBuilder.java    |   2 +
 .../camel/builder/DefaultErrorHandlerBuilder.java  |   2 +
 .../camel/model/DefaultRouteTemplateContext.java   |  18 +
 .../errorhandler/RedeliveryPolicyConfigurer.java   | 187 ++++++++
 ...e.camel.processor.errorhandler.RedeliveryPolicy |   2 +
 .../processor/errorhandler/RedeliveryPolicy.java   |   2 +
 .../modules/ROOT/pages/camel-jbang.adoc            |  36 ++
 dsl/camel-yaml-dsl/camel-yaml-dsl/pom.xml          |  10 +
 .../camel-yaml-dsl/src/main/docs/yaml-dsl.adoc     |  51 +++
 .../camel/dsl/yaml/YamlRoutesBuilderLoader.java    | 307 ++++++++++---
 .../dsl/yaml/YamlRoutesBuilderLoaderSupport.java   |  37 ++
 .../camel/dsl/yaml/KameletBindingLoaderTest.groovy | 496 +++++++++++++++++++++
 .../dsl/yaml/KameletIntegrationLoaderTest.groovy   |  61 +++
 .../apache/camel/dsl/yaml/RemoveHeaderTest.groovy  |   2 +-
 .../camel/dsl/yaml/support/YamlTestSupport.groovy  |  32 ++
 .../resources/kamelets/error-handler.kamelet.yaml  |  73 +++
 .../test/resources/kamelets/log-sink.kamelet.yaml  |  61 +++
 .../resources/kamelets/prefix-action.kamelet.yaml  |  45 ++
 .../resources/kamelets/timer-source.kamelet.yaml   |  69 +++
 25 files changed, 1737 insertions(+), 77 deletions(-)
 create mode 100644 core/camel-core-model/src/generated/java/org/apache/camel/builder/DeadLetterChannelBuilderConfigurer.java
 create mode 100644 core/camel-core-model/src/generated/java/org/apache/camel/builder/DefaultErrorHandlerBuilderConfigurer.java
 create mode 100644 core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.builder.DeadLetterChannelBuilder
 create mode 100644 core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.builder.DefaultErrorHandlerBuilder
 create mode 100644 core/camel-core-processor/src/generated/java/org/apache/camel/processor/errorhandler/RedeliveryPolicyConfigurer.java
 create mode 100644 core/camel-core-processor/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.processor.errorhandler.RedeliveryPolicy
 create mode 100644 dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy
 create mode 100644 dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletIntegrationLoaderTest.groovy
 create mode 100644 dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/error-handler.kamelet.yaml
 create mode 100644 dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/log-sink.kamelet.yaml
 create mode 100644 dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/prefix-action.kamelet.yaml
 create mode 100644 dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/timer-source.kamelet.yaml

[camel] 02/08: CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file. WIP.

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

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

commit 65d9ed1dce2446d5d26013f15f20818319de7e6b
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Dec 7 07:58:51 2021 +0100

    CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file. WIP.
---
 .../camel/dsl/yaml/YamlRoutesBuilderLoader.java    | 14 +++++
 .../camel/dsl/yaml/KameletBindingLoaderTest.groovy |  5 +-
 .../resources/kamelets/error-handler.kamelet.yaml  | 73 ++++++++++++++++++++++
 3 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
index fa7ca59..2bd9348 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
@@ -36,6 +36,7 @@ import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.model.rest.VerbDefinition;
 import org.apache.camel.spi.CamelContextCustomizer;
 import org.apache.camel.spi.annotations.RoutesLoader;
+import org.apache.camel.support.IntrospectionSupport;
 import org.apache.camel.util.URISupport;
 import org.snakeyaml.engine.v2.nodes.MappingNode;
 import org.snakeyaml.engine.v2.nodes.Node;
@@ -236,6 +237,19 @@ public class YamlRoutesBuilderLoader extends YamlRoutesBuilderLoaderSupport {
                 String ehName = asText(nt.getKeyNode());
                 if ("dead-letter-channel".equals(ehName)) {
                     DeadLetterChannelBuilder dlcb = new DeadLetterChannelBuilder();
+
+                    // endpoint
+                    MappingNode endpoint = asMappingNode(nodeAt(nt.getValueNode(), "/endpoint"));
+                    String dlq = extractCamelEndpointUri(endpoint);
+                    dlcb.setDeadLetterUri(dlq);
+
+                    // properties (TODO: via reflection - need builder)
+                    MappingNode prop = asMappingNode(nodeAt(nt.getValueNode(), "/parameters"));
+                    Map<String, Object> params = asMap(prop);
+                    if (params != null) {
+                        IntrospectionSupport.setProperties(getCamelContext(), getCamelContext().getTypeConverter(), dlcb, params);
+                    }
+                    route.errorHandler(dlcb);
                }
             }
 
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy
index d80319e..b2f6c81 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy
@@ -24,7 +24,7 @@ class KameletBindingLoaderTest extends YamlTestSupport {
     def doSetup() {
         context.start()
     }
-
+/*
     def "kamelet binding from kamelet to kamelet"() {
         when:
             loadBindings('''
@@ -244,6 +244,7 @@ class KameletBindingLoaderTest extends YamlTestSupport {
         when:
 
         // stub kafka for testing as it requires to setup connection to a real kafka broker
+        context.removeComponent("kafka")
         context.addComponent("kafka", context.getComponent("stub"))
 
         loadBindings('''
@@ -277,7 +278,7 @@ class KameletBindingLoaderTest extends YamlTestSupport {
             }
         }
     }
-
+*/
     def "kamelet binding with error handler"() {
         when:
 
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/error-handler.kamelet.yaml b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/error-handler.kamelet.yaml
new file mode 100644
index 0000000..7fcd6bd
--- /dev/null
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/error-handler.kamelet.yaml
@@ -0,0 +1,73 @@
+# ---------------------------------------------------------------------------
+# 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: error-handler
+spec:
+  definition:
+    title: "DLC and Log"
+    description: "Push an event to a kafka topic and log an error message"
+    required:
+      - kafka-brokers
+      - kafka-topic
+      - kafka-service-account-id
+      - kafka-service-account-secret
+      - log-message
+    properties:
+      kafka-brokers:
+        title: Kafka Brokers
+        description: the bootstrap server
+        type: string
+        example: "xyz-ins--rplssqfz-yyyyyyy-crojg.bf2.kafka.my-clud-service.com:443"
+      kafka-topic:
+        title: Kafka Topic
+        description: the DLC topic
+        type: string
+        example: "my-dlc"
+      kafka-service-account-id:
+        title: Service Account ID
+        description: the SA to use
+        type: string
+        example: "srvc-acct-xxxxxx-519b-453f-9f68-yyyyyyyyy"
+      kafka-service-account-secret:
+        title: Service Account Secret
+        description: the SA secrete to use
+        type: string
+        example: "xxxxxxxxx-46c7-4c6c-a753-yyyyyyyyyyyyyyy"
+      log-message:
+        title: Message
+        description: A message warning to log
+        type: string
+        example: "error while checking the source"
+  flow:
+    from:
+      uri: kamelet:source
+      steps:
+        # First step: send to the DLC for future processing
+        - to:
+            uri: kafka:{{kafka-topic}}
+            parameters:
+              brokers: "{{kafka-brokers}}"
+              security-protocol: SASL_SSL
+              sasl-mechanism: PLAIN
+              sasl-jaas-config: "org.apache.kafka.common.security.plain.PlainLoginModule required username={{kafka-service-account-id}} password={{kafka-service-account-secret}};"
+        # Log an error message to notify about the failure
+        - set-body:
+            constant: "{{log-message}} - worry not, the event is stored in the DLC"
+        - to: "log:error-sink"

[camel] 06/08: CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file. WIP.

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

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

commit dfae5bb564373e2c2b2783144c0b24fcb201bd36
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Dec 7 11:55:03 2021 +0100

    CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file. WIP.
---
 .../errorhandler/RedeliveryPolicyConfigurer.java   | 187 +++++++++++++++++++++
 ...e.camel.processor.errorhandler.RedeliveryPolicy |   2 +
 .../processor/errorhandler/RedeliveryPolicy.java   |   2 +
 .../dsl/yaml/deserializers/ModelDeserializers.java |  37 ++++
 .../deserializers/ModelDeserializersResolver.java  |   3 +
 .../src/generated/resources/camel-yaml-dsl.json    |   9 +
 .../camel/dsl/yaml/YamlRoutesBuilderLoader.java    |  13 +-
 7 files changed, 248 insertions(+), 5 deletions(-)

diff --git a/core/camel-core-processor/src/generated/java/org/apache/camel/processor/errorhandler/RedeliveryPolicyConfigurer.java b/core/camel-core-processor/src/generated/java/org/apache/camel/processor/errorhandler/RedeliveryPolicyConfigurer.java
new file mode 100644
index 0000000..830bf4d
--- /dev/null
+++ b/core/camel-core-processor/src/generated/java/org/apache/camel/processor/errorhandler/RedeliveryPolicyConfigurer.java
@@ -0,0 +1,187 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.processor.errorhandler;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.processor.errorhandler.RedeliveryPolicy;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@SuppressWarnings("unchecked")
+public class RedeliveryPolicyConfigurer extends org.apache.camel.support.component.PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+        org.apache.camel.processor.errorhandler.RedeliveryPolicy target = (org.apache.camel.processor.errorhandler.RedeliveryPolicy) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowredeliverywhilestopping":
+        case "AllowRedeliveryWhileStopping": target.setAllowRedeliveryWhileStopping(property(camelContext, boolean.class, value)); return true;
+        case "asyncdelayedredelivery":
+        case "AsyncDelayedRedelivery": target.setAsyncDelayedRedelivery(property(camelContext, boolean.class, value)); return true;
+        case "backoffmultiplier":
+        case "BackOffMultiplier": target.setBackOffMultiplier(property(camelContext, double.class, value)); return true;
+        case "collisionavoidancefactor":
+        case "CollisionAvoidanceFactor": target.setCollisionAvoidanceFactor(property(camelContext, double.class, value)); return true;
+        case "collisionavoidancepercent":
+        case "CollisionAvoidancePercent": target.setCollisionAvoidancePercent(property(camelContext, double.class, value)); return true;
+        case "delaypattern":
+        case "DelayPattern": target.setDelayPattern(property(camelContext, java.lang.String.class, value)); return true;
+        case "exchangeformatterref":
+        case "ExchangeFormatterRef": target.setExchangeFormatterRef(property(camelContext, java.lang.String.class, value)); return true;
+        case "logcontinued":
+        case "LogContinued": target.setLogContinued(property(camelContext, boolean.class, value)); return true;
+        case "logexhausted":
+        case "LogExhausted": target.setLogExhausted(property(camelContext, boolean.class, value)); return true;
+        case "logexhaustedmessagebody":
+        case "LogExhaustedMessageBody": target.setLogExhaustedMessageBody(property(camelContext, java.lang.Boolean.class, value)); return true;
+        case "logexhaustedmessagehistory":
+        case "LogExhaustedMessageHistory": target.setLogExhaustedMessageHistory(property(camelContext, boolean.class, value)); return true;
+        case "loghandled":
+        case "LogHandled": target.setLogHandled(property(camelContext, boolean.class, value)); return true;
+        case "lognewexception":
+        case "LogNewException": target.setLogNewException(property(camelContext, boolean.class, value)); return true;
+        case "logretryattempted":
+        case "LogRetryAttempted": target.setLogRetryAttempted(property(camelContext, boolean.class, value)); return true;
+        case "logretrystacktrace":
+        case "LogRetryStackTrace": target.setLogRetryStackTrace(property(camelContext, boolean.class, value)); return true;
+        case "logstacktrace":
+        case "LogStackTrace": target.setLogStackTrace(property(camelContext, boolean.class, value)); return true;
+        case "maximumredeliveries":
+        case "MaximumRedeliveries": target.setMaximumRedeliveries(property(camelContext, int.class, value)); return true;
+        case "maximumredeliverydelay":
+        case "MaximumRedeliveryDelay": target.setMaximumRedeliveryDelay(property(camelContext, long.class, value)); return true;
+        case "redeliverydelay":
+        case "RedeliveryDelay": target.setRedeliveryDelay(property(camelContext, long.class, value)); return true;
+        case "retriesexhaustedloglevel":
+        case "RetriesExhaustedLogLevel": target.setRetriesExhaustedLogLevel(property(camelContext, org.apache.camel.LoggingLevel.class, value)); return true;
+        case "retryattemptedloginterval":
+        case "RetryAttemptedLogInterval": target.setRetryAttemptedLogInterval(property(camelContext, int.class, value)); return true;
+        case "retryattemptedloglevel":
+        case "RetryAttemptedLogLevel": target.setRetryAttemptedLogLevel(property(camelContext, org.apache.camel.LoggingLevel.class, value)); return true;
+        case "usecollisionavoidance":
+        case "UseCollisionAvoidance": target.setUseCollisionAvoidance(property(camelContext, boolean.class, value)); return true;
+        case "useexponentialbackoff":
+        case "UseExponentialBackOff": target.setUseExponentialBackOff(property(camelContext, boolean.class, value)); return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowredeliverywhilestopping":
+        case "AllowRedeliveryWhileStopping": return boolean.class;
+        case "asyncdelayedredelivery":
+        case "AsyncDelayedRedelivery": return boolean.class;
+        case "backoffmultiplier":
+        case "BackOffMultiplier": return double.class;
+        case "collisionavoidancefactor":
+        case "CollisionAvoidanceFactor": return double.class;
+        case "collisionavoidancepercent":
+        case "CollisionAvoidancePercent": return double.class;
+        case "delaypattern":
+        case "DelayPattern": return java.lang.String.class;
+        case "exchangeformatterref":
+        case "ExchangeFormatterRef": return java.lang.String.class;
+        case "logcontinued":
+        case "LogContinued": return boolean.class;
+        case "logexhausted":
+        case "LogExhausted": return boolean.class;
+        case "logexhaustedmessagebody":
+        case "LogExhaustedMessageBody": return java.lang.Boolean.class;
+        case "logexhaustedmessagehistory":
+        case "LogExhaustedMessageHistory": return boolean.class;
+        case "loghandled":
+        case "LogHandled": return boolean.class;
+        case "lognewexception":
+        case "LogNewException": return boolean.class;
+        case "logretryattempted":
+        case "LogRetryAttempted": return boolean.class;
+        case "logretrystacktrace":
+        case "LogRetryStackTrace": return boolean.class;
+        case "logstacktrace":
+        case "LogStackTrace": return boolean.class;
+        case "maximumredeliveries":
+        case "MaximumRedeliveries": return int.class;
+        case "maximumredeliverydelay":
+        case "MaximumRedeliveryDelay": return long.class;
+        case "redeliverydelay":
+        case "RedeliveryDelay": return long.class;
+        case "retriesexhaustedloglevel":
+        case "RetriesExhaustedLogLevel": return org.apache.camel.LoggingLevel.class;
+        case "retryattemptedloginterval":
+        case "RetryAttemptedLogInterval": return int.class;
+        case "retryattemptedloglevel":
+        case "RetryAttemptedLogLevel": return org.apache.camel.LoggingLevel.class;
+        case "usecollisionavoidance":
+        case "UseCollisionAvoidance": return boolean.class;
+        case "useexponentialbackoff":
+        case "UseExponentialBackOff": return boolean.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        org.apache.camel.processor.errorhandler.RedeliveryPolicy target = (org.apache.camel.processor.errorhandler.RedeliveryPolicy) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowredeliverywhilestopping":
+        case "AllowRedeliveryWhileStopping": return target.isAllowRedeliveryWhileStopping();
+        case "asyncdelayedredelivery":
+        case "AsyncDelayedRedelivery": return target.isAsyncDelayedRedelivery();
+        case "backoffmultiplier":
+        case "BackOffMultiplier": return target.getBackOffMultiplier();
+        case "collisionavoidancefactor":
+        case "CollisionAvoidanceFactor": return target.getCollisionAvoidanceFactor();
+        case "collisionavoidancepercent":
+        case "CollisionAvoidancePercent": return target.getCollisionAvoidancePercent();
+        case "delaypattern":
+        case "DelayPattern": return target.getDelayPattern();
+        case "exchangeformatterref":
+        case "ExchangeFormatterRef": return target.getExchangeFormatterRef();
+        case "logcontinued":
+        case "LogContinued": return target.isLogContinued();
+        case "logexhausted":
+        case "LogExhausted": return target.isLogExhausted();
+        case "logexhaustedmessagebody":
+        case "LogExhaustedMessageBody": return target.isLogExhaustedMessageBody();
+        case "logexhaustedmessagehistory":
+        case "LogExhaustedMessageHistory": return target.isLogExhaustedMessageHistory();
+        case "loghandled":
+        case "LogHandled": return target.isLogHandled();
+        case "lognewexception":
+        case "LogNewException": return target.isLogNewException();
+        case "logretryattempted":
+        case "LogRetryAttempted": return target.isLogRetryAttempted();
+        case "logretrystacktrace":
+        case "LogRetryStackTrace": return target.isLogRetryStackTrace();
+        case "logstacktrace":
+        case "LogStackTrace": return target.isLogStackTrace();
+        case "maximumredeliveries":
+        case "MaximumRedeliveries": return target.getMaximumRedeliveries();
+        case "maximumredeliverydelay":
+        case "MaximumRedeliveryDelay": return target.getMaximumRedeliveryDelay();
+        case "redeliverydelay":
+        case "RedeliveryDelay": return target.getRedeliveryDelay();
+        case "retriesexhaustedloglevel":
+        case "RetriesExhaustedLogLevel": return target.getRetriesExhaustedLogLevel();
+        case "retryattemptedloginterval":
+        case "RetryAttemptedLogInterval": return target.getRetryAttemptedLogInterval();
+        case "retryattemptedloglevel":
+        case "RetryAttemptedLogLevel": return target.getRetryAttemptedLogLevel();
+        case "usecollisionavoidance":
+        case "UseCollisionAvoidance": return target.isUseCollisionAvoidance();
+        case "useexponentialbackoff":
+        case "UseExponentialBackOff": return target.isUseExponentialBackOff();
+        default: return null;
+        }
+    }
+}
+
diff --git a/core/camel-core-processor/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.processor.errorhandler.RedeliveryPolicy b/core/camel-core-processor/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.processor.errorhandler.RedeliveryPolicy
new file mode 100644
index 0000000..41037d1
--- /dev/null
+++ b/core/camel-core-processor/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.processor.errorhandler.RedeliveryPolicy
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.processor.errorhandler.RedeliveryPolicyConfigurer
diff --git a/core/camel-core-processor/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryPolicy.java b/core/camel-core-processor/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryPolicy.java
index 7f6a6a9..87e5ffe 100644
--- a/core/camel-core-processor/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryPolicy.java
+++ b/core/camel-core-processor/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryPolicy.java
@@ -22,6 +22,7 @@ import java.util.Random;
 import org.apache.camel.Exchange;
 import org.apache.camel.LoggingLevel;
 import org.apache.camel.Predicate;
+import org.apache.camel.spi.Configurer;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.StringHelper;
 import org.slf4j.Logger;
@@ -78,6 +79,7 @@ import org.slf4j.LoggerFactory;
  * If you want to set a starting delay, then use 0 as the first limit, eg: <tt>0:1000;5:5000</tt> will use 1 sec delay
  * until attempt number 5 where it will use 5 seconds going forward.
  */
+@Configurer
 public class RedeliveryPolicy implements Cloneable, Serializable {
     // default policy using out of the box settings which can be shared
     public static final RedeliveryPolicy DEFAULT_POLICY = new RedeliveryPolicy();
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
index a6eb0f8..1804ce1 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
@@ -69,6 +69,7 @@ import org.apache.camel.model.Resilience4jConfigurationDefinition;
 import org.apache.camel.model.RestContextRefDefinition;
 import org.apache.camel.model.RollbackDefinition;
 import org.apache.camel.model.RouteBuilderDefinition;
+import org.apache.camel.model.RouteConfigurationContextRefDefinition;
 import org.apache.camel.model.RouteContextRefDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RouteTemplateParameterDefinition;
@@ -12918,6 +12919,42 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
     }
 
     @YamlType(
+            types = org.apache.camel.model.RouteConfigurationContextRefDefinition.class,
+            order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
+            nodes = {
+                    "route-configuration-context-ref",
+                    "routeConfigurationContextRef"
+            },
+            properties = @YamlProperty(name = "ref", type = "string", required = true)
+    )
+    public static class RouteConfigurationContextRefDefinitionDeserializer extends YamlDeserializerBase<RouteConfigurationContextRefDefinition> {
+        public RouteConfigurationContextRefDefinitionDeserializer() {
+            super(RouteConfigurationContextRefDefinition.class);
+        }
+
+        @Override
+        protected RouteConfigurationContextRefDefinition newInstance() {
+            return new RouteConfigurationContextRefDefinition();
+        }
+
+        @Override
+        protected boolean setProperty(RouteConfigurationContextRefDefinition target,
+                String propertyKey, String propertyName, Node node) {
+            switch(propertyKey) {
+                case "ref": {
+                    String val = asText(node);
+                    target.setRef(val);
+                    break;
+                }
+                default: {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    @YamlType(
             types = org.apache.camel.model.RouteContextRefDefinition.class,
             order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
             nodes = {
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
index f5837a5..f0629b1 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
@@ -363,6 +363,9 @@ public final class ModelDeserializersResolver implements YamlDeserializerResolve
             case "route-builder": return new ModelDeserializers.RouteBuilderDefinitionDeserializer();
             case "routeBuilder": return new ModelDeserializers.RouteBuilderDefinitionDeserializer();
             case "org.apache.camel.model.RouteBuilderDefinition": return new ModelDeserializers.RouteBuilderDefinitionDeserializer();
+            case "route-configuration-context-ref": return new ModelDeserializers.RouteConfigurationContextRefDefinitionDeserializer();
+            case "routeConfigurationContextRef": return new ModelDeserializers.RouteConfigurationContextRefDefinitionDeserializer();
+            case "org.apache.camel.model.RouteConfigurationContextRefDefinition": return new ModelDeserializers.RouteConfigurationContextRefDefinitionDeserializer();
             case "route-context-ref": return new ModelDeserializers.RouteContextRefDefinitionDeserializer();
             case "routeContextRef": return new ModelDeserializers.RouteContextRefDefinitionDeserializer();
             case "org.apache.camel.model.RouteContextRefDefinition": return new ModelDeserializers.RouteContextRefDefinitionDeserializer();
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
index 89dfbf3..62e992b 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
@@ -2131,6 +2131,15 @@
         } ],
         "required" : [ "ref" ]
       },
+      "org.apache.camel.model.RouteConfigurationContextRefDefinition" : {
+        "type" : "object",
+        "properties" : {
+          "ref" : {
+            "type" : "string"
+          }
+        },
+        "required" : [ "ref" ]
+      },
       "org.apache.camel.model.RouteConfigurationDefinition" : {
         "oneOf" : [ {
           "type" : "string"
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
index 030d971..2d44291 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
@@ -34,9 +34,10 @@ import org.apache.camel.model.RouteTemplateDefinition;
 import org.apache.camel.model.rest.RestConfigurationDefinition;
 import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.model.rest.VerbDefinition;
+import org.apache.camel.processor.errorhandler.RedeliveryPolicy;
 import org.apache.camel.spi.CamelContextCustomizer;
 import org.apache.camel.spi.annotations.RoutesLoader;
-import org.apache.camel.support.IntrospectionSupport;
+import org.apache.camel.support.PropertyBindingSupport;
 import org.apache.camel.util.URISupport;
 import org.snakeyaml.engine.v2.nodes.MappingNode;
 import org.snakeyaml.engine.v2.nodes.Node;
@@ -244,15 +245,17 @@ public class YamlRoutesBuilderLoader extends YamlRoutesBuilderLoaderSupport {
                     String dlq = extractCamelEndpointUri(endpoint);
                     dlcb.setDeadLetterUri(dlq);
 
-                    // properties (TODO: via reflection - need builder)
-                    // TODO: route templates store user parameters in cameCase (eg convert dash to camel case) (like camel-main)
+                    // properties
                     MappingNode prop = asMappingNode(nodeAt(nt.getValueNode(), "/parameters"));
                     Map<String, Object> params = asMap(prop);
                     if (params != null) {
-                        IntrospectionSupport.setProperties(getCamelContext(), getCamelContext().getTypeConverter(), dlcb, params);
+                        // the parameters are for redelivery policy
+                        RedeliveryPolicy rp = new RedeliveryPolicy();
+                        dlcb.setRedeliveryPolicy(rp);
+                        PropertyBindingSupport.build().withIgnoreCase(true).bind(getCamelContext(), rp, params);
                     }
                     route.errorHandler(dlcb);
-               }
+                }
             }
 
             target = route;

[camel] 05/08: CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file. WIP.

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

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

commit c2e6268c0ad854d1f8eb5e926d6590cc68b9cc13
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Dec 7 11:41:43 2021 +0100

    CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file. WIP.
---
 .../camel/dsl/yaml/KameletBindingLoaderTest.groovy | 64 +++++++++++++++++++++-
 1 file changed, 61 insertions(+), 3 deletions(-)

diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy
index 7e27750..166bdc5 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy
@@ -16,17 +16,19 @@
  */
 package org.apache.camel.dsl.yaml
 
+import org.apache.camel.Exchange
+import org.apache.camel.Processor
 import org.apache.camel.builder.DeadLetterChannelBuilder
+import org.apache.camel.component.mock.MockEndpoint
 import org.apache.camel.dsl.yaml.support.YamlTestSupport
 import org.apache.camel.model.ToDefinition
-import org.apache.camel.processor.errorhandler.DeadLetterChannel
 
 class KameletBindingLoaderTest extends YamlTestSupport {
     @Override
     def doSetup() {
         context.start()
     }
-/*
+
     def "kamelet binding from kamelet to kamelet"() {
         when:
             loadBindings('''
@@ -280,7 +282,7 @@ class KameletBindingLoaderTest extends YamlTestSupport {
             }
         }
     }
-*/
+
     def "kamelet binding with error handler"() {
         when:
 
@@ -341,4 +343,60 @@ class KameletBindingLoaderTest extends YamlTestSupport {
         }
     }
 
+    def "kamelet binding with error handler move to dlq"() {
+        when:
+
+        context.registry.bind 'chaos', new Processor() {
+            @Override
+            void process(Exchange exchange) throws Exception {
+                throw new IllegalArgumentException("Forced");
+            }
+        };
+
+        loadBindings('''
+                apiVersion: camel.apache.org/v1alpha1
+                kind: KameletBinding
+                metadata:
+                  name: timer-event-source                  
+                spec:
+                  source:
+                    ref:
+                      kind: Kamelet
+                      apiVersion: camel.apache.org/v1
+                      name: timer-source
+                    properties:
+                      message: "Hello world!"
+                  steps:
+                    - uri: bean:chaos  
+                  sink:
+                    ref:
+                      kind: Kamelet
+                      apiVersion: camel.apache.org/v1alpha1
+                      name: log-sink
+                  errorHandler:
+                    dead-letter-channel:
+                      endpoint:
+                        uri: mock:dead
+                      parameters:
+                        maximumRedeliveries: 3
+                        redeliveryDelay: 100    
+                    ''')
+        then:
+        context.routeDefinitions.size() == 3
+
+        MockEndpoint mock = context.getEndpoint("mock:dead", MockEndpoint.class)
+        mock.expectedMinimumMessageCount(1)
+
+        mock.assertIsSatisfied()
+
+        with (context.routeDefinitions[0]) {
+            errorHandlerFactory != null
+            errorHandlerFactory instanceof DeadLetterChannelBuilder
+            var eh = errorHandlerFactory as DeadLetterChannelBuilder
+            eh.deadLetterUri == 'mock:dead'
+            eh.redeliveryPolicy.maximumRedeliveries == 3
+            eh.redeliveryPolicy.redeliveryDelay == 100
+        }
+    }
+
 }

[camel] 08/08: CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file.

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

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

commit ccb89aa0a1a413ffc3dacaed3af1a0c0ab089c3b
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Dec 7 14:48:55 2021 +0100

    CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file.
---
 .../DeadLetterChannelBuilderConfigurer.java        | 145 +++++++++++++++++++++
 .../DefaultErrorHandlerBuilderConfigurer.java      | 145 +++++++++++++++++++++
 ...g.apache.camel.builder.DeadLetterChannelBuilder |   2 +
 ...apache.camel.builder.DefaultErrorHandlerBuilder |   2 +
 .../camel/builder/DeadLetterChannelBuilder.java    |   2 +
 .../camel/builder/DefaultErrorHandlerBuilder.java  |   2 +
 .../modules/ROOT/pages/camel-jbang.adoc            |  36 +++++
 .../camel-yaml-dsl/src/main/docs/yaml-dsl.adoc     |  51 ++++++++
 .../camel/dsl/yaml/YamlRoutesBuilderLoader.java    |  41 ++++--
 .../camel/dsl/yaml/KameletBindingLoaderTest.groovy |  94 +++++++++++++
 .../dsl/yaml/KameletIntegrationLoaderTest.groovy   |  61 +++++++++
 .../camel/dsl/yaml/support/YamlTestSupport.groovy  |  10 ++
 12 files changed, 580 insertions(+), 11 deletions(-)

diff --git a/core/camel-core-model/src/generated/java/org/apache/camel/builder/DeadLetterChannelBuilderConfigurer.java b/core/camel-core-model/src/generated/java/org/apache/camel/builder/DeadLetterChannelBuilderConfigurer.java
new file mode 100644
index 0000000..8c62d65
--- /dev/null
+++ b/core/camel-core-model/src/generated/java/org/apache/camel/builder/DeadLetterChannelBuilderConfigurer.java
@@ -0,0 +1,145 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.builder;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.builder.DeadLetterChannelBuilder;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@SuppressWarnings("unchecked")
+public class DeadLetterChannelBuilderConfigurer extends org.apache.camel.support.component.PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+        org.apache.camel.builder.DeadLetterChannelBuilder target = (org.apache.camel.builder.DeadLetterChannelBuilder) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "asyncdelayedredelivery":
+        case "AsyncDelayedRedelivery": target.setAsyncDelayedRedelivery(property(camelContext, boolean.class, value)); return true;
+        case "deadletterhandlenewexception":
+        case "DeadLetterHandleNewException": target.setDeadLetterHandleNewException(property(camelContext, boolean.class, value)); return true;
+        case "deadletteruri":
+        case "DeadLetterUri": target.setDeadLetterUri(property(camelContext, java.lang.String.class, value)); return true;
+        case "executorservice":
+        case "ExecutorService": target.setExecutorService(property(camelContext, java.util.concurrent.ScheduledExecutorService.class, value)); return true;
+        case "executorserviceref":
+        case "ExecutorServiceRef": target.setExecutorServiceRef(property(camelContext, java.lang.String.class, value)); return true;
+        case "logger":
+        case "Logger": target.setLogger(property(camelContext, org.apache.camel.spi.CamelLogger.class, value)); return true;
+        case "onexceptionoccurred":
+        case "OnExceptionOccurred": target.setOnExceptionOccurred(property(camelContext, org.apache.camel.Processor.class, value)); return true;
+        case "onexceptionoccurredref":
+        case "OnExceptionOccurredRef": target.setOnExceptionOccurredRef(property(camelContext, java.lang.String.class, value)); return true;
+        case "onpreparefailure":
+        case "OnPrepareFailure": target.setOnPrepareFailure(property(camelContext, org.apache.camel.Processor.class, value)); return true;
+        case "onpreparefailureref":
+        case "OnPrepareFailureRef": target.setOnPrepareFailureRef(property(camelContext, java.lang.String.class, value)); return true;
+        case "onredelivery":
+        case "OnRedelivery": target.setOnRedelivery(property(camelContext, org.apache.camel.Processor.class, value)); return true;
+        case "onredeliveryref":
+        case "OnRedeliveryRef": target.setOnRedeliveryRef(property(camelContext, java.lang.String.class, value)); return true;
+        case "redeliverypolicy":
+        case "RedeliveryPolicy": target.setRedeliveryPolicy(property(camelContext, org.apache.camel.processor.errorhandler.RedeliveryPolicy.class, value)); return true;
+        case "retrywhile":
+        case "RetryWhile": target.setRetryWhile(property(camelContext, org.apache.camel.Predicate.class, value)); return true;
+        case "retrywhileref":
+        case "RetryWhileRef": target.setRetryWhileRef(property(camelContext, java.lang.String.class, value)); return true;
+        case "useoriginalbody":
+        case "UseOriginalBody": target.setUseOriginalBody(property(camelContext, boolean.class, value)); return true;
+        case "useoriginalmessage":
+        case "UseOriginalMessage": target.setUseOriginalMessage(property(camelContext, boolean.class, value)); return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "asyncdelayedredelivery":
+        case "AsyncDelayedRedelivery": return boolean.class;
+        case "deadletterhandlenewexception":
+        case "DeadLetterHandleNewException": return boolean.class;
+        case "deadletteruri":
+        case "DeadLetterUri": return java.lang.String.class;
+        case "executorservice":
+        case "ExecutorService": return java.util.concurrent.ScheduledExecutorService.class;
+        case "executorserviceref":
+        case "ExecutorServiceRef": return java.lang.String.class;
+        case "logger":
+        case "Logger": return org.apache.camel.spi.CamelLogger.class;
+        case "onexceptionoccurred":
+        case "OnExceptionOccurred": return org.apache.camel.Processor.class;
+        case "onexceptionoccurredref":
+        case "OnExceptionOccurredRef": return java.lang.String.class;
+        case "onpreparefailure":
+        case "OnPrepareFailure": return org.apache.camel.Processor.class;
+        case "onpreparefailureref":
+        case "OnPrepareFailureRef": return java.lang.String.class;
+        case "onredelivery":
+        case "OnRedelivery": return org.apache.camel.Processor.class;
+        case "onredeliveryref":
+        case "OnRedeliveryRef": return java.lang.String.class;
+        case "redeliverypolicy":
+        case "RedeliveryPolicy": return org.apache.camel.processor.errorhandler.RedeliveryPolicy.class;
+        case "retrywhile":
+        case "RetryWhile": return org.apache.camel.Predicate.class;
+        case "retrywhileref":
+        case "RetryWhileRef": return java.lang.String.class;
+        case "useoriginalbody":
+        case "UseOriginalBody": return boolean.class;
+        case "useoriginalmessage":
+        case "UseOriginalMessage": return boolean.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        org.apache.camel.builder.DeadLetterChannelBuilder target = (org.apache.camel.builder.DeadLetterChannelBuilder) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "asyncdelayedredelivery":
+        case "AsyncDelayedRedelivery": return target.isAsyncDelayedRedelivery();
+        case "deadletterhandlenewexception":
+        case "DeadLetterHandleNewException": return target.isDeadLetterHandleNewException();
+        case "deadletteruri":
+        case "DeadLetterUri": return target.getDeadLetterUri();
+        case "executorservice":
+        case "ExecutorService": return target.getExecutorService();
+        case "executorserviceref":
+        case "ExecutorServiceRef": return target.getExecutorServiceRef();
+        case "logger":
+        case "Logger": return target.getLogger();
+        case "onexceptionoccurred":
+        case "OnExceptionOccurred": return target.getOnExceptionOccurred();
+        case "onexceptionoccurredref":
+        case "OnExceptionOccurredRef": return target.getOnExceptionOccurredRef();
+        case "onpreparefailure":
+        case "OnPrepareFailure": return target.getOnPrepareFailure();
+        case "onpreparefailureref":
+        case "OnPrepareFailureRef": return target.getOnPrepareFailureRef();
+        case "onredelivery":
+        case "OnRedelivery": return target.getOnRedelivery();
+        case "onredeliveryref":
+        case "OnRedeliveryRef": return target.getOnRedeliveryRef();
+        case "redeliverypolicy":
+        case "RedeliveryPolicy": return target.getRedeliveryPolicy();
+        case "retrywhile":
+        case "RetryWhile": return target.getRetryWhile();
+        case "retrywhileref":
+        case "RetryWhileRef": return target.getRetryWhileRef();
+        case "useoriginalbody":
+        case "UseOriginalBody": return target.isUseOriginalBody();
+        case "useoriginalmessage":
+        case "UseOriginalMessage": return target.isUseOriginalMessage();
+        default: return null;
+        }
+    }
+}
+
diff --git a/core/camel-core-model/src/generated/java/org/apache/camel/builder/DefaultErrorHandlerBuilderConfigurer.java b/core/camel-core-model/src/generated/java/org/apache/camel/builder/DefaultErrorHandlerBuilderConfigurer.java
new file mode 100644
index 0000000..cf45d98
--- /dev/null
+++ b/core/camel-core-model/src/generated/java/org/apache/camel/builder/DefaultErrorHandlerBuilderConfigurer.java
@@ -0,0 +1,145 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.builder;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.builder.DefaultErrorHandlerBuilder;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@SuppressWarnings("unchecked")
+public class DefaultErrorHandlerBuilderConfigurer extends org.apache.camel.support.component.PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+        org.apache.camel.builder.DefaultErrorHandlerBuilder target = (org.apache.camel.builder.DefaultErrorHandlerBuilder) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "asyncdelayedredelivery":
+        case "AsyncDelayedRedelivery": target.setAsyncDelayedRedelivery(property(camelContext, boolean.class, value)); return true;
+        case "deadletterhandlenewexception":
+        case "DeadLetterHandleNewException": target.setDeadLetterHandleNewException(property(camelContext, boolean.class, value)); return true;
+        case "deadletteruri":
+        case "DeadLetterUri": target.setDeadLetterUri(property(camelContext, java.lang.String.class, value)); return true;
+        case "executorservice":
+        case "ExecutorService": target.setExecutorService(property(camelContext, java.util.concurrent.ScheduledExecutorService.class, value)); return true;
+        case "executorserviceref":
+        case "ExecutorServiceRef": target.setExecutorServiceRef(property(camelContext, java.lang.String.class, value)); return true;
+        case "logger":
+        case "Logger": target.setLogger(property(camelContext, org.apache.camel.spi.CamelLogger.class, value)); return true;
+        case "onexceptionoccurred":
+        case "OnExceptionOccurred": target.setOnExceptionOccurred(property(camelContext, org.apache.camel.Processor.class, value)); return true;
+        case "onexceptionoccurredref":
+        case "OnExceptionOccurredRef": target.setOnExceptionOccurredRef(property(camelContext, java.lang.String.class, value)); return true;
+        case "onpreparefailure":
+        case "OnPrepareFailure": target.setOnPrepareFailure(property(camelContext, org.apache.camel.Processor.class, value)); return true;
+        case "onpreparefailureref":
+        case "OnPrepareFailureRef": target.setOnPrepareFailureRef(property(camelContext, java.lang.String.class, value)); return true;
+        case "onredelivery":
+        case "OnRedelivery": target.setOnRedelivery(property(camelContext, org.apache.camel.Processor.class, value)); return true;
+        case "onredeliveryref":
+        case "OnRedeliveryRef": target.setOnRedeliveryRef(property(camelContext, java.lang.String.class, value)); return true;
+        case "redeliverypolicy":
+        case "RedeliveryPolicy": target.setRedeliveryPolicy(property(camelContext, org.apache.camel.processor.errorhandler.RedeliveryPolicy.class, value)); return true;
+        case "retrywhile":
+        case "RetryWhile": target.setRetryWhile(property(camelContext, org.apache.camel.Predicate.class, value)); return true;
+        case "retrywhileref":
+        case "RetryWhileRef": target.setRetryWhileRef(property(camelContext, java.lang.String.class, value)); return true;
+        case "useoriginalbody":
+        case "UseOriginalBody": target.setUseOriginalBody(property(camelContext, boolean.class, value)); return true;
+        case "useoriginalmessage":
+        case "UseOriginalMessage": target.setUseOriginalMessage(property(camelContext, boolean.class, value)); return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "asyncdelayedredelivery":
+        case "AsyncDelayedRedelivery": return boolean.class;
+        case "deadletterhandlenewexception":
+        case "DeadLetterHandleNewException": return boolean.class;
+        case "deadletteruri":
+        case "DeadLetterUri": return java.lang.String.class;
+        case "executorservice":
+        case "ExecutorService": return java.util.concurrent.ScheduledExecutorService.class;
+        case "executorserviceref":
+        case "ExecutorServiceRef": return java.lang.String.class;
+        case "logger":
+        case "Logger": return org.apache.camel.spi.CamelLogger.class;
+        case "onexceptionoccurred":
+        case "OnExceptionOccurred": return org.apache.camel.Processor.class;
+        case "onexceptionoccurredref":
+        case "OnExceptionOccurredRef": return java.lang.String.class;
+        case "onpreparefailure":
+        case "OnPrepareFailure": return org.apache.camel.Processor.class;
+        case "onpreparefailureref":
+        case "OnPrepareFailureRef": return java.lang.String.class;
+        case "onredelivery":
+        case "OnRedelivery": return org.apache.camel.Processor.class;
+        case "onredeliveryref":
+        case "OnRedeliveryRef": return java.lang.String.class;
+        case "redeliverypolicy":
+        case "RedeliveryPolicy": return org.apache.camel.processor.errorhandler.RedeliveryPolicy.class;
+        case "retrywhile":
+        case "RetryWhile": return org.apache.camel.Predicate.class;
+        case "retrywhileref":
+        case "RetryWhileRef": return java.lang.String.class;
+        case "useoriginalbody":
+        case "UseOriginalBody": return boolean.class;
+        case "useoriginalmessage":
+        case "UseOriginalMessage": return boolean.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        org.apache.camel.builder.DefaultErrorHandlerBuilder target = (org.apache.camel.builder.DefaultErrorHandlerBuilder) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "asyncdelayedredelivery":
+        case "AsyncDelayedRedelivery": return target.isAsyncDelayedRedelivery();
+        case "deadletterhandlenewexception":
+        case "DeadLetterHandleNewException": return target.isDeadLetterHandleNewException();
+        case "deadletteruri":
+        case "DeadLetterUri": return target.getDeadLetterUri();
+        case "executorservice":
+        case "ExecutorService": return target.getExecutorService();
+        case "executorserviceref":
+        case "ExecutorServiceRef": return target.getExecutorServiceRef();
+        case "logger":
+        case "Logger": return target.getLogger();
+        case "onexceptionoccurred":
+        case "OnExceptionOccurred": return target.getOnExceptionOccurred();
+        case "onexceptionoccurredref":
+        case "OnExceptionOccurredRef": return target.getOnExceptionOccurredRef();
+        case "onpreparefailure":
+        case "OnPrepareFailure": return target.getOnPrepareFailure();
+        case "onpreparefailureref":
+        case "OnPrepareFailureRef": return target.getOnPrepareFailureRef();
+        case "onredelivery":
+        case "OnRedelivery": return target.getOnRedelivery();
+        case "onredeliveryref":
+        case "OnRedeliveryRef": return target.getOnRedeliveryRef();
+        case "redeliverypolicy":
+        case "RedeliveryPolicy": return target.getRedeliveryPolicy();
+        case "retrywhile":
+        case "RetryWhile": return target.getRetryWhile();
+        case "retrywhileref":
+        case "RetryWhileRef": return target.getRetryWhileRef();
+        case "useoriginalbody":
+        case "UseOriginalBody": return target.isUseOriginalBody();
+        case "useoriginalmessage":
+        case "UseOriginalMessage": return target.isUseOriginalMessage();
+        default: return null;
+        }
+    }
+}
+
diff --git a/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.builder.DeadLetterChannelBuilder b/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.builder.DeadLetterChannelBuilder
new file mode 100644
index 0000000..358dea6
--- /dev/null
+++ b/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.builder.DeadLetterChannelBuilder
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.builder.DeadLetterChannelBuilderConfigurer
diff --git a/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.builder.DefaultErrorHandlerBuilder b/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.builder.DefaultErrorHandlerBuilder
new file mode 100644
index 0000000..4365a67
--- /dev/null
+++ b/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.builder.DefaultErrorHandlerBuilder
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.builder.DefaultErrorHandlerBuilderConfigurer
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java b/core/camel-core-model/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java
index e7c10f9..67e49b3 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java
@@ -23,11 +23,13 @@ import org.apache.camel.model.errorhandler.DeadLetterChannelProperties;
 import org.apache.camel.model.errorhandler.DefaultErrorHandlerConfiguration;
 import org.apache.camel.processor.errorhandler.DeadLetterChannel;
 import org.apache.camel.spi.CamelLogger;
+import org.apache.camel.spi.Configurer;
 import org.slf4j.LoggerFactory;
 
 /**
  * A builder of a <a href="http://camel.apache.org/dead-letter-channel.html">Dead Letter Channel</a>
  */
+@Configurer
 public class DeadLetterChannelBuilder extends DefaultErrorHandlerBuilder implements DeadLetterChannelProperties {
 
     public DeadLetterChannelBuilder() {
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java b/core/camel-core-model/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java
index 45dcbfc..400a536 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java
@@ -28,6 +28,7 @@ import org.apache.camel.model.errorhandler.DefaultErrorHandlerProperties;
 import org.apache.camel.processor.errorhandler.DefaultErrorHandler;
 import org.apache.camel.processor.errorhandler.RedeliveryPolicy;
 import org.apache.camel.spi.CamelLogger;
+import org.apache.camel.spi.Configurer;
 import org.apache.camel.spi.Language;
 import org.apache.camel.support.ExpressionToPredicateAdapter;
 import org.slf4j.LoggerFactory;
@@ -35,6 +36,7 @@ import org.slf4j.LoggerFactory;
 /**
  * The default error handler builder.
  */
+@Configurer
 public class DefaultErrorHandlerBuilder extends ErrorHandlerBuilderSupport implements DefaultErrorHandlerProperties {
 
     private final DefaultErrorHandlerConfiguration configuration;
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
index 0108fee..d7e3115 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
@@ -144,6 +144,42 @@ You can also use Camel JBang to try local Kamelets, without the need to publish
 jbang -Dcamel.jbang.version=3.14.0 CamelJBang@apache/camel run --local-kamelet-dir=/path/to/local/kamelets earthquake.yaml
 ----
 
+=== Running Camel K integrations or bindings
+
+Camel also supports running Camel K integrations and binding files, which are in CRD format (Kubernetes Custom Resource Definitions).
+
+For example a kamelet binding file named `joke.yaml`:
+
+[source,yaml]
+----
+apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  name: joke
+spec:
+  source:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1
+      name: chuck-norris-source
+    properties:
+      period: 2000
+  sink:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1
+      name: log-sink
+    properties:
+      show-headers: false
+----
+
+Can be run with CamelJBang:
+
+[source,bash]
+----
+jbang -Dcamel.jbang.version=3.14.0 CamelJBang@apache/camel run joke.yaml
+----
+
 === Search
 
 You can use the CLI to search for kamelets, components, languages and miscellaneous components (others). Running the following command will present a list of items that can be searched:
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/docs/yaml-dsl.adoc b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/docs/yaml-dsl.adoc
index fb2c28e..2567b0f 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/docs/yaml-dsl.adoc
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/docs/yaml-dsl.adoc
@@ -271,3 +271,54 @@ which demonstrate creating Camel Routes with YAML.
 
 Another way to find examples of YAML DSL is to look in https://github.com/apache/camel-kamelets[Camel Kamelets]
 where each Kamelet is defined using YAML.
+
+== Camel K support
+
+The `camel-yaml-dsl` is supported by Camel K.
+
+=== Loading Camel K integrations
+
+A Camel K integration (in CRD format (Custom Resource Definition in Kubernetes))
+can be loaded by `camel-yaml-dsl` and run as routes:
+
+[source,yaml]
+----
+apiVersion: camel.apache.org/v1
+kind: Integration
+metadata:
+  name: hello.yaml
+spec:
+  flows:
+    - from:
+        uri: "timer:tick?period=5000"
+    steps:
+      - to: "log:tick"
+----
+
+=== Loading Camel K bindings
+
+A Camel K binding (in CRD format (Custom Resource Definition in Kubernetes))
+can be loaded by `camel-yaml-dsl` and run as routes:
+
+[source,yaml]
+----
+apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  name: joke
+spec:
+  source:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1
+      name: chuck-norris-source
+    properties:
+      period: 2000
+  sink:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1
+      name: log-sink
+    properties:
+      show-headers: false
+----
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
index 2d44291..dd370a6 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
@@ -22,7 +22,9 @@ import java.util.Objects;
 import org.apache.camel.CamelContextAware;
 import org.apache.camel.api.management.ManagedResource;
 import org.apache.camel.builder.DeadLetterChannelBuilder;
+import org.apache.camel.builder.DefaultErrorHandlerBuilder;
 import org.apache.camel.builder.ErrorHandlerBuilder;
+import org.apache.camel.builder.NoErrorHandlerBuilder;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.builder.RouteConfigurationBuilder;
 import org.apache.camel.dsl.yaml.common.YamlDeserializerSupport;
@@ -31,10 +33,10 @@ import org.apache.camel.model.OnExceptionDefinition;
 import org.apache.camel.model.RouteConfigurationDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RouteTemplateDefinition;
+import org.apache.camel.model.errorhandler.DefaultErrorHandlerProperties;
 import org.apache.camel.model.rest.RestConfigurationDefinition;
 import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.model.rest.VerbDefinition;
-import org.apache.camel.processor.errorhandler.RedeliveryPolicy;
 import org.apache.camel.spi.CamelContextCustomizer;
 import org.apache.camel.spi.annotations.RoutesLoader;
 import org.apache.camel.support.PropertyBindingSupport;
@@ -231,30 +233,47 @@ public class YamlRoutesBuilderLoader extends YamlRoutesBuilderLoaderSupport {
             route.to(to);
 
             // is there any error handler?
-            // TODO: set it globally via configuration so its inherited
             MappingNode errorHandler = asMappingNode(nodeAt(root, "/spec/errorHandler"));
             if (errorHandler != null) {
                 // there are 5 different error handlers, which one is it
                 NodeTuple nt = errorHandler.getValue().get(0);
                 String ehName = asText(nt.getKeyNode());
-                if ("dead-letter-channel".equals(ehName)) {
-                    DeadLetterChannelBuilder dlcb = new DeadLetterChannelBuilder();
 
+                DefaultErrorHandlerProperties ehb = null;
+                if ("dead-letter-channel".equals(ehName)) {
+                    DeadLetterChannelBuilder dlch = new DeadLetterChannelBuilder();
                     // endpoint
                     MappingNode endpoint = asMappingNode(nodeAt(nt.getValueNode(), "/endpoint"));
                     String dlq = extractCamelEndpointUri(endpoint);
-                    dlcb.setDeadLetterUri(dlq);
+                    dlch.setDeadLetterUri(dlq);
+                    ehb = dlch;
+                } else if ("log".equals(ehName)) {
+                    // log is the default error handler
+                    ehb = new DefaultErrorHandlerBuilder();
+                } else if ("none".equals(ehName)) {
+                    route.errorHandler(new NoErrorHandlerBuilder());
+                } else if ("bean".equals(ehName)) {
+                    throw new IllegalArgumentException("Bean error handler is not supported");
+                } else if ("ref".equals(ehName)) {
+                    throw new IllegalArgumentException("Ref error handler is not supported");
+                }
 
-                    // properties
+                // some error handlers support additional parameters
+                if (ehb != null) {
+                    // properties that are general for all kind of error handlers
                     MappingNode prop = asMappingNode(nodeAt(nt.getValueNode(), "/parameters"));
                     Map<String, Object> params = asMap(prop);
                     if (params != null) {
-                        // the parameters are for redelivery policy
-                        RedeliveryPolicy rp = new RedeliveryPolicy();
-                        dlcb.setRedeliveryPolicy(rp);
-                        PropertyBindingSupport.build().withIgnoreCase(true).bind(getCamelContext(), rp, params);
+                        PropertyBindingSupport.build()
+                                .withIgnoreCase(true)
+                                .withFluentBuilder(true)
+                                .withRemoveParameters(true)
+                                .withCamelContext(getCamelContext())
+                                .withTarget(ehb)
+                                .withProperties(params)
+                                .bind();
                     }
-                    route.errorHandler(dlcb);
+                    route.errorHandler(ehb);
                 }
             }
 
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy
index 166bdc5..724f867 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy
@@ -19,6 +19,8 @@ package org.apache.camel.dsl.yaml
 import org.apache.camel.Exchange
 import org.apache.camel.Processor
 import org.apache.camel.builder.DeadLetterChannelBuilder
+import org.apache.camel.builder.DefaultErrorHandlerBuilder
+import org.apache.camel.builder.NoErrorHandlerBuilder
 import org.apache.camel.component.mock.MockEndpoint
 import org.apache.camel.dsl.yaml.support.YamlTestSupport
 import org.apache.camel.model.ToDefinition
@@ -399,4 +401,96 @@ class KameletBindingLoaderTest extends YamlTestSupport {
         }
     }
 
+    def "kamelet binding with log error handler"() {
+        when:
+
+        // stub kafka for testing as it requires to setup connection to a real kafka broker
+        context.addComponent("kafka", context.getComponent("stub"))
+
+        loadBindings('''
+                apiVersion: camel.apache.org/v1alpha1
+                kind: KameletBinding
+                metadata:
+                  name: timer-event-source                  
+                spec:
+                  source:
+                    ref:
+                      kind: Kamelet
+                      apiVersion: camel.apache.org/v1
+                      name: timer-source
+                    properties:
+                      message: "Hello world!"
+                  sink:
+                    ref:
+                      kind: Kamelet
+                      apiVersion: camel.apache.org/v1alpha1
+                      name: log-sink
+                  errorHandler:
+                    log:
+                      parameters:
+                        use-original-message: true
+                        maximumRedeliveries: 1
+                        redeliveryDelay: 2000    
+                    ''')
+        then:
+        context.routeDefinitions.size() == 3
+
+        with (context.routeDefinitions[0]) {
+            errorHandlerFactory != null
+            errorHandlerFactory instanceof DefaultErrorHandlerBuilder
+            var eh = errorHandlerFactory as DefaultErrorHandlerBuilder
+            eh.redeliveryPolicy.maximumRedeliveries == 1
+            eh.redeliveryPolicy.redeliveryDelay == 2000
+            eh.isUseOriginalMessage() == true
+            routeId == 'timer-event-source'
+            input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+            outputs.size() == 1
+            with (outputs[0], ToDefinition) {
+                endpointUri == 'kamelet:log-sink'
+            }
+        }
+    }
+
+    def "kamelet binding with none error handler"() {
+        when:
+
+        // stub kafka for testing as it requires to setup connection to a real kafka broker
+        context.addComponent("kafka", context.getComponent("stub"))
+
+        loadBindings('''
+                apiVersion: camel.apache.org/v1alpha1
+                kind: KameletBinding
+                metadata:
+                  name: timer-event-source                  
+                spec:
+                  source:
+                    ref:
+                      kind: Kamelet
+                      apiVersion: camel.apache.org/v1
+                      name: timer-source
+                    properties:
+                      message: "Hello world!"
+                  sink:
+                    ref:
+                      kind: Kamelet
+                      apiVersion: camel.apache.org/v1alpha1
+                      name: log-sink
+                  errorHandler:
+                    none:
+                    ''')
+        then:
+        context.routeDefinitions.size() == 3
+
+        with (context.routeDefinitions[0]) {
+            errorHandlerFactory != null
+            errorHandlerFactory instanceof NoErrorHandlerBuilder
+            routeId == 'timer-event-source'
+            input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+            outputs.size() == 1
+            with (outputs[0], ToDefinition) {
+                endpointUri == 'kamelet:log-sink'
+            }
+        }
+    }
+
 }
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletIntegrationLoaderTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletIntegrationLoaderTest.groovy
new file mode 100644
index 0000000..289b9f4
--- /dev/null
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletIntegrationLoaderTest.groovy
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.yaml
+
+import org.apache.camel.dsl.yaml.support.YamlTestSupport
+import org.apache.camel.model.KameletDefinition
+
+class KameletIntegrationLoaderTest extends YamlTestSupport {
+    @Override
+    def doSetup() {
+        context.start()
+    }
+
+    def "kamelet integration"() {
+        when:
+            loadIntegrations('''
+                apiVersion: camel.apache.org/v1
+                kind: Integration
+                metadata:
+                  name: foobar
+                spec:
+                  flows:
+                    - from:
+                        uri: 'kamelet:timer-source'
+                        steps:
+                          - kamelet:
+                              name: log-sink
+                              parameters:
+                                showStreams: false
+                                showHeaders: false
+                        parameters:
+                          message: Hello Camel K
+                          period: 1234
+                      ''')
+        then:
+            context.routeDefinitions.size() == 3
+
+            with (context.routeDefinitions[0]) {
+                input.endpointUri == 'kamelet:timer-source?message=Hello Camel K&period=1234'
+                outputs.size() == 1
+                with (outputs[0], KameletDefinition) {
+                    name == 'log-sink?showStreams=false&showHeaders=false'
+                }
+            }
+    }
+
+}
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/YamlTestSupport.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/YamlTestSupport.groovy
index e9da693..78c81da 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/YamlTestSupport.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/YamlTestSupport.groovy
@@ -106,6 +106,16 @@ class YamlTestSupport extends Specification implements HasCamelContext {
         )
     }
 
+    def loadIntegrations(String... resources) {
+        int index = 0
+
+        context.routesLoader.loadRoutes(
+            resources.collect {
+                it -> ResourceHelper.fromString("integration-${index++}.yaml", it.stripIndent())
+            }
+        )
+    }
+
     def loadBindings(String... resources) {
         int index = 0
 

[camel] 03/08: CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file. WIP.

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

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

commit a937b49e17307c9c2759ac07820a28ad1fe2af7c
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Dec 7 11:00:26 2021 +0100

    CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file. WIP.
---
 .../java/org/apache/camel/RouteTemplateContext.java    |  8 ++++++++
 .../main/java/org/apache/camel/impl/DefaultModel.java  |  4 ++--
 .../camel/model/DefaultRouteTemplateContext.java       | 18 ++++++++++++++++++
 .../apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java |  2 ++
 .../camel/dsl/yaml/KameletBindingLoaderTest.groovy     | 12 ++++++++++--
 .../test/resources/kamelets/error-handler.kamelet.yaml | 18 +++++++++---------
 6 files changed, 49 insertions(+), 13 deletions(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/RouteTemplateContext.java b/core/camel-api/src/main/java/org/apache/camel/RouteTemplateContext.java
index 0b1996b..fa2c77d 100644
--- a/core/camel-api/src/main/java/org/apache/camel/RouteTemplateContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/RouteTemplateContext.java
@@ -124,6 +124,14 @@ public interface RouteTemplateContext extends HasCamelContext {
     Map<String, Object> getParameters();
 
     /**
+     * Whether the route template has a parameter with the given name
+     *
+     * @param  name the parameter name
+     * @return      true if exists
+     */
+    boolean hasParameter(String name);
+
+    /**
      * Gets the local bean repository for the route template when creating the new route
      */
     BeanRepository getLocalBeanRepository();
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
index 2ff0362..83465a8 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
@@ -343,7 +343,7 @@ public class DefaultModel implements Model {
                 if (temp.getDefaultValue() != null) {
                     prop.put(temp.getName(), temp.getDefaultValue());
                 } else {
-                    if (temp.isRequired() && !routeTemplateContext.getParameters().containsKey(temp.getName())) {
+                    if (temp.isRequired() && !routeTemplateContext.hasParameter(temp.getName())) {
                         // this is a required parameter which is missing
                         templatesBuilder.add(temp.getName());
                     }
@@ -364,7 +364,7 @@ public class DefaultModel implements Model {
         // so it has all parameters available
         if (target.getTemplateParameters() != null) {
             for (RouteTemplateParameterDefinition temp : target.getTemplateParameters()) {
-                if (!routeTemplateContext.getParameters().containsKey(temp.getName()) && temp.getDefaultValue() != null) {
+                if (!routeTemplateContext.hasParameter(temp.getName()) && temp.getDefaultValue() != null) {
                     routeTemplateContext.setParameter(temp.getName(), temp.getDefaultValue());
                 }
             }
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/DefaultRouteTemplateContext.java b/core/camel-core-model/src/main/java/org/apache/camel/model/DefaultRouteTemplateContext.java
index 4e81852..79a7452 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/DefaultRouteTemplateContext.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/DefaultRouteTemplateContext.java
@@ -27,6 +27,7 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.RouteTemplateContext;
 import org.apache.camel.spi.BeanRepository;
 import org.apache.camel.support.LocalBeanRegistry;
+import org.apache.camel.util.StringHelper;
 
 /**
  * Default {@link RouteTemplateContext}.
@@ -107,6 +108,23 @@ public final class DefaultRouteTemplateContext implements RouteTemplateContext {
     }
 
     @Override
+    public boolean hasParameter(String name) {
+        if (parameters.containsKey(name)) {
+            return true;
+        }
+        // lookup key with both dash and camel style
+        name = StringHelper.dashToCamelCase(name);
+        if (parameters.containsKey(name)) {
+            return true;
+        }
+        name = StringHelper.camelCaseToDash(name);
+        if (parameters.containsKey(name)) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
     public BeanRepository getLocalBeanRepository() {
         return registry;
     }
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
index 2bd9348..030d971 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
@@ -212,6 +212,7 @@ public class YamlRoutesBuilderLoader extends YamlRoutesBuilderLoaderSupport {
             route.from(from);
 
             // steps in the middle (optional)
+            // TODO: make steps as Kamelet EIP and not TO
             Node steps = nodeAt(root, "/spec/steps");
             if (steps != null) {
                 SequenceNode sn = asSequenceNode(steps);
@@ -244,6 +245,7 @@ public class YamlRoutesBuilderLoader extends YamlRoutesBuilderLoaderSupport {
                     dlcb.setDeadLetterUri(dlq);
 
                     // properties (TODO: via reflection - need builder)
+                    // TODO: route templates store user parameters in cameCase (eg convert dash to camel case) (like camel-main)
                     MappingNode prop = asMappingNode(nodeAt(nt.getValueNode(), "/parameters"));
                     Map<String, Object> params = asMap(prop);
                     if (params != null) {
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy
index b2f6c81..7e27750 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy
@@ -16,8 +16,10 @@
  */
 package org.apache.camel.dsl.yaml
 
+import org.apache.camel.builder.DeadLetterChannelBuilder
 import org.apache.camel.dsl.yaml.support.YamlTestSupport
 import org.apache.camel.model.ToDefinition
+import org.apache.camel.processor.errorhandler.DeadLetterChannel
 
 class KameletBindingLoaderTest extends YamlTestSupport {
     @Override
@@ -321,14 +323,20 @@ class KameletBindingLoaderTest extends YamlTestSupport {
                         redeliveryDelay: 2000    
                     ''')
         then:
-        context.routeDefinitions.size() == 2
+        context.routeDefinitions.size() == 4
 
         with (context.routeDefinitions[0]) {
+            errorHandlerFactory != null
+            errorHandlerFactory instanceof DeadLetterChannelBuilder
+            var eh = errorHandlerFactory as DeadLetterChannelBuilder
+            eh.deadLetterUri == 'kamelet:error-handler?kafkaTopic=my-first-test&logMessage=ERROR%21&kafkaServiceAccountId=scott&kafkaBrokers=my-broker&kafkaServiceAccountSecret=tiger'
+            eh.redeliveryPolicy.maximumRedeliveries == 1
+            eh.redeliveryPolicy.redeliveryDelay == 2000
             routeId == 'timer-event-source'
             input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
             outputs.size() == 1
             with (outputs[0], ToDefinition) {
-                endpointUri == 'kafka:my-topic'
+                endpointUri == 'kamelet:log-sink'
             }
         }
     }
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/error-handler.kamelet.yaml b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/error-handler.kamelet.yaml
index 7fcd6bd..f088fb2 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/error-handler.kamelet.yaml
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/error-handler.kamelet.yaml
@@ -30,27 +30,27 @@ spec:
       - kafka-service-account-secret
       - log-message
     properties:
-      kafka-brokers:
+      kafkaBrokers:
         title: Kafka Brokers
         description: the bootstrap server
         type: string
         example: "xyz-ins--rplssqfz-yyyyyyy-crojg.bf2.kafka.my-clud-service.com:443"
-      kafka-topic:
+      kafkaTopic:
         title: Kafka Topic
         description: the DLC topic
         type: string
         example: "my-dlc"
-      kafka-service-account-id:
+      kafkaServiceAccountId:
         title: Service Account ID
         description: the SA to use
         type: string
         example: "srvc-acct-xxxxxx-519b-453f-9f68-yyyyyyyyy"
-      kafka-service-account-secret:
+      kafkaServiceAccountSecret:
         title: Service Account Secret
         description: the SA secrete to use
         type: string
         example: "xxxxxxxxx-46c7-4c6c-a753-yyyyyyyyyyyyyyy"
-      log-message:
+      logMessage:
         title: Message
         description: A message warning to log
         type: string
@@ -61,13 +61,13 @@ spec:
       steps:
         # First step: send to the DLC for future processing
         - to:
-            uri: kafka:{{kafka-topic}}
+            uri: kafka:{{kafkaTopic}}
             parameters:
-              brokers: "{{kafka-brokers}}"
+              brokers: "{{kafkaBrokers}}"
               security-protocol: SASL_SSL
               sasl-mechanism: PLAIN
-              sasl-jaas-config: "org.apache.kafka.common.security.plain.PlainLoginModule required username={{kafka-service-account-id}} password={{kafka-service-account-secret}};"
+              sasl-jaas-config: "org.apache.kafka.common.security.plain.PlainLoginModule required username={{kafkaServiceAccountId}} password={{kafkaServiceAccountSecret}};"
         # Log an error message to notify about the failure
         - set-body:
-            constant: "{{log-message}} - worry not, the event is stored in the DLC"
+            constant: "{{logMessage}} - worry not, the event is stored in the DLC"
         - to: "log:error-sink"

[camel] 07/08: CAMEL-17282: RemoveHeader EIP remove deprecated headerName

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

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

commit f28834cfdfc858f431a6251ddc3b822184d920b4
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Dec 7 11:56:21 2021 +0100

    CAMEL-17282: RemoveHeader EIP remove deprecated headerName
---
 .../src/test/groovy/org/apache/camel/dsl/yaml/RemoveHeaderTest.groovy   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RemoveHeaderTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RemoveHeaderTest.groovy
index a669843..3dc0765 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RemoveHeaderTest.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RemoveHeaderTest.groovy
@@ -28,7 +28,7 @@ class RemoveHeaderTest extends YamlTestSupport {
             context.routesLoader.loadRoutes(resource)
         then:
             with(context.routeDefinitions[0].outputs[0], RemoveHeaderDefinition) {
-                headerName == 'test'
+                name == 'test'
             }
         where:
             resource << [

[camel] 01/08: CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file. WIP.

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

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

commit 30b2fbc7b761231bf6ed5f2e38156d49e00a96b9
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Dec 7 07:03:17 2021 +0100

    CAMEL-17261: camel-yaml-dsl - Add support for loading Camel K KameletBinding file. WIP.
---
 .../dsl/yaml/deserializers/ModelDeserializers.java |  37 ---
 .../deserializers/ModelDeserializersResolver.java  |   3 -
 dsl/camel-yaml-dsl/camel-yaml-dsl/pom.xml          |  10 +
 .../src/generated/resources/camel-yaml-dsl.json    |   9 -
 .../camel/dsl/yaml/YamlRoutesBuilderLoader.java    | 269 ++++++++++++-----
 .../dsl/yaml/YamlRoutesBuilderLoaderSupport.java   |  37 +++
 .../camel/dsl/yaml/KameletBindingLoaderTest.groovy | 335 +++++++++++++++++++++
 .../camel/dsl/yaml/support/YamlTestSupport.groovy  |  22 ++
 .../test/resources/kamelets/log-sink.kamelet.yaml  |  61 ++++
 .../resources/kamelets/prefix-action.kamelet.yaml  |  45 +++
 .../resources/kamelets/timer-source.kamelet.yaml   |  69 +++++
 11 files changed, 776 insertions(+), 121 deletions(-)

diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
index 1804ce1..a6eb0f8 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
@@ -69,7 +69,6 @@ import org.apache.camel.model.Resilience4jConfigurationDefinition;
 import org.apache.camel.model.RestContextRefDefinition;
 import org.apache.camel.model.RollbackDefinition;
 import org.apache.camel.model.RouteBuilderDefinition;
-import org.apache.camel.model.RouteConfigurationContextRefDefinition;
 import org.apache.camel.model.RouteContextRefDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RouteTemplateParameterDefinition;
@@ -12919,42 +12918,6 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
     }
 
     @YamlType(
-            types = org.apache.camel.model.RouteConfigurationContextRefDefinition.class,
-            order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
-            nodes = {
-                    "route-configuration-context-ref",
-                    "routeConfigurationContextRef"
-            },
-            properties = @YamlProperty(name = "ref", type = "string", required = true)
-    )
-    public static class RouteConfigurationContextRefDefinitionDeserializer extends YamlDeserializerBase<RouteConfigurationContextRefDefinition> {
-        public RouteConfigurationContextRefDefinitionDeserializer() {
-            super(RouteConfigurationContextRefDefinition.class);
-        }
-
-        @Override
-        protected RouteConfigurationContextRefDefinition newInstance() {
-            return new RouteConfigurationContextRefDefinition();
-        }
-
-        @Override
-        protected boolean setProperty(RouteConfigurationContextRefDefinition target,
-                String propertyKey, String propertyName, Node node) {
-            switch(propertyKey) {
-                case "ref": {
-                    String val = asText(node);
-                    target.setRef(val);
-                    break;
-                }
-                default: {
-                    return false;
-                }
-            }
-            return true;
-        }
-    }
-
-    @YamlType(
             types = org.apache.camel.model.RouteContextRefDefinition.class,
             order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
             nodes = {
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
index f0629b1..f5837a5 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
@@ -363,9 +363,6 @@ public final class ModelDeserializersResolver implements YamlDeserializerResolve
             case "route-builder": return new ModelDeserializers.RouteBuilderDefinitionDeserializer();
             case "routeBuilder": return new ModelDeserializers.RouteBuilderDefinitionDeserializer();
             case "org.apache.camel.model.RouteBuilderDefinition": return new ModelDeserializers.RouteBuilderDefinitionDeserializer();
-            case "route-configuration-context-ref": return new ModelDeserializers.RouteConfigurationContextRefDefinitionDeserializer();
-            case "routeConfigurationContextRef": return new ModelDeserializers.RouteConfigurationContextRefDefinitionDeserializer();
-            case "org.apache.camel.model.RouteConfigurationContextRefDefinition": return new ModelDeserializers.RouteConfigurationContextRefDefinitionDeserializer();
             case "route-context-ref": return new ModelDeserializers.RouteContextRefDefinitionDeserializer();
             case "routeContextRef": return new ModelDeserializers.RouteContextRefDefinitionDeserializer();
             case "org.apache.camel.model.RouteContextRefDefinition": return new ModelDeserializers.RouteContextRefDefinitionDeserializer();
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/pom.xml b/dsl/camel-yaml-dsl/camel-yaml-dsl/pom.xml
index 787cfb2..7170e1d4 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/pom.xml
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/pom.xml
@@ -116,6 +116,16 @@
         </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
+            <artifactId>camel-timer</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-stub</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
             <artifactId>camel-log</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
index 62e992b..89dfbf3 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
@@ -2131,15 +2131,6 @@
         } ],
         "required" : [ "ref" ]
       },
-      "org.apache.camel.model.RouteConfigurationContextRefDefinition" : {
-        "type" : "object",
-        "properties" : {
-          "ref" : {
-            "type" : "string"
-          }
-        },
-        "required" : [ "ref" ]
-      },
       "org.apache.camel.model.RouteConfigurationDefinition" : {
         "oneOf" : [ {
           "type" : "string"
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
index 30cd3fa..fa7ca59 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
@@ -16,11 +16,12 @@
  */
 package org.apache.camel.dsl.yaml;
 
-import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 
 import org.apache.camel.CamelContextAware;
 import org.apache.camel.api.management.ManagedResource;
+import org.apache.camel.builder.DeadLetterChannelBuilder;
 import org.apache.camel.builder.ErrorHandlerBuilder;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.builder.RouteConfigurationBuilder;
@@ -35,11 +36,15 @@ import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.model.rest.VerbDefinition;
 import org.apache.camel.spi.CamelContextCustomizer;
 import org.apache.camel.spi.annotations.RoutesLoader;
+import org.apache.camel.util.URISupport;
 import org.snakeyaml.engine.v2.nodes.MappingNode;
 import org.snakeyaml.engine.v2.nodes.Node;
 import org.snakeyaml.engine.v2.nodes.NodeTuple;
 import org.snakeyaml.engine.v2.nodes.NodeType;
+import org.snakeyaml.engine.v2.nodes.SequenceNode;
 
+import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.asMap;
+import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.asMappingNode;
 import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.asSequenceNode;
 import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.asText;
 import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.nodeAt;
@@ -47,8 +52,15 @@ import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.nodeAt;
 @ManagedResource(description = "Managed YAML RoutesBuilderLoader")
 @RoutesLoader(YamlRoutesBuilderLoader.EXTENSION)
 public class YamlRoutesBuilderLoader extends YamlRoutesBuilderLoaderSupport {
+
     public static final String EXTENSION = "yaml";
 
+    // API versions for Camel-K Integration and Kamelet Binding
+    // we are lenient so lets just assume we can work with any of the v1 even if they evolve
+    private static final String INTEGRATION_VERSION = "camel.apache.org/v1";
+    private static final String BINDING_VERSION = "camel.apache.org/v1";
+    private static final String STRIMZI_VERSION = "kafka.strimzi.io/v1";
+
     public YamlRoutesBuilderLoader() {
         super(EXTENSION);
     }
@@ -57,103 +69,216 @@ public class YamlRoutesBuilderLoader extends YamlRoutesBuilderLoaderSupport {
         return new RouteConfigurationBuilder() {
             @Override
             public void configure() throws Exception {
-                Node target = preConfigureNode(root);
-
-                for (Node node : asSequenceNode(target).getValue()) {
-                    Object item = getDeserializationContext().mandatoryResolve(node).construct(node);
-
-                    if (item instanceof OutputAwareFromDefinition) {
-                        RouteDefinition route = new RouteDefinition();
-                        route.setInput(((OutputAwareFromDefinition) item).getDelegate());
-                        route.setOutputs(((OutputAwareFromDefinition) item).getOutputs());
-
-                        CamelContextAware.trySetCamelContext(getRouteCollection(), getCamelContext());
-                        getRouteCollection().route(route);
-                    } else if (item instanceof RouteDefinition) {
-                        CamelContextAware.trySetCamelContext(getRouteCollection(), getCamelContext());
-                        getRouteCollection().route((RouteDefinition) item);
-                    } else if (item instanceof CamelContextCustomizer) {
-                        ((CamelContextCustomizer) item).configure(getCamelContext());
-                    } else if (item instanceof OnExceptionDefinition) {
-                        if (!getRouteCollection().getRoutes().isEmpty()) {
-                            throw new IllegalArgumentException(
-                                    "onException must be defined before any routes in the RouteBuilder");
-                        }
-                        CamelContextAware.trySetCamelContext(getRouteCollection(), getCamelContext());
-                        getRouteCollection().getOnExceptions().add((OnExceptionDefinition) item);
-                    } else if (item instanceof ErrorHandlerBuilder) {
-                        if (!getRouteCollection().getRoutes().isEmpty()) {
-                            throw new IllegalArgumentException(
-                                    "errorHandler must be defined before any routes in the RouteBuilder");
-                        }
-                        errorHandler((ErrorHandlerBuilder) item);
-                    } else if (item instanceof RouteTemplateDefinition) {
-                        CamelContextAware.trySetCamelContext(getRouteTemplateCollection(), getCamelContext());
-                        getRouteTemplateCollection().routeTemplate((RouteTemplateDefinition) item);
-                    } else if (item instanceof RestDefinition) {
-                        RestDefinition definition = (RestDefinition) item;
-                        for (VerbDefinition verb : definition.getVerbs()) {
-                            verb.setRest(definition);
-                        }
-                        CamelContextAware.trySetCamelContext(getRestCollection(), getCamelContext());
-                        getRestCollection().rest(definition);
-                    } else if (item instanceof RestConfigurationDefinition) {
-                        ((RestConfigurationDefinition) item).asRestConfiguration(
-                                getCamelContext(),
-                                getCamelContext().getRestConfiguration());
+                Object target = preConfigureNode(root);
+                if (target == null) {
+                    return;
+                }
+
+                if (target instanceof Node) {
+                    SequenceNode seq = asSequenceNode((Node) target);
+                    for (Node node : seq.getValue()) {
+                        Object item = getDeserializationContext().mandatoryResolve(node).construct(node);
+                        doConfigure(item);
+                    }
+                } else {
+                    doConfigure(target);
+                }
+            }
+
+            private void doConfigure(Object item) throws Exception {
+                if (item instanceof OutputAwareFromDefinition) {
+                    RouteDefinition route = new RouteDefinition();
+                    route.setInput(((OutputAwareFromDefinition) item).getDelegate());
+                    route.setOutputs(((OutputAwareFromDefinition) item).getOutputs());
+
+                    CamelContextAware.trySetCamelContext(getRouteCollection(), getCamelContext());
+                    getRouteCollection().route(route);
+                } else if (item instanceof RouteDefinition) {
+                    CamelContextAware.trySetCamelContext(getRouteCollection(), getCamelContext());
+                    getRouteCollection().route((RouteDefinition) item);
+                } else if (item instanceof CamelContextCustomizer) {
+                    ((CamelContextCustomizer) item).configure(getCamelContext());
+                } else if (item instanceof OnExceptionDefinition) {
+                    if (!getRouteCollection().getRoutes().isEmpty()) {
+                        throw new IllegalArgumentException(
+                                "onException must be defined before any routes in the RouteBuilder");
+                    }
+                    CamelContextAware.trySetCamelContext(getRouteCollection(), getCamelContext());
+                    getRouteCollection().getOnExceptions().add((OnExceptionDefinition) item);
+                } else if (item instanceof ErrorHandlerBuilder) {
+                    if (!getRouteCollection().getRoutes().isEmpty()) {
+                        throw new IllegalArgumentException(
+                                "errorHandler must be defined before any routes in the RouteBuilder");
+                    }
+                    errorHandler((ErrorHandlerBuilder) item);
+                } else if (item instanceof RouteTemplateDefinition) {
+                    CamelContextAware.trySetCamelContext(getRouteTemplateCollection(), getCamelContext());
+                    getRouteTemplateCollection().routeTemplate((RouteTemplateDefinition) item);
+                } else if (item instanceof RestDefinition) {
+                    RestDefinition definition = (RestDefinition) item;
+                    for (VerbDefinition verb : definition.getVerbs()) {
+                        verb.setRest(definition);
                     }
+                    CamelContextAware.trySetCamelContext(getRestCollection(), getCamelContext());
+                    getRestCollection().rest(definition);
+                } else if (item instanceof RestConfigurationDefinition) {
+                    ((RestConfigurationDefinition) item).asRestConfiguration(
+                            getCamelContext(),
+                            getCamelContext().getRestConfiguration());
                 }
             }
 
             @Override
             public void configuration() throws Exception {
-                Node target = preConfigureNode(root);
+                Object target = preConfigureNode(root);
+                if (target == null) {
+                    return;
+                }
 
-                for (Node node : asSequenceNode(target).getValue()) {
-                    Object item = getDeserializationContext().mandatoryResolve(node).construct(node);
-                    if (item instanceof RouteConfigurationDefinition) {
-                        CamelContextAware.trySetCamelContext(getRouteConfigurationCollection(), getCamelContext());
-                        getRouteConfigurationCollection().routeConfiguration((RouteConfigurationDefinition) item);
+                if (target instanceof Node) {
+                    SequenceNode seq = asSequenceNode((Node) target);
+                    for (Node node : seq.getValue()) {
+                        Object item = getDeserializationContext().mandatoryResolve(node).construct(node);
+                        doConfiguration(item);
                     }
+                } else {
+                    doConfiguration(target);
+                }
+            }
+
+            private void doConfiguration(Object item) {
+                if (item instanceof RouteConfigurationDefinition) {
+                    CamelContextAware.trySetCamelContext(getRouteConfigurationCollection(), getCamelContext());
+                    getRouteConfigurationCollection().routeConfiguration((RouteConfigurationDefinition) item);
                 }
             }
         };
     }
 
-    private static Node preConfigureNode(Node root) {
-        Node target = root;
+    private Object preConfigureNode(Node root) throws Exception {
+        Object target = root;
 
-        // check if the yaml is a camel-k yaml with embedded routes (called flow(s))
+        // check if the yaml is a camel-k yaml with embedded binding/routes (called flow(s))
         if (Objects.equals(root.getNodeType(), NodeType.MAPPING)) {
             final MappingNode mn = YamlDeserializerSupport.asMappingNode(root);
-            boolean camelk = anyTupleMatches(mn.getValue(), "apiVersion", "camel.apache.org/v1") &&
+            // camel-k: integration
+            boolean integration = anyTupleMatches(mn.getValue(), "apiVersion", v -> v.startsWith(INTEGRATION_VERSION)) &&
                     anyTupleMatches(mn.getValue(), "kind", "Integration");
-            if (camelk) {
-                Node routes = nodeAt(root, "/spec/flows");
-                if (routes == null) {
-                    routes = nodeAt(root, "/spec/flow");
-                }
-                if (routes != null) {
-                    target = routes;
-                }
+            // camel-k: kamelet binding are still at v1alpha1
+            boolean binding = anyTupleMatches(mn.getValue(), "apiVersion", v -> v.startsWith(BINDING_VERSION)) &&
+                    anyTupleMatches(mn.getValue(), "kind", "KameletBinding");
+            if (integration) {
+                target = preConfigureIntegration(root, target);
+            } else if (binding) {
+                target = preConfigureKameletBinding(root, target);
             }
         }
 
         return target;
     }
 
-    private static boolean anyTupleMatches(List<NodeTuple> list, String aKey, String aValue) {
-        for (NodeTuple tuple : list) {
-            final String key = asText(tuple.getKeyNode());
-            final Node val = tuple.getValueNode();
-            if (Objects.equals(aKey, key) && NodeType.SCALAR.equals(val.getNodeType())) {
-                String value = asText(tuple.getValueNode());
-                if (Objects.equals(aValue, value)) {
-                    return true;
+    /**
+     * Camel K Integration file
+     */
+    private Object preConfigureIntegration(Node root, Object target) {
+        Node routes = nodeAt(root, "/spec/flows");
+        if (routes == null) {
+            routes = nodeAt(root, "/spec/flow");
+        }
+        if (routes != null) {
+            target = routes;
+        }
+        return target;
+    }
+
+    /**
+     * Camel K Kamelet Binding file
+     */
+    private Object preConfigureKameletBinding(Node root, Object target) throws Exception {
+        final RouteDefinition route = new RouteDefinition();
+        String routeId = asText(nodeAt(root, "/metadata/name"));
+        if (routeId != null) {
+            route.routeId(routeId);
+        }
+
+        // kamelet binding is a bit more complex, so grab the source and sink
+        // and map those to Camel route definitions
+        MappingNode source = asMappingNode(nodeAt(root, "/spec/source"));
+        MappingNode sink = asMappingNode(nodeAt(root, "/spec/sink"));
+        if (source != null && sink != null) {
+            // source at the beginning (mandatory)
+            String from = extractCamelEndpointUri(source);
+            route.from(from);
+
+            // steps in the middle (optional)
+            Node steps = nodeAt(root, "/spec/steps");
+            if (steps != null) {
+                SequenceNode sn = asSequenceNode(steps);
+                for (Node node : sn.getValue()) {
+                    MappingNode step = asMappingNode(node);
+                    String uri = extractCamelEndpointUri(step);
+                    if (uri != null) {
+                        route.to(uri);
+                    }
                 }
             }
+
+            // sink is at the end (mandatory)
+            String to = extractCamelEndpointUri(sink);
+            route.to(to);
+
+            // is there any error handler?
+            // TODO: set it globally via configuration so its inherited
+            MappingNode errorHandler = asMappingNode(nodeAt(root, "/spec/errorHandler"));
+            if (errorHandler != null) {
+                // there are 5 different error handlers, which one is it
+                NodeTuple nt = errorHandler.getValue().get(0);
+                String ehName = asText(nt.getKeyNode());
+                if ("dead-letter-channel".equals(ehName)) {
+                    DeadLetterChannelBuilder dlcb = new DeadLetterChannelBuilder();
+               }
+            }
+
+            target = route;
+        }
+
+        return target;
+    }
+
+    private String extractCamelEndpointUri(MappingNode node) throws Exception {
+        MappingNode mn = null;
+        Node ref = nodeAt(node, "/ref");
+        if (ref != null) {
+            mn = asMappingNode(ref);
+        }
+
+        // extract uri is different if kamelet or not
+        boolean kamelet = mn != null && anyTupleMatches(mn.getValue(), "kind", "Kamelet");
+        boolean strimzi
+                = !kamelet && mn != null && anyTupleMatches(mn.getValue(), "apiVersion", v -> v.startsWith(STRIMZI_VERSION))
+                        && anyTupleMatches(mn.getValue(), "kind", "KafkaTopic");
+        String uri;
+        if (kamelet || strimzi) {
+            uri = extractTupleValue(mn.getValue(), "name");
+        } else {
+            uri = extractTupleValue(node.getValue(), "uri");
+        }
+
+        // properties
+        MappingNode prop = asMappingNode(nodeAt(node, "/properties"));
+        Map<String, Object> params = asMap(prop);
+        if (params != null && !params.isEmpty()) {
+            String query = URISupport.createQueryString(params);
+            uri = uri + "?" + query;
+        }
+
+        if (kamelet) {
+            return "kamelet:" + uri;
+        } else if (strimzi) {
+            return "kafka:" + uri;
+        } else {
+            return uri;
         }
-        return false;
     }
 
 }
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoaderSupport.java b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoaderSupport.java
index ed74dc6..e6821e0 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoaderSupport.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoaderSupport.java
@@ -18,8 +18,11 @@ package org.apache.camel.dsl.yaml;
 
 import java.io.FileNotFoundException;
 import java.io.InputStream;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
+import java.util.function.Predicate;
 
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.dsl.support.RouteBuilderLoaderSupport;
@@ -36,10 +39,14 @@ import org.snakeyaml.engine.v2.api.LoadSettings;
 import org.snakeyaml.engine.v2.api.YamlUnicodeReader;
 import org.snakeyaml.engine.v2.composer.Composer;
 import org.snakeyaml.engine.v2.nodes.Node;
+import org.snakeyaml.engine.v2.nodes.NodeTuple;
+import org.snakeyaml.engine.v2.nodes.NodeType;
 import org.snakeyaml.engine.v2.parser.Parser;
 import org.snakeyaml.engine.v2.parser.ParserImpl;
 import org.snakeyaml.engine.v2.scanner.StreamReader;
 
+import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.asText;
+
 public abstract class YamlRoutesBuilderLoaderSupport extends RouteBuilderLoaderSupport {
     public static final String DESERIALIZATION_MODE = "CamelYamlDslDeserializationMode";
 
@@ -130,4 +137,34 @@ public abstract class YamlRoutesBuilderLoaderSupport extends RouteBuilderLoaderS
     }
 
     protected abstract RouteBuilder builder(Node node);
+
+    protected boolean anyTupleMatches(List<NodeTuple> list, String aKey, String aValue) {
+        return anyTupleMatches(list, aKey, Predicate.isEqual(aValue));
+    }
+
+    protected boolean anyTupleMatches(List<NodeTuple> list, String aKey, Predicate<String> predicate) {
+        for (NodeTuple tuple : list) {
+            final String key = asText(tuple.getKeyNode());
+            final Node val = tuple.getValueNode();
+            if (Objects.equals(aKey, key) && NodeType.SCALAR.equals(val.getNodeType())) {
+                String value = asText(tuple.getValueNode());
+                if (predicate.test(value)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    protected String extractTupleValue(List<NodeTuple> list, String aKey) {
+        for (NodeTuple tuple : list) {
+            final String key = asText(tuple.getKeyNode());
+            final Node val = tuple.getValueNode();
+            if (Objects.equals(aKey, key) && NodeType.SCALAR.equals(val.getNodeType())) {
+                return asText(tuple.getValueNode());
+            }
+        }
+        return null;
+    }
+
 }
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy
new file mode 100644
index 0000000..d80319e
--- /dev/null
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletBindingLoaderTest.groovy
@@ -0,0 +1,335 @@
+/*
+ * 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 org.apache.camel.dsl.yaml
+
+import org.apache.camel.dsl.yaml.support.YamlTestSupport
+import org.apache.camel.model.ToDefinition
+
+class KameletBindingLoaderTest extends YamlTestSupport {
+    @Override
+    def doSetup() {
+        context.start()
+    }
+
+    def "kamelet binding from kamelet to kamelet"() {
+        when:
+            loadBindings('''
+                apiVersion: camel.apache.org/v1alpha1
+                kind: KameletBinding
+                metadata:
+                  name: timer-event-source                  
+                spec:
+                  source:
+                    ref:
+                      kind: Kamelet
+                      apiVersion: camel.apache.org/v1
+                      name: timer-source
+                    properties:
+                      message: "Hello world!"
+                  sink:
+                    ref:
+                      kind: Kamelet
+                      apiVersion: camel.apache.org/v1
+                      name: log-sink
+            ''')
+        then:
+            context.routeDefinitions.size() == 3
+
+            with (context.routeDefinitions[0]) {
+                routeId == 'timer-event-source'
+                input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+                outputs.size() == 1
+                with (outputs[0], ToDefinition) {
+                    endpointUri == 'kamelet:log-sink'
+                }
+            }
+    }
+
+    def "kamelet binding from uri to kamelet"() {
+        when:
+        loadBindings('''
+                apiVersion: camel.apache.org/v1alpha1
+                kind: KameletBinding
+                metadata:
+                  name: timer-event-source                  
+                spec:
+                  source:
+                    uri: timer:foo
+                  sink:
+                    ref:
+                      kind: Kamelet
+                      apiVersion: camel.apache.org/v1
+                      name: log-sink
+            ''')
+        then:
+        context.routeDefinitions.size() == 2
+
+        with (context.routeDefinitions[0]) {
+            routeId == 'timer-event-source'
+            input.endpointUri == 'timer:foo'
+            outputs.size() == 1
+            with (outputs[0], ToDefinition) {
+                endpointUri == 'kamelet:log-sink'
+            }
+        }
+    }
+
+    def "kamelet binding from uri to uri"() {
+        when:
+        loadBindings('''
+                apiVersion: camel.apache.org/v1alpha1
+                kind: KameletBinding
+                metadata:
+                  name: timer-event-source                  
+                spec:
+                  source:
+                    uri: timer:foo
+                  sink:
+                    uri: log:bar
+            ''')
+        then:
+        context.routeDefinitions.size() == 1
+
+        with (context.routeDefinitions[0]) {
+            routeId == 'timer-event-source'
+            input.endpointUri == 'timer:foo'
+            outputs.size() == 1
+            with (outputs[0], ToDefinition) {
+                endpointUri == 'log:bar'
+            }
+        }
+    }
+
+    def "kamelet binding steps"() {
+        when:
+        loadBindings('''
+            apiVersion: camel.apache.org/v1alpha1
+            kind: KameletBinding
+            metadata:
+              name: steps-binding
+            spec:
+              source:
+                ref:
+                  kind: Kamelet
+                  apiVersion: camel.apache.org/v1alpha1
+                  name: timer-source
+                properties:
+                  message: "Camel"
+              steps:
+              - ref:
+                  kind: Kamelet
+                  apiVersion: camel.apache.org/v1alpha1
+                  name: prefix-action
+                properties:
+                  prefix: "Apache"
+              - ref:
+                  kind: Kamelet
+                  apiVersion: camel.apache.org/v1alpha1
+                  name: prefix-action
+                properties:
+                  prefix: "Hello"
+              sink:
+                uri: log:info
+                ''')
+        then:
+        context.routeDefinitions.size() == 4
+
+        with (context.routeDefinitions[0]) {
+            routeId == 'steps-binding'
+            input.endpointUri == 'kamelet:timer-source?message=Camel'
+            outputs.size() == 3
+            with (outputs[2], ToDefinition) {
+                endpointUri == 'log:info'
+            }
+        }
+    }
+
+    def "kamelet binding steps kamelet uri"() {
+        when:
+        loadBindings('''
+            apiVersion: camel.apache.org/v1alpha1
+            kind: KameletBinding
+            metadata:
+              name: steps-binding
+            spec:
+              source:
+                ref:
+                  kind: Kamelet
+                  apiVersion: camel.apache.org/v1alpha1
+                  name: timer-source
+                properties:
+                  message: "Camel"
+              steps:
+              - ref:
+                  kind: Kamelet
+                  apiVersion: camel.apache.org/v1alpha1
+                  name: prefix-action
+                properties:
+                  prefix: "Apache"
+              - uri: mock:dummy
+              sink:
+                uri: log:info
+                ''')
+        then:
+        context.routeDefinitions.size() == 3
+
+        with (context.routeDefinitions[0]) {
+            routeId == 'steps-binding'
+            input.endpointUri == 'kamelet:timer-source?message=Camel'
+            outputs.size() == 3
+            with (outputs[1], ToDefinition) {
+                endpointUri == 'mock:dummy'
+            }
+            with (outputs[2], ToDefinition) {
+                endpointUri == 'log:info'
+            }
+        }
+    }
+
+    def "kamelet binding steps uri uri"() {
+        when:
+        loadBindings('''
+            apiVersion: camel.apache.org/v1alpha1
+            kind: KameletBinding
+            metadata:
+              name: steps-binding
+            spec:
+              source:
+                ref:
+                  kind: Kamelet
+                  apiVersion: camel.apache.org/v1alpha1
+                  name: timer-source
+                properties:
+                  message: "Camel"
+              steps:
+              - uri: mock:dummy
+              - uri: mock:dummy2
+              sink:
+                uri: log:info
+                ''')
+        then:
+        context.routeDefinitions.size() == 2
+
+        with (context.routeDefinitions[0]) {
+            routeId == 'steps-binding'
+            input.endpointUri == 'kamelet:timer-source?message=Camel'
+            outputs.size() == 3
+            with (outputs[0], ToDefinition) {
+                endpointUri == 'mock:dummy'
+            }
+            with (outputs[1], ToDefinition) {
+                endpointUri == 'mock:dummy2'
+            }
+            with (outputs[2], ToDefinition) {
+                endpointUri == 'log:info'
+            }
+        }
+    }
+
+    def "kamelet binding from kamelet to strimzi"() {
+        when:
+
+        // stub kafka for testing as it requires to setup connection to a real kafka broker
+        context.addComponent("kafka", context.getComponent("stub"))
+
+        loadBindings('''
+                apiVersion: camel.apache.org/v1alpha1
+                kind: KameletBinding
+                metadata:
+                  name: timer-event-source                  
+                spec:
+                  source:
+                    ref:
+                      kind: Kamelet
+                      apiVersion: camel.apache.org/v1
+                      name: timer-source
+                    properties:
+                      message: "Hello world!"
+                  sink:
+                    ref:
+                      kind: KafkaTopic
+                      apiVersion: kafka.strimzi.io/v1beta2
+                      name: my-topic
+            ''')
+        then:
+        context.routeDefinitions.size() == 2
+
+        with (context.routeDefinitions[0]) {
+            routeId == 'timer-event-source'
+            input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+            outputs.size() == 1
+            with (outputs[0], ToDefinition) {
+                endpointUri == 'kafka:my-topic'
+            }
+        }
+    }
+
+    def "kamelet binding with error handler"() {
+        when:
+
+        // stub kafka for testing as it requires to setup connection to a real kafka broker
+        context.addComponent("kafka", context.getComponent("stub"))
+
+        loadBindings('''
+                apiVersion: camel.apache.org/v1alpha1
+                kind: KameletBinding
+                metadata:
+                  name: timer-event-source                  
+                spec:
+                  source:
+                    ref:
+                      kind: Kamelet
+                      apiVersion: camel.apache.org/v1
+                      name: timer-source
+                    properties:
+                      message: "Hello world!"
+                  sink:
+                    ref:
+                      kind: Kamelet
+                      apiVersion: camel.apache.org/v1alpha1
+                      name: log-sink
+                  errorHandler:
+                    dead-letter-channel:
+                      endpoint:
+                        ref:
+                          kind: Kamelet
+                          apiVersion: camel.apache.org/v1alpha1
+                          name: error-handler
+                        properties:
+                          log-message: "ERROR!"
+                          kafka-brokers: my-broker
+                          kafka-topic: my-first-test
+                          kafka-service-account-id: scott
+                          kafka-service-account-secret: tiger
+                      parameters:
+                        maximumRedeliveries: 1
+                        redeliveryDelay: 2000    
+                    ''')
+        then:
+        context.routeDefinitions.size() == 2
+
+        with (context.routeDefinitions[0]) {
+            routeId == 'timer-event-source'
+            input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+            outputs.size() == 1
+            with (outputs[0], ToDefinition) {
+                endpointUri == 'kafka:my-topic'
+            }
+        }
+    }
+
+}
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/YamlTestSupport.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/YamlTestSupport.groovy
index efd01cf..e9da693 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/YamlTestSupport.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/YamlTestSupport.groovy
@@ -25,6 +25,7 @@ import org.apache.camel.CamelContext
 import org.apache.camel.FluentProducerTemplate
 import org.apache.camel.builder.RouteBuilder
 import org.apache.camel.component.mock.MockEndpoint
+import org.apache.camel.dsl.yaml.KameletRoutesBuilderLoader
 import org.apache.camel.dsl.yaml.YamlRoutesBuilderLoader
 import org.apache.camel.dsl.yaml.common.YamlDeserializationMode
 import org.apache.camel.impl.DefaultCamelContext
@@ -84,6 +85,17 @@ class YamlTestSupport extends Specification implements HasCamelContext {
         )
     }
 
+    def loadKamelets(Resource... resources) {
+        loadKamelets(resources.toList())
+    }
+
+    def loadKamelets(Collection<Resource> resources) {
+        KameletRoutesBuilderLoader kl = new KameletRoutesBuilderLoader()
+        kl.setCamelContext(context)
+        kl.start()
+        resources.forEach(r -> kl.loadRoutesBuilder(r))
+    }
+
     def loadKamelets(String... resources) {
         int index = 0
 
@@ -94,6 +106,16 @@ class YamlTestSupport extends Specification implements HasCamelContext {
         )
     }
 
+    def loadBindings(String... resources) {
+        int index = 0
+
+        context.routesLoader.loadRoutes(
+            resources.collect {
+                it -> ResourceHelper.fromString("binding-${index++}.yaml", it.stripIndent())
+            }
+        )
+    }
+
     def withMock(
             String uri,
             @DelegatesTo(MockEndpoint) Closure<?> closure) {
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/log-sink.kamelet.yaml b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/log-sink.kamelet.yaml
new file mode 100644
index 0000000..54b37d52
--- /dev/null
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/log-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: log-sink
+  annotations:
+    camel.apache.org/kamelet.support.level: "Preview"
+    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: "sink"
+spec:
+  definition:
+    title: "Log Sink"
+    description: |-
+      A sink that logs all data that it receives, useful for debugging purposes.
+    type: object
+    properties:
+      showHeaders:
+        title: Show Headers
+        description: Show the headers received
+        type: boolean
+        default: false
+        x-descriptors:
+          - 'urn:alm:descriptor:com.tectonic.ui:checkbox'
+      showStreams:
+        title: Show Streams
+        description: Show the stream bodies (they may not be available in following steps)
+        type: boolean
+        default: false
+        x-descriptors:
+          - 'urn:alm:descriptor:com.tectonic.ui:checkbox'
+  dependencies:
+    - "camel:kamelet"
+    - "camel:log"
+  flow:
+    from:
+      uri: "kamelet:source"
+      steps:
+        - to:
+            uri: "log:info"
+            parameters:
+              showHeaders: "{{?showHeaders}}"
+              showStreams: "{{?showStreams}}"
\ No newline at end of file
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/prefix-action.kamelet.yaml b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/prefix-action.kamelet.yaml
new file mode 100644
index 0000000..e8e9b6a
--- /dev/null
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/prefix-action.kamelet.yaml
@@ -0,0 +1,45 @@
+# ---------------------------------------------------------------------------
+# 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: prefix-action
+  labels:
+    camel.apache.org/kamelet.type: "step"
+spec:
+  definition:
+    title: "Prefix"
+    description: "Adds a prefix to the incoming payload"
+    required:
+      - prefix
+    properties:
+      prefix:
+        title: Prefix
+        description: The prefix to add
+        type: string
+  types:
+    in:
+      mediaType: text/plain
+    out:
+      mediaType: text/plain
+  flow:
+    from:
+      uri: "kamelet:source"
+      steps:
+        - set-body:
+            simple: "{{prefix}} ${body}"
\ No newline at end of file
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/timer-source.kamelet.yaml b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/timer-source.kamelet.yaml
new file mode 100644
index 0000000..96195c1
--- /dev/null
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/timer-source.kamelet.yaml
@@ -0,0 +1,69 @@
+# ---------------------------------------------------------------------------
+# 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: timer-source
+  annotations:
+    camel.apache.org/kamelet.support.level: "Preview"
+    camel.apache.org/catalog.version: "main-SNAPSHOT"
+    camel.apache.org/kamelet.icon: data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gU3ZnIFZlY3RvciBJY29ucyA6IGh0dHA6Ly93d3cub25saW5ld2ViZm9udHMuY29tL2ljb24gLS0+DQo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm9 [...]
+    camel.apache.org/provider: "Apache Software Foundation"
+    camel.apache.org/kamelet.group: "Timer"
+  labels:
+    camel.apache.org/kamelet.type: source
+    camel.apache.org/kamelet.verified: "true"
+spec:
+  definition:
+    title: Timer Source
+    description: Produces periodic events with a custom payload.
+    required:
+      - message
+    type: object
+    properties:
+      period:
+        title: Period
+        description: The interval between two events in milliseconds
+        type: integer
+        default: 1000
+      message:
+        title: Message
+        description: The message to generate
+        type: string
+        example: hello world
+      contentType:
+        title: Content Type
+        description: The content type of the message being generated
+        type: string
+        default: text/plain
+  dependencies:
+    - "camel:core"
+    - "camel:timer"
+    - "camel:kamelet"
+  flow:
+    from:
+      uri: timer:tick
+      parameters:
+        period: "{{period}}"
+      steps:
+        - set-body:
+            constant: "{{message}}"
+        - set-header:
+            name: "Content-Type"
+            constant: "{{contentType}}"
+        - to: kamelet:sink
\ No newline at end of file

[camel] 04/08: CAMEL-17288: camel-core - Route template parameters dash vs camel case keys and required

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

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

commit 4ef0dc7bfdc02eaf546e7172835c38896e16c5b4
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Dec 7 11:33:09 2021 +0100

    CAMEL-17288: camel-core - Route template parameters dash vs camel case keys and required
---
 .../main/java/org/apache/camel/impl/DefaultModel.java  | 15 +++++++++++++--
 .../test/resources/kamelets/error-handler.kamelet.yaml | 18 +++++++++---------
 2 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
index 83465a8..86d12af 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
@@ -334,6 +334,7 @@ public class DefaultModel implements Model {
             throw new IllegalArgumentException("Cannot find RouteTemplate with id " + routeTemplateId);
         }
 
+        // support both camelCase and kebab-case keys
         final Map<String, Object> prop = new HashMap<>();
         // include default values first from the template (and validate that we have inputs for all required parameters)
         if (target.getTemplateParameters() != null) {
@@ -341,7 +342,7 @@ public class DefaultModel implements Model {
 
             for (RouteTemplateParameterDefinition temp : target.getTemplateParameters()) {
                 if (temp.getDefaultValue() != null) {
-                    prop.put(temp.getName(), temp.getDefaultValue());
+                    addProperty(prop, temp.getName(), temp.getDefaultValue());
                 } else {
                     if (temp.isRequired() && !routeTemplateContext.hasParameter(temp.getName())) {
                         // this is a required parameter which is missing
@@ -358,7 +359,7 @@ public class DefaultModel implements Model {
 
         // then override with user parameters part 1
         if (routeTemplateContext.getParameters() != null) {
-            prop.putAll(routeTemplateContext.getParameters());
+            routeTemplateContext.getParameters().forEach((k, v) -> addProperty(prop, k, v));
         }
         // route template context should include default template parameters from the target route template
         // so it has all parameters available
@@ -415,6 +416,16 @@ public class DefaultModel implements Model {
         return def.getId();
     }
 
+    private static void addProperty(Map<String, Object> prop, String key, Object value) {
+        prop.put(key, value);
+        // support also camelCase and kebab-case because route templates (kamelets)
+        // can be defined using different key styles
+        key = StringHelper.dashToCamelCase(key);
+        prop.put(key, value);
+        key = StringHelper.camelCaseToDash(key);
+        prop.put(key, value);
+    }
+
     private void addTemplateBeans(RouteTemplateContext routeTemplateContext, RouteTemplateDefinition target) throws Exception {
         for (RouteTemplateBeanDefinition b : target.getTemplateBeans()) {
             final Map<String, Object> props = new HashMap<>();
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/error-handler.kamelet.yaml b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/error-handler.kamelet.yaml
index f088fb2..7fcd6bd 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/error-handler.kamelet.yaml
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/error-handler.kamelet.yaml
@@ -30,27 +30,27 @@ spec:
       - kafka-service-account-secret
       - log-message
     properties:
-      kafkaBrokers:
+      kafka-brokers:
         title: Kafka Brokers
         description: the bootstrap server
         type: string
         example: "xyz-ins--rplssqfz-yyyyyyy-crojg.bf2.kafka.my-clud-service.com:443"
-      kafkaTopic:
+      kafka-topic:
         title: Kafka Topic
         description: the DLC topic
         type: string
         example: "my-dlc"
-      kafkaServiceAccountId:
+      kafka-service-account-id:
         title: Service Account ID
         description: the SA to use
         type: string
         example: "srvc-acct-xxxxxx-519b-453f-9f68-yyyyyyyyy"
-      kafkaServiceAccountSecret:
+      kafka-service-account-secret:
         title: Service Account Secret
         description: the SA secrete to use
         type: string
         example: "xxxxxxxxx-46c7-4c6c-a753-yyyyyyyyyyyyyyy"
-      logMessage:
+      log-message:
         title: Message
         description: A message warning to log
         type: string
@@ -61,13 +61,13 @@ spec:
       steps:
         # First step: send to the DLC for future processing
         - to:
-            uri: kafka:{{kafkaTopic}}
+            uri: kafka:{{kafka-topic}}
             parameters:
-              brokers: "{{kafkaBrokers}}"
+              brokers: "{{kafka-brokers}}"
               security-protocol: SASL_SSL
               sasl-mechanism: PLAIN
-              sasl-jaas-config: "org.apache.kafka.common.security.plain.PlainLoginModule required username={{kafkaServiceAccountId}} password={{kafkaServiceAccountSecret}};"
+              sasl-jaas-config: "org.apache.kafka.common.security.plain.PlainLoginModule required username={{kafka-service-account-id}} password={{kafka-service-account-secret}};"
         # Log an error message to notify about the failure
         - set-body:
-            constant: "{{logMessage}} - worry not, the event is stored in the DLC"
+            constant: "{{log-message}} - worry not, the event is stored in the DLC"
         - to: "log:error-sink"