Skip to content

chore: write the Kamelets in canonical YAML DSL - #3089

Merged
davsclaus merged 2 commits into
apache:mainfrom
davsclaus:quick-fix/canonical-yaml-kamelets
Oct 6, 2026
Merged

davsclaus merged 2 commits into
apache:mainfrom
davsclaus:quick-fix/canonical-yaml-kamelets

Conversation

@davsclaus

@davsclaus davsclaus commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Claude Code on behalf of Claus Ibsen.

The templates of 187 of the 262 Kamelets use the YAML DSL compact notation, so Camel logs this for each of them on every load and dev-mode reload:

WARN YAML DSL compact notation detected in: classpath:kamelets/timer-source.kamelet.yaml. ... Use Camel CLI to normalize: camel validate normalize <file>

The user (or an AI agent reading the log) is told to fix a file inside a jar they cannot change. This PR writes all 262 templates in the canonical form.

How it was generated

With camel validate normalize, which can now normalize Kamelet files: apache/camel#27449 (CAMEL-25381, for Camel 4.23.0). It rewrites only spec.template, and keeps the license header, metadata, definition, types and dependencies exactly as written. The comments inside the template (82 lines in 16 Kamelets) are put back before the line they were written before. The library copies under library/camel-kamelets/src/main/resources/kamelets were regenerated by the build.

What changes in a template:

  • EIPs: expressions under expression:, for example setBody: {expression: {simple: {expression: ...}}}.
  • Endpoints:
    • to: is written as uri: plus parameters:, with options in the order Camel builds them: path options first, then alphabetical.
    • A kamelet: endpoint keeps the Kamelet in the uri: uri: kamelet:sink.
    • A uri that cannot be split without changing its meaning is kept as written. Examples: https://wttr.in/{{?wttrLocation}}?..., azure-storage-blob:{{accountName}} (fewer path parts than its syntax), azure-files:{{accountName}}/{{shareName}}/{{directoryName}} (more path parts than its syntax), and pulsar:{{topicType}}/{{tenant}}/....
  • Secret options are written as RAW({{?accessKey}}). Camel's YAML DSL wraps a secret option in RAW() when it builds a uri from parameters:, so this is what each Kamelet runs with. For a Kamelet that had its secrets in a uri string, such as splunk-source's password, that is a change: the value is no longer URL-decoded, which is the safer behaviour.
  • A step without steps: (a split followed by sibling steps) gets its following steps nested inside it, as the YAML DSL already loads it.

How it was checked

  • Same route templates. Each original and normalized Kamelet was loaded into Camel and its route template dumped:
    • 97 are byte-identical.
    • 163 differ only in how endpoint uris are written: path options as parameters, RAW(), option order. In each, the endpoint options parse to the same values through the Camel catalog, and the same {{placeholders}} are present.
    • 2 (splunk-sink, splunk-source): splunk:{{mode}}?… becomes splunk?name={{mode}}&…, with the same options, checked by hand.
  • Compact warning: 187 Kamelets logged it before, 0 after.
  • Comments: all 82 comment lines of the templates are kept, in their order.
  • Idempotent: normalizing the normalized Kamelets again changes none of the 262. That run loads them with the real components, so it also proves Camel builds the endpoint each one says.
  • At runtime: the normalized timer-source and log-sink run in a route. The normalized aws-s3-sink creates its endpoint (the bucket name given as a parameter) and stops at AWS credentials, exactly where the original stops.
  • Builds: ./mvnw clean install and ./mvnw verify pass. The Citrus integration tests (-Denable.integration.tests) were not run locally; the integration test workflow on this PR runs them.

Validator changes (ValidateKameletsMojo)

The canonical form moved some options from the uri string into parameters:, where the validator reads them. That showed two gaps in the validator:

  1. The wrong component. It checked the parameters of from: against the component of the Kamelet's first dependency. For azure-storage-blob-changefeed-source, from: is a timer and its timerName was checked against azure-storage-blob. It now uses the component of the from: uri, and falls back to the dependency when that is not a known component.
  2. Prefixed options. It didn't know options taken by prefix, such as mail.imaps.auth.mechanisms on imaps, which fills the mail properties map. Those are now accepted.

