Skip to content

feat(operator): add the Rust workspace, the KatesTest CRD and its CI - #608

Merged
bmscomp merged 1 commit into
mainfrom
feat/operator-workspace
Nov 5, 2026
Merged

bmscomp merged 1 commit into
mainfrom
feat/operator-workspace

Conversation

@bmscomp

@bmscomp bmscomp commented Nov 5, 2026

Copy link
Copy Markdown
Owner

Why

The Kubernetes operator needs a home and a CRD before it can reconcile anything, and the schema is the riskiest part: the API drops an unknown spec key silently, so a pass-through spec with a typo would run on defaults and report Ready=True on the wrong run. This PR opens operator/ with the KatesTest type and CI, and nothing else.

What changed

  • operator/: a Rust workspace (edition 2024, kube 5.0) with kates-crds, the KatesTest type, conditions, printer columns and CEL rules: exactly one of spec.spec / spec.scenario, sla only with spec.spec, the whole spec frozen once status.runId is set.
  • crdgen derives spec, scenario and sla from schemas/test-request.v1.schema.json, names and types only. default, ranges and required are dropped, because values stay the API's job. Keys the schema accepts and the API never binds are dropped too, because on sla they would mean Ready=True on an empty SLA.
  • ci-operator.yml: fmt, clippy, tests, cargo deny, a one-crypto-provider check, CRD freshness, kubeconform, and a Kind job that dry-runs the CRD, since only the apiserver can judge CEL.
  • rust-toolchain.toml pins Rust. CARGO_DENY_VERSION joins versions.env, !operator/Cargo.lock joins .gitignore, and Dependabot watches /operator.

Deliberately not done

  • No binary, Dockerfile or image build: nothing would run them until the reconciler lands. They come with PR 3.
  • No chart: publish-charts.yml publishes every tracked chart at the next tag and never re-pushes a version.

Deviations worth a look

  • kubeconform cannot read a CRD, because no catalog publishes a CustomResourceDefinition schema. CI validates a good and a mistyped sample KatesTest against the CRD's own schema instead.
  • ttlSecondsAfterFinished keeps minimum: 0: the API never sees that field, so the CRD is its only check.
  • spec.type is required even with a scenario, because CreateTestRequest has @NotNull on type.

Tests

Passing locally after the final trim: cargo fmt --check, clippy -D warnings, cargo test --locked (19), cargo deny check, the provider check, CRD freshness, check-versions.sh, actionlint, yamllint, book style, version matrix and index.

Before the trim, with an identical CRD: kubectl apply --dry-run=server on a Kind v1.34.11 node, where mistyped keys and post-runId spec edits were refused on the installed CRD; kubeconform on both samples. That Kind run used one node and kubectl 1.37, not config/cluster.yaml and the pinned client.

ci-operator.yml has never run on GitHub, so this PR's run is the first proof of its wiring. The CRD is byte-identical with PR 1's schema, so the two merge in either order.

The operator needs a place to live before it can reconcile anything. This
opens operator/ with the KatesTest type and its CEL rules. The binary, its
Dockerfile and the image build come with the reconciler in the next PR,
since nothing would run them yet. No chart yet either: publish-charts.yml pushes every tracked
chart at the next tag and never re-pushes a version.

crdgen derives spec, scenario and sla from the shipped request schema,
names and types only, so a mistyped key is refused by the apiserver while
values stay the API's job. That includes `required`: the API runs a
scenario with no name, so the CRD must not refuse one. Keys the schema
accepts and the API never binds are dropped, because on sla they would
otherwise mean Ready=True on an empty SLA.

ttlSecondsAfterFinished keeps minimum: 0. The API never sees that field,
so the CRD is the only check on it.

ci-operator.yml gates on the workspace and on versions.env, since its Rust
job reads the cargo-deny and kubeconform pins. Only the apiserver can judge
the CEL rules, so a Kind job dry-runs the CRD.
@bmscomp
bmscomp merged commit 56ca708 into main Nov 5, 2026
70 checks passed
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.

1 participant