Context
A Component owns an ordered set of resources (baseline + feature mutations).
Consumers building components want to snapshot-test the desired output: given
a spec, render every resource the component would apply and assert it against a
golden file. This is the natural end-to-end test for a component — it exercises
baseline construction, mutation wiring, and registration order in one place.
Today the only public surface on Component is Reconcile(...) plus name/
condition accessors. The assembled resources are reachable only via the
unexported allManagedResources() / managedResources() (pkg/component/component.go),
and the Resource interface (pkg/component/resource.go) exposes Object() /
Identity() but not a cluster-free "render desired state" path at the
component level. There's no way to ask a built Component "what would you
apply?" without a fake client and a full reconcile.
The problem
Without a public accessor, whole-component golden tests can't be written
against the real BuildComponent(...) wiring. The test either:
- reaches into unexported state (impossible from another package), or
- reassembles the resource pipeline itself in test code, which duplicates the
exact baseline+mutation registration the component already encodes and drifts
the moment the real wiring changes — defeating the purpose of the test.
The per-resource-type PreviewObject() (e.g. on the statefulset primitive
Resource) covers single resources, so consumers can golden one resource at
a time by calling that resource's builder. What's missing is the
component-level view: render all of a component's resources together into one
golden, straight from the component the controller actually builds.
Workarounds today (all unsatisfying)
- Golden each resource individually by calling its own builder, and accept that
nothing tests the component's full resource set / registration order as a
unit.
- Reassemble the baseline+mutation pipeline in test code. Duplicates wiring,
drifts from the real component, asserts a copy rather than the real thing.
- Spin up a fake client and run
Reconcile, then read objects back from the
fake client. Heavyweight, conflates reconcile/IO behavior with desired-state
rendering, and is awkward for a pure "what would you apply" snapshot.
Proposed solution shape
A public, cluster-free way to obtain a component's assembled resources for
inspection/snapshotting. Some options:
Component.Resources() []Resource — expose the managed (and optionally
read-only) resources so callers can iterate and call Object() /
type-asserted PreviewObject() themselves.
- A higher-level
Component.Preview() ([]client.Object, error) that returns the
rendered desired-state objects (baseline + mutations applied), with no client
and no reconcile — the most directly golden-able form.
Either keeps Reconcile as the only IO path while giving consumers a
first-class hook for desired-state assertions.
Open question
Whether this should expose []Resource (flexible, caller does the rendering) or
return already-rendered []client.Object (convenient, opinionated about preview
semantics), and how read-only resources should figure in the result. Happy to
PR whichever shape you prefer.
Context
A
Componentowns an ordered set of resources (baseline + feature mutations).Consumers building components want to snapshot-test the desired output: given
a spec, render every resource the component would apply and assert it against a
golden file. This is the natural end-to-end test for a component — it exercises
baseline construction, mutation wiring, and registration order in one place.
Today the only public surface on
ComponentisReconcile(...)plus name/condition accessors. The assembled resources are reachable only via the
unexported
allManagedResources()/managedResources()(pkg/component/component.go),and the
Resourceinterface (pkg/component/resource.go) exposesObject()/Identity()but not a cluster-free "render desired state" path at thecomponent level. There's no way to ask a built
Component"what would youapply?" without a fake client and a full reconcile.
The problem
Without a public accessor, whole-component golden tests can't be written
against the real
BuildComponent(...)wiring. The test either:exact baseline+mutation registration the component already encodes and drifts
the moment the real wiring changes — defeating the purpose of the test.
The per-resource-type
PreviewObject()(e.g. on the statefulset primitiveResource) covers single resources, so consumers can golden one resource ata time by calling that resource's builder. What's missing is the
component-level view: render all of a component's resources together into one
golden, straight from the component the controller actually builds.
Workarounds today (all unsatisfying)
nothing tests the component's full resource set / registration order as a
unit.
drifts from the real component, asserts a copy rather than the real thing.
Reconcile, then read objects back from thefake client. Heavyweight, conflates reconcile/IO behavior with desired-state
rendering, and is awkward for a pure "what would you apply" snapshot.
Proposed solution shape
A public, cluster-free way to obtain a component's assembled resources for
inspection/snapshotting. Some options:
Component.Resources() []Resource— expose the managed (and optionallyread-only) resources so callers can iterate and call
Object()/type-asserted
PreviewObject()themselves.Component.Preview() ([]client.Object, error)that returns therendered desired-state objects (baseline + mutations applied), with no client
and no reconcile — the most directly golden-able form.
Either keeps
Reconcileas the only IO path while giving consumers afirst-class hook for desired-state assertions.
Open question
Whether this should expose
[]Resource(flexible, caller does the rendering) orreturn already-rendered
[]client.Object(convenient, opinionated about previewsemantics), and how read-only resources should figure in the result. Happy to
PR whichever shape you prefer.