Notes for review

  • nominatim-geocode-action: geocoder:address:toOverride becomes address: address, latlng: toOverride. The catalog's split of that path is odd, but it rebuilds exactly the same uri, so the behaviour is unchanged.
  • The Kamelets work with any Camel 4 runtime: the canonical form is not new syntax. Only regenerating them needs the new camel validate normalize.
  • A follow-up could add a check that keeps the catalog canonical, failing the build when a Kamelet logs the compact notation warning.

The templates of 187 of the 262 Kamelets used the compact notation, so Camel
logged "YAML DSL compact notation detected" for every one of them on each load
and reload: a warning a user cannot act on, about a file inside a jar.

Generated with camel validate normalize (apache/camel#27449, CAMEL-25381), which
rewrites only spec.template and keeps the rest of each file as written. The
Kamelet validator now checks the parameters of from: against the component of
its uri (not the first dependency) and accepts prefixed options such as
mail.imaps.auth.mechanisms, which the canonical form makes visible to it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01STT6whBgK1AqsSsUKrnE8m
@Croway

Croway commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

I checked the touched YAML files: they all parse, keep everything outside spec.template unchanged, and keep the same {{placeholders}}. The library/ copies are identical to kamelets/.

One problem: the comments inside spec.template are dropped, although the description says comments are kept. It's 20 comment blocks in 16 Kamelets, and several of them document security decisions (why a header family is stripped, why identity is captured before a parse, why Reply-To stays disabled):

  • aws-bedrock-agent-sink
  • aws-ec2-sink
  • ceph-event-based-source
  • counter-source
  • djl-image-to-text-action
  • docling-convert-action
  • kafka-source
  • kafka-apicurio-registry-not-secured-source
  • kafka-azure-schema-registry-source
  • kafka-not-secured-apicurio-registry-source
  • kafka-not-secured-apicurio-registry-json-source
  • langchain4j-ingest-file-source
  • langchain4j-ingest-sink
  • mail-sink
  • sap-netweaver-sink
  • tika-extract-text-action

Could you restore them? And could you check whether camel validate normalize (apache/camel#27449) can keep the comments in spec.template? Then a future regeneration won't drop them silently again, or at least it would warn when a comment can't be kept.

… as Camel builds the uris

Review: the comments inside spec.template were dropped (82 lines in 16 Kamelets).
Regenerated with camel validate normalize from apache/camel#27449 as it is now:
the comments are back where they were, normalizing a normalized Kamelet changes
nothing, azure-storage-files-source is kept as written (an option given two path
parts was broken by the uri Camel builds), and the options are in the order Camel
builds them with secret options in RAW(), as the YAML DSL wraps them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01STT6whBgK1AqsSsUKrnE8m
@davsclaus

Copy link
Copy Markdown
Contributor Author

Thanks @Croway, you're right, and the description was wrong about comments. Fixed in 88bca4c, generated again with apache/camel#27449 as it is now.

  • The comments are back. The dump is of the route model, which has no comments, so camel validate normalize now puts each comment block back before the line it was written before. It walks the original and normalized templates in order. All 82 comment lines of the 16 Kamelets are kept, in their order. The one block whose line no longer exists (mail-sink, whose options stay in the uri because the scheme is {{protocol}}) is placed right after that endpoint, and the command reports such a case instead of dropping it.
  • Regenerating is now safe. Normalizing the normalized Kamelets again changes nothing. Checking that turned up three more things, all fixed:
    • azure-storage-files-source had share: "{{shareName}}/{{directoryName}}", which the uri Camel builds from the options breaks into {}}. It is now kept as written, as is any uri with a different number of path parts than its syntax, or whose parse loses a {{placeholder}}.
    • The options were in two different orders.
    • Secret options get RAW() as Camel adds it at load time.

./mvnw verify passes, and #3090 is rebased on this.

Claude Code on behalf of Claus Ibsen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants