allthingssecurity opened a new pull request, #28716: URL: https://github.com/apache/camel/pull/28716
# Description [CAMEL-26330](https://issues.apache.org/jira/browse/CAMEL-26330): the first part of the `camel-chaos` module from `design/chaos.adoc` (#28539). It uses the send hook ([CAMEL-26331](https://issues.apache.org/jira/browse/CAMEL-26331), merged as #28598) and the step hook ([CAMEL-26338](https://issues.apache.org/jira/browse/CAMEL-26338), merged as #28646), only through their public SPI (`SendHook`, `StepHook` and the getters and setters on `ExtendedCamelContext`). With the JAR on the classpath and profile `dev` (or `camel.chaos.enabled=true`), a developer adds rules such as `endpoint=kafka:orders* error rate=0.3 until=1m` or `step=enrich delay duration=500ms` while the application runs, and sees how `onException`, redelivery and the dead letter channel cope. A report says what each rule did. Never with profile `prod`. This is the core only: the switch, the options, the rules, the faults at sends (`error`, `delay`, `drop`) and steps (`error`, `delay`), and a report per rule. A second PR on top adds the poll and route-entry faults, `corrupt`, `error status=` for HTTP, the counts per route and the expectations with a verdict; none of that is here (the parser rejects `route=`, `at=poll`, `corrupt`, `status=`, `expect=`, and the docs do not mention them). The console, CLI and MCP tools, and `stall`/`lifecycle`, come after. ## What is in it - `components/camel-chaos`: a `ContextServicePlugin` that decides when the context initializes (`prod` never; `camel.chaos.enabled` wins otherwise; without it only `dev`). When off, nothing is installed but that idle lifecycle strategy. When on: the send hook, the step hook, the manager, a WARN, and the startup rules; an invalid rule or option vetoes the start. A hand-written rule parser (no regular expressions, at most 2000 characters), copy-on-write rule sets, a seeded random sequence per rule, and delays that wait through `TimeSource` on the calling thread. Docs page and registration files. - camel-main: `camel.chaos.*` (`ChaosConfigurationProperties`: `enabled`, `seed`, `rules`, `maxDuration`, `reportOnShutdown`) with the generated configurer and metadata. `rules` is `insecure:dev`, so `prod` refuses to start with rules. - camel-util: `SecurityUtils` matches `camel.chaos.rules` by its whole key; the `TimeSource` Javadoc says camel-chaos reads the clock through it (camel-core waits for its delays through it). Public API (`@since 4.24`): `ChaosManager.get(context)`, `addRule`, `changeRule`, `removeRule`, `clearRules`, `report()`, and `ChaosReport` (`getSeed`, `toText`, `toJson`), so tests and a plain `Main` can use chaos before the CLI and MCP tools exist. ## Where this differs from the design - **A rule ends** when `TimeSource` time passes its end, checked at each match, not by a scheduled task: no thread to manage, and virtual time in a DST world. - **Options outside camel-main.** camel-main publishes `camel.chaos.*` in the properties component (as for `camel.aiObservability.enabled`), and the plugin reads them there. So `camel.chaos.enabled=true` also works on Spring Boot and Quarkus, but there (and for rules set from Java) camel-main's `insecure:dev` check does not run; chaos stays off in `prod` anyway. - **`SecurityUtils`.** The generated map is keyed by the bare option name, and `rules` would also catch schematron's option. So a small hand-written map matches the whole key first; its `insecureValue` is `null`, meaning any non-blank value. - **Patterns** are globs matched without backtracking: case-sensitive, `*` anywhere, no regular-expression fallback, unlike `PatternHelper`. Rules can come from tools, so matching must stay cheap. - **Limits the design leaves open:** 100 rules (ended ones move to the history to make room), a history of 100, 2000 characters per rule, `delay` and `until` at most `camel.chaos.maxDuration`, the first matching rule that fires decides, and a changed rule keeps its id and starts again. **Cost** (no JMH; a `ProducerTemplate` into three routes, the mean of 3 JVM runs of 9 x 100,000 calls, ns per call, in the order no JAR / chaos off / on without rules / on with three rules that match nothing): empty route 411 / 413 / 431 / 464; one `to` 609 / 600 / 622 / 732; a recipient list of two 1800 / 1778 / 1820 / 1971. Development-time cost only. **Promised fold-in moved:** the `SendHelper` parentheses gnodet-bot asked for in #28598 wait for the next chaos PR that touches camel-support. ## Tests - camel-chaos: 130 tests in 12 classes, no `Thread.sleep`. They cover the parser (57, with a fuzz test and adversarial inputs), fail-closed activation (22, including `prod` with rules and `enabled=true`), camel-main, send and step faults under the error handlers, the report, the seed, and a stress test (8 threads, 16,000 sends, rules added, changed and removed 30 times; every send is failed, dropped or delivered exactly once). Delays and rule ends run on a virtual `TimeSource` clock. - Each class ran 20 times alone, one JVM per run: 240 runs, 0 failures. Ten negative controls (the key behaviours broken one at a time) each fail at least one test. - camel-main: `ChaosConfigurationPropertiesTest` (8) and `MainSecurityPolicyTest`; the whole camel-main suite passes (318). camel-util: `SecurityUtilsTest` (22, 3 new). # Target - [x] I checked that the commit is targeting the correct branch (Camel 4 uses the `main` branch) # Tracking - [x] If this is a large change, bug fix, or code improvement, I checked there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL-26330) filed for the change (usually before you start working on it): [CAMEL-26330](https://issues.apache.org/jira/browse/CAMEL-26330). # Apache Camel coding standards and style - [x] I checked that each commit in the pull request has a meaningful subject line and body. - [ ] I have run `mvn clean install -DskipTests` locally from root folder and I have committed all auto-generated changes. (I built the core modules, camel-main and the module with the formatter, impsort and camel-main generators; the catalog and docs copies are byte-identical to their sources. I did not run the full root build.) # AI-assisted contributions - [x] If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR description identifies the AI tool used. This PR was prepared with Claude Code (Claude Opus 5.5). The commit carries a `Co-Authored-By` trailer. _Claude Code on behalf of allthingssecurity_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- 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]
