Documentation
¶
Overview ¶
pkg/kordinator/cr_children.go
Child resource fetching and readiness for the CR detail endpoint.
pkg/kordinator/crd_health.go
pkg/kordinator/crd_health_handlers.go
pkg/kordinator/crd_rbac_health.go
pkg/kordinator/degraded.go
pkg/kordinator/dependency_kordinator.go
╔═══════════════════════════════════════════════════════════════════════════════╗ ║ CRD Lifecycle Management Flow ║ ╚═══════════════════════════════════════════════════════════════════════════════╝
The retryMissingCRDs goroutine runs forever, handling both activation and deactivation of CRDs. This is the self‑healing core of Orkestra.
───────────────────────────────────────────────────────────────────────────────── SCENARIO 1: CRD MISSING AT STARTUP ─────────────────────────────────────────────────────────────────────────────────
Startup:
- CRD A is missing from the cluster
- Kordinate loop processes A → startedCh["A"] remains open
- Kordinate continues (does NOT block) because missing CRDs are skipped
- Retry loop starts in background
Retry loop (every PostStartRetryInterval):
- Phase 1: checks missing map
- finds A is missing
- calls utils.WaitForCRD() → false
- remains in missing map
- Phase 2: checks running CRDs (none)
- Phase 3: checks deferred (not‑started) CRDs (A not ready due to missing)
- Phase 4: allReady? false
Later:
- User applies CRD A to cluster
- Retry loop runs again
- Phase 1: utils.WaitForCRD() → true
- activateCRD(A) is called:
- starts informer (entry.Informer.Run)
- starts workers
- closes startedCh["A"] ← UNBLOCKS dependents in Kordinate
- Phase 3: allCRDsPresent() may still be false if other CRDs missing
Result: CRD A becomes operational without restarting Orkestra.
───────────────────────────────────────────────────────────────────────────────── SCENARIO 2: CRD DELETED AFTER STARTUP ─────────────────────────────────────────────────────────────────────────────────
Running state:
- CRD A is active (workers running, informer watching)
- Retry loop runs periodically
User deletes CRD A:
- Informer reflector starts logging "failed to list... the server could not find..."
- Retry loop runs:
- Phase 1: missing map (A not there)
- Phase 2: checks running CRDs
- calls crdExists(A) → false
- deactivateCRD(A) is called:
- stopCRDWorkers(A) → stops workers, drains queue
- removes from started map
- marks as missing in informerFactory
- health.SetStarted(false)
- DOES NOT close startedCh[A]
- Phase 4: allReady becomes false
Result: CRD A becomes degraded, workers stop, but dependents continue (degraded). No more reflector errors.
───────────────────────────────────────────────────────────────────────────────── SCENARIO 3: CRD REAPPEARS AFTER BEING DELETED ─────────────────────────────────────────────────────────────────────────────────
After deactivation:
CRD A is in missing map
Retry loop runs:
Phase 1: missing map contains A
utils.WaitForCRD() → true
activateCRD(A) is called (same as scenario 1)
Workers restart, informer starts
startedCh[A] is closed again (it was never closed during deactivation, but we create a new channel? No — startedCh persists. Actually we don't close it during deactivation, so it remains open. We need to be careful: during activation, we should close it regardless of whether it was closed before.)
In activateCRD, we already handle this with select/default: select { case <-ch: // already closed default: close(ch) }
Result: CRD A becomes operational again without restarting Orkestra.
───────────────────────────────────────────────────────────────────────────────── SCENARIO 4: DEPENDENCY CHAIN WITH DELAYED ACTIVATION (FIXED BEHAVIOR) ─────────────────────────────────────────────────────────────────────────────────
StartupOrder: [A, B, C] where B depends on A:started, C depends on B:healthy
Initial state:
- A: present
- B: present
- C: present
Kordinate loop:
- A → starts, closes startedCh["A"]
- B → dependenciesReady? true (A started) → starts, closes startedCh["B"]
- C → dependenciesReady? false (B not yet healthy) → SKIPS (does NOT block)
- Main loop finishes.
Retry loop (periodic):
- Phase 3: checks not‑started CRDs
- C: dependenciesReady? false (B still not healthy) → skip
- Later, B becomes healthy → health checker closes healthyCh["B"]
- Next retry tick:
- Phase 3: C dependenciesReady? true → activateCRD(C)
- Workers start, C becomes operational
Result: A and B start immediately; C starts only when B becomes healthy, without blocking the main goroutine or starving other CRDs.
───────────────────────────────────────────────────────────────────────────────── SCENARIO 5: DEPENDENCY CHAIN WITH DELETION IN THE MIDDLE ─────────────────────────────────────────────────────────────────────────────────
Running state:
- A, B, C all active and healthy
- D depends on C:started
User deletes CRD C:
- Retry loop detects C missing
- deactivateCRD(C):
- stops workers
- marks missing
- DOES NOT close startedCh[C] (it's already closed from startup)
Result:
- C is degraded, workers stopped
- D continues running (degraded) because its dependency C is not ready
- Health endpoints show C as degraded, D as degraded
Later, C is recreated:
- activateCRD(C):
- starts workers
- attempts to close startedCh[C] (already closed, safe)
- D's health becomes healthy again automatically
───────────────────────────────────────────────────────────────────────────────── KEY DESIGN DECISIONS ─────────────────────────────────────────────────────────────────────────────────
- startedCh is NEVER closed during deactivation. Reason: Dependents should continue running (degraded) rather than block. If we closed the channel, dependents would think the dependency is ready when it's actually missing.
- retry loop runs FOREVER, not just at startup. Reason: CRDs can be deleted at any time. We need continuous monitoring.
- activateCRD closes startedCh safely using select/default. Reason: startedCh may already be closed from initial startup or previous activation.
- deactivateCRD does NOT remove from startedCh map. Reason: The channel is still needed for future activations. The channel is never closed, so it remains in the map.
- health.SetStarted(false) on deactivation. Reason: Allows health endpoint to show the CRD as not started.
- Main Kordinate loop NEVER BLOCKS on dependency conditions. Reason: Dependencies with "healthy" requirement may take arbitrary time. Blocking would starve other CRDs that are ready to start. Instead, we skip CRDs whose dependencies aren't ready and rely on the retry loop to activate them later when conditions are satisfied.
╚═══════════════════════════════════════════════════════════════════════════════╝
Package kordinator is the orchestration heart of every Orkestra operator.
It sits between the informer factory and the reconcilers: it decides when each CRD's workers start, in what order, under what conditions, and how they recover when the cluster changes beneath them.
Architecture ¶
The package is built in two layers.
The base layer is Kontroller — the worker manager. It holds the reconciler instances, the per-CRD context cancel functions, the WaitGroups, and the queue references. It knows how to start and stop workers for a GVK; it does not know anything about dependencies.
The coordination layer is DependencyKordinator, which embeds Kontroller and adds the dependency graph, the channel-based readiness signals, the self-healing retry loop, and the runtime health checker. It is the only component that calls Kordinate() — the method that blocks for the operator's lifetime and owns the startup → run → shutdown sequence.
ResourceKatalog ¶
ResourceKatalog is the in-memory registry written once during konstructOrkestra and read many times thereafter. Every GVK maps to a RegistryEntry that holds the informer, the reconciler factory closure, and the CRD configuration. Workers are created by calling entry.ReconcilerFactory() — the closure captures the provider registry, kube client, and provider stats so they never pass through the kordinator's own API.
CRD lifecycle ¶
The DependencyKordinator drives every CRD through the following states:
pending → informer created, workers not yet started started → workers running, no successful reconcile yet healthy → at least one successful reconcile completed degraded → consecutive failures exceeded threshold, or CRD missing
The transitions are recorded in CRDHealth using atomic operations — no locks in the hot path. State changes from workers (MarkWorkerProcessing, MarkWorkerIdle, RecordSuccess, RecordFailure) and from the health checker (SetDegraded, SetStarted) are all safe for concurrent callers.
Dependency channels ¶
CRDs may declare dependencies with two possible conditions:
dependsOn:
other-crd:
condition: started # default — workers are running
another-crd:
condition: healthy # first successful reconcile has completed
Each CRD gets two channels at startup:
startedCh[gvk] — closed when startCRDWorkers returns healthyCh[gvk] — closed by dependencyHealthChecker on first healthy state
dependenciesReady() checks these channels non-blocking using select/default. It returns false immediately if any channel is still open — it never blocks.
This is intentional. A dependency with condition: healthy may take minutes to satisfy. Blocking the startup loop on that condition would starve every CRD that appears later in the topological order, regardless of whether those CRDs depend on the slow one. The fix: skip and defer.
Non-blocking startup and deferred activation ¶
Kordinate() iterates the topological order exactly once. For each CRD:
- if dependenciesReady() returns false → skip, the retry loop handles it
- if the CRD is missing from the cluster → skip, the retry loop handles it
- otherwise → startCRDWorkers, close startedCh[gvk]
The background retryMissingCRDs goroutine runs for the operator's lifetime. On each tick it executes four phases in order:
Phase 1 — Detect runtime disappearances: polls every registered GVK.
When a CRD vanishes, deactivateCRD drains the workers,
marks the CRD degraded, and propagates degradation to any
dependent that requires condition: healthy.
Phase 2 — Re-activate missing CRDs: for every GVK in the missing map,
checks whether the CRD has appeared in the cluster. If yes,
activateCRD restarts the informer, launches workers, and
closes startedCh[gvk] to unblock waiting dependents.
Phase 3 — Deferred activation: iterates the topological order looking
for CRDs that were skipped at startup. When dependenciesReady()
finally returns true, activateCRD is called and the CRD joins
the running set. This is what handles condition: healthy.
Phase 4 — Aggregate health: if all CRDs are started and none are missing,
sets katalog health to ready.
Self-healing invariants ¶
startedCh is never closed during deactivation. This is load-bearing: if it were closed, dependents would believe the deactivated CRD is still ready and start processing against a resource that no longer exists. Keeping it open means dependents stay in their current state (degraded) and resume normally when activateCRD closes the channel again on re-activation.
activateCRD closes startedCh with a select/default guard:
select {
case <-ch: // already closed from a previous activation — no-op
default: close(ch)
}
Without this guard, re-activating a CRD that was previously started would panic with "close of closed channel".
Runtime health checker ¶
dependencyHealthChecker runs on a ticker independent of the retry loop. It evaluates the health of every active CRD's dependencies and updates the DependencyStatus map inside CRDHealth — this feeds the Control Center and the /katalog/{crd} endpoint. It also closes healthyCh[gvk] exactly once when a CRD transitions to healthy for the first time, which unblocks any deferred CRDs waiting for condition: healthy.
Worker loop ¶
runWorkerForGVK (in worker.go) is the inner loop for every worker goroutine:
for {
select {
case <-ctx.Done(): return
default:
item, shutdown := wq.Queue.Get()
if shutdown { return }
health.MarkWorkerProcessing(workerID)
func() {
defer wq.Queue.Done(item)
k.processItemForGVK(ctx, gvk, item)
}()
health.MarkWorkerIdle(workerID)
}
}
wq.Queue.Done(item) is always called — deferred inside the closure — whether the reconcile succeeds or fails. Re-queuing with rate-limit backoff is handled inside processItemForGVK on error.
stopCRDWorkers cancels the CRD context and then calls wq.Queue.ShutDown() before waiting on the WaitGroup. The shutdown call is required: a worker blocking on wq.Queue.Get() waiting for its next item will never observe the context cancellation until it is unblocked by the queue shutdown.
HTTP surface ¶
All three runtime introspection handlers are in crd_health_handers.go.
BuildCRDHealthHandler — /katalog/{crd}/health
BuildCRDInfoHandler — /katalog/{crd}
BuildKatalogHandler — /katalog
BuildCRDInfoHandler assembles a full CRD detail response on every request from live atomic reads — no caching. When the CRD declares provider blocks, it merges static ProviderBlocks metadata (declared kinds) with runtime ProviderStats (total calls, errors, error rate) into a providers array.
Resource count is len(inf.GetStore().List()) — the informer's local cache, updated in real time by the informer watch loop without any API calls.
pkg/config/pkg/kordinator/registry.go
pkg/kordinator/registry_cross.go
GetInformerByName — satisfies reconciler.KatalogRegistry.
Allows GenericReconciler to look up a sibling CRD's SharedIndexInformer for cross-CRD observation without importing pkg/kordinator directly (which would create an import cycle).
The lookup is by CRD name (the map key in spec.crds — lowercase). The GVK string stored in the registry is used internally; callers only need to know the short name.
Index ¶
- Constants
- func BuildCRDEnrichedHandler(kat *katalog.Katalog, crdName string) http.HandlerFunc
- func BuildCRDHealthHandler(crd orktypes.CRDEntry, kfg *konfig.Konfig, inf cache.SharedIndexInformer, ...) http.HandlerFunc
- func BuildCRDInfoHandler(crd orktypes.CRDEntry, kfg *konfig.Konfig, inf cache.SharedIndexInformer, ...) http.HandlerFunc
- func BuildCRDRawHandler(m *merger.Merger, crdName string) http.HandlerFunc
- func BuildCRDetailAndEventsHandler(crd orktypes.CRDEntry, inf cache.SharedIndexInformer, ...) http.HandlerFunc
- func BuildCRDetailHandler(crd orktypes.CRDEntry, inf cache.SharedIndexInformer, ...) http.HandlerFunc
- func BuildCREventsHandler(crd orktypes.CRDEntry, kube *kubeclient.Kubeclient) http.HandlerFunc
- func BuildCRListHandler(crd orktypes.CRDEntry, inf cache.SharedIndexInformer) http.HandlerFunc
- func BuildEnrichedKatalogHandler(kat *katalog.Katalog) http.HandlerFunc
- func BuildKatalogHandler(kat *katalog.Katalog, kfg *konfig.Konfig, reg *ResourceKatalog, ...) http.HandlerFunc
- func BuildRawKatalogHandler(m *merger.Merger) http.HandlerFunc
- func InvalidateChildrenCache(namespace, name string)
- func RegisterCRRoutes(mux *http.ServeMux, crd orktypes.CRDEntry, inf cache.SharedIndexInformer, ...)
- type AdmissionStatsResponse
- type CRDHealth
- func (h *CRDHealth) CRDExists() bool
- func (h *CRDHealth) ConsecutiveFails() int64
- func (h *CRDHealth) ErrorRate() float64
- func (h *CRDHealth) ErrorRatePercent() float64
- func (h *CRDHealth) FailedReconciles() int64
- func (h *CRDHealth) GetActiveWorkers() int32
- func (h *CRDHealth) GetAutoMetrics() map[string]interface{}
- func (h *CRDHealth) GetDependencyStatuses() map[string]DependencyStatus
- func (h *CRDHealth) GetIdleWorkers() int32
- func (h *CRDHealth) GetProcessingWorkers() int32
- func (h *CRDHealth) GetTotalWorkers() int32
- func (h *CRDHealth) GetWorkerInfo() *ork_autoscaler.WorkerInfo
- func (h *CRDHealth) GetWorkerStates() map[string]string
- func (h *CRDHealth) HasUnhealthyDependencies() bool
- func (h *CRDHealth) HealthAsMap() map[string]interface{}
- func (h *CRDHealth) IsHealthy() bool
- func (h *CRDHealth) IsMissing() bool
- func (h *CRDHealth) LastCRDCheck() time.Time
- func (h *CRDHealth) LastError() string
- func (h *CRDHealth) LastReconcile() string
- func (h *CRDHealth) MarkHealthySignaled()
- func (h *CRDHealth) MarkWorkerIdle(workerID string)
- func (h *CRDHealth) MarkWorkerProcessing(workerID string)
- func (h *CRDHealth) Name() string
- func (h *CRDHealth) Pending() bool
- func (h *CRDHealth) QueueDepth(gvk string) int
- func (h *CRDHealth) RecordFailure(err error, degradeThreshold int)
- func (h *CRDHealth) RecordRollbackCleared()
- func (h *CRDHealth) RecordRollbackTriggered()
- func (h *CRDHealth) RecordStartupFailure(err error, degradeThreshold int)
- func (h *CRDHealth) RecordSuccess()
- func (h *CRDHealth) ResetWorkerCounts()
- func (h *CRDHealth) RollbackStats() RollbackStats
- func (h *CRDHealth) SetAutoMetricsFn(fn func() map[string]interface{})
- func (h *CRDHealth) SetCRDExists(exists bool)
- func (h *CRDHealth) SetDegraded()
- func (h *CRDHealth) SetDependencyHealth(depName string, status DependencyStatus)
- func (h *CRDHealth) SetMissingAtRuntime()
- func (h *CRDHealth) SetNotStarted()
- func (h *CRDHealth) SetStarted()
- func (h *CRDHealth) SetTotalWorkers(count int32)
- func (h *CRDHealth) SetWorkerInfoFn(fn func() *ork_autoscaler.WorkerInfo)
- func (h *CRDHealth) SignaledHealthy() bool
- func (h *CRDHealth) Started() bool
- func (h *CRDHealth) StartedAt() string
- func (h *CRDHealth) StateAndStatus() (string, int)
- func (h *CRDHealth) TotalReconciles() int64
- func (h *CRDHealth) UpdateDependencyStatus(depName string, status DependencyStatus)
- func (h *CRDHealth) Uptime() string
- type CRDHealthResponse
- type CRDInfoResponse
- type CRDSummaryResponse
- type CRDetailResponse
- type CREvent
- type CREventsResponse
- type CRListResponse
- type CRSummary
- type ChildSummary
- type ConstructorInfo
- type ConversionStatsResponse
- type DeletionProtectionStatsResponse
- type DependencyKordinator
- func (k *DependencyKordinator) GVKToCRD(gvk schema.GroupVersionKind) types.CRDEntry
- func (k *DependencyKordinator) Kordinate(ctx context.Context)
- func (k *DependencyKordinator) Name() string
- func (k *DependencyKordinator) NameToCRD(name string) types.CRDEntry
- func (k *DependencyKordinator) NameToGVK(name string) schema.GroupVersionKind
- func (k *DependencyKordinator) NameToGVKMap() map[string]string
- type DependencyStatus
- type EndpointInfo
- type FinalizersInfo
- type HooksInfo
- type KatalogResponse
- type Kontroller
- func (k *Kontroller) Degraded(h domain.Health)
- func (k *Kontroller) IsDegraded(gvk string) bool
- func (k *Kontroller) MissingCRDs() map[string]*informer.InformerEntry
- func (k *Kontroller) Name() string
- func (k *Kontroller) SetReady(h domain.Health)
- func (k *Kontroller) Shutdown(ctx context.Context)
- func (k *Kontroller) Start(ctx context.Context) error
- func (k *Kontroller) Started() bool
- type NamespaceProtectionResponse
- type OperatorBoxInfo
- type OperatorBoxSummary
- type OrkestraHealth
- type ProviderInfoResponse
- type RBACInfo
- type RBACRule
- type RegistryEntry
- type ResourceKatalog
- func (r *ResourceKatalog) Entries() map[string]RegistryEntry
- func (r *ResourceKatalog) Get(gvk string) (RegistryEntry, bool)
- func (r *ResourceKatalog) GetInformerByLabelSelector(key, value string) (cache.SharedIndexInformer, bool)
- func (r *ResourceKatalog) GetInformerByName(name string) (cache.SharedIndexInformer, bool)
- func (r *ResourceKatalog) GetWorkers(gvk string, defaultWorkers int) int
- func (r *ResourceKatalog) ListGVKs() []string
- func (r *ResourceKatalog) Register(gvk string, crd orktypes.CRDEntry, inf cache.SharedIndexInformer, ...)
- func (r *ResourceKatalog) Unregister(gvk string)
- type RollbackStats
- type StatusCounts
- type WebhookControllerStats
- type WorkerStats
Constants ¶
const ( // Dependency checks DefaultDependencyTimeout = 60 * time.Second DefaultDependencyRetries = 3 DefaultDependencyInterval = 10 * time.Second // PostStart Retry loop // PostStartRetryInterval = 30 * time.Second PostStartRetryInterval = 3 * time.Second // DEBUG PostStartBackoff = 5 * time.Second DependencyHealthCheckInterval = 10 * time.Second // Healthcheck RuntimeHealthCheckInterval = 5 * time.Second )
const ( WorkerStateIdle = "idle" WorkerStateProcessing = "processing" WorkerStateStopped = "stopped" )
Worker state constants
Variables ¶
This section is empty.
Functions ¶
func BuildCRDEnrichedHandler ¶
func BuildCRDEnrichedHandler(kat *katalog.Katalog, crdName string) http.HandlerFunc
───────────────────────────────────────────────────────────────────────────── CRD Enriched Handler Returns a single CRD definition with all enriched/default values applied. This endpoint powers the "View Enriched" button in the CRD detail view, allowing users to see exactly what Orkestra uses at runtime after applying default workers, default resync, enriched API types, and resolved dependencies.
The enriched view shows:
- Fully resolved API types (group, version, plural enriched from discovery API)
- Default workers applied when not specified (from DEFAULT_WORKERS env var)
- Default resync applied when not specified (from DEFAULT_RESYNC env var)
- Default queue depth applied when not specified (from MAX_QUEUE_DEPTH env var)
- All validation and mutation rules merged from sources
- Complete operatorBox: configuration after inheritance
Endpoint: /katalog/{crd}/enriched
Example response (user wrote only `kind: Service`):
{
"name": "service-watcher",
"apiTypes": {
"group": "",
"version": "v1",
"kind": "Service",
"plural": "services"
},
"workers": 3,
"resync": "30s",
"maxQueueDepth": 2000,
"dependsOn": {
"pod-manager": {
"condition": "started"
}
}
}
This shows what Orkestra actually uses at runtime versus what the user wrote. ─────────────────────────────────────────────────────────────────────────────
func BuildCRDHealthHandler ¶
func BuildCRDHealthHandler( crd orktypes.CRDEntry, kfg *konfig.Konfig, inf cache.SharedIndexInformer, h *CRDHealth, ) http.HandlerFunc
───────────────────────────────────────────────────────────────────────────── CRD Health Handler Returns the live health status of a single CRD reconciler. This endpoint is used by:
- /katalog/<crd>/health
- dashboards
- readiness/liveness checks
- operator self‑diagnostics
The handler exposes:
- health state (healthy/degraded)
- startup state
- uptime
- reconcile counters
- last error
- last reconcile timestamp
─────────────────────────────────────────────────────────────────────────────
func BuildCRDInfoHandler ¶
func BuildCRDInfoHandler( crd orktypes.CRDEntry, kfg *konfig.Konfig, inf cache.SharedIndexInformer, h *CRDHealth, convStats *health.ConversionStats, admStats *health.AdmissionStats, protStats *health.DeletionProtectionStats, webhookControllerStats *health.WebhookStats, provStats *health.ProviderStats, nsStats *health.NamespaceProtectionStats, isDeletionProtected bool, isNamespaceProtected bool, isConversionEnabled bool, isAdmissionEnabled bool, ) http.HandlerFunc
───────────────────────────────────────────────────────────────────────────── CRD Info Handler Returns static + dynamic metadata about a CRD:
- GVK/GVR
- mode (dynamic/typed)
- workers, resync, queue depth (with source: default or configured)
- reconciler configuration (hooks, finalizers, constructor)
- resource count from informer
- health summary
This endpoint powers:
- /katalog/<crd>
- dashboards
- operator introspection
─────────────────────────────────────────────────────────────────────────────
func BuildCRDRawHandler ¶
func BuildCRDRawHandler(m *merger.Merger, crdName string) http.HandlerFunc
───────────────────────────────────────────────────────────────────────────── CRD Raw Handler Returns a single CRD definition from the merged Katalog as JSON. This endpoint powers the "View Source" button in the CRD detail view, allowing users to see exactly how the CRD was defined in the Katalog.
Endpoint: /katalog/{crd}/raw
Example response:
{
"name": "website",
"apiTypes": {
"group": "demo.orkestra.io",
"version": "v1alpha1",
"kind": "Website",
"plural": "websites"
},
"operatorBox:": {
"onCreate": {
"deployments": [
{
"image": "{{ .spec.image }}"
}
]
}
}
}
─────────────────────────────────────────────────────────────────────────────
func BuildCRDetailAndEventsHandler ¶
func BuildCRDetailAndEventsHandler( crd orktypes.CRDEntry, inf cache.SharedIndexInformer, kube *kubeclient.Kubeclient, rc orktypes.OperatorBoxConfig, ) http.HandlerFunc
BuildCRDetailAndEventsHandler handles all sub-paths under /katalog/{crd}/cr/ Dispatches to detail or events based on whether the path ends with /events. Register at "/katalog/{crd}/cr/" (with trailing slash).
func BuildCRDetailHandler ¶
func BuildCRDetailHandler( crd orktypes.CRDEntry, inf cache.SharedIndexInformer, kube *kubeclient.Kubeclient, rc orktypes.OperatorBoxConfig, ) http.HandlerFunc
───────────────────────────────────────────────────────────────────────────── CR Detail Handler GET /katalog/{crd}/cr/{name} (cluster-scoped) GET /katalog/{crd}/cr/{namespace}/{name} (namespaced)
Returns the full CR status and its child resources. CR is read from the informer cache — no API server call. Children are read from the API server on demand.
rcMap maps GVK → OperatorBoxConfig so we know which resource types to look for as children (from onCreate/onReconcile templates). ─────────────────────────────────────────────────────────────────────────────
func BuildCREventsHandler ¶
func BuildCREventsHandler( crd orktypes.CRDEntry, kube *kubeclient.Kubeclient, ) http.HandlerFunc
───────────────────────────────────────────────────────────────────────────── CR Events Handler GET /katalog/{crd}/cr/{name}/events (cluster-scoped) GET /katalog/{crd}/cr/{namespace}/{name}/events (namespaced)
Returns recent Kubernetes events involving this CR. Events are listed from the API server using field selectors on involvedObject.name and involvedObject.namespace.
Includes events emitted by Orkestra (reason: Reconciled, ReconcileError, ValidationWarning, Deleting) and by Kubernetes itself.
Events are sorted newest-first and capped at 100. ─────────────────────────────────────────────────────────────────────────────
func BuildCRListHandler ¶
func BuildCRListHandler( crd orktypes.CRDEntry, inf cache.SharedIndexInformer, ) http.HandlerFunc
───────────────────────────────────────────────────────────────────────────── CR List Handler GET /katalog/{crd}/cr
Lists all CR instances from the informer cache. No API server calls — purely in-memory. Sort order: namespace/name ascending for deterministic output. ─────────────────────────────────────────────────────────────────────────────
func BuildEnrichedKatalogHandler ¶
func BuildEnrichedKatalogHandler(kat *katalog.Katalog) http.HandlerFunc
───────────────────────────────────────────────────────────────────────────── Enriched Katalog Handler Returns the complete enriched Katalog as JSON, including metadata and all CRDs with all default values and enrichments applied. This endpoint shows what Orkestra actually uses at runtime after processing the user's Katalog.
Endpoint: /katalog/enriched
The response contains the same structure as /katalog/raw, but with:
- All defaults applied (workers, resync, queue depth)
- All API types enriched (group, version, plural from discovery API)
- All validation and mutation rules merged
- Complete operatorBox: configuration after inheritance
- Resolved dependencies with conditions
This endpoint is useful for:
- Understanding what Orkestra actually does with your Katalog
- Debugging why certain values are being used at runtime
- Seeing the full effect of inheritance and defaults
- Comparing user intent with runtime reality
Example response (user wrote minimal Katalog with just `kind: Pod`):
{
"apiVersion": "orkestra.orkspace.io/v1",
"kind": "Katalog",
"metadata": {
"name": "platform-katalog",
"description": "Production operator suite"
},
"spec": {
"crds": [
{
"name": "pod-manager",
"apiTypes": {
"group": "",
"version": "v1",
"kind": "Pod",
"plural": "pods"
},
"workers": 3,
"resync": "30s",
"maxQueueDepth": 2000,
"degradeThreshold": 10,
"namespaced": true,
"operatorBox:": {
"default": true
}
}
]
}
}
─────────────────────────────────────────────────────────────────────────────
func BuildKatalogHandler ¶
func BuildKatalogHandler( kat *katalog.Katalog, kfg *konfig.Konfig, reg *ResourceKatalog, healthMap map[string]*CRDHealth, o *OrkestraHealth, ) http.HandlerFunc
───────────────────────────────────────────────────────────────────────────── Katalog Handler Returns a full list of CRDs in the running operator, including:
- metadata (GVK, mode, namespace, dependencies)
- resolved operational values (workers, resync, queue depth)
- reconciler configuration summary
- health summary (uptime, error rate, startedAt)
- per‑CRD endpoints (/health, /info)
This is the top‑level endpoint for dashboards and operator UIs. ─────────────────────────────────────────────────────────────────────────────
func BuildRawKatalogHandler ¶
func BuildRawKatalogHandler(m *merger.Merger) http.HandlerFunc
───────────────────────────────────────────────────────────────────────────── Raw Katalog Handler Returns the complete merged Katalog as JSON, including metadata and all CRDs. This endpoint is used by the Control Center to display the source Katalog that defines the current operator.
Endpoint: /katalog/raw
The response contains:
- apiVersion: The Orkestra API version
- kind: Always "Katalog" at runtime (merged from sources)
- metadata: Katalog metadata (name, description, version, author, license)
- spec.crds: All merged CRD definitions from all sources
Example response:
{
"apiVersion": "orkestra.orkspace.io/v1",
"kind": "Katalog",
"metadata": {
"name": "platform-katalog",
"description": "Production operator suite",
"version": "1.0.0",
"author": "Platform Team"
},
"spec": {
"crds": [
{
"name": "website",
"apiTypes": { ... },
"operatorBox:": { ... }
}
]
}
}
─────────────────────────────────────────────────────────────────────────────
func InvalidateChildrenCache ¶ added in v0.4.7
func InvalidateChildrenCache(namespace, name string)
InvalidateChildrenCache removes the cached children for a CR. Called by the reconciler after a successful reconcile so the next endpoint request reflects the latest state immediately.
func RegisterCRRoutes ¶
func RegisterCRRoutes( mux *http.ServeMux, crd orktypes.CRDEntry, inf cache.SharedIndexInformer, kube *kubeclient.Kubeclient, rc orktypes.OperatorBoxConfig, )
RegisterCRRoutes adds the CR list, detail, and events handlers to mux. Call this alongside BuildCRDHealthHandler and BuildCRDInfoHandler for each CRD.
Types ¶
type AdmissionStatsResponse ¶
type AdmissionStatsResponse struct {
WebhooksEnabled bool `json:"webhooksEnabled"`
ValidationTotal int64 `json:"validationTotal"`
ValidationAllowed int64 `json:"validationAllowed"`
ValidationDenied int64 `json:"validationDenied"`
ValidationWarned int64 `json:"validationWarned"`
ValAvgLatencyMs float64 `json:"valAvgLatencyMs"`
ValP95LatencyMs float64 `json:"valP95LatencyMs"`
ValMaxLatencyMs float64 `json:"valMaxLatencyMs"`
MutationTotal int64 `json:"mutationTotal"`
MutationApplied int64 `json:"mutationApplied"`
MutationSkipped int64 `json:"mutationSkipped"`
MutAvgLatencyMs float64 `json:"mutAvgLatencyMs"`
MutP95LatencyMs float64 `json:"mutP95LatencyMs"`
MutMaxLatencyMs float64 `json:"mutMaxLatencyMs"`
}
type CRDHealth ¶
type CRDHealth struct {
// contains filtered or unexported fields
}
CRDHealth tracks the runtime health of a single CRD's reconciler. It is fully concurrency‑safe and designed to be updated from multiple goroutines.
Fields tracked:
started: whether the reconciler has begun processing events
healthy: whether the reconciler is currently considered healthy
totalReconciles: total number of reconcile attempts (success + failure)
failedReconciles: number of failed reconciles
consecutiveFails: number of failures in a row (used for degradation)
lastError: last error message (string)
lastReconcile: timestamp of last reconcile attempt
startTime: timestamp when the reconciler first started
The activeWarnings: tracks current warn-mode violations per CR. It answers the question: "which CRs are currently violating advisory rules?"
Map key: "namespace/name" — unique per CR Map value: slice of ActiveWarning, one per violated warn rule
This struct powers:
- /katalog/<crd> endpoint
- /katalog/<crd>/health endpoint
- dashboard status
- operator self‑diagnostics
func NewCRDHealth ¶
NewCRDHealth initializes a CRDHealth tracker for a given CRD name. The reconciler starts in an "unhealthy" state until the first successful reconcile.
func (*CRDHealth) ConsecutiveFails ¶
ConsecutiveFails returns the number of consecutive failed reconciles.
func (*CRDHealth) ErrorRate ¶
ErrorRate returns the ratio of failed reconciles to total reconciles. If no reconciles have occurred, the error rate is 0.
func (*CRDHealth) ErrorRatePercent ¶ added in v0.1.9
ErrorRatePercent returns the error rate as a percentage.
func (*CRDHealth) FailedReconciles ¶
FailedReconciles returns the number of failed reconcile attempts.
func (*CRDHealth) GetActiveWorkers ¶
GetActiveWorkers returns total workers (all are "active" if running)
func (*CRDHealth) GetAutoMetrics ¶ added in v0.1.9
GetAutoMetrics returns the live AutoMetrics map, or nil when not available. Included in the /katalog/{crd} response as "metrics" so cross-binary autoscale conditions can observe this CRD's metrics via HTTP fallback.
func (*CRDHealth) GetDependencyStatuses ¶
func (h *CRDHealth) GetDependencyStatuses() map[string]DependencyStatus
GetDependencyStatuses returns a copy of all dependency statuses
func (*CRDHealth) GetIdleWorkers ¶
GetIdleWorkers returns number of workers waiting for work
func (*CRDHealth) GetProcessingWorkers ¶
GetProcessingWorkers returns number of workers currently reconciling
func (*CRDHealth) GetTotalWorkers ¶
GetTotalWorkers returns the expected total workers
func (*CRDHealth) GetWorkerInfo ¶ added in v0.1.9
func (h *CRDHealth) GetWorkerInfo() *ork_autoscaler.WorkerInfo
GetWorkerInfo returns the live WorkerInfo, or nil when not available.
func (*CRDHealth) GetWorkerStates ¶
GetWorkerStates returns a map of worker states for debugging
func (*CRDHealth) HasUnhealthyDependencies ¶
HasUnhealthyDependencies returns true if any dependency is not satisfied
func (*CRDHealth) HealthAsMap ¶ added in v0.4.4
HealthAsMap returns a snapshot of this CRD's health as a plain map, suitable for injection into the template resolver under the "health" key.
Available in conditions status.fields templates as:
{{ .health.healthy }} — bool: reconciler is healthy
{{ .health.state }} — string: "healthy" / "degraded" / "pending" / "not started"
{{ .health.status }} — int: HTTP status code representing health state
{{ .health.started }} — bool: reconciler has started
{{ .health.pending }} — bool: reconciler is pending
{{ .health.degraded }} — bool: reconciler is degraded
{{ .health.totalReconciles }} — int64: total reconcile attempts
{{ .health.failedReconciles }} — int64: total failed reconciles
{{ .health.consecutiveFails }} — int64: current consecutive failure streak
{{ .health.errorRatePercent }} — float64: error rate as percentage
{{ .health.lastReconcile }} — string: RFC3339 timestamp of last reconcile
{{ .health.uptime }} — string: how long the reconciler has been running
{{ .health.lastError }} — string: most recent error message (empty if none)
{{ .health.rollbackActive }} — bool: rollback is currently blocking reconcile
{{ .health.rollbackTotal }} — int64: total rollback triggers since startup
{{ .health.hasUnhealthyDeps }} — bool: any dependency is unsatisfied
func (*CRDHealth) IsHealthy ¶
IsHealthy reports whether the reconciler is currently considered healthy. Health is degraded after N consecutive failures.
func (*CRDHealth) LastCRDCheck ¶
LastCRDCheck returns when the CRD existence was last verified.
func (*CRDHealth) LastError ¶
LastError returns the last recorded error message. If no error has occurred, it returns an empty string.
func (*CRDHealth) LastReconcile ¶
LastReconcile returns a human‑readable timestamp of the last reconcile. If the reconciler has started but not yet reconciled, it returns a placeholder.
func (*CRDHealth) MarkHealthySignaled ¶
func (h *CRDHealth) MarkHealthySignaled()
func (*CRDHealth) MarkWorkerIdle ¶
MarkWorkerIdle is called when a worker finishes processing
func (*CRDHealth) MarkWorkerProcessing ¶
MarkWorkerProcessing is called when a worker starts processing an item
func (*CRDHealth) QueueDepth ¶
QueueDepth returns the queue for this CRD
func (*CRDHealth) RecordFailure ¶
RecordFailure marks a failed reconcile event. It increments failure counters, stores the error, and may degrade health if the number of consecutive failures exceeds the configured threshold.
func (*CRDHealth) RecordRollbackCleared ¶ added in v0.1.9
func (h *CRDHealth) RecordRollbackCleared()
RecordRollbackCleared marks rollback inactive. Called by the reconciler when it clears the rollback annotation.
func (*CRDHealth) RecordRollbackTriggered ¶ added in v0.1.9
func (h *CRDHealth) RecordRollbackTriggered()
RecordRollbackTriggered increments the rollback counter and marks rollback active. Called by the reconciler when it triggers a rollback.
func (*CRDHealth) RecordStartupFailure ¶
RecordStartupFailure is used when the reconciler fails before it has fully started. It does not affect total reconcile counts, only consecutive failure tracking.
func (*CRDHealth) RecordSuccess ¶
func (h *CRDHealth) RecordSuccess()
RecordSuccess marks a successful reconcile event. It resets the consecutive failure counter and updates timestamps.
func (*CRDHealth) ResetWorkerCounts ¶
func (h *CRDHealth) ResetWorkerCounts()
ResetWorkerCounts resets all worker counters (used during deactivation)
func (*CRDHealth) RollbackStats ¶ added in v0.1.9
func (h *CRDHealth) RollbackStats() RollbackStats
RollbackStats returns a snapshot of rollback activity for this CRD.
func (*CRDHealth) SetAutoMetricsFn ¶ added in v0.1.9
SetAutoMetricsFn stores the function that returns live AutoMetrics as a map. Called by startCRDWorkers when autoscale: is declared.
func (*CRDHealth) SetCRDExists ¶
SetCRDExists records that the CRD exists in the cluster.
func (*CRDHealth) SetDegraded ¶
func (h *CRDHealth) SetDegraded()
SetDegraded marks the reconciler as degraded This is used when a CRD goes missing at runtime
func (*CRDHealth) SetDependencyHealth ¶
func (h *CRDHealth) SetDependencyHealth(depName string, status DependencyStatus)
SetDependencyHealth updates a single dependency's status
func (*CRDHealth) SetMissingAtRuntime ¶
func (h *CRDHealth) SetMissingAtRuntime()
func (*CRDHealth) SetNotStarted ¶
func (h *CRDHealth) SetNotStarted()
SetNotStarted marks the reconciler as not started.
func (*CRDHealth) SetStarted ¶
func (h *CRDHealth) SetStarted()
SetStarted marks the reconciler as started and records the start time. CompareAndSwap ensures the timestamp is only set once.
func (*CRDHealth) SetTotalWorkers ¶
SetTotalWorkers sets the expected number of workers
func (*CRDHealth) SetWorkerInfoFn ¶ added in v0.1.9
func (h *CRDHealth) SetWorkerInfoFn(fn func() *ork_autoscaler.WorkerInfo)
SetWorkerInfoFn stores the function that returns live WorkerInfo for this CRD. Called by startCRDWorkers after constructing the reconciler.
func (*CRDHealth) SignaledHealthy ¶
func (*CRDHealth) StartedAt ¶
StartedAt returns the timestamp when the reconciler first started. If not started, returns "not started". If starting, returns "starting".
func (*CRDHealth) StateAndStatus ¶ added in v0.4.4
StateAndStatus returns the reconciler's derived health state and the corresponding HTTP status code used by the /health endpoint.
State is one of:
"not started", "pending", "degraded", "healthy"
Status is either:
200 — healthy or pending 503 — degraded or not started
func (*CRDHealth) TotalReconciles ¶
TotalReconciles returns the total number of reconcile attempts.
func (*CRDHealth) UpdateDependencyStatus ¶
func (h *CRDHealth) UpdateDependencyStatus(depName string, status DependencyStatus)
Dependency tracking
type CRDHealthResponse ¶
type CRDHealthResponse struct {
Name string `json:"name"`
State string `json:"state"` // "not started", "pending", "started", "healthy", "degraded"
Status int `json:"status"`
Healthy bool `json:"healthy"`
Started bool `json:"started"`
Pending bool `json:"pending"`
StartedAt string `json:"startedAt"`
Uptime string `json:"uptime"`
QueueDepth int `json:"queueDepth"`
ErrorRate float64 `json:"errorRate"`
ConsecutiveFails int64 `json:"consecutiveFails"`
TotalReconciles int64 `json:"totalReconciles"`
ResourceCount int `json:"resourceCount"`
LastError string `json:"lastError"`
LastReconcile string `json:"lastReconcile"`
HasUnhealthyDependencies bool `json:"hasUnhealthyDependencies"`
Dependencies map[string]DependencyStatus `json:"dependencies,omitempty"`
Missing bool `json:"missing,omitempty"`
}
type CRDInfoResponse ¶
type CRDInfoResponse struct {
Name string `json:"name"`
Description string `json:"description"`
Mode string `json:"mode"`
GVK string `json:"gvk"`
GVR string `json:"gvr"`
Namespaced bool `json:"namespaced"`
Namespace string `json:"namespace"`
DependsOn []string `json:"dependsOn,omitempty"`
Workers int `json:"workers"`
WorkersActive int32 `json:"workersActive"`
WorkersIdle int32 `json:"workersIdle"`
WorkersProcessing int32 `json:"workersProcessing"`
WorkerDetails map[string]string `json:"workerDetails,omitempty"`
WorkersSource string `json:"workersSource"`
Resync string `json:"resync"`
ResyncSource string `json:"resyncSource"`
QueueDepth int `json:"queueDepth"`
MaxQueueDepth int `json:"maxQueueDepth"`
MaxQueueDepthSource string `json:"maxQueueDepthSource"`
ResourceCount int `json:"resourceCount"`
TotalReconciles int64 `json:"totalReconciles"`
OperatorBox OperatorBoxInfo `json:"operatorBox"`
Healthy bool `json:"healthy"`
Started bool `json:"started"`
Pending bool `json:"pending"`
ErrorRate float64 `json:"errorRate"`
Conversion *ConversionStatsResponse `json:"conversion,omitempty"`
Admission *AdmissionStatsResponse `json:"admission,omitempty"`
DeletionProtection *DeletionProtectionStatsResponse `json:"deletionProtection,omitempty"`
NamespaceProtection *NamespaceProtectionResponse `json:"namespaceProtection,omitempty"`
WebhookControllerStats *WebhookControllerStats `json:"webhookControllerStats,omitempty"`
Providers []ProviderInfoResponse `json:"providers,omitempty"`
RBAC RBACInfo `json:"rbac,omitempty"`
AutoscalerEnabled bool `json:"autoscalerEnabled,omitempty"`
AutoscalerWorkers *ork_autoscaler.WorkerInfo `json:"autoscalerWorkers,omitempty"`
Rollback *RollbackStats `json:"rollback,omitempty"`
// Metrics is the live AutoMetrics map for this operatorbox.
// Populated only when autoscale: is declared. Used by cross-binary autoscale
// conditions via the source.endpoint HTTP fallback — the remote autoscaler
// calls this endpoint and reads "metrics.*" fields from the response.
Metrics map[string]interface{} `json:"metrics,omitempty"`
}
type CRDSummaryResponse ¶
type CRDSummaryResponse struct {
Name string `json:"name"`
Description string `json:"description"`
Mode string `json:"mode"`
GVK string `json:"gvk"`
GVR string `json:"gvr"`
Namespaced bool `json:"namespaced"`
Namespace string `json:"namespace"`
DependsOn []string `json:"dependsOn,omitempty"`
HasUnhealthyDependencies bool `json:"hasUnhealthyDependencies"`
Workers int `json:"workers"`
WorkersSource string `json:"workersSource"`
WorkersActive int32 `json:"workersActive"`
Resync string `json:"resync"`
ResyncSource string `json:"resyncSource"`
QueueDepth int `json:"queueDepth"`
MaxQueueDepth int `json:"maxQueueDepth"`
MaxQueueDepthSource string `json:"maxQueueDepthSource"`
ResourceCount int `json:"resourceCount"`
OperatorBox OperatorBoxSummary `json:"operatorBox"`
Healthy bool `json:"healthy"`
State string `json:"state"`
Started bool `json:"started"`
Pending bool `json:"pending"`
StartedAt string `json:"startedAt"`
Uptime string `json:"uptime"`
ErrorRate float64 `json:"errorRate"`
Endpoints EndpointInfo `json:"endpoints"`
RBACCount int `json:"rbacCount,omitempty"`
DeletionProtection bool `json:"deletionProtection"`
ProviderCount int `json:"providerCount,omitempty"`
}
type CRDetailResponse ¶
type CRDetailResponse struct {
Name string `json:"name"`
Namespace string `json:"namespace,omitempty"`
Generation int64 `json:"generation"`
CreationTimestamp string `json:"creationTimestamp"`
Labels map[string]string `json:"labels,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
// Ready reflects the Orkestra Ready condition.
// true = operator reconciled successfully.
// The CR may still be in a non-terminal phase (e.g. Running/build).
Ready bool `json:"ready"`
ReadyReason string `json:"readyReason,omitempty"`
ReadyMessage string `json:"readyMessage,omitempty"`
// Status is the full status subresource as returned by the API server.
// Includes phase, conditions, and any declared status fields.
Status map[string]interface{} `json:"status,omitempty"`
// Children holds the child resources created by Orkestra for this CR.
// Keyed by lowercase kind (e.g. "deployment", "job", "cronjob").
// Value is a single ChildSummary when one child exists, []ChildSummary when multiple.
// Populated on demand from the API server — may be empty on first reconcile.
Children map[string]interface{} `json:"children"`
// EventsEndpoint is the URL to fetch recent events for this CR.
EventsEndpoint string `json:"eventsEndpoint"`
// Debug to know if it has templates
HasTemplateBlocks bool `json:"hasTemplateBlocks"`
}
CRDetailResponse is returned by GET /katalog/{crd}/cr/{namespace}/{name}.
type CREvent ¶
type CREvent struct {
Type string `json:"type"` // Normal or Warning
Reason string `json:"reason"`
Message string `json:"message"`
Source string `json:"source"` // component that emitted the event
Object string `json:"object"` // involved object kind/name
Count int32 `json:"count"`
FirstSeen string `json:"firstSeen"`
LastSeen string `json:"lastSeen"`
Age string `json:"age"`
}
CREvent is one Kubernetes event involving this CR or its children.
type CREventsResponse ¶
type CREventsResponse struct {
Name string `json:"name"`
Namespace string `json:"namespace,omitempty"`
Total int `json:"total"`
Events []CREvent `json:"events"`
}
CREventsResponse is returned by GET /katalog/{crd}/cr/{namespace}/{name}/events.
type CRListResponse ¶
type CRListResponse struct {
CRD string `json:"crd"`
GVK string `json:"gvk"`
Total int `json:"total"`
Items []CRSummary `json:"items"`
}
CRListResponse is returned by GET /katalog/{crd}/cr.
type CRSummary ¶
type CRSummary struct {
Name string `json:"name"`
Namespace string `json:"namespace,omitempty"`
Phase string `json:"phase,omitempty"` // from status.phase if declared
Ready bool `json:"ready"` // from status.conditions[type=Ready]
ReadyReason string `json:"readyReason,omitempty"`
Age string `json:"age"`
Generation int64 `json:"generation"`
}
CRSummary is one row in the CR list — equivalent to one line of kubectl get.
type ChildSummary ¶
type ChildSummary struct {
Name string `json:"name"`
Namespace string `json:"namespace,omitempty"`
Kind string `json:"kind"`
Status map[string]interface{} `json:"status,omitempty"`
Ready bool `json:"ready"`
}
ChildSummary is a condensed view of one child resource. Only the fields that matter for observability are included — not the full object.
type ConstructorInfo ¶
type ConversionStatsResponse ¶
type DeletionProtectionStatsResponse ¶ added in v0.1.9
type DeletionProtectionStatsResponse struct {
Enabled bool `json:"enabled"`
Total int64 `json:"total"` // total DELETE admission reviews received
Blocked int64 `json:"blocked"` // DELETE requests denied
Allowed int64 `json:"allowed"` // DELETE requests allowed through
}
DeletionProtectionStatsResponse exposes deletion protection status for the CRD detail view. All counts are cumulative since operator startup.
type DependencyKordinator ¶
type DependencyKordinator struct {
*Kontroller
// contains filtered or unexported fields
}
DependencyKordinator extends the base Kontroller with dependency‑aware startup. It ensures CRDs start in topological order and shut down in reverse order.
func NewDependencyKordinator ¶
func NewDependencyKordinator( kube *kubeclient.Kubeclient, factory *informer.Factory, katalog *ResourceKatalog, events *event.Event, hs domain.Health, queueRegistry *queue.QueueRegistry, defaultWorkqueue *queue.Workqueue, crdHealthMap map[string]*CRDHealth, orkHealth *OrkestraHealth, defaultWorkers int, depGraph *katalog.DependencyGraph, drainTimeout time.Duration, ) *DependencyKordinator
NewDependencyKordinator constructs a dependency‑aware kordinator. It embeds the base Kontroller and handles dependencies in the correct order.
func (*DependencyKordinator) GVKToCRD ¶
func (k *DependencyKordinator) GVKToCRD(gvk schema.GroupVersionKind) types.CRDEntry
GVKToCRD returns the CRD entry for a given gvk
func (*DependencyKordinator) Kordinate ¶
func (k *DependencyKordinator) Kordinate(ctx context.Context)
Kordinate starts CRDs in dependency order and blocks until leadership is lost. When leadership ends, it shuts down CRDs in reverse dependency order.
The startup loop is non‑blocking: if a CRD's dependencies are not yet satisfied (e.g., waiting for "healthy"), the CRD is skipped. The background retry loop will activate it later when dependencies become ready.
func (*DependencyKordinator) Name ¶
func (k *DependencyKordinator) Name() string
Name returns the name of the dependency kordinator
func (*DependencyKordinator) NameToCRD ¶
func (k *DependencyKordinator) NameToCRD(name string) types.CRDEntry
NameToCRD returns the CRD for a given name
func (*DependencyKordinator) NameToGVK ¶
func (k *DependencyKordinator) NameToGVK(name string) schema.GroupVersionKind
NameToGVK returns the GVK for a given name
func (*DependencyKordinator) NameToGVKMap ¶
func (k *DependencyKordinator) NameToGVKMap() map[string]string
NameToGVKMap returns a map of names to gvk string
type DependencyStatus ¶
type DependencyStatus struct {
Name string `json:"name"`
State string `json:"state"` // "healthy", "degraded", "missing", "started"
Condition string `json:"condition"` // "started", "healthy", "ready"
AcceptableCondition string `json:"acceptableCondition"` // "started", "healthy", "ready"
Satisfied bool `json:"satisfied"`
LastCheck string `json:"lastCheck,omitempty"`
}
type EndpointInfo ¶
type FinalizersInfo ¶
type KatalogResponse ¶
type KatalogResponse struct {
CRDs []CRDSummaryResponse `json:"crds"`
Total int `json:"total"`
TotalEnabled int `json:"totalEnabled"`
OrkReady bool `json:"OrkReady"`
DeletionProtection bool `json:"deletionProtection"`
Healthy bool `json:"healthy"`
Status int `json:"status"`
DegradedReason string `json:"degradedReason,omitempty"`
StatusCounts StatusCounts `json:"statusCounts"`
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
CreatedBy string `json:"createdBy,omitempty"`
Author string `json:"author,omitempty"`
Description string `json:"description,omitempty"`
License string `json:"license,omitempty"`
RuntimeVersion string `json:"runtimeVersion,omitempty"`
Projects map[string]orktypes.ProjectInfo `json:"projects,omitempty"`
}
type Kontroller ¶
type Kontroller struct {
// contains filtered or unexported fields
}
Every map has the same key GVK
func NewKontroller ¶
func NewKontroller( kube *kubeclient.Kubeclient, informerFactory *informer.Factory, katalog *ResourceKatalog, event *event.Event, hs domain.Health, crdHealthMap map[string]*CRDHealth, orkHealth *OrkestraHealth, queueRegistry *queue.QueueRegistry, defaultWorkqueue *queue.Workqueue, defaultWorkers int, ) *Kontroller
func (*Kontroller) Degraded ¶
func (k *Kontroller) Degraded(h domain.Health)
Set the controller to degraded
func (*Kontroller) IsDegraded ¶
func (k *Kontroller) IsDegraded(gvk string) bool
func (*Kontroller) MissingCRDs ¶
func (k *Kontroller) MissingCRDs() map[string]*informer.InformerEntry
MissingCRDs returns a map of missing crds keyed by gvk
func (*Kontroller) SetReady ¶
func (k *Kontroller) SetReady(h domain.Health)
Set the controller ready
func (*Kontroller) Shutdown ¶
func (k *Kontroller) Shutdown(ctx context.Context)
Shutdown gracefully stops orkestra
type NamespaceProtectionResponse ¶ added in v0.1.9
type NamespaceProtectionResponse struct {
Enabled bool `json:"enabled"`
HasNamespaceRules bool `json:"hasNamespaceRules"`
Total int64 `json:"total"`
Blocked int64 `json:"blocked"`
Allowed int64 `json:"allowed"`
AllowedNamespaces []string `json:"allowedNamespaces,omitempty"` // non-nil only when allowedNamespaces: is declared
RestrictedNamespaces []string `json:"restrictedNamespaces,omitempty"` // non-nil only when restrictedNamespaces: is declared
}
NamespaceProtectionResponse exposes namespace protection status for the CRD detail view.
type OperatorBoxInfo ¶
type OperatorBoxInfo struct {
Type string `json:"type"`
Finalizers FinalizersInfo `json:"finalizers"`
Hooks HooksInfo `json:"hooks"`
Constructor ConstructorInfo `json:"constructor"`
Templates map[string]interface{} `json:"templates,omitempty"`
}
type OperatorBoxSummary ¶
type OrkestraHealth ¶
type OrkestraHealth struct {
// contains filtered or unexported fields
}
func NewOrkestraHealth ¶
func NewOrkestraHealth() *OrkestraHealth
NewOrkestraHEalth initializes a CRDHealth tracker for Orkestra
func (*OrkestraHealth) IsKatalogReady ¶
func (h *OrkestraHealth) IsKatalogReady() bool
IsKatalogReady is used to track ready state of a katalog
func (*OrkestraHealth) IsOrkReady ¶
func (h *OrkestraHealth) IsOrkReady() bool
IsOrkReady is used to track ready state of orkestra
func (*OrkestraHealth) SetKatalogDegraded ¶
func (h *OrkestraHealth) SetKatalogDegraded()
SetKatalogDegraded marks a katalog as degraded
func (*OrkestraHealth) SetKatalogReady ¶
func (h *OrkestraHealth) SetKatalogReady()
SetKatalogReady marks a katalog as ready
func (*OrkestraHealth) SetOrkDegraded ¶
func (h *OrkestraHealth) SetOrkDegraded()
SetOrkDegraded marks orkestra engine as degraded
func (*OrkestraHealth) SetOrkReady ¶
func (h *OrkestraHealth) SetOrkReady()
SetOrkReady marks orkestra engine as ready
type ProviderInfoResponse ¶
type ProviderInfoResponse struct {
Name string `json:"name"`
Kinds []string `json:"kinds"` // declared resource kinds (static, from Katalog)
Total int64 `json:"total"` // reconcile calls since startup
Errors int64 `json:"errors"` // failed reconcile calls since startup
ErrorRate float64 `json:"errorRate"` // errors / total, 0 when no calls yet
}
ProviderInfoResponse exposes per-provider metadata and error rate for one CRD. No auth, URLs, or credentials are exposed — metadata only.
type RegistryEntry ¶
type RegistryEntry struct {
CRD orktypes.CRDEntry
Informer cache.SharedIndexInformer
ReconcilerFactory func() domain.Reconciler // factory lives here
DegradeThreshold int
}
type ResourceKatalog ¶
type ResourceKatalog struct {
// contains filtered or unexported fields
}
func NewKordinatorRegistry ¶
func NewKordinatorRegistry() *ResourceKatalog
func (*ResourceKatalog) Entries ¶
func (r *ResourceKatalog) Entries() map[string]RegistryEntry
func (*ResourceKatalog) Get ¶
func (r *ResourceKatalog) Get(gvk string) (RegistryEntry, bool)
func (*ResourceKatalog) GetInformerByLabelSelector ¶ added in v0.1.9
func (r *ResourceKatalog) GetInformerByLabelSelector(key, value string) (cache.SharedIndexInformer, bool)
GetInformerByLabelSelector returns the SharedIndexInformer for a CRD whose metadata.labelSelector contain the given key/value pair.
This enables cross‑CRD observation by semantic grouping rather than by CRD name. Platform teams can labelSelector CRDs (e.g. "tier=platform", "domain=payments") and application‑level logic can reference them without knowing the exact CRD name.
Lookup rules:
- Match is case‑insensitive on both key and value
- Returns the first CRD whose labelSelector contain key=value
- Returns nil, false when no CRD matches
This is used by GenericReconciler via the KatalogRegistry interface to support cross‑context reads without importing pkg/kordinator directly (avoiding import cycles).
func (*ResourceKatalog) GetInformerByName ¶
func (r *ResourceKatalog) GetInformerByName(name string) (cache.SharedIndexInformer, bool)
GetInformerByName returns the SharedIndexInformer for a CRD by its lowercase name (the spec.crds map key: "pipeline", "database", "website").
The registry stores entries keyed by GVK string (e.g. "demo.orkestra.io/v1alpha1, Kind=Pipeline"). This method searches by Kind name match (case-insensitive) so callers use simple names.
Returns nil, false when no CRD with that name is registered.
func (*ResourceKatalog) GetWorkers ¶
func (r *ResourceKatalog) GetWorkers(gvk string, defaultWorkers int) int
func (*ResourceKatalog) ListGVKs ¶
func (r *ResourceKatalog) ListGVKs() []string
func (*ResourceKatalog) Register ¶
func (r *ResourceKatalog) Register( gvk string, crd orktypes.CRDEntry, inf cache.SharedIndexInformer, rec func() domain.Reconciler, )
func (*ResourceKatalog) Unregister ¶
func (r *ResourceKatalog) Unregister(gvk string)
type RollbackStats ¶ added in v0.1.9
type RollbackStats struct {
// TotalRollbacks is the number of times rollback was triggered since startup.
TotalRollbacks int64 `json:"totalRollbacks"`
// Active is true when rollback is currently blocking normal reconciliation.
Active bool `json:"active"`
// LastRollbackAt is the RFC3339 timestamp of the most recent rollback trigger.
// Empty when no rollback has occurred.
LastRollbackAt string `json:"lastRollbackAt,omitempty"`
}
RollbackStats is a snapshot of rollback activity for one CRD.
type StatusCounts ¶
type WebhookControllerStats ¶
type WebhookControllerStats struct {
Reconciled int64 // total successful reconciliation cycles
Failed int64 // reconciliation attempts that encountered errors
}
WebhookControllerStats tracks reconciliation counters for the webhook controller.
type WorkerStats ¶
type WorkerStats struct {
Workers int32 `json:"workers"`
WorkersActive int32 `json:"workersActive"`
WorkersIdle int32 `json:"workersIdle"`
WorkersProcessing int32 `json:"workersProcessing"`
WorkerDetails map[string]string `json:"workerDetails,omitempty"`
}
───────────────────────────────────────────────────────────────────────────── CRD Info Response ─────────────────────────────────────────────────────────────────────────────
Source Files
¶
- constants.go
- cr_children.go
- cr_extract_parent.go
- cr_handlers.go
- cr_routes.go
- crd_config_handlers.go
- crd_health.go
- crd_health_handers.go
- crd_rbac_health.go
- crd_worker_health.go
- degraded.go
- dependency_kordinator.go
- doc.go
- kontroller.go
- kordinator_registry.go
- post_start_hooks.go
- registry_cross.go
- runtime_dependency_checker.go
- worker.go