Skip to content

discover extraobjects#212

Merged
dgunzy merged 1 commit into
mainfrom
extra-objects-config-tweak
Jul 16, 2026
Merged

discover extraobjects#212
dgunzy merged 1 commit into
mainfrom
extra-objects-config-tweak

Conversation

@dgunzy

@dgunzy dgunzy commented Jul 16, 2026

Copy link
Copy Markdown
Owner

Closes #197

Why

The Flux ecosystem no longer ends at the core reconciler kinds. The Flux Operator ships ResourceSets, source-watcher produces ExternalArtifacts behind the RFC-0012 feature gate, and controllers like tf-controller extend clusters with their own Flux-adjacent CRDs. A Flux dashboard that only knows a closed enum of kinds goes blind exactly where clusters are heading.

The question was how to support extra kinds without making users maintain config lists of GVKs. Upstream already answered it: the Flux Operator's FluxReport discovers which reconciler CRDs exist on a cluster by reading the app.kubernetes.io/part-of=<instance> label on CustomResourceDefinitions (internal/reporter/crds.go) — the FluxInstance labels the CRDs it manages, and anything else carrying the label is declared part of the Flux instance. flux9s now follows the exact same convention: one boolean opt-in, and the cluster itself says what to show. Staying on upstream's convention means zero per-kind config, and whatever the operator considers part of Flux, flux9s does too.

Discovered kinds are deliberately view-only. Flux's runtime conventions (spec.suspend, the reconcile.fluxcd.io/requestedAt annotation) are what would make suspend/resume/reconcile safe on arbitrary kinds, and RFC-0012 explicitly keeps arbitrary CRs as sourceRefs out of scope for now — so operations stay gated on the built-in FluxResourceKind enum until there's an upstream contract to lean on (tracked with the Flux v2.10 roadmap items in #198).

What

Opt-in flagdiscoverFluxResources: false by default. Off means no CRD watch, no extra API calls, no UI change whatsoever.

flux9s config set discoverFluxResources true

Dynamic discovery (src/models/extra_kinds.rs, src/watcher/mod.rs) — a CRD watcher with the app.kubernetes.io/part-of=flux label selector feeds a process-wide ExtraKindRegistry. Each discovered kind gets a DynamicObject watcher; resources land in the unified list with generic columns (readiness from standard status.conditions). Labeling/unlabeling a CRD adds/removes the kind live — no restart.

Guard rails, in the order they bit during development:

  • Built-in kinds are excluded — the FluxInstance labels its own CRDs part-of=<instance>, so without this every Kustomization would be double-watched.
  • Namespaced CRDs only (v1) — key formats and watch scoping assume namespaces.
  • Storage version resolution matches the operator (last stored version, falling back to the spec's storage version).
  • View-only enforced, not impliedDelete/Reconcile had is_valid_for → true for all kinds (pre-existing, latent); both are now gated on FluxResourceKind, and a zero-impact test proves discovered kinds get no operations.

UX: commands from the CRD's own names (kind, plural, shortNames — e.g. :widget / :widgets / :wd), Tab autocomplete, y/d describe/yaml via GVK resolution, and a help entry that only renders while kinds are actually registered.

Lifecycle correctness — the registry is cleared in ResourceWatcher::stop(), so discovered kinds can't leak across context switches (caught in manual testing: :wd followed me from the kind cluster back to a cluster with no Widget CRD). Re-discovery on the new watcher repopulates from whatever that cluster actually has.

config list made schema-driven — the new flag exposed that the listing was hand-maintained and silently incomplete. It's now derived from serde against a Config::fully_populated() skeleton: every field always shows with a # (default) marker, adding a schema field without updating the reference docs is a compile error + failing test, and config get resolves any field through a serialized-config fallback.

Testing

  • just ci green (fmt, clippy -D warnings, audit, 690+ unit/integration tests).
  • New live test labeled_crd_discovers_and_lists_instances (7/7 live suite passing) against a real labeled CRD fixture: scripts/dev-manifests/simple/00-discovered-crd.yaml + two Widget CRs (one Ready=True, one Ready=False) on the flux9s-simple kind cluster — also exercised weekly by the live-tests workflow.
  • Zero-impact tests: with the flag off (or registry empty) command resolution, autocomplete, help, and operations are byte-identical to before.
  • Manual: discovery, live label add/remove, context-switch cleanup, and readiness rendering verified on kind-flux9s-simple and a real cluster.

🤖 Generated with Claude Code

Signed-off-by: Daniel Guns <danbguns@gmail.com>
@dgunzy
dgunzy merged commit b237e1c into main Jul 16, 2026
7 checks passed
@dgunzy
dgunzy deleted the extra-objects-config-tweak branch July 16, 2026 22:36
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.

Config-driven extra resource kinds (Flagger, tofu-controller, ExternalArtifact SDK controllers)

2 participants