Documentation
¶
Index ¶
- Constants
- Variables
- func GetContainerPorts() []corev1.ContainerPort
- func GetServicePorts() []corev1.ServicePort
- func MaybeCrash(_ string, _ CrashPoint)
- type AutoStopDecision
- type AutoStopObservation
- type CrashPoint
- type DrainProbeError
- type EngineReconcileResult
- type EngineState
- type FireboltEngineClassInfo
- type FireboltEngineClassReconciler
- type FireboltEngineReconciler
- type FireboltInstanceReconciler
- type InstanceInfo
- type StorageBackend
Constants ¶
const ( // OperatorFieldManager is the Server-Side Apply field-manager name // stamped on every operator-emitted apply (applySSA). All // `ensure*` functions across the engine, instance, gateway, metadata, // postgres, and RBAC paths converge on this single identifier so // `kubectl get <resource> -o yaml` shows one consistent owner under // `metadata.managedFields[].manager` for everything the operator // produces. Changing the value is a breaking change: existing // resources would be left half-owned by the old manager name until // the operator next applies them with ForceOwnership. OperatorFieldManager = "firebolt-operator" // LabelEngine identifies the engine a resource belongs to. LabelEngine = "firebolt.io/engine" // LabelGeneration identifies the generation of a resource. LabelGeneration = "firebolt.io/generation" // LabelInstance identifies the instance a resource belongs to. LabelInstance = "firebolt.io/instance" // LabelComponent identifies the component type (metadata, gateway, etc.). LabelComponent = "firebolt.io/component" // AnnotationMetadataOverride records the MetadataEndpointOverride used // to build the engine ConfigMap. stsMatchesSpec compares against this to // detect changes that require a new generation. AnnotationMetadataOverride = "firebolt.io/metadata-override" // AnnotationEngineClassHash records a content-hash of the resolved // FireboltEngineClass.spec.template merged into the engine pod spec. // Absent when spec.engineClassRef is nil. stsMatchesSpec compares the // annotation to the freshly resolved class hash and rolls a new // blue-green generation on any mismatch — covers both // engineClassRef changes and in-place edits to the referenced class. AnnotationEngineClassHash = "firebolt.io/engine-class-hash" // AnnotationCustomEngineConfigHash records a content-hash of the // spec.customEngineConfig payload baked into the engine ConfigMap. // stsMatchesSpec compares against this to detect changes that require // a new generation, since ConfigMap content drift is not checked // independently. AnnotationCustomEngineConfigHash = "firebolt.io/custom-engine-config-hash" // AnnotationConfigHash carries a content-hash of the rendered config // for the gateway and metadata Deployments. It is set on the pod // template and serves two purposes: (1) any config change propagates // here and triggers a rollout via the resulting template-spec diff, // (2) deploymentSpecEqual uses it as the single pod-template equality // signal, avoiding a DeepEqual on server-defaulted PodSpec fields. AnnotationConfigHash = "firebolt.io/config-hash" // AnnotationWakeRequested is the contract between the gateway and the // engine autoStop: the gateway patches this annotation with an // RFC 3339 timestamp when it observes a request for an engine that is // currently scaled to zero. The engine autoStop treats a fresh value // (within DefaultAutoStopWakeTTL of now) as a request to immediately // scale up to spec.autoStop.activeReplicas, bypassing the idle-timeout // check. Stale values are ignored, so the gateway must keep stamping // the annotation while it has buffered queries waiting for the engine. // // The annotation is honored only when spec.autoStop.enabled=true: // without an autoStop policy the operator has no ActiveReplicas to // scale to, and respecting the wake from a non-policy actor would // silently override the user's spec.replicas==0 intent. AnnotationWakeRequested = "firebolt.io/wake-requested" // SuffixService is appended to form the cluster Service name. SuffixService = "-service" // SuffixGen is appended to form generation-scoped resource names. SuffixGen = "-g" // SuffixHL is appended to form headless Service names. SuffixHL = "-hl" // SuffixConfig is appended to form ConfigMap names. SuffixConfig = "-config" // SuffixMetadataService is appended to form metadata Deployment/Service names. SuffixMetadataService = "-metadata" // SuffixMetadataPG is appended to form the internal PostgreSQL resource names. SuffixMetadataPG = "-metadata-pg" // SuffixMetadataPostgresCreds is appended to form the PG credentials Secret name. SuffixMetadataPostgresCreds = "-metadata-postgres-creds" //nolint:gosec // resource name suffix, not a credential // SuffixGateway is appended to form gateway Deployment/Service names. SuffixGateway = "-gateway" // MetadataServicePort is the gRPC port the metadata service listens on. MetadataServicePort = 7000 // PostgresPort is the default PostgreSQL port. PostgresPort = 5432 // PostgresDBName is the database name for the internal PostgreSQL instance. PostgresDBName = "firebolt_metadata" // PostgresDefaultSchema is the schema used by the metadata service when // the user does not specify spec.metadata.postgres.schema (and always for // the internal Postgres deployment, which is created with this schema). PostgresDefaultSchema = "public" // PostgresUser is the database user for the internal PostgreSQL instance. PostgresUser = "firebolt" // PostgresPVCSize is the default PVC size for the internal PostgreSQL instance. PostgresPVCSize = "10Gi" // PostgresUID is the numeric UID/GID of the built-in `postgres` user in // the `postgres:16-alpine` image. We pin RunAsUser/RunAsGroup/FSGroup to // this value so the pod-level SecurityContext can enforce RunAsNonRoot=true // and the kubelet chowns the per-pod data PVC to a UID the postgres // process actually runs as. The Debian-flavored `postgres` images use // UID 999 instead; if PostgresImage is ever switched off Alpine this // constant must be revisited. PostgresUID int64 = 70 // MetadataUID is the numeric UID/GID of the built-in `dedicated-pensieve` // user in the metadata image. The Dockerfile creates the user with this // fixed UID and sets `USER dedicated-pensieve`, so pinning // RunAsUser/RunAsGroup here just locks in the image's own default and // lets the pod-level SecurityContext assert RunAsNonRoot=true. Revisit // if the metadata image's user is ever renumbered. MetadataUID int64 = 1111 // DefaultDrainCheckInterval is how often the operator polls draining pods. DefaultDrainCheckInterval = 5 * time.Second // HealthReadyPath is the HTTP path for readiness probes on engine pods. HealthReadyPath = "/health/ready" // HealthLivePath is the HTTP path for liveness probes on engine pods. HealthLivePath = "/health/live" // HealthPort is the port exposing health endpoints on engine pods. HealthPort = 8122 // MetricsPort is the port exposing Prometheus metrics on engine pods. // The operator scrapes firebolt_running_queries and firebolt_suspended_queries // here via the Kubernetes pod-proxy subresource to drive the drain check. MetricsPort = 9090 // MetricsPath is the HTTP path exposing Prometheus metrics on engine pods. MetricsPath = "/metrics" // MetricRunningQueries is the Prometheus metric name for in-flight queries. MetricRunningQueries = "firebolt_running_queries" // MetricSuspendedQueries is the Prometheus metric name for suspended queries. MetricSuspendedQueries = "firebolt_suspended_queries" // ConfigMountPath is where the engine config.yaml is mounted in the container. // FireboltCoreServer reads <root>/config.yaml from its --data-dir when present, // so the file must land at this path inside the container. ConfigMountPath = "/firebolt-core/volume/config.yaml" // DataMountPath is where the engine's per-pod PVC is mounted. Matches the // path the engine binary uses for its working data. DataMountPath = "/firebolt-core/volume" // DataVolumeName is the name of the data volume inside the StatefulSet's // VolumeClaimTemplates and the corresponding container VolumeMount. DataVolumeName = "data" // DefaultEngineStorageSize is the PVC size applied when // FireboltEngineSpec.Storage.Size is unset. Mirrors the kubebuilder default // so unit tests building specs as Go literals see the same value as // CRD-loaded specs. DefaultEngineStorageSize = "1Gi" // DefaultTerminationGracePeriodSeconds is the default value applied to the // engine pod's terminationGracePeriodSeconds when FireboltEngine.spec leaves // it unset. 60s gives in-flight queries up to 55s (TGPS − EngineShutdownMarginSeconds) // to complete after SIGTERM before SIGKILL is sent. DefaultTerminationGracePeriodSeconds = 60 // DefaultEngineFSGroup is the pod-level fsGroup applied to engine pods // when spec.podSecurityContext.fsGroup is unset. Matches the engine // container's listening port (3473) as a memorable shared GID; the // kernel uses it to chown the per-pod data PVC so the (non-root) engine // process can read and write its own volume. DefaultEngineFSGroup int64 = 3473 // DefaultEngineWebD is the non-root UID the engine container runs // under when FireboltEngine.spec.securityContext does not override // it. 3473 matches DefaultEngineFSGroup so the process's primary // GID, the volume-mount fsGroup, and the port mnemonic all line up // — and matches the sibling firebolt-instance-helm chart's engine // StatefulSet, so engines moved between deployment paths keep their // on-disk ownership. DefaultEngineWebD int64 = 3473 // DefaultEngineGID is the non-root GID the engine container runs // under. Pinned to the same value as DefaultEngineWebD and // DefaultEngineFSGroup; see DefaultEngineWebD. DefaultEngineGID int64 = 3473 // EngineShutdownMarginSeconds is subtracted from terminationGracePeriodSeconds // to compute shutdown_wait_unfinished. The remaining margin covers container // runtime teardown and pod API deletion after the engine process exits. EngineShutdownMarginSeconds = 5 )
const ( // EngineWebPortName / EngineWebPort are the name and number of the container // port the engine web UI listens on. EngineWebPortName = "web-ui" EngineWebPort int32 = 9100 // EngineWebWritableVolumeName is the emptyDir mounted into the UI container // at nginx's writable paths, since it runs with a read-only root FS. It is // listed in operatorOwnedPodVolumeNames so a user volume of this name is // dropped at render and cannot collide with the operator's. EngineWebWritableVolumeName = "nginx-writable-dir" // EngineWebBackendURL is the local engine endpoint the UI talks to: the // engine's http-query port (3473) on loopback within the same pod. EngineWebBackendURL = "http://localhost:3473" )
Engine Web UI sidecar constants. The sidecar is injected only when an engine or its class opts in via uiSidecar: true; see buildEngineWebSidecar. Its container name is the operator-owned EngineWebContainerName (api/v1alpha1), which the validating webhook reserves so a user container cannot collide.
const ( DefaultAutoStopIdleTimeout = 30 * time.Minute DefaultAutoStopPollInterval = 1 * time.Minute DefaultAutoStopIdleReplicas = int32(0) // DefaultAutoStopWakeTTL bounds how long an unrefreshed // AnnotationWakeRequested value still triggers a scale-up. Generous // enough to cover engine cold-start (image pull on a fresh node, blue- // green creating phase) while short enough that an abandoned request // does not pin the engine indefinitely after the gateway gives up. DefaultAutoStopWakeTTL = 5 * time.Minute )
AutoStop defaults applied when the corresponding spec fields are unset. Mirroring the kubebuilder defaults here keeps unit tests that build specs as Go literals consistent with CRD-loaded specs.
const ( AutoStopReasonDisabled = "Disabled" AutoStopReasonScheduleActive = "ScheduleActive" AutoStopReasonStopped = "Stopped" AutoStopReasonActivity = "ActivityObserved" AutoStopReasonScrapeFailed = "ScrapeFailed" AutoStopReasonIdle = "Idle" AutoStopReasonWakeRequested = "WakeRequested" // AutoStopReasonInitializing covers the first quiet observation on // an engine that has no LastActivityTime yet: there is nothing to // measure idleFor against, so the decision is "anchor the timestamp // and observe again". Distinct from ActivityObserved, which carries // the stronger claim that the most recent scrape saw running queries. AutoStopReasonInitializing = "Initializing" )
AutoStop reason tokens written to status.autoStopReason. Constants are defined in one place so reconciler code, tests, and documentation share the exact spelling.
const ConfigFileName = "config.yaml"
ConfigFileName is the key under which the rendered engine configuration is stored in the engine ConfigMap and the filename mounted into the pod. It matches the path FireboltCoreServer looks for in its data-dir.
const EngineConfigSchemaVersion = "1.0"
EngineConfigSchemaVersion is the schema_version stamped on the rendered config.yaml. FireboltCoreServer rejects unknown versions at startup, so bumping here requires a matching engine release.
const EngineStartupScript = `` /* 174-byte string literal not displayed */
EngineStartupScript is the script used to start the engine process. POD_INDEX is injected via the downward API in buildStatefulSet, sourced from the apps.kubernetes.io/pod-index label that the StatefulSet controller sets on each pod (GA in Kubernetes 1.28). On older clusters the label is absent and POD_INDEX will be empty; in that case we fall back to extracting the ordinal from HOSTNAME (<sts-name>-<ordinal>).
`firebolt server` is the engine image's unified entrypoint; FIREBOLT_CORE_MODE=1 (set as a container env var) selects the firebolt-core code path so the operator-rendered config (config.yaml at the data-dir root) is treated as authoritative and not rewritten at startup.
const MetricScrapeModeDefault = computev1alpha1.MetricScrapeModePodIP
MetricScrapeModeDefault is the fallback when the parent FireboltInstance is missing or carries an empty spec.metricScrapeMode. See the docstring on FireboltInstanceSpec.MetricScrapeMode for why PodIP is the default.
const ( // SuffixGatewayWakeRole is appended to the instance name to form the // per-instance RoleBinding name that binds the chart-managed // gateway-wake ClusterRole to the gateway ServiceAccount. SuffixGatewayWakeRole = "-gateway-wake" )
Variables ¶
var ( PostgresImage = images.PostgresImage DefaultMetadataRepository = images.MetadataImage DefaultMetadataTag = images.MetadataTag DefaultEnvoyRepository = images.EnvoyImage DefaultEnvoyTag = images.EnvoyTag DefaultEngineImage = images.DefaultEngine() DefaultEngineRepository = images.EngineImage DefaultEngineTag = images.EngineTag // DefaultEngineWebImage is the "repository:tag" reference for the optional // engine web UI sidecar injected when an engine/class sets uiSidecar: true. DefaultEngineWebImage = images.DefaultEngineWeb() )
Default container images, sourced from the variant-specific config/images/defaults.<variant>.env file embedded by the images package.
The Default*Image strings are the convenience "repository:tag" form used when comparing or stamping a fully-resolved reference; the matching Default*Repository / Default*Tag pairs are exposed separately so the resolveImageRef helper can fall back to either half independently when a user supplies a partial ImageSpec override.
Functions ¶
func GetContainerPorts ¶
func GetContainerPorts() []corev1.ContainerPort
GetContainerPorts returns the container ports for the engine container. Mirrors GetServicePorts (see its docstring): intra-engine peer ports are omitted because ContainerPort declarations are informational only and the engine binary opens those listeners regardless.
func GetServicePorts ¶
func GetServicePorts() []corev1.ServicePort
GetServicePorts returns the externally-meaningful service ports for a Firebolt engine. The aragog / shufflepuff / storage-manager / storage- agent ports are intentionally omitted: they are intra-engine peer traffic carried over the headless service's pod-IP DNS records, so they don't need a Service port declaration to be reachable, and they are never directly consumed by users or the gateway.
func MaybeCrash ¶
func MaybeCrash(_ string, _ CrashPoint)
MaybeCrash is a no-op in production builds. When built with the e2e tag, this function checks for active crash points.
Types ¶
type AutoStopDecision ¶
type AutoStopDecision struct {
// DesiredReplicas is the value spec.replicas should converge to. Equal
// to the current replica count when no scale change is needed.
DesiredReplicas int32
// ScaleAction is true when DesiredReplicas != current spec.replicas.
ScaleAction bool
// Reason is the token written to status.autoStopReason.
Reason string
// RequeueAfter is the suggested delay before the next autoStop
// evaluation. Zero means "use the controller's default requeue".
RequeueAfter time.Duration
// NewLastActivityTime, when non-nil, is the value to write to
// status.lastActivityTime. Nil means leave the existing value alone.
NewLastActivityTime *metav1.Time
}
AutoStopDecision is the output of computeAutoStopDecision and is applied by the reconciler: DesiredReplicas may be patched onto spec.replicas, NewLastActivityTime may be written to status.
type AutoStopObservation ¶
type AutoStopObservation struct {
// ActiveQueries is the sum of firebolt_running_queries +
// firebolt_suspended_queries across the active generation. Set to 0
// when the engine has zero replicas (no pods to scrape).
ActiveQueries int64
// ScrapeFailed indicates the metric scrape itself failed (network
// error, missing metric, RBAC failure). When true the autoStop
// conservatively treats this as "activity observed" so a broken probe
// never trips an unintended scale-down.
ScrapeFailed bool
// WakeRequestedAt is the parsed timestamp from
// metadata.annotations[AnnotationWakeRequested], or nil when the
// annotation is absent or malformed. The autoStop treats a value
// within DefaultAutoStopWakeTTL of now as a request to immediately
// scale up to ActiveReplicas.
WakeRequestedAt *time.Time
}
AutoStopObservation is the runtime input the autoStop consumes each cycle, sourced from a metric scrape over the active generation's pods and the FireboltEngine's wake-up annotation.
type CrashPoint ¶
type CrashPoint string
CrashPoint identifies a specific point in the reconciliation loop where a crash can be triggered. This is the production stub - crash points are no-ops when not built with e2e tag.
const ( // CrashAfterEngineConfigMapCreated fires after the engine ConfigMap is written. CrashAfterEngineConfigMapCreated CrashPoint = "after_engine_configmap_created" // CrashAfterHeadlessServiceCreated fires after the headless Service is written. CrashAfterHeadlessServiceCreated CrashPoint = "after_headless_service_created" // CrashAfterStatefulSetCreated fires after the StatefulSet is written. CrashAfterStatefulSetCreated CrashPoint = "after_statefulset_created" // CrashAfterClusterServiceEnsured fires after the cluster Service is ensured. CrashAfterClusterServiceEnsured CrashPoint = "after_cluster_service_ensured" // CrashBeforeCreatingToSwitching fires before transitioning from creating to switching. CrashBeforeCreatingToSwitching CrashPoint = "before_creating_to_switching" // CrashAfterServiceSelectorUpdate fires after the Service selector is updated. CrashAfterServiceSelectorUpdate CrashPoint = "after_service_selector_update" // CrashBeforeSwitchingStatusUpdate fires before the switching status write. CrashBeforeSwitchingStatusUpdate CrashPoint = "before_switching_status_update" // CrashAfterStatefulSetDeleted fires after the old StatefulSet is deleted. CrashAfterStatefulSetDeleted CrashPoint = "after_statefulset_deleted" // CrashBeforeCleaningToTerminal fires before transitioning from cleaning // to a terminal phase (stable or stopped). CrashBeforeCleaningToTerminal CrashPoint = "before_cleaning_to_terminal" )
Crash-point constants used by the e2e test harness to inject failures at deterministic locations in the reconciliation loop. In production builds MaybeCrash is inlined as a no-op.
type DrainProbeError ¶
DrainProbeError indicates that the drain-readiness probe (pod /metrics scrape) could not tell the operator whether an old-generation pod has finished serving queries. It does NOT mean the engine itself is unhealthy: the active-generation pods may still be serving traffic normally. What it does mean is that the blue-green cannot proceed past PhaseDraining until the probe works again, because cutting over without a clean drain could abort in-flight queries.
Reconcile uses errors.As to detect this and surface it as a user-facing ConditionReady=False with Reason=DrainCheckFailing, so a broken drain does not look like a silent infinite loop. The original error is still returned to controller-runtime so its exponential backoff applies to retries; there is no hidden RequeueAfter racing with the work-queue rate-limiter.
func (*DrainProbeError) Error ¶
func (e *DrainProbeError) Error() string
func (*DrainProbeError) Unwrap ¶
func (e *DrainProbeError) Unwrap() error
type EngineReconcileResult ¶
type EngineReconcileResult struct {
Status computev1alpha1.FireboltEngineStatus
EnsureConfigMap *corev1.ConfigMap
EnsureHeadlessSvc *corev1.Service
EnsureStatefulSet *appsv1.StatefulSet
EnsureClusterSvc *corev1.Service
DeleteResources []client.Object
RequeueAfter time.Duration
Requeue bool
}
EngineReconcileResult describes the resources to create, update, or delete and the new status to write after reconciling a FireboltEngine.
type EngineState ¶
type EngineState struct {
CurrentSTS *appsv1.StatefulSet
CurrentConfigMap *corev1.ConfigMap
CurrentHeadlessSvc *corev1.Service
CurrentPodsReady bool
// CurrentPodTotal is the number of pods that currently exist for the
// active generation (including non-running and non-ready ones). It can
// be less than spec.replicas if the StatefulSet has not finished
// creating pods yet.
CurrentPodTotal int
// CurrentPodReady is the subset of CurrentPodTotal that is in
// PodRunning phase with PodReady=True. Always <= CurrentPodTotal.
CurrentPodReady int
DrainingSTS *appsv1.StatefulSet
DrainingConfigMap *corev1.ConfigMap
DrainingHeadlessSvc *corev1.Service
DrainingPodsDrained bool
ClusterService *corev1.Service
ClusterServiceTargetGen int
}
EngineState captures the observed cluster state for a FireboltEngine, including all generation-scoped resources, pod readiness, and drain status.
type FireboltEngineClassInfo ¶
type FireboltEngineClassInfo struct {
// Name is the class name copied from engine.spec.engineClassRef.
Name string
// Template is the FireboltEngineClass.spec.template ready to merge.
Template *corev1.PodTemplateSpec
// UISidecar, Storage, CustomEngineConfig, Rollout, DrainCheckEnabled,
// DrainCheckInterval, and AutoStop carry the class's defaults for the
// matching engine settings. They are consumed by the effective* helpers,
// each of which resolves engine-if-set → class-if-set → operator default.
// Copied verbatim from the class spec.
UISidecar *bool
Storage computev1alpha1.EngineStorageSpec
CustomEngineConfig *apiextensionsv1.JSON
Rollout computev1alpha1.RolloutStrategy
DrainCheckEnabled *bool
DrainCheckInterval *metav1.Duration
AutoStop *computev1alpha1.AutoStopSpec
// Hash is a stable content hash of Template. Used as the value of
// AnnotationEngineClassHash on the rendered StatefulSet so drift is
// detected by stsMatchesSpec when the class template changes. Storage
// and CustomEngineConfig drift is detected through their own
// effective-aware comparators (storageMatchesSpec, customEngineConfigHash)
// rather than this hash; Rollout / DrainCheckEnabled / DrainCheckInterval /
// AutoStop do not reshape the StatefulSet and are read live, so they
// are not hashed.
Hash string
}
FireboltEngineClassInfo carries the resolved FireboltEngineClass template plus a content hash. The template is merged underneath the operator-built pod spec in buildStatefulSet so engines can inherit shared pod-level settings (serviceAccountName, nodeSelector, tolerations, pod annotations, affinity, sidecars, init containers) without restating them per engine. The hash is stamped on the StatefulSet as AnnotationEngineClassHash and consumed by stsMatchesSpec to detect drift when either spec.engineClassRef or the referenced class's spec.template content changes.
A nil *FireboltEngineClassInfo means the engine has no engineClassRef set; the merge is a no-op and the hash annotation is absent.
type FireboltEngineClassReconciler ¶
FireboltEngineClassReconciler keeps FireboltEngineClass status in sync with cluster state and manages the deletion-guard finalizer. It writes status and finalizers on the FireboltEngineClass itself; the operator never creates child resources for a FireboltEngineClass.
Two status fields are maintained:
- BoundEngines: the count of FireboltEngines in the class's namespace whose spec.engineClassRef names this class. FireboltEngineClass is namespaced, so engines outside the class's namespace cannot bind to it and are not counted. Both the deletion-blocking webhook and reconcileDelete do their own live list (status can be stale across reconciles); this value is purely a visibility surface. The count is recomputed from scratch each reconcile by listing FireboltEngines in the class's namespace.
- Conditions[Ready]: True when the class's spec.template passes ValidateOperatorOwnedPodTemplate. Admission normally catches offending specs, so Ready=False/OperatorOwnedFieldSet is reserved for classes admitted under an older operator with a narrower rejection set — a defense in depth, not an everyday signal. Ready=False/DeletionBlocked is surfaced while reconcileDelete is holding the finalizer because at least one engine still binds.
func (*FireboltEngineClassReconciler) Reconcile ¶
func (r *FireboltEngineClassReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)
Reconcile recomputes status for one FireboltEngineClass and manages the deletion-guard finalizer. The finalizer is added at first reconcile; once a deletionTimestamp is set the reconciler holds the finalizer while at least one FireboltEngine in the same namespace references the class.
func (*FireboltEngineClassReconciler) SetupWithManager ¶
func (r *FireboltEngineClassReconciler) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager registers the FireboltEngineClass controller. The controller watches its own CR for Create / Update / Delete and watches FireboltEngines so a referencing engine appearing or disappearing triggers an immediate boundEngines recount on the relevant class.
type FireboltEngineReconciler ¶
type FireboltEngineReconciler struct {
client.Client
Scheme *runtime.Scheme
// Clientset is used for the drain-check pod-proxy scrape
// (Pods/proxy subresource). Populated in SetupWithManager if nil.
Clientset *kubernetes.Clientset
// InstanceFilter, when non-empty, restricts this reconciler to engines
// referencing a single FireboltInstance (by spec.instanceRef). Requests
// for engines bound to any other instance are dropped, and instance
// watches are short-circuited so unrelated instance events do not fan
// out. Intended for E2E tests that run multiple isolated operator
// instances in the same namespace; in production this is left empty so
// the reconciler processes every FireboltEngine it watches.
InstanceFilter string
// MetricsRecorder records Prometheus metrics for engine CRs.
// Must be non-nil; use metrics.NoOpEngineRecorder{} in tests.
MetricsRecorder metrics.EngineRecorder
// EventRecorder emits Kubernetes Events on the engine CR. Populated
// in SetupWithManager when nil; unit tests that exercise event-emitting
// paths should inject an events.FakeRecorder. Nil is tolerated: the
// emit-event helpers no-op so tests that do not care about events can
// leave the field unset.
EventRecorder events.EventRecorder
// DisableGC disables the orphaned-generation garbage collector. When
// true, the reconciler will not sweep resources from abandoned
// generations. E2E tests set this to verify that the happy path never
// produces orphans; only tests that explicitly exercise mid-flight
// spec changes should enable GC.
DisableGC bool
// ResourceBounds caps per-dimension values in
// FireboltEngine.spec.resources at reconcile time. Identical to the
// admission webhook's ResourceBounds (both sourced from the
// --engine-max-* CLI flags in cmd/main.go) so admission and
// reconcile report the same field-path errors. When admission is on
// the controller-side gate is a redundant defense-in-depth check;
// when admission is bypassed (chart default), it is the only
// enforcement. An empty value disables the gate.
ResourceBounds computev1alpha1.EngineResourceBounds
}
FireboltEngineReconciler reconciles FireboltEngine objects by managing blue-green generational deployments of Firebolt engine StatefulSets.
func (*FireboltEngineReconciler) Reconcile ¶
func (r *FireboltEngineReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)
Reconcile reads the current engine state from the cluster, computes the reconcile actions needed, and applies them. Deletion is handled separately via a finalizer.
func (*FireboltEngineReconciler) SetupWithManager ¶
func (r *FireboltEngineReconciler) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager sets up the controller with the Manager.
func (*FireboltEngineReconciler) SetupWithManagerNamed ¶
func (r *FireboltEngineReconciler) SetupWithManagerNamed(mgr ctrl.Manager, name string) error
SetupWithManagerNamed sets up the controller with the Manager using a custom controller name.
type FireboltInstanceReconciler ¶
type FireboltInstanceReconciler struct {
client.Client
Scheme *runtime.Scheme
// MetricsRecorder records Prometheus metrics for instance CRs.
// Must be non-nil; use metrics.NoOpInstanceRecorder{} in tests.
MetricsRecorder metrics.InstanceRecorder
// NameFilter, when non-empty, restricts this reconciler to a single
// FireboltInstance by name. Requests for any other instance are dropped.
// Intended for E2E tests that run multiple isolated operator instances
// in the same namespace; in production this is left empty so the
// reconciler processes every FireboltInstance it watches.
NameFilter string
// GatewayWakeClusterRole is the name of the chart-managed ClusterRole
// that grants get/list/patch on fireboltengines to the gateway
// ServiceAccount. The reconciler binds this ClusterRole via a per-
// instance RoleBinding in the instance's namespace; the operator never
// creates the ClusterRole itself, so the cluster-wide `roles` verbs
// no longer appear in the operator's RBAC. Empty means the user takes
// ownership of gateway RBAC entirely — instances that reach the
// operator-managed branch (no user-supplied gateway SA) fail with a
// surfaced GatewayReady=False condition until the flag is set.
GatewayWakeClusterRole string
}
FireboltInstanceReconciler reconciles FireboltInstance objects by deploying PostgreSQL, the metadata service, and the gateway.
func (*FireboltInstanceReconciler) Reconcile ¶
func (r *FireboltInstanceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)
Reconcile ensures the PostgreSQL, metadata service, and gateway components described by a FireboltInstance are running and healthy.
func (*FireboltInstanceReconciler) SetupWithManager ¶
func (r *FireboltInstanceReconciler) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager sets up the controller with the Manager.
func (*FireboltInstanceReconciler) SetupWithManagerNamed ¶
func (r *FireboltInstanceReconciler) SetupWithManagerNamed(mgr ctrl.Manager, name string) error
SetupWithManagerNamed sets up the controller with the Manager using a custom controller name. Useful for E2E tests that spin up multiple in-process reconcilers per suite and need unique metric names across them.
type InstanceInfo ¶
InstanceInfo holds the multi-engine endpoint and instance ID (a ULID) resolved from the FireboltInstance in the engine's namespace. These are injected into the engine ConfigMap so engine nodes can connect to the metadata service and stamp the correct identity.
type StorageBackend ¶
type StorageBackend string
StorageBackend identifies which of the EngineStorageSpec sibling pointers the operator should honor for a given FireboltEngine. The full enum is declared up front (BackendEmptyDir / BackendHostPath are wired in follow-up commits) so the switch infrastructure can settle separately from the per-backend wiring.
const ( BackendPersistentVolumeClaim StorageBackend = "PersistentVolumeClaim" BackendEmptyDir StorageBackend = "EmptyDir" BackendHostPath StorageBackend = "HostPath" )
StorageBackend values, one per EngineStorageSpec sibling pointer.
Source Files
¶
- apply.go
- constants.go
- crash_points.go
- engine_apply.go
- engine_autostop.go
- engine_controller.go
- engine_gc.go
- engine_reconcile.go
- engine_scrape.go
- engine_state.go
- engine_types.go
- fireboltengineclass_controller.go
- instance_controller.go
- instance_gateway.go
- instance_gateway_rbac.go
- instance_metadata.go
- instance_postgres.go