allthingssecurity opened a new pull request, #28788:
URL: https://github.com/apache/camel/pull/28788

   # Description
   
   [CAMEL-26436](https://issues.apache.org/jira/browse/CAMEL-26436) (related to 
CAMEL-26330 and CAMEL-26418): live control
   of `camel-chaos` from the Camel CLI, step 3 of "Order of work" in 
`design/chaos.adoc`, on top of #28716 and #28754.
   Until now a rule could only come from `camel.chaos.rules` at startup or from 
Java (`ChaosManager`).
   
   - **A `chaos` dev console** (camel-chaos), read only. JSON: `enabled`, the 
current rules (`id`, `version`, `state`,
     `rule`, `hooks`, `matches`, `fired`, `skipped`, `endsIn`, `expectation`) 
and the whole report (verdict, `final`,
     seed, every version of every rule, counts per route). Text: the report as 
`toText()` gives it. When chaos is off it
     says why (off without profile `dev` or `camel.chaos.enabled=true`; stays 
off with profile `prod`). It has no option
     that changes anything, so over HTTP (`/q/dev/chaos`) chaos only lists and 
reports, as the design says.
   - **A `chaos` action of the CLI connector**: `add`, `change`, `remove`, 
`clear` through `ChaosManager`. A rule goes
     through the same parser as `camel.chaos.rules`; a rule that is not valid 
comes back as an error with the reason
     (`Invalid chaos rule [...]: rate=2 is not a probability above 0 and at 
most 1`), an unknown id (change or remove)
     as "not found" (exit code 3 in the CLI).
   - **`camel cmd chaos-add | chaos-change | chaos-remove | chaos-clear`** and 
**`camel get chaos [--report] [--json]`**,
     the flat verb-noun shape of `stop-route` / `camel get circuit-breaker`. 
The id of a rule only means something in one
     integration, so `chaos-add`, `chaos-change` and `chaos-remove` need the 
name or pid of exactly one (as
     `camel cmd sql`). `chaos-clear` without one acts on all integrations whose 
status says chaos is on (as `stop-route`
     acts on all), so an integration without camel-chaos is not asked. `camel 
get chaos` reads the console from the status
     file of each integration (the CLI connector now adds it, as it does for 
the circuit breakers). The report shows why
     an expectation is pending: time left, or "not decided" when its rule was 
removed or changed first.
   - **`camel run --chaos`** adds `camel:chaos`, as `--observe` adds 
`camel:observability-services`: in process, with
     `--background`, and with `--runtime=main` (also for an existing Maven 
project). Chaos then switches itself on with
     profile `dev`, the default of `camel run`. With `--runtime=spring-boot` or 
`quarkus` it is refused for now: the run
     would have to add camel-chaos to the exported project and give it Camel 
profile `dev`; I can open a follow-up JIRA
     for that. `design/chaos.adoc` ("Getting it") says so. Only `camel run` 
(and `camel dev` / `camel debug`, which
     extend it) gets it; it is not an export option.
   - Docs: "Control while it runs" on the chaos page, "Chaos rules" in the CLI 
managing page, the generated command
     pages, the security model and its YAML index (see below), and
     `design/chaos.adoc` brought in line with what #28716 and #28754 built 
(suggestion 1 of the #28754 review: the poll
     strategy is wrapped once before the consumer starts, the counts come from 
the route policy, and netty-http `status=`
     is CAMEL-26432).
   
   ```
   $ camel run orders.camel.yaml --chaos
   $ camel cmd chaos-add orders --rule='endpoint=kafka:orders* error 
exception=java.net.ConnectException rate=0.3 until=1m'
   Added chaos rule r1
   $ camel cmd chaos-change orders --id=r1 --rule='endpoint=kafka:orders* delay 
duration=2s rate=0.5 until=1m'
   Changed chaos rule r1 (version 2)
   $ camel get chaos
   $ camel get chaos orders --report
   ```
   
   ## Safety: the CLI cannot switch chaos on
   
   - The action works only when the context has a `ChaosManager`, which only 
