Skip to main content

Pod template merge layer

Per-engine pod-template overrides live on FireboltEngine.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:
  1. 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.
  2. FireboltEngineClass.spec.template (when spec.engineClassRef is set): Fills in user-owned fields the engine template doesn’t set.
  3. FireboltEngine.spec.template: Wins over the class on conflict.
The validating webhook applies the same allowlist (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, a FireboltEngineClass 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 refuses DELETE 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 watches FireboltEngineClass 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.