Pod template merge layer
Per-engine pod-template overrides live onFireboltEngine.spec.template,
parallel to the existing FireboltEngineClass.spec.template.
When an engine sets spec.engineClassRef, the reconciler resolves the
referenced FireboltEngineClass and composes the rendered pod
template from three layers, top wins on conflict for scalar and
struct fields:
- Firebolt Operator defaults: Hardcoded engine container identity
(
name,command,args,ports, probes, reserved env keys), the StatefulSet-bound pod fields (terminationGracePeriodSeconds=60,subdomain,hostname,restartPolicy,activeDeadlineSeconds), and the operator-owned volumes / mounts (engine-config, data). Always win. FireboltEngineClass.spec.template(whenspec.engineClassRefis set): Fills in user-owned fields the engine template doesn’t set.FireboltEngine.spec.template: Wins over the class on conflict.
FireboltEngineClassPodTemplateRules)
to both class and engine templates, so a field accepted on one side is
also accepted on the other and operator-owned paths are rejected
uniformly on both.
Merge rules (centralized in the effective* helpers in
engine_reconcile.go so buildStatefulSet and stsMatchesSpec agree
on the resolved value):
The engine controller watches
FireboltEngineClass via
EnqueueRequestsFromMapFunc so a class edit immediately enqueues
every consumer engine. The validating webhooks on FireboltEngine
and FireboltEngineClass reject user input on paths the Firebolt
Operator owns end-to-end. See
fireboltengineclass-crd-reference
and engine-crd-reference. The
merge layer therefore assumes both resolved templates only carry
fields it knows how to handle.
Inherited engine settings
Beyond the pod template, aFireboltEngineClass carries defaults for a subset
of FireboltEngine settings. Each resolves the engine value first, then the
class value, then the operator default, the same precedence the pod template
follows. The effective* helpers in engine_reconcile.go centralize the
resolution so the renderer and the drift comparator agree.
rollout, drainCheckEnabled, drainCheckInterval, and uiSidecar carry no
CRD default on FireboltEngine. The Firebolt Operator applies the default in
the resolver instead, so an unset engine value falls through to the class
rather than being filled in at admission.
Deletion
The validating webhook refusesDELETE while any FireboltEngine in
the class’s namespace references the class via spec.engineClassRef.
Only same-namespace engines count. The check lists engines live from the API
server at admission time rather than reading status.boundEngines, so a
class bound between reconciler runs is still protected. Clear
spec.engineClassRef on every referencing engine first, then delete the
class. failurePolicy: Fail on the webhook configuration prevents a webhook
outage from opening a window in which a bound class could be removed.
Class edit rollouts
Editing the class spec can trigger a blue-green rollout on every referencing engine in the same namespace. The engine controller watchesFireboltEngineClass and enqueues every consumer whose
spec.engineClassRef matches. stsMatchesSpec compares the resolved class
template hash against the firebolt.io/engine-class-hash annotation on the
StatefulSet, and detects storage, customEngineConfig, and uiSidecar
changes (from either the engine or the class) through their own resolved-value
comparators.
Any mismatch bumps currentGeneration, whether the class template was edited in
place, the engine flipped to a different class, or the reference was cleared.
Class changes to rollout, drainCheckEnabled, drainCheckInterval, and
autoStop do not reshape the pod, so they take effect on the next reconcile
without forcing a new generation.