the plugin creates, only with profile `dev`
     or `camel.chaos.enabled=true`, never with `prod`. The action never creates 
one: with profile `prod` (also with
     `camel.chaos.enabled=true`), with no profile, or without the JAR, it 
answers with an error and nothing is installed
     (`LocalCliConnectorChaosActionTest.refusedWithProfileProd`, 
`refusedWhenChaosIsOff`, `refusedWithoutCamelChaos`).
   - The console only reads, whatever options it gets 
(`ChaosDevConsoleTest.optionsDoNotAddChangeOrRemoveRules`).
   - `exception=` instantiates any public `Throwable` class on the classpath 
with a public `String` or no-argument
     constructor. That is now written on the chaos page and in the security 
model (a new row under "Per-option opt-ins":
     a development tool, rules only from the developer, `camel.chaos.rules` is 
`insecure:dev`). `camel ask` reaches the
     commands only through its `camel` command tool, which already asks the 
user before a `camel cmd` (a test pins it for
     `chaos-*`; `camel get chaos` runs without asking).
   
   camel-cli-connector does not get a dependency on camel-chaos: with `camel 
run`, the camel-chaos JAR comes with
   `--chaos` / `--dep` into the class loader of the integration, while 
camel-cli-connector is on the class path of the CLI,
   so it cannot link against `ChaosManager`. The action finds the manager by 
class name through the class resolver of the
   context and calls its public methods by reflection (`ChaosAction`: 
`addRule`, `changeRule`, `hasRule`, `removeRule`,
   `clearRules`; `getMethod` only, no `setAccessible`). camel-chaos is a test 
dependency only.
   
   ## Split: the MCP tool group is the next PR
   
   This PR has the dev console, the CLI action, the commands and `camel run 
--chaos` (step 3 of the design). The MCP tool
   group (`camel_runtime_chaos_add/change/remove/clear/list/report` in 
`RuntimeTools` and the shared `ToolRegistry`, the
   `chaos` group in `camel_runtime_tool_groups`, and the TUI/`camel ask` 
confirmations) is its own step in the design, and
   comes next. As agreed in the review of #28716, `chaos_add` and 
`chaos_change` will be `destructiveHint=true` and in
   `ToolConfirms`, and the tools will key report entries by id plus version 
