operator(P5a): ClosureJVMCampaign CRD + driver-Job reconciler - #19
Conversation
The second CRD (DD-025): a bounded coverage-guided test run against an
instrumented target. P5a scope — CRD + driver Job (per-campaign dashboard
is P5b).
- ClosureJVMCampaign CRD: targetRef + driver (grammar/corpus,
duration|iterations via a CEL XOR rule, classesPath) + dashboard;
status phase/driverJob/coveragePct/findings/times.
- Reconciler: gate on the target being Injected + having a
status.coverageEndpoint (else Pending); launch the driver Job wired to
the target's app Service (baseURL), coverage endpoint, and a
coverage-classes initContainer that copies .class files out of the
TARGET's own image (DD-025 §7b) so they always match. On completion,
read coverage %/findings from the driver pod's termination message
(§7a) into status. TargetGone terminal state if the target vanishes
mid-run. Owns(&Job{}) + owner-ref GC.
- --runner-image flag; batch/jobs + core/pods,configmaps RBAC.
envtest: gate→Pending, launch+wire+owner-ref→Running, complete+read
summary, TargetGone, CEL rejection. 18/18 controller specs green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JuGqspSB9zpA5AyvHJBiDK
A linter smart-quoted the '' empty-string literal in the XValidation rule to a unicode ” (same failure mode as the coverage.includes rule earlier), which would break the CRD on regeneration. Switch to the quote-free size(self.driver.duration) > 0 form so nothing can mangle it. Regenerated CRD; envtest still 18/18. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JuGqspSB9zpA5AyvHJBiDK
|
@claude please review — operator P5a: the ClosureJVMCampaign CRD + driver-Job reconciler (DD-025). P5a scope is CRD + driver Job; per-campaign dashboard is P5b, and wiring a real runner image + in-cluster e2e is the follow-up. Worth checking:
Verified: envtest 18/18 (5 new campaign specs). Depends on the merged #18 runner flags. |
|
Claude finished @ianp94's task in 7m 51s —— View job Review: operator P5a — ClosureJVMCampaign CRD + driver-Job reconcilerTodo list:
Went through the reconciler, 1. Command injection via
|
…view) PR #19 review found three real issues; all fixed with tests (envtest 22/22): 1. HIGH command injection — the classes initContainer ran `sh -c "cp ... " + classesPath`, and classesPath is a free-form spec field, so a campaign author could inject shell commands. Now cp is exec'd directly (no shell), making the arg inert. 2. HIGH broken grammar path — grammarConfigMap without an explicit grammarKey produced `-Dclosurejvm.grammar=<dir>/` (a directory), so the grammar silently never loaded. The reconciler now resolves the sole key (erroring/Pending if ambiguous) and always projects it to a fixed filename the flag points at. 3. MEDIUM target-revert — a target dropping out of Injected (not deleted) while Running regressed the campaign to Pending and stopped inspecting the Job; now it fails TargetGone like the deleted case. Also added the target->campaign Watches (so a Pending campaign starts on the target's injection event, not just the 15s poll). Logged the spec-hash idempotency follow-up to TODO. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JuGqspSB9zpA5AyvHJBiDK
|
@claude re-review — all three fixed in
Also added the |
|
Claude finished @ianp94's task in 1m 39s —— View job Re-review: operator P5a — fixes in
|
Non-blocking nit from the #19 re-review: a classesPath starting with `-` would be read as a cp flag. Add `--` so it's always treated as a path. envtest 22/22. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JuGqspSB9zpA5AyvHJBiDK
|
Thanks — LGTM confirmed. Closed the residual too ( |
Operator P5a —
ClosureJVMCampaignCRD + driver-Job reconcilerThe second CRD (DD-025): a bounded coverage-guided test run against an instrumented target. P5a scope = CRD + driver Job; the per-campaign dashboard is P5b, wiring an actual runner image + in-cluster e2e is the follow-up (needs the runner changes in #18).
CRD
ClosureJVMCampaign—targetRef+driver(grammar/corpus ConfigMaps,durationXORiterationsvia a CEL rule,classesPath) +dashboard; statusphase/driverJob/coveragePct/findings/times, with print columns.Reconciler
Injectedand having astatus.coverageEndpoint(elsePending, requeue).baseURL, the target's coverage endpoint, and a coverage-classes initContainer that copies the app's.classfiles out of the target's own image (DD-025 §7b) — so they always match what's running (the non-obvious gap the design surfaced).-Dclosurejvm.summary.out=/dev/termination-log).TargetGoneterminal state if the referenced target vanishes mid-run (not silent connection-refused "findings").Owns(&Job{})+ owner-ref GC;--runner-imageflag;batch/jobs+core/pods,configmapsRBAC.Verification
Pending; launch+wire+owner-ref→Running; complete+read-summary→Completedwith coverage/findings;TargetGone; CEL rejection of both-set.duration/summaryflags) for a real end-to-end run; the operator logic is fully envtest-verified here. The runner image + in-cluster e2e assert-non-zero-coverage is the next P5a slice.🤖 Generated with Claude Code
https://claude.ai/code/session_01JuGqspSB9zpA5AyvHJBiDK