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
The following commit(s) were added to refs/heads/main by this push:
new 96921011d3db CAMEL-25820: camel-yaml-dsl-validator - the Kamelet
schema keeps the schema of the template under definitions, so validating a
Kamelet logs no warning (#28115)
96921011d3db is described below
commit 96921011d3db2763cc7cedd8e5da803f07be9251
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Oct 19 18:51:35 2026 +0200
CAMEL-25820: camel-yaml-dsl-validator - the Kamelet schema keeps the schema
of the template under definitions, so validating a Kamelet logs no warning
(#28115)
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
---
.../camel/dsl/yaml/validator/YamlValidator.java | 10 +++--
.../dsl/yaml/validator/KameletValidationTest.java | 45 ++++++++++++++++++++++
2 files changed, 52 insertions(+), 3 deletions(-)
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlValidator.java
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlValidator.java
index 6b787a151989..4552f458b1e4 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlValidator.java
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlValidator.java
@@ -675,8 +675,12 @@ public class YamlValidator {
* <p/>
* The envelope is described loosely on purpose. Camel does not own the
Kamelet CRD, so the parts it does not read
* are accepted as they come rather than failed for being unknown.
+ * <p/>
+ * The schema of the template is kept under {@code definitions}, where
draft 4 (the dialect of the route schema)
+ * keeps a schema that is only referenced: under a key of its own at the
root it is no keyword, and the validator
+ * warns about an unknown keyword each time a JVM loads the schema
(CAMEL-25820).
*/
- private JsonNode kameletModel(JsonNode routeModel) {
+ JsonNode kameletModel(JsonNode routeModel) {
ObjectNode root = mapper.createObjectNode();
JsonNode dialect = routeModel.get("$schema");
if (dialect != null) {
@@ -696,14 +700,14 @@ public class YamlValidator {
specProperties.putObject("types").put("type", "object");
specProperties.putObject("dataTypes").put("type", "object");
specProperties.putObject("dependencies").put("type", "array");
- specProperties.putObject("template").put("$ref", "#/templateEntry");
+ specProperties.putObject("template").put("$ref",
"#/definitions/templateEntry");
// an entry of a route file is exactly one of route/from/beans/...,
which is what maxProperties says. The
// template of a Kamelet is not: counter-source declares its bean
beside its from, and 60 of the 250 kamelets
// of the library do the same. Everything else about an entry still
holds, and the $refs inside the copy point
// at #/items/definitions/..., which is why the items node is kept as
well.
ObjectNode template = routeModel.get("items").deepCopy();
template.remove("maxProperties");
- root.set("templateEntry", template);
+ root.putObject("definitions").set("templateEntry", template);
root.set("items", routeModel.get("items"));
return root;
}
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/KameletValidationTest.java
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/KameletValidationTest.java
index 0b553fd1b423..22cba4c2d7a6 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/KameletValidationTest.java
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/KameletValidationTest.java
@@ -16,9 +16,20 @@
*/
package org.apache.camel.dsl.yaml.validator;
+import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.networknt.schema.Error;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.appender.AbstractAppender;
+import org.apache.logging.log4j.core.config.Property;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@@ -60,6 +71,40 @@ class KameletValidationTest {
return YamlValidator.describeAll(content, errors);
}
+ @Test
+ void aKameletIsValidatedWithoutAWarningAboutTheSchema() throws Exception {
+ // CAMEL-25820: the schema of a Kamelet kept the schema of its
template under a key of its own at the root, which
+ // is no keyword, and the validator warned "Unknown keyword
templateEntry" each time it loaded the schema
+ List<String> warnings = new CopyOnWriteArrayList<>();
+ LoggerContext context = (LoggerContext) LogManager.getContext(false);
+ Appender appender = new AbstractAppender("kamelet-schema-warnings",
null, null, true, Property.EMPTY_ARRAY) {
+ @Override
+ public void append(LogEvent event) {
+ if (event.getLevel().isMoreSpecificThan(Level.WARN)) {
+ warnings.add(event.getLoggerName() + ": " +
event.getMessage().getFormattedMessage());
+ }
+ }
+ };
+ appender.start();
+ context.getConfiguration().getRootLogger().addAppender(appender,
Level.ALL, null);
+ context.updateLoggers();
+ try {
+ assertThat(validate(WORKING)).isEmpty();
+ } finally {
+
context.getConfiguration().getRootLogger().removeAppender(appender.getName());
+ context.updateLoggers();
+ appender.stop();
+ }
+
+ assertThat(warnings).noneMatch(w -> w.contains("Unknown keyword"));
+ // the validator warns once in a JVM, so the schema is checked as
well: only keywords at its root
+ YamlValidator validator = new YamlValidator();
+ JsonNode model = new
ObjectMapper().readTree(YamlValidator.class.getResourceAsStream("/schema/camelYamlDsl.json"));
+ List<String> keys = new ArrayList<>();
+ validator.kameletModel(model).fieldNames().forEachRemaining(keys::add);
+ assertThat(keys).containsOnly("$schema", "type",
"additionalProperties", "properties", "definitions", "items");
+ }
+
@Test
void aKameletThatRunsIsValid() throws Exception {
// this is the file of the issue: camel run logs the filtered body for
it