(the `version` that #28754 added, which this
   PR's console and `camel get chaos` already show).
   
   ## API change in camel-chaos (not released yet)
   
   `ChaosManager.changeRule(id, rule)` returns the version of the new rule (was 
`void`), so the CLI can print it, and
   `ChaosManager.hasRule(id)` is new, so the CLI can tell an unknown id ("not 
found") from a rule that is not valid.
   `ChaosReport.rulesJson(boolean)` (package-private) gives the console the 
current rules from the same report.
   
   ## Tests
   
   New test classes (each run 20 times in its own JVM, all passed):
   
   - `ChaosDevConsoleTest` (camel-chaos, 7): found by id as the console 
registry finds it; read only; the current rules
     with id, version 2 after a change, state, matches, fired, `endsIn`; the 
report with every version (`r1 v2 active`,
     `r1 v1 replaced`, `r2 v1 removed`) and the route counts; text; an ended 
rule; off without a profile (with
     `camel.chaos.rules` set) and with profile `prod`; `hasRule`. 
`optionsDoNotAddChangeOrRemoveRules` is a control (the
     console has no write path to call).
   - `LocalCliConnectorChaosActionTest` (camel-cli-connector, 10, `@Isolated`): 
add, change (version 2), remove, clear
     through `CliActionOutcome.dispatch` (the code both transports use) and 
once through the action file; a rule that is
     not valid (reason reported, not thrown); an unknown id for change and 
remove (not-found); missing arguments and an
     unknown command; refused with profile `prod` (also with 
`camel.chaos.enabled=true`; nothing is installed), with chaos
     off, and without the JAR (a class resolver that does not find 
`ChaosManager`); the status has the console, or why
     chaos is off.
   - `CamelChaosActionTest` (camel-jbang-core, 13): the action and options each 
command sends, quotes in a rule, what it
     prints, a refused rule and chaos off as errors with the integration's 
reason (exit 1), an unknown id (exit 3), add,
     change and remove need one integration (picocli refuses without a name; no 
match is exit 3), `chaos-clear` without a
     name skips integrations whose status says chaos is off.
   - `ListChaosTest` (camel-jbang-core, 8): rules as a table and as JSON (with 
`hooks` and `expectation`), the report as
     text (verdict, seed, lost, FAIL reasons, every version, the route counts, 
"not decided" / time left for pending
     expectations) and as JSON, chaos off (reason on stderr), and an 
integration without camel-chaos.
   
   Added to existing tests: 
`ProjectRunnerTest.aCamelMainRunWithChaosAddsCamelChaos` and
   `anExistingCamelMainProjectRunsWithChaos` (camel-jbang-run), 
`CommandInputErrorsTest.runWithChaosOnSpringBootOrQuarkus`,
   the golden cases `chaos` (run) and `maven-main-chaos` in 
`RunExportGoldenTest`, and
   `ToolConfirmsTest.aChaosRuleFromCamelAskIsAsked` (a control: `camel ask` 
already asks before any `camel cmd`; it pins
   that for `chaos-*`, and that `camel get chaos` runs without asking).
   
   Negative controls: 21 mutants of the new code, each compiled into the module 
and run against its test class; every
   one makes a test fail. Among them: the console listing all rules instead of 
the current ones, `enabled` always true,
   the prod reason; `changeRule` returning 1, `hasRule` always true; the action 
without its "chaos is off" check (the
   prod case), without its "no JAR" check, not-found reported as a plain error, 
change of an unknown id not checked, a
   refused rule thrown instead of reported, the status without the console; the 
commands dropping the rule or the id, not
   printing the error, asking integrations with chaos off; `camel get chaos` 
taking an off integration as on, listing the
   report's rules, hiding "not decided" or the JSON expectation; `camel run 
--chaos` not adding camel-chaos for
   `--runtime=main` or for a Maven project.
   
   Offline runs: the camel-chaos suite (261 tests), the camel-cli-connector 
`LocalCliConnector*Test` classes,
   `ActionCommandsTest`, `ExitCodeContractTest`, 
`CamelJBangMainOnlyCommandTest`, `ProjectRunnerTest` and the run cases of
   `RunExportGoldenTest` pass. Its export cases (and `maven-main-mixed`) fail 
in this offline build for reasons outside
   this change: they do not use `--chaos`, and the errors come from older 
snapshot jars here (no Java/XML routes loader,
   catalog differences in the expected files); CI runs them.
   
   ## Your note on #28754 (abandoned expectations and `isFinal()`)
   
   Now that a tool reads the report: the behaviour stays as the design says (an 
expectation whose rule was removed or
   changed, or whose context stopped, stays pending, and the report is not 
final). The JSON already marks those entries
   `notDecided`; `camel get chaos --report` now shows "not decided" next to 
them (and the time left next to the others),
   and the text of the report names "changed" too. So a "not final" PASS always 
shows which expectation keeps it open.
   
   ## Open questions
   
   - Reflection in the CLI connector, instead of a dependency: is that 
acceptable, or would you prefer a small SPI
     (for example a context plugin the connector knows) for module-provided CLI 
actions?
   - `chaos-remove` needs the name of one integration, as add and change do, 
where the design said "the others may omit
     it and then act on all": ids are per integration, so `r1` may be a 
different rule in each. The design's Control
     section is updated. OK?
   
   _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]

Reply via email to