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 a760d0e1ab30c4284515ceee83eaa6df5070289a Author: Claus Ibsen <[email protected]> AuthorDate: Wed Aug 10 13:55:26 2022 +0200 CAMEL-18366: camel-yaml-dsl - Allow to configure route options in route-templates/kamelets. --- .../dsl/yaml/common/YamlDeserializerBase.java | 8 +++ .../common/exception/InvalidRouteException.java | 30 +++++++++ .../deserializers/RouteDefinitionDeserializer.java | 12 ++++ .../RouteTemplateDefinitionDeserializer.java | 22 ++++++- .../generated/resources/schema/camel-yaml-dsl.json | 14 ++++- .../generated/resources/schema/camelYamlDsl.json | 14 ++++- .../camel/dsl/yaml/KameletBindingLoaderTest.groovy | 35 +++++++++++ .../apache/camel/dsl/yaml/RouteTemplateTest.groovy | 30 +++++++++ .../kamelets/route-timer-source.kamelet.yaml | 72 ++++++++++++++++++++++ 9 files changed, 233 insertions(+), 4 deletions(-) diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-common/src/main/java/org/apache/camel/dsl/yaml/common/YamlDeserializerBase.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-common/src/main/java/org/apache/camel/dsl/yaml/common/YamlDeserializerBase.java index 118b30d041e..9ad857c5f8a 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-common/src/main/java/org/apache/camel/dsl/yaml/common/YamlDeserializerBase.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-common/src/main/java/org/apache/camel/dsl/yaml/common/YamlDeserializerBase.java @@ -63,6 +63,7 @@ public abstract class YamlDeserializerBase<T> extends YamlDeserializerSupport im target = newInstance(); onNewTarget(node, target, line); setProperties(target, mn); + afterPropertiesSet(target, mn); } else { throw new UnsupportedNodeTypeException(node); } @@ -77,6 +78,13 @@ public abstract class YamlDeserializerBase<T> extends YamlDeserializerSupport im */ protected abstract T newInstance(); + /** + * Allows custom validation after the properties has been set on the target + */ + protected void afterPropertiesSet(T target, Node node) { + // noop + } + /** * Creates a Java instance of the expected type from a string. * diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-common/src/main/java/org/apache/camel/dsl/yaml/common/exception/InvalidRouteException.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-common/src/main/java/org/apache/camel/dsl/yaml/common/exception/InvalidRouteException.java new file mode 100644 index 00000000000..fc0a9fa53b4 --- /dev/null +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-common/src/main/java/org/apache/camel/dsl/yaml/common/exception/InvalidRouteException.java @@ -0,0 +1,30 @@ +/* + * 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.common.exception; + +import java.util.Optional; + +import org.snakeyaml.engine.v2.exceptions.MarkedYamlEngineException; +import org.snakeyaml.engine.v2.nodes.Node; + +public class InvalidRouteException extends MarkedYamlEngineException { + + public InvalidRouteException(Node node, String message) { + super(null, Optional.empty(), message, node.getStartMark()); + } + +} diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteDefinitionDeserializer.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteDefinitionDeserializer.java index 719829d4272..f1d3c615a24 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteDefinitionDeserializer.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteDefinitionDeserializer.java @@ -45,6 +45,9 @@ import org.snakeyaml.engine.v2.nodes.NodeTuple; @YamlProperty(name = "route-policy", type = "string"), @YamlProperty(name = "startup-order", type = "number"), @YamlProperty(name = "stream-caching", type = "boolean"), + @YamlProperty(name = "message-history", type = "boolean"), + @YamlProperty(name = "log-mask", type = "boolean"), + @YamlProperty(name = "trace", type = "boolean"), @YamlProperty(name = "from", type = "object:org.apache.camel.model.FromDefinition", required = true) }) public class RouteDefinitionDeserializer extends YamlDeserializerBase<RouteDefinition> { @@ -96,6 +99,15 @@ public class RouteDefinitionDeserializer extends YamlDeserializerBase<RouteDefin case "stream-caching": target.setStreamCache(asText(val)); break; + case "log-mask": + target.setLogMask(asText(val)); + break; + case "message-history": + target.setMessageHistory(asText(val)); + break; + case "trace": + target.setTrace(asText(val)); + break; case "from": val.setProperty(RouteDefinition.class.getName(), target); target.setInput(asType(val, FromDefinition.class)); diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteTemplateDefinitionDeserializer.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteTemplateDefinitionDeserializer.java index aaf0417b51f..f68aaae710c 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteTemplateDefinitionDeserializer.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteTemplateDefinitionDeserializer.java @@ -19,6 +19,7 @@ package org.apache.camel.dsl.yaml.deserializers; import java.util.List; import org.apache.camel.dsl.yaml.common.YamlDeserializerBase; +import org.apache.camel.dsl.yaml.common.exception.InvalidRouteException; import org.apache.camel.model.RouteDefinition; import org.apache.camel.model.RouteTemplateBeanDefinition; import org.apache.camel.model.RouteTemplateDefinition; @@ -37,9 +38,10 @@ import org.snakeyaml.engine.v2.nodes.Node; @YamlProperty(name = "id", type = "string", required = true), + @YamlProperty(name = "route", + type = "object:org.apache.camel.model.RouteDefinition"), @YamlProperty(name = "from", - type = "object:org.apache.camel.model.FromDefinition", - required = true), + type = "object:org.apache.camel.model.FromDefinition"), @YamlProperty(name = "parameters", type = "array:org.apache.camel.model.RouteTemplateParameterDefinition"), @YamlProperty(name = "beans", @@ -64,6 +66,11 @@ public class RouteTemplateDefinitionDeserializer extends YamlDeserializerBase<Ro target.setId(asText(node)); break; } + case "route": { + RouteDefinition route = asType(node, RouteDefinition.class); + target.setRoute(route); + break; + } case "from": { OutputAwareFromDefinition val = asType(node, OutputAwareFromDefinition.class); RouteDefinition route = new RouteDefinition(); @@ -88,4 +95,15 @@ public class RouteTemplateDefinitionDeserializer extends YamlDeserializerBase<Ro } return true; } + + @Override + protected void afterPropertiesSet(RouteTemplateDefinition target, Node node) { + // either from or route must be set + if (target.getRoute() == null) { + throw new InvalidRouteException(node, "RouteTemplate must have route or from set"); + } + if (target.getRoute().getInput() == null) { + throw new InvalidRouteException(node, "RouteTemplate must have from set"); + } + } } diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camel-yaml-dsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camel-yaml-dsl.json index 7630c7f567d..abb996ff519 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camel-yaml-dsl.json +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camel-yaml-dsl.json @@ -2421,6 +2421,12 @@ "id" : { "type" : "string" }, + "log-mask" : { + "type" : "boolean" + }, + "message-history" : { + "type" : "boolean" + }, "precondition" : { "type" : "string" }, @@ -2435,6 +2441,9 @@ }, "stream-caching" : { "type" : "boolean" + }, + "trace" : { + "type" : "boolean" } }, "required" : [ "from" ] @@ -2486,9 +2495,12 @@ "items" : { "$ref" : "#/items/definitions/org.apache.camel.model.RouteTemplateParameterDefinition" } + }, + "route" : { + "$ref" : "#/items/definitions/org.apache.camel.model.RouteDefinition" } }, - "required" : [ "from", "id" ] + "required" : [ "id" ] }, "org.apache.camel.model.RouteTemplateParameterDefinition" : { "type" : "object", diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json index 800351a0e61..9a159975e99 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json @@ -2325,6 +2325,12 @@ "id" : { "type" : "string" }, + "logMask" : { + "type" : "boolean" + }, + "messageHistory" : { + "type" : "boolean" + }, "precondition" : { "type" : "string" }, @@ -2339,6 +2345,9 @@ }, "streamCaching" : { "type" : "boolean" + }, + "trace" : { + "type" : "boolean" } }, "required" : [ "from" ] @@ -2390,9 +2399,12 @@ "items" : { "$ref" : "#/items/definitions/org.apache.camel.model.RouteTemplateParameterDefinition" } + }, + "route" : { + "$ref" : "#/items/definitions/org.apache.camel.model.RouteDefinition" } }, - "required" : [ "from", "id" ] + "required" : [ "id" ] }, "org.apache.camel.model.RouteTemplateParameterDefinition" : { "type" : "object", 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 a4c4a97ae64..096aedf01d1 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 @@ -552,4 +552,39 @@ class KameletBindingLoaderTest extends YamlTestSupport { } } + def "kamelet start route"() { + 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: route-timer-source + properties: + message: "Hello world!" + sink: + ref: + kind: Kamelet + apiVersion: camel.apache.org/v1 + name: log-sink + ''') + then: + context.routeDefinitions.size() == 3 + + // global stream caching enabled + context.streamCaching == true + + with (context.routeDefinitions[1]) { + template == true + // stream-caching is disabled in the kamelet + streamCache == "false" + messageHistory == "true" + } + } + } diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteTemplateTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteTemplateTest.groovy index 7fba412d4fa..362eb48a614 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteTemplateTest.groovy +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteTemplateTest.groovy @@ -20,6 +20,7 @@ import org.apache.camel.component.mock.MockEndpoint import org.apache.camel.dsl.yaml.support.YamlTestSupport import org.apache.camel.dsl.yaml.support.model.MySetBody import org.apache.camel.dsl.yaml.support.model.MyUppercaseProcessor +import org.apache.camel.impl.engine.DefaultRoute import org.apache.camel.model.LogDefinition import org.apache.camel.model.RouteTemplateDefinition import org.apache.camel.model.ToDefinition @@ -454,4 +455,33 @@ class RouteTemplateTest extends YamlTestSupport { } } + def "create route-template with route"() { + setup: + loadRoutes """ + - route-template: + id: "myTemplate" + parameters: + - name: "foo" + - name: "bar" + route: + stream-caching: false + message-history: true + log-mask: true + from: + uri: "direct:{{foo}}" + steps: + - to: "mock:{{bar}}" + """ + when: + context.addRouteFromTemplate('myId', 'myTemplate', [foo: "start", bar: "result"]) + context.start() + + then: + with(context.routes[0], DefaultRoute) { + it.isStreamCaching() == false + it.isMessageHistory() == true + it.isLogMask() == true + } + } + } diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/route-timer-source.kamelet.yaml b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/route-timer-source.kamelet.yaml new file mode 100644 index 00000000000..08dd0217d75 --- /dev/null +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/resources/kamelets/route-timer-source.kamelet.yaml @@ -0,0 +1,72 @@ +# --------------------------------------------------------------------------- +# 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: route-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: "Route 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" + template: + route: + stream-caching: false + message-history: true + 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
