Croway commented on PR #27447:
URL: https://github.com/apache/camel/pull/27447#issuecomment-6019737773
Thanks, the Kamelet checks are a useful addition. I ran reproducers against
the PR branch, and three issues fail there:
**1. Crash on unknown names that repeat a word**
(`KameletDefinitions.suggest`)
`Set.of(lower.split("[-_.]"))` throws when a word appears twice:
```yaml
- to: kamelet:aws-s3-to-aws-sqs
```
This gives `IllegalArgumentException: duplicate element: aws`, thrown from
`KameletChecks.validateYaml`, from `SourceValidator.validate` and from
`CatalogDocs.catalogDoc("kafka-to-kafka")`. So a made-up name crashes the
write/validate tool instead of returning "did you mean". Changing it to `new
HashSet<>(Arrays.asList(...))` fixes it.
**2. The kamelet component's own endpoint options are reported as unknown
properties** (`KameletChecks.check`)
```yaml
- to: kamelet:log-sink?routeId=myLog&noErrorHandler=false
```
This is reported as `unknown property 'routeId'` and `unknown property
'noErrorHandler'`. `location` and `timeout` under `parameters:` are reported
the same way. A runtime test in `camel-kamelet` with the same URI passes and
creates the route `myLog`, so the validator rejects a valid route. The endpoint
options (`templateId`, `routeId`, `location`, `uuid`, `block`, `timeout`,
`failIfNoConsumers`, `noErrorHandler`, `bridgeErrorHandler`,
`lazyStartProducer`, `exchangePattern`, `exceptionHandler`) could be skipped.
They could be taken from the catalog's `kamelet` component model rather than
hard-coded.
**3. Required properties set in other valid ways are reported as missing**
(`projectProperties` / `inProperties`)
Both of these still give "the required property message is missing":
- `camel.kamelet.timer-source.message: hello` (`:` is a valid
`java.util.Properties` separator)
- `camel.component.kamelet.template-properties[timer-source].message=hello`,
which `KameletComponent` reads
Loading the files with `java.util.Properties` would cover the separators.
Matching `template-properties[<name>]` / `route-properties[...]` would cover
the component form.
The reproducer tests are below, if useful for the PR.
<details><summary>KameletChecksReproducerTest (all fail on the PR
branch)</summary>
```java
@Test
void unknownNameWithRepeatedWordDoesNotCrashValidator() {
String yaml = """
- route:
from:
uri: timer:tick
steps:
- to: kamelet:aws-s3-to-aws-sqs
""";
assertThatCode(() -> KameletChecks.validateYaml(yaml,
null)).doesNotThrowAnyException();
}
@Test
void catalogDocWithRepeatedWordDoesNotCrash() {
assertThatCode(() -> CatalogDocs.catalogDoc(new DefaultCamelCatalog(),
"kafka-to-kafka", null, null, null, null,
false, false, null)).doesNotThrowAnyException();
}
@Test
void kameletComponentOptionsAreNotUnknownProperties() {
String yaml = """
- route:
from:
uri: timer:tick
steps:
- to: kamelet:log-sink?routeId=myLog&noErrorHandler=false
- to:
uri: kamelet:log-sink
parameters:
location: file:/k/log-sink.kamelet.yaml
timeout: 5000
""";
assertThat(KameletChecks.validateYaml(yaml, null)).isEmpty();
}
@Test
void requiredPropertyWithColonSeparator(@TempDir Path dir) throws Exception {
Files.writeString(dir.resolve("application.properties"),
"camel.kamelet.timer-source.message: hello\n");
String yaml = """
- route:
from:
uri: kamelet:timer-source
steps:
- to: kamelet:log-sink
""";
assertThat(KameletChecks.validateYaml(yaml, dir)).isEmpty();
}
@Test
void requiredPropertyFromComponentTemplateProperties(@TempDir Path dir)
throws Exception {
Files.writeString(dir.resolve("application.properties"),
"camel.component.kamelet.template-properties[timer-source].message=hello\n");
// same route as above
assertThat(KameletChecks.validateYaml(yaml, dir)).isEmpty();
}
```
</details>
<details><summary>Runtime check in camel-kamelet (passes: routeId /
noErrorHandler as query parameters are valid)</summary>
```java
class KameletRouteIdQueryParamReproducerTest extends CamelTestSupport {
@Test
void routeIdQueryParamIsAcceptedAtRuntime() {
assertThat(context.getRoute("myLog")).isNotNull();
assertThat(fluentTemplate.toF("direct:start").withBody("hi").request(String.class)).isEqualTo("hi");
}
@Override
protected RoutesBuilder createRouteBuilder() {
return new RouteBuilder() {
@Override
public void configure() {
routeTemplate("log-sink").templateParameter("showHeaders",
"false")
.from("kamelet:source").log("${body}");
from("direct:start").to("kamelet:log-sink?routeId=myLog&noErrorHandler=false");
}
};
}
}
```
</details>
_Claude Code on behalf of Croway_
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]