Documentation
¶
Overview ¶
pkg/types/admission.go
pkg/types/autoscale.go
Autoscale configuration for an operatorbox.
The autoscaler adjusts workers, queueDepth, and resync at runtime based on metric conditions, time windows, and cron expressions. The CRD's declared values are always the baseline — overrides are temporary and automatically reverted when conditions are no longer met.
YAML shape (inside operatorBox:):
operatorBox:
autoscale:
interval: 15s
cooldown: 2m
conditions:
anyOf:
- time:
after: "08:00"
before: "17:00"
- cron: "0 20 * * 1-5"
duration: 4h
when:
- field: metrics.queueDepth
greaterThan: "200"
do:
workers: 12
queueDepth: 1000
resync: 20s
pkg/types/conditions.go
pkg/types/conversion.go
pkg/types/cross.go
Cross-CRD observation declarations.
The cross: block under a CRD's reconciler allows one CR to observe another CRD's CR instances without making API server calls — data is read from the target CRD's informer cache directly.
YAML:
spec:
crds:
application:
cross:
- crd: database # target CRD name (lowercase, matches spec.crds key)
selector:
name: "{{ .metadata.name }}" # find by name
namespace: "{{ .metadata.namespace }}"
as: database # available as .cross.database.*
database:
operatorBox: ... # database CRD — already has an informer
After ReadCross runs, the Application reconciler has access to:
{{ .cross.database.found }} → "true" if CR was found
{{ .cross.database.status.phase }} → Database CR's status.phase
{{ .cross.database.status.endpoint }} → Database CR's status.endpoint
{{ .cross.database.spec.storageGb }} → Database CR's spec field
This is zero API calls for same-binary CRDs — data comes from the informer cache that is already maintained for the target CRD. For cross-binary or cross-cluster observation, set source.endpoint.
Use cases:
- Wait for a Database CR to be Ready before creating the Application Deployment
- Copy a Database endpoint into the Application status
- Gate resource creation on another CRD's phase
- Service mesh without a service mesh: Application watches Database watches Network
pkg/types/external.go
External HTTP call declarations.
The external: block under onReconcile allows declarative HTTP calls before resource creation. Results are injected into the resolver context and available in subsequent template expressions and when: conditions.
YAML:
onReconcile:
external:
- name: health-check
url: "{{ .spec.serviceUrl }}/health"
method: GET
expectedStatus: 200
continueOnError: false
timeout: 5s
- name: feature-flags
url: "https://flags.internal/api/{{ .metadata.name }}"
method: GET
token: "$FEATURE_FLAG_TOKEN"
continueOnError: true
deployments:
- name: "{{ .metadata.name }}"
image: "{{ .spec.image }}"
when:
- field: external.health-check.status
equals: "200"
- field: external.feature-flags.body
contains: "\"enabled\":true"
Calls run sequentially in declaration order before any resource groups. Results are immutable once injected — a call cannot see a later call's result.
Security: tokens are resolved via the standard resolver — use environment variable references ($TOKEN) or Kubernetes Secret references via the KubeReader mechanism. Never put raw secrets in Katalog YAML.
pkg/types/foreach.go
ForEachSpec — declares dynamic resource expansion over a list field.
When a template source declares forEach, the reconciler expands it into N resource declarations — one per element in the list field.
The item is injected into the resolver context and available as:
{{ .item }} — always available
{{ .<as> }} — the name declared in forEach.as
{{ .index }} — 0-based position in the list
YAML:
onReconcile:
deployments:
- name: "{{ .metadata.name }}-{{ .item }}"
image: "{{ .spec.image }}"
forEach:
field: spec.regions # list field on the CR
as: item # optional, default: "item"
For CR with spec.regions: [us-east-1, eu-west-1, ap-southeast-1]: Produces three Deployments:
my-app-us-east-1 my-app-eu-west-1 my-app-ap-southeast-1
Each declaration is fully independent — when:, anyOf:, labels, and all other fields are evaluated per-item with .item in context.
forEach works on all resource types: deployments, services, secrets, configmaps, jobs, cronjobs, serviceaccounts.
Nesting: forEach is not nestable. One level of expansion per declaration. For matrix expansion (regions × environments), declare two separate resource types or use a hook.
pkg/types/katalog.go
pkg/types/notification_refined.go
This file replaces the KatalogNotification type in pkg/types. It adds:
- enabled: true/false at the notification block level
- per-team Slack webhookUrl (overrides the global default)
- a global default Slack webhook
- message template field per team for customisation
- rollback integration (notify on rollback via existing team references)
YAML shape:
notification:
enabled: true
defaults:
interval: 15m
slackWebhookUrl: "https://hooks.slack.com/services/..." # global default
teams:
platform:
email: ["platform@company.io"]
slack: ["#platform-alerts"]
slackWebhookUrl: "https://hooks.slack.com/services/..." # override
interval: 5m
message: "{{ .metadata.name }} in {{ .metadata.namespace }}: {{ .status.conditions.Ready.message }}"
oncall:
slack: ["#oncall"]
interval: 1m
# On conditions:
when:
- field: status.phase
equals: Degraded
notify: [platform, oncall]
# On rollback:
rollback:
trigger:
consecutiveFailures: 3
notify: [oncall] # fires when rollback activates
SMTP config is read from pkg/konfig env vars — not declared in YAML. Slack webhook URL is per-team or global default — not from env (user choice).
pkg/types/ns_allowed.go
pkg/types/ns_restricted.go
pkg/types/provider.go
Provider interface — the extension point for external infrastructure.
A provider handles a named YAML block in onCreate/onReconcile/onDelete. Orkestra dispatches the block to the registered provider after all Kubernetes resource groups have been reconciled.
Registration (in cmd/operator/main.go or wherever komponents are wired):
registry := orktypes.NewProviderRegistry() registry.Register(awsprovider.New(sess)) registry.Register(mongoprovider.New(uri))
Katalog usage:
onCreate:
aws:
- rds:
instanceClass: db.t3.micro
engine: postgres
database:
- driver: mongo
uri: "$MONGO_ATLAS_URI"
createUser: "{{ .spec.dbUser }}"
Orkestra calls provider.Reconcile for each block whose name matches a registered provider. Unregistered blocks are skipped with a warning. Provider errors fail the reconcile cycle and trigger backoff.
pkg/types/provider_katalog.go
Provider types for Katalog YAML parsing and runtime dispatch.
Layer 1 — Katalog-level manifest (KatalogProviderRequirement) ¶
Declared at the top level under providers[]. Lists which providers this Katalog uses and supplies the credentials for each. Credentials support $ENV_VAR expansion. Only providers registered here are active — per-CRD blocks for unregistered providers are skipped with a warning.
providers: is a top-level sibling of spec: and security:, not nested under spec:, because providers represent operational infrastructure dependencies — distinct state from the CRD definitions in spec:.
providers:
- name: aws
required: true
auth:
accessKeyId: "$AWS_ACCESS_KEY_ID"
secretAccessKey: "$AWS_SECRET_ACCESS_KEY"
region: "$AWS_REGION"
- name: mongodb
required: true
auth:
mongoUri: "$MONGODB_URL"
Layer 2 — Per-CRD provider blocks (ProviderBlock, RawProviderDeclaration) ¶
Declared under spec.crds[].operatorBox.providers. Each named block is dispatched to the registered provider library. Template expressions are resolved before the provider is called. A per-CRD auth block can override the katalog-level credentials for that CRD.
operatorBox:
providers:
aws:
- s3:
bucket: "{{ .metadata.name }}-assets"
region: "{{ .spec.region }}"
mongodb:
- database:
name: "{{ .metadata.name }}"
- user:
name: "{{ .spec.dbUser }}"
database: "{{ .metadata.name }}"
credentials:
secretName: "{{ .metadata.name }}-mongo-creds"
pkg/types/registry.go
pkg/types/rollback.go
Rollback — declarative failure recovery for operatorboxes.
When a reconcile fails a configurable number of times (or within a time window), Orkestra enters a rollback phase. In this phase it applies the previous desired state — captured before the failing spec change was applied — and blocks normal reconciliation until the operator fixes the spec.
Rollback is not "undo" in the transactional sense. It is "re-apply the last known good declaration." The existing Update functions handle idempotent re-application — no new primitives are needed.
YAML shape (inside operatorBox:):
operatorBox:
rollback:
trigger:
consecutiveFailures: 3 # OR
withinDuration: 5m # triggers if N failures occur within this window
onRollback:
deployments:
- name: "{{ .previous.metadata.name }}"
image: "{{ .previous.spec.image }}"
replicas: "{{ .previous.spec.replicas }}"
reconcile: true
configMaps:
- name: "{{ .previous.metadata.name }}-config"
reconcile: true
The .previous.* context is hydrated from the annotation:
orkestra.konductor.io/previous-spec
which is written atomically before each spec change is applied.
The rollback phase exits only when the spec changes (new generation). Until then, normal onCreate/onReconcile is blocked.
pkg/types/security.go
Security configuration at the Katalog level.
The unified security block covers four concerns:
- Deletion protection — webhook that blocks deletion of managed CRDs and the operator itself.
- Admission webhooks — ValidatingWebhookConfiguration and MutatingWebhookConfiguration.
- Conversion — CRD version conversion via /convert (separate from webhooks).
- RBAC auto-apply — ClusterRole, ClusterRoleBinding, ServiceAccount at startup.
YAML shape:
security:
deletionProtection:
enabled: true # default: true when block is present
serviceName: orkestra # default: ORKESTRA_SERVICE_NAME env / "orkestra"
failurePolicy: Fail # default: Fail
webhooks:
admission:
enabled: true # default: ENABLE_ADMISSION_WEBHOOK env / false
failurePolicy: Ignore # default: WEBHOOKS_FAILURE_POLICY env / "Ignore"
serviceName: orkestra # default: ORKESTRA_SERVICE_NAME env / "orkestra"
conversion:
enabled: true # default: ENABLE_CONVERSION env / false
conversionWindow: 100 # default: CONVERSION_WINDOW env / 100
Precedence: katalog YAML value > ENV value > hard default. ENV values populate SecurityConfig during Init() and act as defaults. Katalog values are merged on top in KomposeKatalogFromYaml.
pkg/types/sources.go
pkg/types/status.go
pkg/orktypes/types.go
pkg/types/when.go
EvaluateWhen — extended condition evaluation with OR logic.
The when: field ([]Condition) uses AND semantics. anyOf: is a new parallel field on template sources with OR semantics.
# AND only
when:
- field: status.phase
equals: "Ready"
# OR
anyOf:
- field: status.phase
equals: "Failed"
- field: status.phase
equals: "Succeeded"
# Combined: (spec.enabled=true) AND (phase=Failed OR phase=Succeeded)
when:
- field: spec.enabled
equals: "true"
anyOf:
- field: status.phase
equals: "Failed"
- field: status.phase
equals: "Succeeded"
Index ¶
- Constants
- Variables
- func EvaluateOneCond(data map[string]interface{}, cond Condition) bool
- func EvaluateWhen(data map[string]interface{}, allOf []Condition, anyOf []Condition) bool
- func NavigateDotPath(m map[string]interface{}, path string) string
- func NavigateRawPath(m map[string]interface{}, path string) interface{}
- func NeedsRotation(generatedAt, rotateAfter string) bool
- func ParseRotationDuration(s string) (time.Duration, error)
- func TickCronWindow(windows map[string]time.Time, cronExpr string, ...) bool
- type APITypes
- type AdmissionWebhookConfig
- type AdmissionWebhookToggle
- type AllowedNamespaces
- type AutoscaleAction
- type AutoscaleBaseline
- type AutoscaleConditions
- type AutoscaleSpec
- func (a *AutoscaleSpec) EffectiveCooldown() time.Duration
- func (a *AutoscaleSpec) EffectiveInterval() time.Duration
- func (a *AutoscaleSpec) HasAnyOfConditions() bool
- func (a *AutoscaleSpec) HasCooldownDuration() bool
- func (a *AutoscaleSpec) HasDoQueueDepth() bool
- func (a *AutoscaleSpec) HasDoResync() bool
- func (a *AutoscaleSpec) HasDoWorkers() bool
- func (a *AutoscaleSpec) HasIntervalDuration() bool
- func (a *AutoscaleSpec) HasWhenConditions() bool
- type AutoscaleState
- type CRDConversion
- type CRDEntry
- func (c *CRDEntry) AllAllowedNamespaces() AllowedNamespaces
- func (c *CRDEntry) AllRestrictedNamespaces() RestrictedNamespaces
- func (c *CRDEntry) AllowedNamespacesOnly() bool
- func (c *CRDEntry) AutoScaleProfile() string
- func (c *CRDEntry) AutoscaleEnabled() bool
- func (e CRDEntry) Config() OperatorBoxConfig
- func (c *CRDEntry) ConstructorEnabled() bool
- func (c *CRDEntry) CustomHooksEnabled() bool
- func (c *CRDEntry) DefaultQueue() bool
- func (c *CRDEntry) DefaultReconcile() bool
- func (c *CRDEntry) GVK() schema.GroupVersionKind
- func (c *CRDEntry) GVKString() string
- func (c *CRDEntry) GVR() schema.GroupVersionResource
- func (c *CRDEntry) GVRString() string
- func (c *CRDEntry) GetDependencies() []string
- func (c *CRDEntry) GetRuntimeObjects() (runtime.Object, runtime.Object)
- func (c *CRDEntry) HasAllowedNamespaces() bool
- func (c *CRDEntry) HasAnyHPA() bool
- func (c *CRDEntry) HasAnyHooks() bool
- func (c *CRDEntry) HasAnySecrets() bool
- func (c *CRDEntry) HasAnyTLSSecrets() bool
- func (c *CRDEntry) HasAutoscaleProfile() bool
- func (c *CRDEntry) HasMutationRules() bool
- func (c *CRDEntry) HasNamespaceRules() bool
- func (c *CRDEntry) HasOnCreate() bool
- func (c *CRDEntry) HasOnDelete() bool
- func (c *CRDEntry) HasOnReconcile() bool
- func (c *CRDEntry) HasProviders() bool
- func (c *CRDEntry) HasRestrictedNamespaces() bool
- func (c *CRDEntry) HasRollbackRules() bool
- func (c *CRDEntry) HasTemplates() bool
- func (c *CRDEntry) HasValidationOrMutationRules() bool
- func (c *CRDEntry) HasValidationRules() bool
- func (c *CRDEntry) IsBuiltInType() bool
- func (c *CRDEntry) IsDynamic() bool
- func (c *CRDEntry) IsEnabled() bool
- func (c *CRDEntry) IsEnabledAllEndpoints() bool
- func (c *CRDEntry) IsHealthEnabled() bool
- func (c *CRDEntry) IsInfoEnabled() bool
- func (c *CRDEntry) IsNamespaced() bool
- func (c *CRDEntry) IsNotificationEnabled() bool
- func (c *CRDEntry) IsStatuslessType() bool
- func (c *CRDEntry) RestrictedNamespacesOnly() bool
- func (c *CRDEntry) SetMaxQueueDepth(def int) int
- func (c *CRDEntry) SetWorkers(def int) int
- func (c *CRDEntry) SkipObservedGeneration() bool
- func (c *CRDEntry) SkipStatusSubresource() bool
- func (c *CRDEntry) UpdateCRDCaBundle() bool
- func (c *CRDEntry) ValidateMetricField(field string) error
- type CRDMode
- type Condition
- type ConditionOperator
- type ConfigMapKeyRef
- type ConfigMapTemplateSource
- type ConstructorDeclaration
- type ConversionConfig
- type ConversionPath
- type ConversionRules
- type ConversionVersionSpec
- type CronJobTemplateSource
- type CrossCRDDeclaration
- type CrossSelector
- type CrossSource
- type DayOfWeekCondition
- type DeleteRequest
- type DeletionProtectionConfig
- type DependencyCondtion
- type DependsOnCondition
- type DependsOnMap
- type DeploymentTemplateSource
- type DockerHookSpec
- type Duration
- type EndpointsConfig
- type EnrichmentOutcome
- type EnvFromSource
- type EnvVarSource
- type ExternalCallResult
- type ExternalCallSpec
- type FileSource
- type FileSourceAuth
- type ForEachSpec
- type GitHookSpec
- type HPATemplateSource
- type HelmSource
- type HookDeclaration
- type HookTemplates
- type IngressTLSSpec
- type IngressTemplateSource
- type JobTemplateSource
- type KatalogFile
- type KatalogForUI
- type KatalogMeta
- type KatalogNotification
- func (n *KatalogNotification) EffectiveInterval(teamName string) Duration
- func (n *KatalogNotification) EffectiveMessage(teamName string) string
- func (n *KatalogNotification) EffectiveSlackWebhook(teamName string) string
- func (n *KatalogNotification) HasEmailTargets(teamName string) bool
- func (n *KatalogNotification) HasSlackTargets(teamName string) bool
- func (n *KatalogNotification) HasTeams() bool
- func (n *KatalogNotification) IsEmailEnabled(hasSMTPConfig bool) bool
- func (n *KatalogNotification) IsEnabled() bool
- func (n *KatalogNotification) IsSlackEnabled() bool
- type KatalogProviderRequirement
- type KatalogSecurity
- func (s *KatalogSecurity) DeletionProtectionFailurePolicy() string
- func (s *KatalogSecurity) DeletionProtectionServiceName(envDefault string) string
- func (s *KatalogSecurity) IsAdmissionEnabled() bool
- func (s *KatalogSecurity) IsConversionEnabled() bool
- func (s *KatalogSecurity) IsDeletionProtectionEnabled() bool
- func (s *KatalogSecurity) IsNamespaceProtectionEnabled() bool
- func (s *KatalogSecurity) NamespaceProtectionFailurePolicy() string
- func (s *KatalogSecurity) NamespaceProtectionServiceName(envDefault string) string
- func (s *KatalogSecurity) WebhooksFailurePolicy(envDefault string) string
- func (s *KatalogSecurity) WebhooksServiceName(envDefault string) string
- type KatalogSources
- type KatalogSpec
- type KatalogSpecForUI
- type KubeReader
- type MutationConfig
- type MutationRule
- type NamespaceProtectionConfig
- type NamespaceTemplateSource
- type NewReconcilerFunc
- type NormalizeConfig
- type NotificationDefaults
- type NotificationTeam
- type NotifyBlock
- type OperatorBoxConfig
- type PDBTemplateSource
- type PVCTemplateSource
- type PVTemplateSource
- type PlaceholderSource
- type PodTemplateSource
- type Provider
- type ProviderBlock
- type ProviderDeclaration
- type ProviderRegistry
- type Queue
- type RBACConfig
- type RawProviderDeclaration
- type ReconcileRequest
- type RegistryRef
- type RegistrySource
- type ReplicaSetTemplateSource
- type ResourceCheck
- type ResourceLabel
- type ResourceRequirements
- type ResourceSelector
- type RestrictedNamespaces
- type RollbackBlock
- type RollbackPhase
- type RollbackTrigger
- type ScaleTargetRef
- type SecretKeyRef
- type SecretTemplateSource
- type SelectorMap
- type ServiceAccountTemplateSource
- type ServiceTemplateSource
- type StatefulSetTemplateSource
- type StatusConfig
- type StatusFieldSpec
- type TLSSpec
- type TimeWindow
- type ValidationAction
- type ValidationConfig
- type ValidationRule
- type WebhooksConfig
Constants ¶
const ( // AnnotationGeneratedAt is the RFC3339 timestamp when the secret was last generated. AnnotationGeneratedAt = "orkestra.konductor.io/generated-at" // AnnotationRotateAfter stores the declared rotation duration. AnnotationRotateAfter = "orkestra.konductor.io/rotate-after" )
const ( CRDModeTyped CRDMode = "typed" CRDModeDynamic CRDMode = "dynamic" DependencyConditionStarted DependencyCondtion = "started" DependencyConditionHealthy DependencyCondtion = "healthy" // Future DependencyCondtionPending DependencyCondtion = "pending" DependencyCondtionReady DependencyCondtion = "ready" DependencyConditionDegraded DependencyCondtion = "degraded" DependencyConditionDeleted DependencyCondtion = "deleted" )
const PreviousSpecAnnotation = "orkestra.konductor.io/previous-spec"
PreviousSpecAnnotation is the annotation key where the previous spec is stored before a spec change is applied. Value is a base64-encoded, gzip-compressed JSON of the CR spec.
const RollbackGenerationAnnotation = "orkestra.konductor.io/rollback-at-generation"
RollbackGenerationAnnotation records the generation at which rollback was last triggered. Used to detect spec changes that should exit rollback.
Variables ¶
var HookRegistry = map[schema.GroupVersionKind]func() domain.AnyReconcileHooks{}
var ListRegistry = map[schema.GroupVersionKind]func() runtime.Object{}
var ObjectRegistry = map[schema.GroupVersionKind]func() runtime.Object{}
var ReconcilerRegistry = map[schema.GroupVersionKind]NewReconcilerFunc{}
var RequiredFiles = []string{
"crd.yaml",
"katalog.yaml",
"komposer.yaml",
"cr.yaml",
"README.md",
}
RequiredFiles lists the five files every valid registry pattern must contain. Validated after pull — fail fast if any are missing or empty.
These five files define the standard pattern structure. Enforcing their presence at pull time means every pattern in the ecosystem is documented, testable, and consistent. A registry entry without a README, a CRD, or an example CR is not ready for distribution.
var ResourceChecks = map[string]ResourceCheck{ "deployments": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []DeploymentTemplateSource { return t.Deployments }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []DeploymentTemplateSource { return t.Deployments }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []DeploymentTemplateSource { return t.Deployments }) }, }, "statefulsets": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []StatefulSetTemplateSource { return t.StatefulSets }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []StatefulSetTemplateSource { return t.StatefulSets }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []StatefulSetTemplateSource { return t.StatefulSets }) }, }, "daemonsets": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []PlaceholderSource { return t.DaemonSets }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []PlaceholderSource { return t.DaemonSets }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []PlaceholderSource { return t.DaemonSets }) }, }, "jobs": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []JobTemplateSource { return t.Jobs }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []JobTemplateSource { return t.Jobs }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []JobTemplateSource { return t.Jobs }) }, }, "cronjobs": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []CronJobTemplateSource { return t.CronJobs }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []CronJobTemplateSource { return t.CronJobs }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []CronJobTemplateSource { return t.CronJobs }) }, }, "services": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []ServiceTemplateSource { return t.Services }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []ServiceTemplateSource { return t.Services }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []ServiceTemplateSource { return t.Services }) }, }, "ingresses": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []IngressTemplateSource { return t.Ingresses }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []IngressTemplateSource { return t.Ingresses }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []IngressTemplateSource { return t.Ingresses }) }, }, "networkpolicies": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []PlaceholderSource { return t.NetworkPolicies }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []PlaceholderSource { return t.NetworkPolicies }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []PlaceholderSource { return t.NetworkPolicies }) }, }, "configmaps": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []ConfigMapTemplateSource { return t.ConfigMaps }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []ConfigMapTemplateSource { return t.ConfigMaps }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []ConfigMapTemplateSource { return t.ConfigMaps }) }, }, "secrets": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []SecretTemplateSource { return t.Secrets }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []SecretTemplateSource { return t.Secrets }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []SecretTemplateSource { return t.Secrets }) }, }, "persistentvolumes": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []PVTemplateSource { return t.PersistentVolumes }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []PVTemplateSource { return t.PersistentVolumes }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []PVTemplateSource { return t.PersistentVolumes }) }, }, "persistentvolumeclaims": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []PVCTemplateSource { return t.PersistentVolumeClaims }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []PVCTemplateSource { return t.PersistentVolumeClaims }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []PVCTemplateSource { return t.PersistentVolumeClaims }) }, }, "volumes": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []PlaceholderSource { return t.Volumes }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []PlaceholderSource { return t.Volumes }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []PlaceholderSource { return t.Volumes }) }, }, "volumemounts": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []PlaceholderSource { return t.VolumeMounts }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []PlaceholderSource { return t.VolumeMounts }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []PlaceholderSource { return t.VolumeMounts }) }, }, "namespaces": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []NamespaceTemplateSource { return t.Namespaces }) || usesTemplates(rc.OnReconcile, func(ht *HookTemplates) []NamespaceTemplateSource { return ht.Namespaces }) || usesTemplates(rc.OnDelete, func(ht *HookTemplates) []NamespaceTemplateSource { return ht.Namespaces }) }, }, "serviceaccounts": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []ServiceAccountTemplateSource { return t.ServiceAccounts }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []ServiceAccountTemplateSource { return t.ServiceAccounts }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []ServiceAccountTemplateSource { return t.ServiceAccounts }) }, }, "roles": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []PlaceholderSource { return t.Roles }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []PlaceholderSource { return t.Roles }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []PlaceholderSource { return t.Roles }) }, }, "rolebindings": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []PlaceholderSource { return t.RoleBindings }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []PlaceholderSource { return t.RoleBindings }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []PlaceholderSource { return t.RoleBindings }) }, }, "horizontalpodautoscalers": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []HPATemplateSource { return t.HorizontalPodAutoscalers }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []HPATemplateSource { return t.HorizontalPodAutoscalers }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []HPATemplateSource { return t.HorizontalPodAutoscalers }) }, }, "poddisruptionbudgets": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []PDBTemplateSource { return t.PodDisruptionBudgets }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []PDBTemplateSource { return t.PodDisruptionBudgets }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []PDBTemplateSource { return t.PodDisruptionBudgets }) }, }, "podtemplates": { Get: func(crd CRDEntry) bool { rc := crd.OperatorBox return usesTemplates(rc.OnCreate, func(t *HookTemplates) []PlaceholderSource { return t.PodTemplates }) || usesTemplates(rc.OnReconcile, func(t *HookTemplates) []PlaceholderSource { return t.PodTemplates }) || usesTemplates(rc.OnDelete, func(t *HookTemplates) []PlaceholderSource { return t.PodTemplates }) }, }, }
ResourceChecks maps resource keys → detection logic. Each entry checks OnCreate, OnReconcile, and OnDelete safely.
Functions ¶
func EvaluateOneCond ¶
EvaluateOneCond evaluates a single Condition against a data map. Exported so the template package and reconciler package can both call it. Defined here in pkg/types to avoid import cycles.
Time-based conditions (time:, dayOfWeek:, cron:) are evaluated against the current wall clock — they do not reference the data map. Metric conditions (metrics.*, cross.<crd>.metrics.*) are navigated as dot-paths through data, so callers must pre-populate the relevant keys.
func EvaluateWhen ¶
EvaluateWhen evaluates when: (allOf, AND) and anyOf: (OR) conditions. data is resolver.Data() — full CR map including children, external, cross.
Both blocks must pass when both are declared. Empty blocks always pass.
func NavigateDotPath ¶
NavigateDotPath walks a dot-notation path through a nested map. Returns "" when any segment is missing — the notExists case. Exported for use by the template package and status field resolver.
func NavigateRawPath ¶
NavigateRawPath walks a dot-notation path through a nested map. Returns interface{} when any segment is missing — the notExists case. Exported for use by the template package and status field resolver.
func NeedsRotation ¶
NeedsRotation returns true when the secret has exceeded its rotation threshold. generatedAt is the value of the AnnotationGeneratedAt annotation. rotateAfter is the declared rotation duration string.
func ParseRotationDuration ¶
ParseRotationDuration parses a human‑friendly rotation duration string.
It extends Go's time.ParseDuration by adding long‑term units:
d = days (24h) w = weeks (7d) mo = months (30d) y = years (365d)
Examples:
"30s" → 30 seconds "5m" → 5 minutes (Go duration) "12h" → 12 hours "10d" → 10 days "2w" → 14 days "3mo" → 90 days "1y" → 365 days
Notes:
- Only "mo" is accepted for months to avoid collision with Go's "m" (minutes).
- Fractional values are supported (e.g., "1.5mo").
- Falls back to time.ParseDuration for standard units.
func TickCronWindow ¶ added in v0.1.9
func TickCronWindow(windows map[string]time.Time, cronExpr string, duration, interval time.Duration, now time.Time) bool
TickCronWindow advances the cron window state machine for one expression. It updates windows (caller-owned state map) and returns whether the window is currently open.
duration is how long the window stays open after a cron fire. interval is the evaluation tick period — used to detect fires between ticks. When duration is zero, interval is used as the window length.
This is the general-purpose cron window tracker. Any part of Orkestra that needs cron-gated behaviour (autoscaler, future job runner, etc.) can bring its own map[string]time.Time and call this on each evaluation tick.
Types ¶
type APITypes ¶
type APITypes struct {
// Object — Go type name for a single CR instance. Required for typed mode.
// Used by ork generate to emit ObjectRegistry entries.
// e.g. "Project" → func() runtime.Object { return &projv1.Project{} }
Object string `yaml:"object" json:"object,omitempty" validate:"omitempty"`
// List — Go type name for the CR list. Required for typed mode.
// Used by ork generate to emit ListRegistry entries.
// e.g. "ProjectList" → func() runtime.Object { return &projv1.ProjectList{} }
List string `yaml:"objectList" json:"objectList,omitempty" validate:"omitempty"`
// Alias — Go import alias for the API types package. Optional.
// Auto-derived from the last two segments of Location if not set.
// e.g. "projv1" → import projv1 "github.com/.../project/v1alpha1"
Alias string `yaml:"alias" json:"alias,omitempty" validate:"omitempty"`
// Group — Kubernetes API group. Required in all modes.
// e.g. "platform.orkestra.io"
Group string `yaml:"group" json:"group" validate:"required,hostname_rfc1123"`
// Version — API version. Required in all modes.
// e.g. "v1alpha1"
Version string `yaml:"version" json:"version" validate:"required"`
// Kind — resource Kind. Required in all modes.
// e.g. "Project"
Kind string `yaml:"kind" json:"kind" validate:"required"`
// Plural — lowercase plural resource name. Required in all modes.
// Used for REST client URL construction.
// e.g. "projects"
Plural string `yaml:"plural" json:"plural" validate:"required"`
// APIPath — REST API path prefix. Default: /apis.
// Override to /api only for core Kubernetes types (Pod, ConfigMap, etc.)
// Almost always leave this empty — Orkestra defaults it to /apis.
APIPath string `yaml:"apiPath" json:"apiPath,omitempty" validate:"omitempty"`
// Location — fully qualified Go import path for the API types package.
// Required for typed mode. Used by ork generate for import statements
// and scheme registration in RegisterScheme().
// Not needed for dynamic mode — omit entirely.
// e.g. "github.com/orkspace/orkestra/api/types/project/v1alpha1"
Location string `yaml:"location" json:"location,omitempty" validate:"omitempty"`
}
type AdmissionWebhookConfig ¶
type AdmissionWebhookConfig struct {
// Validation — include this CRD in the ValidatingWebhookConfiguration.
// Default: true when validation rules are declared.
Validation *bool `yaml:"validation,omitempty" json:"validation,omitempty"`
// Mutation — include this CRD in the MutatingWebhookConfiguration.
// Default: true when mutation rules are declared.
Mutation *bool `yaml:"mutation,omitempty" json:"mutation,omitempty"`
// Operations — which operations trigger the webhook.
// Default: ["CREATE", "UPDATE"]
// Valid values: CREATE, UPDATE, DELETE, CONNECT
Operations []string `yaml:"operations,omitempty" json:"operations,omitempty"`
}
AdmissionWebhookConfig is the per-CRD admission webhook control block. Declared under spec.crds[].webhooks in the Katalog.
Example:
- name: website webhooks: validation: true # intercept at admission — ValidatingWebhookConfiguration mutation: true # intercept at admission — MutatingWebhookConfiguration
Both default to true when ENABLE_ADMISSION_WEBHOOK=true and the corresponding validation/mutation block has rules declared. Set to false to opt a specific CRD out of admission interception while keeping its reconcile-time enforcement.
func (*AdmissionWebhookConfig) EffectiveOperations ¶
func (w *AdmissionWebhookConfig) EffectiveOperations() []string
EffectiveOperations returns the operations this webhook intercepts. Defaults to CREATE and UPDATE when not specified.
func (*AdmissionWebhookConfig) WebhookMutationEnabled ¶
func (w *AdmissionWebhookConfig) WebhookMutationEnabled() bool
WebhookMutationEnabled reports whether admission-time mutation is enabled.
func (*AdmissionWebhookConfig) WebhookValidationEnabled ¶
func (w *AdmissionWebhookConfig) WebhookValidationEnabled() bool
WebhookValidationEnabled reports whether admission-time validation is enabled for this CRD. True when Validation is nil or true.
type AdmissionWebhookToggle ¶
type AdmissionWebhookToggle struct {
// Enabled controls whether ValidatingWebhookConfiguration and
// MutatingWebhookConfiguration are registered at startup.
// Default: ENABLE_ADMISSION_WEBHOOK env / false.
Enabled *bool `yaml:"enabled,omitempty"`
}
AdmissionWebhookToggle controls whether admission webhooks are globally enabled.
type AllowedNamespaces ¶
type AllowedNamespaces []string
AllowedNamespaces holds the set of allowed namespace patterns.
func (AllowedNamespaces) IsAllowed ¶
func (a AllowedNamespaces) IsAllowed(namespace string) bool
IsAllowed reports whether a given namespace matches any allowed pattern. If the list is empty, all namespaces are allowed. Supports exact matches and simple glob patterns (* prefix or suffix).
func (AllowedNamespaces) Merge ¶
func (a AllowedNamespaces) Merge(other AllowedNamespaces) AllowedNamespaces
Merge combines two AllowedNamespaces sets, deduplicating entries. Since allowances are additive, a namespace allowed at any level is allowed at all levels — more specific levels cannot remove allowances.
type AutoscaleAction ¶
type AutoscaleAction struct {
// Workers — number of concurrent reconcile goroutines.
Workers *int `yaml:"workers,omitempty"`
// QueueDepth — maximum queue depth before backpressure.
QueueDepth *int `yaml:"queueDepth,omitempty"`
// Resync — resync interval override. How frequently all CRs are
// re-enqueued regardless of changes.
Resync *Duration `yaml:"resync,omitempty"`
}
AutoscaleAction declares the override values to apply when conditions are met. All fields are optional pointers — only set fields are overridden. Unset fields retain their current value (baseline or previous override).
type AutoscaleBaseline ¶
AutoscaleBaseline captures the CRD's declared configuration before any autoscale override is applied. Always restored when conditions are false.
type AutoscaleConditions ¶
type AutoscaleConditions struct {
// AnyOf — OR semantics. At least one condition in this list must be true.
// Supports all Condition kinds: time, dayOfWeek, cron, and metric fields.
AnyOf []Condition `yaml:"anyOf,omitempty"`
// When — AND semantics. All conditions in this list must be true.
// Supports: metric conditions (metrics.*, cross.<crd>.metrics.*).
When []Condition `yaml:"when,omitempty"`
}
AutoscaleConditions holds the condition blocks for autoscale evaluation.
type AutoscaleSpec ¶
type AutoscaleSpec struct {
// Interval is how often the autoscaler evaluates conditions.
// Shorter intervals respond faster to load changes at the cost of
// more frequent evaluation overhead (negligible in practice).
// Default: 15s
Interval Duration `yaml:"interval,omitempty"`
// Cooldown is the minimum time conditions must be continuously false
// before the baseline is restored. Prevents oscillation when metrics
// fluctuate around a threshold.
// Default: 2m
Cooldown Duration `yaml:"cooldown,omitempty"`
// Conditions declares the trigger conditions. Both blocks must pass
// when both are declared (AND between blocks, OR within anyOf).
Conditions AutoscaleConditions `yaml:"conditions"`
// Do declares the override values applied when conditions are met.
// Fields omitted in Do are not changed — only declared fields are overridden.
Do AutoscaleAction `yaml:"do"`
// A profile is:
// a named preset that expands into a complete autoscale configuration
// using computed heuristics tuned for a specific behavior pattern
Profile string `yaml:"profile,omitempty"`
}
AutoscaleSpec declares the autoscale behavior for one operatorbox. Declared inside OperatorBoxConfig.
func (*AutoscaleSpec) EffectiveCooldown ¶
func (a *AutoscaleSpec) EffectiveCooldown() time.Duration
EffectiveCooldown returns the cooldown duration, applying the default of 2m when not declared.
func (*AutoscaleSpec) EffectiveInterval ¶
func (a *AutoscaleSpec) EffectiveInterval() time.Duration
EffectiveInterval returns the autoscale evaluation interval, applying the default of 15s when not declared.
func (*AutoscaleSpec) HasAnyOfConditions ¶ added in v0.1.9
func (a *AutoscaleSpec) HasAnyOfConditions() bool
HasAnyOfConditions returns whether anyOf conditions are declared.
func (*AutoscaleSpec) HasCooldownDuration ¶ added in v0.1.9
func (a *AutoscaleSpec) HasCooldownDuration() bool
HasCooldownDuration returns whether cooldown is set.
func (*AutoscaleSpec) HasDoQueueDepth ¶ added in v0.1.9
func (a *AutoscaleSpec) HasDoQueueDepth() bool
HasDoQueueDepth returns whether do.queueDepth is set.
func (*AutoscaleSpec) HasDoResync ¶ added in v0.1.9
func (a *AutoscaleSpec) HasDoResync() bool
HasDoResync returns whether do.resync is set.
func (*AutoscaleSpec) HasDoWorkers ¶ added in v0.1.9
func (a *AutoscaleSpec) HasDoWorkers() bool
HasDoWorkers returns whether do.workers is set.
func (*AutoscaleSpec) HasIntervalDuration ¶ added in v0.1.9
func (a *AutoscaleSpec) HasIntervalDuration() bool
HasIntervalDuration returns whether interval is set.
func (*AutoscaleSpec) HasWhenConditions ¶ added in v0.1.9
func (a *AutoscaleSpec) HasWhenConditions() bool
HasWhenConditions returns whether when conditions are declared.
type AutoscaleState ¶
type AutoscaleState struct {
// OverrideActive is true when an override is currently applied.
OverrideActive bool
// ConditionsFalseAt is the time when conditions last became continuously false.
// Used to enforce the cooldown period before restoring the baseline.
// Zero when conditions are currently true or have never been false.
ConditionsFalseAt time.Time
// CronWindowsOpenAt tracks when each cron-condition window opened.
// Key is the cron expression string.
// Without this, a cron fire that happens between two evaluation ticks would
// be missed — the window must stay open across ticks until duration elapses.
CronWindowsOpenAt map[string]time.Time
}
AutoscaleState tracks the runtime state of the autoscaler for one operatorbox. Not serialized — ephemeral, reset on restart.
type CRDConversion ¶
type CRDConversion struct {
// StorageVersion — the version all objects are stored as internally.
// All conversion paths route through this version.
StorageVersion string `yaml:"storageVersion"`
// Paths — one entry per (from, to) pair.
// You need at least two paths for a two-version CRD:
// - old → storage (up-conversion)
// - storage → old (down-conversion)
Paths []ConversionPath `yaml:"paths"`
// UpdateCRD — when true, Orkestra patches the CRD's
// spec.conversion.webhook.clientConfig.caBundle with the CA bundle
// from the generated (or configured) TLS certificate at startup.
// Set this to true when you let Orkestra manage TLS; set it to false
// when you manage caBundle injection yourself (e.g. cert-manager).
// Default: false.
UpdateCRD bool `yaml:"updateCRD,omitempty"`
}
CRDConversion declares declarative version conversion rules for a CRD. When enabled, Orkestra serves the /convert endpoint and translates ConversionReview requests using these rules and the template resolver.
Example Katalog declaration:
conversion:
storageVersion: v1
paths:
- from: v1alpha1
to: v1
spec:
image: "{{ .spec.image }}"
replicas: "{{ .spec.replicas }}"
seo:
enabled: false # default — v1alpha1 has no SEO field
- from: v1
to: v1alpha1
spec:
image: "{{ .spec.image }}"
replicas: "{{ .spec.replicas }}"
theme: "default" # default — v1 has no theme field
type CRDEntry ¶
type CRDEntry struct {
// Name — unique CRD identifier within the Katalog. Must be lowercase.
// Injected from the map key during loading — never set from YAML.
Name string `yaml:"-" json:"name" validate:"required,hostname_rfc1123"`
// KatalogName — unique identifier for the the katalog in the runtime
KatalogName string `yaml:"-" json:"katalogName,omitempty"`
// Enabled — include this CRD in the runtime. false = skipped entirely.
// WARNING: only set to false after stripping Orkestra finalizers from all
// live CRs — disabled CRDs with live finalizers will cause stuck objects.
Enabled *bool `yaml:"enabled,omitempty" json:"enabled,omitempty"`
// Description — human-readable description. Shown in /katalog API responses.
Description string `yaml:"description,omitempty" json:"description,omitempty" validate:"omitempty"`
// Mode — see CRDMode for full documentation.
// Auto-detected when omitted based on whether apiTypes.location is set.
Mode CRDMode `yaml:"mode,omitempty" json:"mode,omitempty" validate:"omitempty,oneof=typed dynamic"`
// ── API Types ─────────────────────────────────────────────────────────────
// See APITypes for full field documentation.
APITypes APITypes `yaml:"apiTypes" json:"apiTypes" validate:"required"`
// ── Runtime objects ───────────────────────────────────────────────────────
// Set by addRuntimeObjects() during Katalog validation. Never set from YAML.
//
// Typed mode: DynamicModeObject and ListDynamicModeObject are factory functions
// from ObjectRegistry and ListRegistry respectively.
// TypedModeObject and ListTypedModeObject are set in BuildKatalogFromGo().
//
// Dynamic mode: DynamicModeObject and ListDynamicModeObject are factory functions
// that return *unstructured.Unstructured and *unstructured.UnstructuredList.
// These are always set by addRuntimeObjects() — never nil after validation.
TypedModeObject runtime.Object `yaml:"-" json:"-"`
ListTypedModeObject runtime.Object `yaml:"-" json:"-"`
DynamicModeObject func() runtime.Object `yaml:"-" json:"-"`
ListDynamicModeObject func() runtime.Object `yaml:"-" json:"-"`
// Scheme — AddToScheme function generated by controller-gen for this API type.
// Required for typed mode so the REST client can decode API server responses.
// Not needed for dynamic mode — the dynamic client bypasses scheme decoding.
// Set in BuildKatalogFromGo() for Go mode. Handled by RegisterScheme() for YAML mode.
Scheme func(s *runtime.Scheme) error `yaml:"-" json:"-"`
// ── Computed GVK/GVR ─────────────────────────────────────────────────────
// Set by setGroupVersionKind() during Katalog validation.
// Derived from APITypes fields. Never set manually.
GroupVersion *schema.GroupVersion `yaml:"-" json:"-"`
GroupVersionKind schema.GroupVersionKind `yaml:"-" json:"-"`
GroupVersionResource schema.GroupVersionResource `yaml:"-" json:"-"`
// Namespaced — true if this CRD is namespace-scoped, false if cluster-scoped.
// Default is true
Namespaced *bool `yaml:"namespaced,omitempty" json:"namespaced,omitempty"`
// Namespace — target namespace for namespace-scoped CRDs.
// Informer watches this namespace only. Empty = all namespaces.
Namespace string `yaml:"namespace,omitempty" json:"namespace,omitempty" validate:"omitempty"`
// Workers — number of concurrent reconcile workers for this CRD.
// Higher values increase throughput but also increase API server load.
// 0 → uses Orkestra-level default (DEFAULT_WORKERS env var).
Workers int `yaml:"workers,omitempty" json:"workers,omitempty" validate:"omitempty,gte=1,lte=50"`
// WorkersActive — records number of active concurrent reconcile workers for this CRD.
WorkersActive int `yaml:"workersActive,omitempty" json:"workersActive,omitempty" validate:"omitempty,gte=1,lte=50"`
// Resync — full re-list interval for the informer cache.
// Triggers a reconcile for every cached object at this interval.
// 0 → uses Orkestra-level default (DEFAULT_RESYNC env var).
Resync time.Duration `yaml:"resync,omitempty" json:"resync,omitempty" validate:"omitempty"`
// DependsOn — names of other CRDs that must reach a condition before this one starts.
// Orkestra resolves the dependency graph and starts CRDs in topological order.
// Cycle detection runs at validation time — cycles fail fast with a clear error.
// Supports three YAML formats (list, key-value, full map) — see DependsOnMap.
DependsOn DependsOnMap `yaml:"dependsOn,omitempty" json:"dependsOn,omitempty"`
// ── OperatorBox ────────────────────────────────────────────────────
OperatorBox OperatorBoxConfig `yaml:"operatorBox,omitempty" json:"operatorBox,omitempty"`
// ── Queue ────────────────────────────────────────────────────
Queue Queue `yaml:"queue,omitempty" json:"queue,omitempty"`
// Labels []ResourceLabel `yaml:"labels,omitempty" json:"labels,omitempty" validate:"omitempty"`
// LabelSelector filters which resources this CRD entry reconciles.
// Only resources whose labels match ALL declared key-value pairs are watched.
// Required for built-in types (ConfigMap, Pod, etc.) — without a selector,
// Orkestra would reconcile every instance in the cluster.
// For custom CRDs this is optional — can narrow scope within a CRD.
LabelSelector SelectorMap `yaml:"labelSelector,omitempty"`
// FieldSelector filters which resources this CRD entry reconciles.
// Only resources whose *fields* match ALL declared key-value expressions
// are listed or watched. Field selectors operate on the server side and
// support exact-match comparisons on well-known metadata paths
// (e.g. "metadata.name", "metadata.namespace").
//
// Unlike label selectors, field selectors cannot match arbitrary user-defined
// keys — only fields exposed by the Kubernetes API server. They are evaluated
// before any client-side filtering, reducing load on the informer pipeline.
//
// Common use cases:
// - Restricting reconciliation to a specific namespace:
// {key: "metadata.namespace", value: "default"}
// - Targeting a single object by name:
// {key: "metadata.name", value: "my-config"}
//
// Field selectors are optional for all types. When omitted, Orkestra will
// watch all objects permitted by LabelSelector and namespace restrictions.
FieldSelector SelectorMap `yaml:"fieldSelector,omitempty"`
// IsBuiltIn is set to true when this CRD entry was enriched from the
// built-in Kubernetes resource registry. Used for ork validate output
// and informational logging only — does not affect runtime behavior.
IsBuiltIn bool `yaml:"-" json:"-"` // never serialized — runtime state only
// IgnoreStatusPatch reports whether or not to patch the status of this CRD
IgnoreStatusPatch bool `yaml:"ignoreStatusPatch,omitempty" json:"ignoreStatusPatch,omitempty"`
// IgnoreObservedGeneration reports whether or not to ignore the observedGeneration field for this CRD.
IgnoreObservedGeneration bool `yaml:"ignoreObservedGeneration,omitempty" json:"ignoreObservedGeneration,omitempty"`
// IsStatusless reports whether this CRD has no meaningful readiness semantics.
// These resources become "Ready" immediately upon creation.
IsStatusless bool `yaml:"-" json:"IsStatusless,omitempty"`
// BuiltInGroup is the display name of the API group for built-in resources.
// "core" for resources in the core group (empty string group).
// Only set when IsBuiltIn is true.
BuiltInGroup string `yaml:"-" json:"-"` // never serialized
// EnrichmentOutcome records the result of the API type enrichment phase.
// During validation, built‑in Kubernetes kinds (e.g., Pod, Deployment, Secret)
// are automatically enriched with their full API metadata — group, version,
// plural, API path, and namespaced scope. This allows users to specify only:
//
// apiTypes:
// kind: Pod
//
// and rely on Orkestra to resolve all remaining fields based on the
// Kubernetes discovery API. Custom resources are enriched using their declared
// group/version/kind. This field is never serialized and is used internally to
// report enrichment status and drive downstream runtime behavior.
EnrichmentOutcome EnrichmentOutcome `yaml:"-" json:"-"` // never serialized
// Endpoints defines which operator HTTP endpoints are enabled for this CRD.
Endpoints EndpointsConfig `yaml:"endpoints,omitempty" json:"endpoints,omitempty"`
// Restricted Namespaces
RestrictedNamespaces RestrictedNamespaces `yaml:"restrictedNamespaces,omitempty" json:"restrictedNamespaces,omitempty"`
// Allowed Namespaces
AllowedNamespaces AllowedNamespaces `yaml:"allowedNamespaces,omitempty" json:"allowedNamespaces,omitempty"`
// Conversion is useful for handling multi-version crd
Conversion *CRDConversion `yaml:"conversion,omitempty" json:"conversion,omitempty"`
// Validation is a list of rules
Validation *ValidationConfig `yaml:"validation,omitempty" json:"validation,omitempty"`
// Mutation is a list of rules
Mutation *MutationConfig `yaml:"mutation,omitempty" json:"mutation,omitempty"`
// Webhooks controls per-CRD admission webhook behaviour.
// Only meaningful when ENABLE_ADMISSION_WEBHOOK=true.
// By default, any CRD with Validation or Mutation rules is included
// in the corresponding webhook configuration automatically.
// Set validation: false or mutation: false to opt a specific CRD out of
// admission-time interception while keeping its reconcile-time enforcement.
Webhooks AdmissionWebhookConfig `yaml:"webhooks,omitempty" json:"webhooks,omitempty"`
// Normalize Spec fields before rendering
Normalize *NormalizeConfig `yaml:"normalize,omitempty"`
// NotificationEnabled returns whether this CRD belongs to katalog with notification access
NotificationEnabled *bool `yaml:"-" json:"-"`
// RemoveFinalizers -> testing
RemoveFinalizers bool `yaml:"removeFinalizers,omitempty" json:"removeFinalizers,omitempty"`
}
func (*CRDEntry) AllAllowedNamespaces ¶ added in v0.1.9
func (c *CRDEntry) AllAllowedNamespaces() AllowedNamespaces
AllAllowedNamespaces returns a list of allowed namespaces for this crd
func (*CRDEntry) AllRestrictedNamespaces ¶ added in v0.1.9
func (c *CRDEntry) AllRestrictedNamespaces() RestrictedNamespaces
AllRestrictedNamespaces returns a list of restricted namespaces for this crd
func (*CRDEntry) AllowedNamespacesOnly ¶ added in v0.1.9
AllowedNamespacesOnly reports if only allowedNamespaces is defined for this crd.
func (*CRDEntry) AutoScaleProfile ¶
AutoScaleProfile returns the string value of the autoscale profile
func (*CRDEntry) AutoscaleEnabled ¶
AutoscaleEnabled reports whether this CRD declares the autoscale block
func (CRDEntry) Config ¶
func (e CRDEntry) Config() OperatorBoxConfig
Config returns the OperatorBox configuration for this CRD. Safe to call when OperatorBox is the zero value.
func (*CRDEntry) ConstructorEnabled ¶ added in v0.2.0
ConstructorEnabled reports whether the reconcile behaviour uses a constructor. Defaults to false when omitted.
func (*CRDEntry) CustomHooksEnabled ¶ added in v0.2.0
CustomHooksEnabled reports whether the reconcile behaviour uses custom hooks. Defaults to false when omitted.
func (*CRDEntry) DefaultQueue ¶
DefaultQueue reports whether this CRD uses the default queue configuration. Defaults to false when omitted.
func (*CRDEntry) DefaultReconcile ¶
DefaultReconcile reports whether this CRD uses the default reconciler behavior. Defaults to true unless explicitly enabled.
func (*CRDEntry) GVK ¶
func (c *CRDEntry) GVK() schema.GroupVersionKind
GVK returns the fully resolved GroupVersionKind for this CRD. Used for logging, routing, and dynamic client operations.
func (*CRDEntry) GVKString ¶
GVKString returns the fully resolved GroupVersionKind for this CRD as a string.
func (*CRDEntry) GVR ¶
func (c *CRDEntry) GVR() schema.GroupVersionResource
GVR returns the fully resolved GroupVersionResource for this CRD. Used for dynamic client list/watch operations.
func (*CRDEntry) GVRString ¶
GVRString returns the fully resolved GroupVersionResource for this CRD as a string.
func (*CRDEntry) GetDependencies ¶
GetDependencies returns the dependency names for this CRD in sorted order.
func (*CRDEntry) GetRuntimeObjects ¶
GetRuntimeObjects returns the object and list constructors appropriate for the current mode (dynamic or typed). Used by the reconciler to instantiate new runtime objects for watches, lists, and reconciliation.
func (*CRDEntry) HasAllowedNamespaces ¶ added in v0.1.9
HasAllowedNamespaces reports if allowedNamespaces is defined for this crd.
func (*CRDEntry) HasAnyHPA ¶ added in v0.2.3
HasAnyHPA reports whether this CRD defines any HPA defined in either OnCreate or OnReconcile phases.
func (*CRDEntry) HasAnyHooks ¶ added in v0.1.9
HasAnyHooks reports whether this CRD declares any onCreate, onReconcile, or onDelete hooks.
func (*CRDEntry) HasAnySecrets ¶ added in v0.2.3
HasAnySecrets reports whether this CRD defines any secrets in either OnCreate or OnReconcile phases.
func (*CRDEntry) HasAnyTLSSecrets ¶ added in v0.2.3
HasAnyTLSSecrets reports whether any secret in either phase defines a TLS configuration.
func (*CRDEntry) HasAutoscaleProfile ¶
HasAutoscaleProfile reports whether this crd defined autoscale profile
func (*CRDEntry) HasMutationRules ¶
Separate helpers for hasMutationRules and hasValidationRules
func (*CRDEntry) HasNamespaceRules ¶ added in v0.1.9
HasNamespaceRules reports whether this CRD declares any namespace rules.
func (*CRDEntry) HasOnCreate ¶ added in v0.1.9
HasOnCreate reports whether this CRD declares any onCreate hooks.
func (*CRDEntry) HasOnDelete ¶ added in v0.1.9
HasOnDelete reports whether this CRD declares any onDelete hooks.
func (*CRDEntry) HasOnReconcile ¶ added in v0.1.9
HasOnReconcile reports whether this CRD declares any onReconcile hooks.
func (*CRDEntry) HasProviders ¶
HasProviders reports whether this CRD declares any provider blocks.
func (*CRDEntry) HasRestrictedNamespaces ¶ added in v0.1.9
HasRestrictedNamespaces reports if restrictedNamespaces is defined for this crd.
func (*CRDEntry) HasRollbackRules ¶ added in v0.1.9
HasRollbackRules reports whether this CRD declares a rollback block.
func (*CRDEntry) HasTemplates ¶
HasTemplates reports whether this CRD declares any declarative hook templates. Used by `ork generate` to determine whether to emit generated runtime hooks.
func (*CRDEntry) HasValidationOrMutationRules ¶
Returns true when either validation or mutation rules are declared. Used to decide whether to create the endpoints and/or populate the admission block in the health response. Even when ENABLE_ADMISSION_WEBHOOK=true
func (*CRDEntry) HasValidationRules ¶
func (*CRDEntry) IsBuiltInType ¶
IsBuiltInType reports whether this CRD represents a built‑in Kubernetes resource. Built‑ins rely on enrichment to populate group, version, plural, and scope.
func (*CRDEntry) IsDynamic ¶
IsDynamic determines whether this CRD should operate in dynamic mode. Resolution order (first match wins):
- mode: dynamic explicitly declared → true
- mode: typed explicitly declared → false
- APITypes.Location is empty → true (no compiled types available)
- APITypes.Location is set → false (compiled types available)
func (*CRDEntry) IsEnabled ¶
IsEnabled reports whether this CRD is enabled. Defaults to true when omitted.
func (*CRDEntry) IsEnabledAllEndpoints ¶
IsEnabledAllEndpoints reports whether the all endpoints are disabled for this CRD. Defaults to false when omitted.
func (*CRDEntry) IsHealthEnabled ¶
IsHealthEnabled reports whether the /health endpoint is enabled for this CRD. Defaults to true when omitted.
func (*CRDEntry) IsInfoEnabled ¶
IsInfoEnabled reports whether the /info endpoint is enabled for this CRD. Defaults to true when omitted.
func (*CRDEntry) IsNamespaced ¶
IsNamespaced reports whether this CRD is namespaced. Defaults to true unless explicitly overridden or determined by enrichment.
func (*CRDEntry) IsNotificationEnabled ¶
NotificationEnabled reports whether this CRD declares the notification block Enabled by default
func (*CRDEntry) IsStatuslessType ¶
IsStatusless reports whether this CRD has no meaningful readiness semantics. These resources become "Ready" immediately upon creation.
func (*CRDEntry) RestrictedNamespacesOnly ¶ added in v0.1.9
RestrictedNamespacesOnly reports if only restrictedNamespaces is defined for this crd.
func (*CRDEntry) SetMaxQueueDepth ¶
SetMaxQueueDepth resolves the queue depth for this CRD. If a per‑CRD value is provided, it is used; otherwise the Orkestra/Konduktor‑level default is applied.
func (*CRDEntry) SetWorkers ¶
SetWorkers resolves the worker count for this CRD. If a per‑CRD value is provided, it is used; otherwise the global default worker count is applied.
func (*CRDEntry) SkipObservedGeneration ¶
SkipObservedGeneration reports whether this CRD belongs to a list to be ignored during status patches. This is applied mainly to builtins or if specifically required by the crd through crd.IgnoreStatusPatch
func (*CRDEntry) SkipStatusSubresource ¶
SkipStatusSubresource reports whether this CRD belongs to a list to be ignored during status patches. This is applied mainly to builtins or if specifically required by the crd through crd.IgnoreStatusPatch
func (*CRDEntry) UpdateCRDCaBundle ¶ added in v0.1.8
UpdateCRDCaBundle reports whether this CRD declares an updateCRD field Used to update the crd when certificate is autogenerted by orkestra
func (*CRDEntry) ValidateMetricField ¶
ValidateMetricField returns an error if the field is not a known autoscale metric.
type CRDMode ¶
type CRDMode string
CRDMode controls how the GenericReconciler handles CR objects at runtime.
typed
Requires compiled API types via apiTypes.location. Objects are decoded into concrete Go structs by the REST client. Full type safety and generated DeepCopy methods. Required when Go hooks reference typed fields directly. Use when you have generated API types and want compile-time guarantees.
dynamic
No compiled types needed. Objects are map[string]interface{} at runtime.
Works with any CRD without code generation or controller-gen.
Required for declarative hook templates (onCreate, onReconcile, onDelete)
because field values are resolved at reconcile time via Go text/template
expressions against the live CR object map.
Use when you want zero-code operator behavior from the Katalog alone.
Auto-detection when mode is omitted:
apiTypes.location is set → typed (compiled types available) apiTypes.location is empty → dynamic (no compiled types)
Override auto-detection by setting mode explicitly:
crd: - name: websites mode: dynamic # force dynamic even if location is set mode: typed # force typed even if location is empty
type Condition ¶
type Condition struct {
// Field — dot-notation path to a field in the CR object or a runtime metric.
// e.g. "spec.environment", "metrics.queueDepth", "cross.managed-database.metrics.queueDepth"
Field string `yaml:"field" validate:"required"`
// Operator — how to compare the field value.
// See ConditionOperator constants below.
Operator ConditionOperator `yaml:"operator,omitempty"`
// Value — the value to compare against.
// Not used for exists/notExists operators.
// Supports template expressions: "{{ .metadata.name }}-prod"
Value string `yaml:"value,omitempty"`
// Equals is a shorthand for operator: equals.
Equals string `yaml:"equals,omitempty"`
// NotEquals is a shorthand for operator: notEquals.
NotEquals string `yaml:"notEquals,omitempty"`
// Contains is a shorthand for operator: contains.
Contains string `yaml:"contains,omitempty"`
// Prefix is a shorthand for operator: prefix.
Prefix string `yaml:"prefix,omitempty"`
// Suffix is a shorthand for operator: suffix.
Suffix string `yaml:"suffix,omitempty"`
// Numeric shorthands
GreaterThan string `yaml:"greaterThan,omitempty"`
LessThan string `yaml:"lessThan,omitempty"`
// Time — active when the current time is within the declared window.
// After and Before are both optional; omit one for a half-open range.
// anyOf:
// - time:
// after: "08:00"
// before: "20:00"
Time *TimeWindow `yaml:"time,omitempty"`
// DayOfWeek — active on the specified days of the week.
// anyOf:
// - dayOfWeek:
// in: [Monday, Tuesday, Wednesday, Thursday, Friday]
DayOfWeek *DayOfWeekCondition `yaml:"dayOfWeek,omitempty"`
// Cron — a standard cron expression (5-field) that defines when the
// window opens. Duration defines how long the window stays open.
// Without Duration, the window closes after one evaluation interval.
Cron string `yaml:"cron,omitempty"`
// Duration — how long a cron-opened window remains active.
Duration Duration `yaml:"duration,omitempty"`
// Notify declares teams to alert when this condition is true.
Notify *NotifyBlock `yaml:"notify,omitempty"`
// Source is the HTTP fallback for cross-binary metric observation.
// Only used when field is a cross.<crd>.metrics.* field and the CRD
// is not registered in GlobalCrossMetricsRegistry (different binary).
// The endpoint must be the remote operator's /katalog/{crd} URL.
//
// when:
// - field: cross.managed-database.metrics.queueDepth
// greaterThan: "500"
// source:
// endpoint: "http://database-operator:8080/katalog/managed-database"
Source *CrossSource `yaml:"source,omitempty"`
}
Condition declares a single condition to evaluate against the CR or runtime state. Fields reference CR paths using dot notation: spec.environment, metadata.name.
The same type is used in:
- when: / anyOf: on template sources (resource conditions)
- operatorBox.autoscale.conditions.anyOf and when: (autoscale conditions)
- operatorBox.rollback.trigger (rollback conditions)
- notification condition blocks
type ConditionOperator ¶
type ConditionOperator string
ConditionOperator defines how a condition's field is compared to its value.
const ( // ConditionEquals — field value exactly equals the condition value (string comparison) ConditionEquals ConditionOperator = "equals" // ConditionNotEquals — field value does not equal the condition value ConditionNotEquals ConditionOperator = "notEquals" // ConditionContains — field value contains the condition value as a substring ConditionContains ConditionOperator = "contains" // ConditionPrefix — field value starts with the condition value ConditionPrefix ConditionOperator = "prefix" // ConditionSuffix — field value ends with the condition value ConditionSuffix ConditionOperator = "suffix" // ConditionExists — the field is present and non-empty // Value is ignored for this operator. ConditionExists ConditionOperator = "exists" // ConditionNotExists — the field is absent or empty // Value is ignored for this operator. // Use for: first-reconcile detection (phase not yet written). // when: // - field: status.phase // operator: notExists ConditionNotExists ConditionOperator = "notExists" // ConditionGt — field value is numerically greater than condition value ConditionGt ConditionOperator = "gt" // ConditionLt — field value is numerically less than condition value ConditionLt ConditionOperator = "lt" // ConditionIn — field value is one of a comma-separated list. // Empty string matches an empty field (for first-reconcile detection). // when: // - field: status.phase // operator: in // value: ",Pending" # empty or "Pending" ConditionIn ConditionOperator = "in" // ConditionUnique — field value is unique across all existing CR instances. // // Only valid in validation rules (deny action). Checks the informer cache // for any existing CR with the same field value. // // validation: // rules: // - field: spec.domain // operator: unique // message: "spec.domain must be unique across all instances" // action: deny // // Not valid in when: blocks on template sources — uniqueness requires // informer access which is not available during template evaluation. // In when: context it is treated as always-true (see pkg/types/when/EvaluateOneCond). ConditionUnique ConditionOperator = "unique" // ConditionTypeOf — check field type // ConditionTypeOf ConditionOperator = "typeOf" // ConditionTypeMap — field value is a map (YAML object) ConditionTypeMap ConditionOperator = "typeMap" // ConditionTypeList — field value is a slice (YAML array) ConditionTypeList ConditionOperator = "typeList" // ConditionTypeString — field value is a string ConditionTypeString ConditionOperator = "typeString" // ConditionTypeNumber — field value is a number (int/float) ConditionTypeNumber ConditionOperator = "typeNumber" // ConditionTypeBool — field value is a boolean ConditionTypeBool ConditionOperator = "typeBool" // ConditionTypeNull — field value is null or missing ConditionTypeNull ConditionOperator = "typeNull" )
func ResolveConditionOp ¶
func ResolveConditionOp(c Condition) (ConditionOperator, string)
ResolveConditionOp resolves the effective operator and comparison value from a Condition, respecting shorthand fields. Exported so the template package can use the same resolution logic.
type ConfigMapKeyRef ¶
type ConfigMapKeyRef struct {
Name string `yaml:"name" json:"name"`
Key string `yaml:"key" json:"key"`
}
ConfigMapKeyRef selects a key from a Kubernetes ConfigMap. Both Name and Key are required.
type ConfigMapTemplateSource ¶
type ConfigMapTemplateSource struct {
// Version — OrkestraRegistry implementation version. Omit for latest.
Version string `yaml:"version" json:"version,omitempty" validate:"omitempty"`
// Name — ConfigMap name.
// Default when omitted: "{{ .metadata.name }}-config"
Name string `yaml:"name" json:"name,omitempty" validate:"omitempty"`
// Namespace — target namespace.
// Default when omitted: "{{ .metadata.namespace }}"
Namespace string `yaml:"namespace" json:"namespace,omitempty" validate:"omitempty"`
// ToNamespaces - a list of target namespaces
// Default when omitted: "{{ .metadata.namespace }}"
ToNamespaces []string `yaml:"toNamespaces" json:"toNamespaces,omitempty" validate:"omitempty"`
// Data — static key-value configuration entries.
// Values are plain strings — template expressions are not supported here.
Data map[string]string `yaml:"data" json:"data,omitempty" validate:"omitempty"`
// Labels — applied to ConfigMap metadata. Values support template expressions.
Labels []ResourceLabel `yaml:"labels" json:"labels,omitempty" validate:"omitempty"`
// FromConfigMap — name of an existing ConfigMap to copy data from.
// Orkestra reads this at reconcile time — copies stay in sync with the source.
FromConfigMap string `yaml:"fromConfigMap" json:"fromConfigMap,omitempty" validate:"omitempty"`
// FromNamespace — namespace where FromConfigMap lives.
// Default: same namespace as the CR.
FromNamespace string `yaml:"fromNamespace" json:"fromNamespace,omitempty" validate:"omitempty"`
// Reconcile: true — also apply this declaration as drift correction on every
// reconcile. Equivalent to declaring the same entry under both onCreate and
// onReconcile. When false (default), only runs on onCreate (idempotent create).
Reconcile bool `yaml:"reconcile" json:"reconcile,omitempty" validate:"omitempty"`
Conditions []Condition `yaml:"when,omitempty" json:"when,omitempty"`
// ForEach declares dynamic expansion over a list field.
// When set, one source declaration becomes N declarations — one per list element.
// .item and .<as> are available in template expressions within this declaration.
ForEach *ForEachSpec `yaml:"forEach,omitempty" json:"forEach,omitempty"`
// AnyOf holds OR conditions — at least one must pass for this resource to be created.
// Works alongside the existing Conditions (when:) field which uses AND semantics.
AnyOf []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`
}
ConfigMapTemplateSource declares one ConfigMap to be managed by Orkestra.
ConfigMap data values are static — template expressions are not evaluated in ConfigMap data entries. For dynamic configuration, use a custom Go hook.
Example:
onCreate:
configMaps:
- name: "{{ .metadata.name }}-config"
data:
LOG_LEVEL: info
MAX_CONNECTIONS: "100"
type ConstructorDeclaration ¶
type ConstructorDeclaration struct {
// Location — fully qualified Go import path. Local or remote module.
Location string `yaml:"location" json:"location" validate:"required"`
// Function — exported constructor function name at Location.
// e.g. "NewManagedNamespaceReconciler"
Function string `yaml:"function" json:"function" validate:"required"`
// Alias — Go import alias. Optional, auto-derived from Location if omitted.
Alias string `yaml:"alias" json:"alias,omitempty" validate:"omitempty"`
}
ConstructorDeclaration declares where a custom reconciler constructor lives. Read by ork generate to emit ReconcilerRegistry entries. The declared function must match: NewReconcilerFunc
type ConversionConfig ¶
type ConversionConfig struct {
// Enabled controls whether the /convert endpoint is registered and the
// CRD conversion webhook is active.
// Default: ENABLE_CONVERSION env / false.
Enabled *bool `yaml:"enabled,omitempty"`
// ConversionWindow is the rolling window size for latency/throughput stats.
// Default: CONVERSION_WINDOW env / 100.
ConversionWindow int `yaml:"conversionWindow,omitempty"`
}
ConversionConfig controls the /convert endpoint and CRD version conversion.
type ConversionPath ¶
type ConversionPath struct {
// From — the source version (bare, e.g. "v1alpha1")
From string `yaml:"from" validate:"required"`
// To — the target version (bare, e.g. "v1")
To string `yaml:"to" validate:"required"`
// Spec — the output spec in the target version's format.
// Values support Go template expressions evaluated against the source object.
// Static values are used as-is.
Spec map[string]interface{} `yaml:"spec" validate:"required"`
}
ConversionPath declares one explicit conversion mapping. Both From and To are bare version strings — not full apiVersion strings.
from: v1alpha1 ← bare version, not "demo.orkestra.io/v1alpha1"
to: v1
spec:
image: "{{ .spec.image }}"
seo:
enabled: false
type ConversionRules ¶
type ConversionRules struct {
Kind string `json:"kind"`
StorageVersion string `json:"storageVersion"`
Paths []ConversionPath `json:"paths"`
}
ConversionRules is the runtime form of CRDConversion, keyed by Kind. Registered in the InMemoryConversionRegistry at Katalog load time.
func (*ConversionRules) FindPath ¶
func (r *ConversionRules) FindPath(fromVersion, toVersion string) *ConversionPath
FindPath returns the conversion path for a given (from, to) pair. Both fromVersion and toVersion must be bare version strings. Returns nil when no path matches.
type ConversionVersionSpec ¶
type CronJobTemplateSource ¶
type CronJobTemplateSource struct {
// Version — OrkestraRegistry implementation version. Omit for latest.
Version string `yaml:"version" json:"version,omitempty" validate:"omitempty"`
// Name — CronJob name.
// Default when omitted: "{{ .metadata.name }}-cronjob"
Name string `yaml:"name" json:"name,omitempty" validate:"omitempty"`
// Schedule — cron schedule expression. Required.
// Static: "0 * * * *" (every hour)
// Dynamic: "{{ .spec.schedule }}"
Schedule string `yaml:"schedule" json:"schedule" validate:"required"`
// Image — container image. Required.
Image string `yaml:"image" json:"image" validate:"omitempty"`
// Command — container entrypoint. Each element supports template expressions.
Command []string `yaml:"command" json:"command,omitempty" validate:"omitempty"`
// Args — container arguments. Each element supports template expressions.
Args []string `yaml:"args" json:"args,omitempty" validate:"omitempty"`
// Namespace — target namespace.
// Default when omitted: "{{ .metadata.namespace }}"
Namespace string `yaml:"namespace" json:"namespace,omitempty" validate:"omitempty"`
// Labels — applied to CronJob metadata. Values support template expressions.
Labels []ResourceLabel `yaml:"labels" json:"labels,omitempty" validate:"omitempty"`
// Reconcile: true — also apply this declaration as drift correction on every
// reconcile. Equivalent to declaring the same entry under both onCreate and
// onReconcile. When false (default), only runs on onCreate (idempotent create).
Reconcile bool `yaml:"reconcile" json:"reconcile,omitempty" validate:"omitempty"`
Conditions []Condition `yaml:"when,omitempty" json:"when,omitempty"`
Suspend string `yaml:"suspend,omitempty" json:"suspend,omitempty"`
SuccessfulJobsHistoryLimit string `yaml:"successfulJobsHistoryLimit,omitempty" json:"successfulJobsHistoryLimit,omitempty"`
FailedJobsHistoryLimit string `yaml:"failedJobsHistoryLimit,omitempty" json:"failedJobsHistoryLimit,omitempty"`
ConcurrencyPolicy string `yaml:"concurrencyPolicy,omitempty" json:"concurrencyPolicy,omitempty"`
StartingDeadlineSeconds string `yaml:"startingDeadlineSeconds,omitempty" json:"startingDeadlineSeconds,omitempty"`
// ForEach declares dynamic expansion over a list field.
// When set, one source declaration becomes N declarations — one per list element.
// .item and .<as> are available in template expressions within this declaration.
ForEach *ForEachSpec `yaml:"forEach,omitempty" json:"forEach,omitempty"`
// AnyOf holds OR conditions — at least one must pass for this resource to be created.
// Works alongside the existing Conditions (when:) field which uses AND semantics.
AnyOf []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`
// WorkingDirectory sets the container's working directory (container.WorkingDir).
// Useful for Git-backed pipelines where build/test commands must run inside
// a checked-out repository path.
WorkingDirectory string `yaml:"workingDirectory,omitempty" json:"workingDirectory,omitempty"`
}
CronJobTemplateSource declares one CronJob to be managed by Orkestra.
Example:
onCreate:
cronJobs:
- name: "{{ .metadata.name }}-sync"
schedule: "{{ .spec.syncSchedule }}"
image: "{{ .spec.syncImage }}"
command: ["sh", "-c", "sync.sh"]
type CrossCRDDeclaration ¶
type CrossCRDDeclaration struct {
// Crd is the target CRD name (lowercase, matches the map key in spec.crds).
// crd: database
Crd string `yaml:"crd"`
// LabelSelector is a label key/value pair for label-based informer lookup.
// Mutually exclusive with Kind.
LabelSelector map[string]string `yaml:"labelSelector,omitempty"`
// Selector identifies which CR instance to observe.
Selector CrossSelector `yaml:"selector"`
// As is the key under .cross.* where the result is accessible.
// as: database → .cross.database.status.phase
// Default: same as Crd.
As string `yaml:"as,omitempty"`
// Strategy controls what happens when multiple CRs match the selector.
// first (default) — use the first match
// all — put all matches in .cross.<as>[] (array)
Strategy string `yaml:"strategy,omitempty"`
// Source is the fallback for cross-binary or cross-cluster observation.
// When absent, the informer cache is used (zero API calls).
// When set, the endpoint is called when the informer is unavailable.
Source *CrossSource `yaml:"source,omitempty"`
}
CrossCRDDeclaration declares one cross-CRD observation. Declared in the operatorBox config under cross: for a CRD.
type CrossSelector ¶
type CrossSelector struct {
// Name is the CR name to look up. Template expressions supported.
// name: "{{ .metadata.name }}" → same name as the current CR
Name string `yaml:"name,omitempty"`
// Namespace is the CR namespace. Template expressions supported.
// Default: same namespace as the current CR.
Namespace string `yaml:"namespace,omitempty"`
// LabelSelector selects CRs by label — for 1:N or N:1 relationships.
// labelSelector: "tenant={{ .spec.tenant }},env={{ .spec.environment }}"
// When set, Name and Namespace are ignored.
LabelSelector string `yaml:"labelSelector,omitempty"`
}
CrossSelector identifies a CR in the target CRD. The selector block on a cross: declaration. Exactly one of Name or LabelSelector should be set per entry.
type CrossSource ¶
type CrossSource struct {
// Endpoint is the URL to call when the informer is unavailable.
// Template expressions supported.
// endpoint: "http://database-operator:8080/katalog/database/cr/{{ .metadata.namespace }}/{{ .metadata.name }}"
Endpoint string `yaml:"endpoint"`
// Token is a bearer token for the endpoint. $ENV_VAR syntax supported.
Token string `yaml:"token,omitempty"`
// CacheFor is how long to cache the result before calling again.
// Default: 30s — prevents hammering the endpoint on every resync.
CacheFor string `yaml:"cacheFor,omitempty"`
}
CrossSource declares an HTTP fallback for cross-binary/cluster observation. The endpoint must return the same JSON shape as the informer cache path — i.e., the Orkestra CR detail endpoint format.
type DayOfWeekCondition ¶
type DayOfWeekCondition struct {
// In — active on these days. Full English names: Monday, Tuesday, etc.
In []string `yaml:"in,omitempty"`
// NotIn — active on all days except these.
NotIn []string `yaml:"notIn,omitempty"`
}
DayOfWeekCondition declares which days the condition is active.
type DeleteRequest ¶
type DeleteRequest struct {
Object map[string]interface{}
Declarations []ProviderDeclaration
Kube KubeReader
Logger zerolog.Logger
OwnerName string
OwnerNamespace string
}
DeleteRequest carries everything a provider needs for cleanup. Identical shape to ReconcileRequest — separate type for clarity at call sites.
type DeletionProtectionConfig ¶
type DeletionProtectionConfig struct {
// Enabled controls whether deletion protection is active.
// Default: true when the deletionProtection block is declared.
Enabled *bool `yaml:"enabled,omitempty"`
// ServiceName is the Kubernetes Service fronting Orkestra's HTTPS server.
// The API server sends webhook requests to this Service.
// Default: ORKESTRA_SERVICE_NAME env / "orkestra".
ServiceName string `yaml:"serviceName,omitempty"`
// FailurePolicy controls what the API server does when Orkestra is unreachable.
// "Fail" — reject the DELETE (recommended for protection; this is the default).
// "Ignore" — allow the DELETE through when Orkestra cannot be reached.
// Default: "Fail".
FailurePolicy string `yaml:"failurePolicy,omitempty"`
// CleanupOnShutdown controls whether Deletion protection webhook is deleted on graceful shutdown.
// Default: false — Deletion protection webhook persists across restarts.
CleanupOnShutdown bool `yaml:"cleanupOnShutdown,omitempty"`
}
DeletionProtectionConfig controls deletion protection behaviour.
type DependencyCondtion ¶
type DependencyCondtion string
type DependsOnCondition ¶
type DependsOnCondition struct {
Condition string `yaml:"condition" json:"condition"`
}
DependsOnCondition is the value in the dependsOn map. Condition values: "started" (workers running) or "healthy" (running + consecutive failures = 0).
func (*DependsOnCondition) UnmarshalYAML ¶
func (d *DependsOnCondition) UnmarshalYAML(value *yaml.Node) error
UnmarshalYAML handles Format 2 (scalar) and Format 3 (map) for a single dependency value.
database: healthy ← Format 2: scalar database: ← Format 3: map condition: healthy
type DependsOnMap ¶
type DependsOnMap map[string]DependsOnCondition
DependsOnMap is the internal representation of all dependsOn formats. All three YAML formats unmarshal into this type.
func (DependsOnMap) ConditionHealthy ¶
func (m DependsOnMap) ConditionHealthy(name string) bool
ConditionHealthy returns true if the dependency condition is healthy
func (DependsOnMap) ConditionStarted ¶
func (m DependsOnMap) ConditionStarted(name string) bool
ConditionStarted returns true if the dependency condition is started
func (DependsOnMap) Names ¶
func (m DependsOnMap) Names() []string
Names returns the dependency names in sorted order.
func (*DependsOnMap) UnmarshalYAML ¶
func (m *DependsOnMap) UnmarshalYAML(value *yaml.Node) error
UnmarshalYAML handles all three dependsOn formats:
Format 1 — list (condition defaults to "started"):
dependsOn:
- database
Format 2 — key-value map (condition explicit):
dependsOn:
database: healthy
Format 3 — full map:
dependsOn:
database:
condition: healthy
type DeploymentTemplateSource ¶
type DeploymentTemplateSource struct {
// Version — OrkestraRegistry implementation version to use. Omit for latest.
Version string `yaml:"version" json:"version,omitempty" validate:"omitempty"`
// Name — Deployment and primary container name.
// Supports template expressions.
// Default when omitted: "{{ .metadata.name }}-deployment"
Name string `yaml:"name" json:"name,omitempty" validate:"omitempty"`
// Image — container image. Required (must be declared here or resolvable from CR).
// Static: "nginx:1.25"
// Dynamic: "{{ .spec.image }}"
Image string `yaml:"image" json:"image" validate:"omitempty"`
// Replicas — number of pod replicas as a string.
// Static: "3"
// Dynamic: "{{ .spec.replicas }}"
// Default: "1"
Replicas string `yaml:"replicas" json:"replicas,omitempty" validate:"omitempty"`
// Port — primary container port as a string.
// Static: "8080"
// Dynamic: "{{ .spec.port }}"
// Omit to expose no port.
Port string `yaml:"port" json:"port,omitempty" validate:"omitempty"`
// Namespace — target namespace for the Deployment.
// Default when omitted: "{{ .metadata.namespace }}" (same namespace as the CR).
Namespace string `yaml:"namespace" json:"namespace,omitempty" validate:"omitempty"`
// Labels — applied to the Deployment ObjectMeta and the pod template.
// Label values support template expressions.
// Orkestra always adds: managed-by=orkestra, orkestra-owner=<cr-name>
Labels []ResourceLabel `yaml:"labels" json:"labels,omitempty" validate:"omitempty"`
// Annotations — applied to the Deployment ObjectMeta only.
// Annotation values support template expressions.
Annotations []ResourceLabel `yaml:"annotations" json:"annotations,omitempty" validate:"omitempty"`
// Resources — CPU and memory requests/limits for the primary container.
// Values are static Kubernetes quantity strings.
// Template expressions are not supported in resource quantities.
Resources *ResourceRequirements `yaml:"resources" json:"resources,omitempty" validate:"omitempty"`
// Env — environment variables for the primary container.
// Keys are env var names. Values support template expressions.
// Example:
// env:
// REGION: "{{ .item }}"
// DB_HOST: "{{ .cross.db.status.endpoint }}"
//
// If omitted, no environment variables are added.
// Env map[string]string `yaml:"env" json:"env,omitempty" validate:"omitempty"`
Env map[string]EnvVarSource `yaml:"env" json:"env,omitempty"`
EnvFrom []EnvFromSource `yaml:"envFrom,omitempty" json:"envFrom,omitempty"`
// Reconcile: true — also apply this declaration as drift correction on every
// reconcile. Equivalent to declaring the same entry under both onCreate and
// onReconcile. When false (default), only runs on onCreate (idempotent create).
Reconcile bool `yaml:"reconcile" json:"reconcile,omitempty" validate:"omitempty"`
Conditions []Condition `yaml:"when,omitempty" json:"when,omitempty"`
// ForEach declares dynamic expansion over a list field.
// When set, one source declaration becomes N declarations — one per list element.
// .item and .<as> are available in template expressions within this declaration.
ForEach *ForEachSpec `yaml:"forEach,omitempty" json:"forEach,omitempty"`
// AnyOf holds OR conditions — at least one must pass for this resource to be created.
// Works alongside the existing Conditions (when:) field which uses AND semantics.
AnyOf []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`
// WorkingDirectory sets the container's working directory (container.WorkingDir).
// Useful for Git-backed pipelines where build/test commands must run inside
// a checked-out repository path.
WorkingDirectory string `yaml:"workingDirectory,omitempty" json:"workingDirectory,omitempty"`
}
DeploymentTemplateSource declares one Deployment to be managed by Orkestra.
Declare under onCreate to create the Deployment on first reconcile. This automatically creates onReconcile Declare under onReconcile to apply drift correction on every reconcile. Declare under both to get idempotent creation and drift correction together. Or simply declare under onCreate
Minimal example — static values only:
onCreate:
deployments:
- image: nginx:1.25
replicas: "3"
port: "8080"
Full example — dynamic values from the CR:
onCreate:
deployments:
- name: "{{ .metadata.name }}-app"
image: "{{ .spec.image }}"
replicas: "{{ .spec.replicas }}"
port: "{{ .spec.port }}"
namespace: "{{ .metadata.namespace }}"
labels:
- key: app
value: "{{ .metadata.name }}"
- key: managed-by
value: orkestra
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
type DockerHookSpec ¶
type DockerHookSpec struct {
// Image is the fully-qualified image reference to build.
//
// Examples:
// "registry.example.com/webapp:{{ .git.commit }}"
// "ghcr.io/org/service:{{ .status.version }}"
//
// This field supports template expressions and is required.
Image string `yaml:"image" json:"image"`
// WorkingDirectory is the directory used as the Docker build context.
//
// In most cases this is the same as the Git hook's .git.path:
// workingDirectory: "{{ .git.path }}"
//
// If omitted, Orkestra defaults to the CR's working directory (rarely useful).
WorkingDirectory string `yaml:"workingDirectory,omitempty" json:"workingDirectory,omitempty"`
// Dockerfile optionally overrides the Dockerfile path.
//
// Examples:
// "Dockerfile"
// "deploy/Dockerfile.prod"
//
// When empty, Orkestra uses "Dockerfile" in the working directory.
Dockerfile string `yaml:"dockerfile,omitempty" json:"dockerfile,omitempty"`
// Push controls whether the built image should be pushed to the registry.
//
// When true:
// • Orkestra executes `docker push <image>` after a successful build.
// • Push failures are surfaced via .docker.error.
//
// When false:
// • The image is built locally only.
Push bool `yaml:"push,omitempty" json:"push,omitempty"`
// Builder selects the OCI build tool to use.
//
// Supported values: "docker" (default), "kaniko", "buildah", "podman".
// When empty, Orkestra checks the OCI_BUILDER environment variable,
// then falls back to "docker".
//
// kaniko — builds without a Docker socket; works in any Kubernetes pod.
// buildah — rootless builds via buildah bud.
// podman — local builds via podman build.
Builder string `yaml:"builder,omitempty" json:"builder,omitempty"`
// Reconcile controls whether this Docker hook runs on every reconcile.
//
// When true:
// • Docker build/push runs on every reconcile cycle.
// • Useful for Git-driven pipelines where .git.changed triggers rebuilds.
//
// When false:
// • Docker build/push runs only during onCreate.
// • Useful for one-time initialization images.
Reconcile bool `yaml:"reconcile,omitempty" json:"reconcile,omitempty"`
// ContinueOnError controls behaviour when the Docker build or push fails.
//
// false (default) — Docker failure returns an error and halts reconciliation.
// true — Docker failure injects .docker.error but reconciliation continues.
ContinueOnError bool `yaml:"continueOnError,omitempty" json:"continueOnError,omitempty"`
// When is an optional list of conditions that must all pass before
// this field is written. If absent or empty, the field is always written.
//
// All conditions are AND-ed together.
// To express OR logic, declare multiple StatusField entries for the same path.
//
// Conditions are evaluated against the full CR object map — the same
// map available to template expressions. This means .status.phase,
// .spec.image, .children.job.status.succeeded are all accessible.
When []Condition `yaml:"when,omitempty"`
AnyOf []Condition `yaml:"anyOf,omitempty"`
}
DockerHookSpec declares a Docker build/push operation as part of a lifecycle hook.
This hook allows Orkestra to build container images directly inside the reconcile loop, using the working directory produced by a Git hook or any other source. It behaves similarly to external calls and git hooks — it is a declarative precondition that runs before resource creation.
Typical usage:
operatorBox:
onReconcile:
git:
repo: "git@github.com:org/webapp.git"
branch: "main"
path: "services/webapp"
reconcile: true
docker:
image: "registry.example.com/webapp:{{ .git.commit }}"
workingDirectory: "{{ .git.path }}"
push: true
deployments:
- name: "{{ .metadata.name }}"
image: "{{ .docker.image }}"
Minimal v1 behaviour:
- Executes `docker build` using workingDirectory as the build context.
- Uses Dockerfile in workingDirectory unless overridden.
- If push=true, executes `docker push` after a successful build.
- Exposes results to templates under `.docker.*`: .docker.image .docker.buildSucceeded .docker.error
- No credentials stored in the CRD — authentication is external.
- No per-reconcile full rebuild unless reconcile=true.
- No caching or layer reuse guarantees (future versions may add this).
This enables fully declarative CI/CD pipelines where Git → Test → Build → Push → Deploy are all expressed in YAML and executed inside the cluster.
type Duration ¶
Duration is a time.Duration that unmarshals from YAML strings like "15s", "2m", "1h".
func (Duration) MarshalYAML ¶
func (*Duration) UnmarshalYAML ¶
type EndpointsConfig ¶
type EndpointsConfig struct {
// Enabled if false disables all endpoints for this CRD
// Default is true
Enabled *bool `yaml:"enabled" json:"enabled,omitempty"`
// Health controls whether the /health endpoint is served.
Health *bool `yaml:"health" json:"health,omitempty"`
// Info controls whether the /info endpoint is served.
Info *bool `yaml:"info" json:"info,omitempty"`
}
EndpointsConfig controls which HTTP endpoints are exposed by the operator.
This allows users to selectively enable/disable endpoints while keeping the configuration minimal and declarative.
type EnrichmentOutcome ¶
type EnrichmentOutcome int
EnrichmentOutcome describes what happened when enrichment was attempted for a CRD entry. Used by ork validate to print clear, actionable output.
const ( // EnrichmentNotNeeded — apiTypes is already fully specified EnrichmentNotNeeded EnrichmentOutcome = iota // EnrichmentApplied — kind-only declaration resolved to a built-in EnrichmentApplied // EnrichmentFailed — kind-only declaration did not match any built-in // and apiTypes is incomplete EnrichmentFailed )
type EnvFromSource ¶
type EnvVarSource ¶
type EnvVarSource struct {
Value string `yaml:"value,omitempty" json:"value,omitempty"`
SecretKeyRef *SecretKeyRef `yaml:"secretKeyRef,omitempty" json:"secretKeyRef,omitempty"`
ConfigMapKeyRef *ConfigMapKeyRef `yaml:"configMapKeyRef,omitempty" json:"configMapKeyRef,omitempty"`
}
EnvVarSource represents a single environment variable value source. Only one of Value, SecretKeyRef, or ConfigMapKeyRef should be set. Values are static strings — template expressions are not supported.
type ExternalCallResult ¶
type ExternalCallResult struct {
// Status is the HTTP status code as a string ("200", "404", "503").
// Empty string when the call failed before receiving a response.
Status string `json:"status"`
// Body is the first 4096 bytes of the response body.
// Truncated to avoid unbounded memory use.
Body string `json:"body"`
// Error is the error message when the call failed.
// Empty on success.
Error string `json:"error"`
// Called is "true" when the call was made, "false" when skipped (conditions failed).
Called string `json:"called"`
// Additional values for metrics
StatusCode int `json:"statusCode"`
DurationSeconds float64 `json:"durationSeconds"`
}
ExternalCallResult is the result of one HTTP call, injected into the resolver context under .external.<name>.
type ExternalCallSpec ¶
type ExternalCallSpec struct {
// Name is the identifier used to access the result in template expressions.
// name: health-check → {{ .external.health-check.status }}
Name string `yaml:"name"`
// URL is the endpoint to call. Template expressions are supported.
// url: "{{ .spec.serviceUrl }}/health"
// url: "https://api.example.com/resources/{{ .metadata.name }}"
URL string `yaml:"url"`
// Method is the HTTP method. Default: GET.
Method string `yaml:"method,omitempty"`
// Body is the request body for POST/PUT/PATCH requests.
// Template expressions supported.
// body: '{"name": "{{ .metadata.name }}"}'
Body string `yaml:"body,omitempty"`
// Token is a bearer token for Authorization header.
// Use $ENV_VAR syntax to reference environment variables:
// token: "$API_TOKEN"
Token string `yaml:"token,omitempty"`
// Headers are additional HTTP headers to include.
Headers map[string]string `yaml:"headers,omitempty"`
// Timeout is the maximum duration for this call.
// Default: 10s. Format: "5s", "1m", "500ms"
Timeout string `yaml:"timeout,omitempty"`
// ExpectedStatus is the HTTP status code that signals success.
// Default: any 2xx status.
// When set to 200, any non-200 response is treated as a failure.
ExpectedStatus int `yaml:"expectedStatus,omitempty"`
// ContinueOnError controls whether a failed call halts reconciliation.
// false (default): a call failure returns an error, halting the reconcile.
// true: failure is logged, result has error set, reconcile continues.
//
// Use true for optional calls: notifications, metrics, feature flags.
// Use false (default) for required calls: health checks, dependency readiness.
ContinueOnError bool `yaml:"continueOnError,omitempty"`
// When conditions gate this call — if conditions fail, the call is skipped.
// The result is not injected when skipped.
Conditions []Condition `yaml:"when,omitempty"`
AnyOf []Condition `yaml:"anyOf,omitempty"`
}
ExternalCallSpec declares one HTTP call to make before resource reconciliation.
type FileSource ¶
type FileSource struct {
// URL or path — the file to load.
// May be a local path, an HTTP(S) URL, or an $ENV_VAR reference.
URL string `yaml:"url"`
// Auth — optional authentication for remote sources.
// Ignored for local paths.
Auth *FileSourceAuth `yaml:"auth,omitempty"`
}
FileSource represents one file source entry. Supports both simple string form (just a path) and authenticated form.
YAML unmarshalling handles both forms transparently via UnmarshalYAML. Users can write either:
files:
- ./simple/path.yaml # simple form
- url: https://private/katalog.yaml # authenticated form
auth:
type: bearer
fromEnv: MY_TOKEN
func (*FileSource) UnmarshalYAML ¶
func (f *FileSource) UnmarshalYAML(unmarshal func(interface{}) error) error
UnmarshalYAML allows FileSource to be declared as either a plain string or a struct with url and auth fields.
Plain string:
- ./path/to/katalog.yaml
- https://public.url/katalog.yaml
- $ENV_VAR
Struct with auth:
- url: https://private.url/katalog.yaml auth: type: github fromEnv: GITHUB_TOKEN
type FileSourceAuth ¶
type FileSourceAuth struct {
// Type — authentication scheme.
// Supported values: "bearer", "github", "basic"
Type string `yaml:"type" validate:"required,oneof=bearer github basic"`
// FromEnv — environment variable containing the bearer token or GitHub token.
// Used when Type is "bearer" or "github".
FromEnv string `yaml:"fromEnv,omitempty"`
// UsernameFromEnv — environment variable containing the username.
// Used when Type is "basic".
UsernameFromEnv string `yaml:"usernameFromEnv,omitempty"`
// PasswordFromEnv — environment variable containing the password.
// Used when Type is "basic".
PasswordFromEnv string `yaml:"passwordFromEnv,omitempty"`
}
FileSourceAuth declares how to authenticate when fetching a remote source. All credential values are resolved from environment variables at load time — credentials never appear as literal values in the Katalog YAML.
type ForEachSpec ¶
type ForEachSpec struct {
// Field is the dot-notation path to a list or map field on the CR.
//
// List field → one item per element:
// field: spec.regions → ["us-east-1", "eu-west-1"]
// .item = element value ("us-east-1")
//
// Map field → one item per key (sorted alphabetically):
// field: spec.regions → {us-east-1: {replicas: 3}, eu-west-1: {replicas: 1}}
// .item = map key ("us-east-1"), .value = map value ({replicas: 3})
// .value.replicas = "3"
Field string `yaml:"field"`
// As is the name used to access the current item in template expressions.
// Default: "item" — {{ .item }}
// When set: both {{ .item }} and {{ .<as> }} work.
// as: region → {{ .region }} and {{ .item }} both resolve to the current element
As string `yaml:"as,omitempty"`
}
ForEachSpec declares dynamic expansion over a list or map field.
type GitHookSpec ¶
type GitHookSpec struct {
// Repo is the Git repository URL.
Repo string `yaml:"repo" json:"repo"`
// Branch is the branch to track. Default: "main".
Branch string `yaml:"branch,omitempty" json:"branch,omitempty"`
// Path optionally scopes change detection to a subdirectory.
Path string `yaml:"path,omitempty" json:"path,omitempty"`
// Reconcile controls whether this Git hook runs on every reconcile.
//
// When true:
// • Git fetch runs on every reconcile cycle.
// • `.git.changed` is updated accordingly.
//
// When false:
// • Git runs only on onCreate.
// • Useful for one-time initialization.
Reconcile bool `yaml:"reconcile,omitempty" json:"reconcile,omitempty"`
// ContinueOnError controls behaviour when the Git operation fails.
//
// false (default) — Git failure returns an error and halts reconciliation.
// true — Git failure injects .git.error but reconciliation continues.
// Subsequent when: conditions on git.changed will not fire.
ContinueOnError bool `yaml:"continueOnError,omitempty" json:"continueOnError,omitempty"`
// When is an optional list of conditions that must all pass before
// this field is written. If absent or empty, the field is always written.
//
// All conditions are AND-ed together.
// To express OR logic, declare multiple StatusField entries for the same path.
//
// Conditions are evaluated against the full CR object map — the same
// map available to template expressions. This means .status.phase,
// .spec.image, .children.job.status.succeeded are all accessible.
When []Condition `yaml:"when,omitempty"`
AnyOf []Condition `yaml:"anyOf,omitempty"`
}
Git declares a Git-backed trigger for this lifecycle hook.
When configured, Orkestra performs a lightweight Git checkout or update before evaluating the rest of the hook. The result is exposed to templates under `.git`:
.git.commit — latest commit hash .git.changed — "true" if the commit changed since last reconcile .git.path — absolute path to the working directory
This enables declarative, in-cluster CI/CD pipelines where Git acts as the source of build/test/deploy logic.
Minimal v1 behaviour:
- On first reconcile: clone repo into a per-CRD working directory.
- On subsequent reconciles: fetch + fast-forward.
- If HEAD changed: mark `.git.changed = "true"`.
- No per-reconcile full clone.
- No credentials stored in CRD.
- No aggressive polling — relies on CRD-level resync.
Future versions may add shallow clones, webhook triggers, caching, subdirectory diffing, and credential sources without breaking this contract.
type HPATemplateSource ¶ added in v0.1.9
type HPATemplateSource struct {
Version string `yaml:"version" json:"version,omitempty"`
// Name — HPA resource name. Default: "{{ .metadata.name }}-hpa"
Name string `yaml:"name" json:"name,omitempty"`
// Namespace — target namespace. Default: CR namespace.
Namespace string `yaml:"namespace" json:"namespace,omitempty"`
// ScaleTargetRef — the target workload this HPA scales.
// Supports Deployment, ReplicaSet, StatefulSet, or any scalable resource.
// Supports template expressions: "{{ .metadata.name }}"
ScaleTargetRef ScaleTargetRef `yaml:"scaleTargetRef" json:"scaleTargetRef,omitempty"`
// MinReplicas — minimum replica count as a string. Supports template expressions.
MinReplicas string `yaml:"minReplicas" json:"minReplicas,omitempty"`
// MaxReplicas — maximum replica count as a string. Supports template expressions.
MaxReplicas string `yaml:"maxReplicas" json:"maxReplicas,omitempty"`
// TargetCPUUtilizationPercentage — CPU utilization target (0-100). Supports templates.
TargetCPUUtilizationPercentage string `yaml:"targetCPUUtilizationPercentage" json:"targetCPUUtilizationPercentage,omitempty"`
// Labels applied to HPA metadata. Values support template expressions.
Labels []ResourceLabel `yaml:"labels" json:"labels,omitempty"`
Reconcile bool `yaml:"reconcile" json:"reconcile,omitempty"`
Conditions []Condition `yaml:"when,omitempty" json:"when,omitempty"`
AnyOf []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`
ForEach *ForEachSpec `yaml:"forEach,omitempty" json:"forEach,omitempty"`
}
HPATemplateSource declares one HorizontalPodAutoscaler to be managed by Orkestra.
Example:
onReconcile:
hpa:
- name: "{{ .metadata.name }}-hpa"
deploymentRef: "{{ .metadata.name }}"
minReplicas: "{{ .spec.minReplicas }}"
maxReplicas: "{{ .spec.maxReplicas }}"
targetCPUUtilizationPercentage: "80"
forEach:
field: spec.services
as: item
type HelmSource ¶
type HelmSource struct {
// Repo — Helm repository URL.
// e.g. "https://charts.myorg.io"
Repo string `yaml:"repo" validate:"required"`
// Chart — chart name within the repository.
// e.g. "platform-crds"
Chart string `yaml:"chart" validate:"required"`
// Version — chart version to use. Required for reproducibility.
// And also used as git ref
// e.g. "1.2.0"
Version string `yaml:"version" validate:"required"`
// Path — chart path within git repo
Path string `yaml:"path" validate:"omitempty"`
// ValueFiles — list of values files to apply when rendering the chart.
// Each entry can be a local path or a remote URL.
// Supports environment variable references: $MY_VALUES_FILE
// Applied in order — later files override earlier ones (same as helm -f).
ValueFiles []string `yaml:"valueFiles,omitempty"`
// Values — inline key-value pairs applied after valueFiles.
// Same as helm --set key=value.
Values map[string]interface{} `yaml:"values,omitempty"`
}
HelmSource declares a Helm chart that produces Katalog CRD definitions. The chart must render at least one template with kind: Katalog.
Example chart template (templates/katalog.yaml):
apiVersion: orkestra.konductor.io/v1Alpha
kind: Katalog
spec:
crds:
{{- range .Values.crds }}
- name: {{ .name }}
enabled: {{ .enabled }}
...
{{- end }}
type HookDeclaration ¶
type HookDeclaration struct {
// Location — fully qualified Go import path. Local or remote module.
// e.g. "github.com/myorg/hooks" or "github.com/orkspace/orkestra/pkg/reconciler/hooks"
Location string `yaml:"location" json:"location" validate:"required"`
// Function — exported function name at Location that returns hooks.
// e.g. "ProjectHooks"
Function string `yaml:"function" json:"function" validate:"required"`
// Alias — Go import alias. Optional, auto-derived from Location if omitted.
// e.g. "projecthooks"
Alias string `yaml:"alias" json:"alias,omitempty" validate:"omitempty"`
}
HookDeclaration declares where a Go hook function lives. Read by ork generate to emit HookRegistry entries in zz_generated_runtime_registry.go. The declared function must match the signature: func() domain.AnyReconcileHooks
type HookTemplates ¶
type HookTemplates struct {
Deployments []DeploymentTemplateSource `yaml:"deployments" json:"deployments,omitempty" validate:"omitempty"`
ReplicaSets []ReplicaSetTemplateSource `yaml:"replicaSets" json:"replicaSets,omitempty" validate:"omitempty"`
Services []ServiceTemplateSource `yaml:"services" json:"services,omitempty" validate:"omitempty"`
Pods []PodTemplateSource `yaml:"pods" json:"pods,omitempty" validate:"omitempty"`
Jobs []JobTemplateSource `yaml:"jobs" json:"jobs,omitempty" validate:"omitempty"`
CronJobs []CronJobTemplateSource `yaml:"cronJobs" json:"cronJobs,omitempty" validate:"omitempty"`
Secrets []SecretTemplateSource `yaml:"secrets" json:"secrets,omitempty" validate:"omitempty"`
ConfigMaps []ConfigMapTemplateSource `yaml:"configMaps" json:"configMaps,omitempty" validate:"omitempty"`
ServiceAccounts []ServiceAccountTemplateSource `yaml:"serviceAccounts" json:"serviceAccounts,omitempty" validate:"omitempty"`
StatefulSets []StatefulSetTemplateSource `yaml:"statefulSets" json:"statefulSets,omitempty" validate:"omitempty"`
Ingresses []IngressTemplateSource `yaml:"ingresses" json:"ingresses,omitempty" validate:"omitempty"`
PersistentVolumes []PVTemplateSource `yaml:"persistentVolumes" json:"persistentVolumes,omitempty" validate:"omitempty"`
PersistentVolumeClaims []PVCTemplateSource `yaml:"persistentVolumeClaims" json:"persistentVolumeClaims,omitempty" validate:"omitempty"`
HorizontalPodAutoscalers []HPATemplateSource `yaml:"hpa" json:"hpa,omitempty" validate:"omitempty"`
PodDisruptionBudgets []PDBTemplateSource `yaml:"pdb" json:"pdb,omitempty" validate:"omitempty"`
Namespaces []NamespaceTemplateSource `yaml:"namespaces" json:"namespaces,omitempty" validate:"omitempty"`
// External declares HTTP calls to make before resource creation.
// Results available as .external.<n>.status, .body, .error
External []ExternalCallSpec `yaml:"external,omitempty" json:"external,omitempty"`
// Git declares optional Git-backed reconcile behaviour for this CRD.
//
// When configured, Orkestra:
// - Maintains a local working copy of the repository.
// - Periodically checks the target branch for new commits.
// - Enqueues reconciles for all CRs of this type when the branch tip changes.
//
// This enables declarative, in-cluster CI/CD pipelines where Git acts
// as the source of pipeline logic and the CRs provide parameters.
//
// When omitted, reconcile behaviour is unchanged and no Git traffic
// is generated for this CRD.
Git *GitHookSpec `yaml:"git,omitempty" json:"git,omitempty"`
// Docker declares optional Docker-backed reconcile behaviour for this CRD.
//
// When configured
// - Builds and optionally pushes a docker image
Docker *DockerHookSpec `yaml:"docker,omitempty" json:"docker,omitempty"`
// Ordered controls whether deletion happens sequentially with verification.
// true — delete groups in order, verify each is gone before proceeding
// false — delete all resources via owner references (default, parallel)
Ordered bool `yaml:"ordered,omitempty" json:"ordered,omitempty"`
// Groups declares sequential deletion stages for ordered deletes.
// Each element is a full HookTemplates block whose resources are deleted
// as a unit. Orkestra deletes stage N, waits until all resources are gone,
// then deletes stage N+1. Omit when Ordered is false.
// When Ordered is true and Groups is empty, the flat resource fields above
// (Jobs, Deployments, …) are treated as a single implicit group.
Groups []HookTemplates `yaml:"groups,omitempty" json:"groups,omitempty"`
// Timeout is the maximum time to wait for each deletion group to complete.
// Defaults to 5m when Ordered is true. Ignored when Ordered is false.
Timeout *Duration `yaml:"timeout,omitempty" json:"timeout,omitempty"`
// TODO with placeholer
Volumes []PlaceholderSource `yaml:"volumes" json:"volumes,omitempty" validate:"omitempty"`
VolumeMounts []PlaceholderSource `yaml:"volumeMounts" json:"volumeMounts,omitempty" validate:"omitempty"`
Roles []PlaceholderSource `yaml:"roles" json:"roles,omitempty" validate:"omitempty"`
RoleBindings []PlaceholderSource `yaml:"roleBindings" json:"roleBindings,omitempty" validate:"omitempty"`
ClusterRoles []PlaceholderSource `yaml:"clusterRoles" json:"clusterRoles,omitempty" validate:"omitempty"`
ClusterRoleBindings []PlaceholderSource `yaml:"clusterRoleBindings" json:"clusterRoleBindings,omitempty" validate:"omitempty"`
ServiceMonitors []PlaceholderSource `yaml:"serviceMonitors" json:"serviceMonitors,omitempty" validate:"omitempty"`
PodSecurityPolicies []PlaceholderSource `yaml:"podSecurityPolicies" json:"podSecurityPolicies,omitempty" validate:"omitempty"`
PriorityClasses []PlaceholderSource `yaml:"priorityClasses" json:"priorityClasses,omitempty" validate:"omitempty"`
LimitRanges []PlaceholderSource `yaml:"limitRanges" json:"limitRanges,omitempty" validate:"omitempty"`
ResourceQuotas []PlaceholderSource `yaml:"resourceQuotas" json:"resourceQuotas,omitempty" validate:"omitempty"`
RuntimeClasses []PlaceholderSource `yaml:"runtimeClasses" json:"runtimeClasses,omitempty" validate:"omitempty"`
PriorityLevelConfigurations []PlaceholderSource `yaml:"priorityLevelConfigurations" json:"priorityLevelConfigurations,omitempty" validate:"omitempty"`
PodTemplates []PlaceholderSource `yaml:"podTemplates" json:"podTemplates,omitempty" validate:"omitempty"`
DaemonSets []PlaceholderSource `yaml:"daemonSets" json:"daemonSets,omitempty" validate:"omitempty"`
NetworkPolicies []PlaceholderSource `yaml:"networkPolicies" json:"networkPolicies,omitempty" validate:"omitempty"`
// Storage
StorageClasses []PlaceholderSource `yaml:"storageClasses" json:"storageClasses,omitempty" validate:"omitempty"`
StorageLocations []PlaceholderSource `yaml:"storageLocations" json:"storageLocations,omitempty" validate:"omitempty"`
StoragePools []PlaceholderSource `yaml:"storagePools" json:"storagePools,omitempty" validate:"omitempty"`
StorageBackups []PlaceholderSource `yaml:"storageBackups" json:"storageBackups,omitempty" validate:"omitempty"`
StorageSnapshots []PlaceholderSource `yaml:"storageSnapshots" json:"storageSnapshots,omitempty" validate:"omitempty"`
StorageVolumes []PlaceholderSource `yaml:"storageVolumes" json:"storageVolumes,omitempty" validate:"omitempty"`
}
── HookTemplates ───────────────────────────────────────────────────────────── Declares the complete set of resources Orkestra manages at each lifecycle event. All resource type slices are optional — omit any type you do not need. Resources not declared in HookTemplates are never created, updated, or deleted by Orkestra — they are invisible to the reconciler.
All resources created via hook templates receive owner references pointing to the CR. This means Kubernetes garbage collection handles deletion automatically when the CR is deleted — no onDelete declaration is needed for cleanup in most cases.
Lifecycle events:
onCreate
Runs on every reconcile. Create calls are idempotent — if the resource
already exists it is skipped without error.
Declare all long-lived child resources here.
Resources are created in the order declared within each type slice.
onReconcile
Runs on every reconcile, after onCreate.
Use for drift correction — re-applies desired state when child resources
have been manually modified, scaled, or deleted outside of Orkestra.
Omit entirely if onCreate alone is sufficient (no drift correction needed).
onDelete
Runs when the CR has a DeletionTimestamp set, before Orkestra removes finalizers.
Use only for resources that need explicit cleanup beyond owner references:
- External resources not in Kubernetes (cloud provider APIs, DNS records, etc.)
- Jobs that must complete successfully before the CR can be considered deleted
- Notification or archival tasks that must run before deletion is finalized
type IngressTLSSpec ¶ added in v0.1.9
type IngressTLSSpec struct {
// Enabled — when true, create a TLS secret and populate ingress.spec.tls.
Enabled bool `yaml:"enabled" json:"enabled,omitempty"`
// SecretName — name of the TLS secret. Supports template expressions.
// Default: "{{ .metadata.name }}-tls"
SecretName string `yaml:"secretName" json:"secretName,omitempty"`
// Hosts — list of hostnames to include in the TLS certificate SANs.
// Each element supports template expressions.
Hosts []string `yaml:"hosts" json:"hosts,omitempty"`
// ValidFor — certificate validity duration (e.g. "1y", "90d"). Default: "1y".
ValidFor string `yaml:"validFor" json:"validFor,omitempty"`
}
IngressTLSSpec configures TLS for an Ingress resource. When Enabled is true, Orkestra generates a kubernetes.io/tls Secret before the Ingress is applied so the Ingress can reference it immediately.
type IngressTemplateSource ¶ added in v0.1.9
type IngressTemplateSource struct {
Version string `yaml:"version" json:"version,omitempty"`
// Name — Ingress resource name. Default: "{{ .metadata.name }}-ingress"
Name string `yaml:"name" json:"name,omitempty"`
// Namespace — target namespace. Default: CR namespace.
Namespace string `yaml:"namespace" json:"namespace,omitempty"`
// Host — virtual host name for the Ingress rule.
Host string `yaml:"host" json:"host,omitempty"`
// ServiceName — backend Service name this Ingress routes to.
ServiceName string `yaml:"serviceName" json:"serviceName,omitempty"`
// ServicePort — backend Service port as a string. Supports template expressions.
ServicePort string `yaml:"servicePort" json:"servicePort,omitempty"`
// Path — HTTP path prefix. Default: "/"
Path string `yaml:"path" json:"path,omitempty"`
// PathType — Kubernetes IngressPathType: Prefix, Exact, ImplementationSpecific.
// Default: Prefix.
PathType string `yaml:"pathType" json:"pathType,omitempty"`
// IngressClass — Ingress class name (nginx, traefik, etc.). Optional.
IngressClass string `yaml:"ingressClass" json:"ingressClass,omitempty"`
// Labels applied to Ingress metadata. Values support template expressions.
Labels []ResourceLabel `yaml:"labels" json:"labels,omitempty"`
// Annotations applied to Ingress metadata. Values support template expressions.
Annotations []ResourceLabel `yaml:"annotations" json:"annotations,omitempty"`
// TLS — optional TLS configuration. When tls.enabled is true, Orkestra
// generates a self-signed TLS Secret before creating the Ingress.
TLS *IngressTLSSpec `yaml:"tls" json:"tls,omitempty"`
Reconcile bool `yaml:"reconcile" json:"reconcile,omitempty"`
Conditions []Condition `yaml:"when,omitempty" json:"when,omitempty"`
AnyOf []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`
ForEach *ForEachSpec `yaml:"forEach,omitempty" json:"forEach,omitempty"`
}
IngressTemplateSource declares one Ingress to be managed by Orkestra.
Example:
onReconcile:
ingresses:
- name: "{{ .metadata.name }}-ingress"
host: "{{ .spec.hostname }}"
serviceName: "{{ .metadata.name }}-svc"
servicePort: "{{ .spec.port }}"
path: /
pathType: Prefix
ingressClass: nginx
tls:
enabled: true
secretName: "{{ .metadata.name }}-tls"
hosts:
- "{{ .spec.hostname }}"
type JobTemplateSource ¶
type JobTemplateSource struct {
// Version — OrkestraRegistry implementation version. Omit for latest.
Version string `yaml:"version" json:"version,omitempty" validate:"omitempty"`
// Name — Job name.
// Default when omitted: "{{ .metadata.name }}-job"
Name string `yaml:"name" json:"name,omitempty" validate:"omitempty"`
// Image — container image. Required.
Image string `yaml:"image" json:"image" validate:"omitempty"`
// Command — container entrypoint command.
// Each element is resolved independently — template expressions are supported per element.
// e.g. ["sh", "-c", "echo cleaning up {{ .metadata.name }}"]
Command []string `yaml:"command" json:"command,omitempty" validate:"omitempty"`
// Args — arguments passed to the container command.
// Each element supports template expressions independently.
Args []string `yaml:"args" json:"args,omitempty" validate:"omitempty"`
// BackoffLimit — number of Pod restart attempts before the Job is marked Failed.
// Default: 3.
BackoffLimit int `yaml:"backoffLimit" json:"backoffLimit,omitempty" validate:"omitempty"`
// Namespace — target namespace.
// Default when omitted: "{{ .metadata.namespace }}"
Namespace string `yaml:"namespace" json:"namespace,omitempty" validate:"omitempty"`
// Labels — applied to Job metadata. Values support template expressions.
Labels []ResourceLabel `yaml:"labels" json:"labels,omitempty" validate:"omitempty"`
Conditions []Condition `yaml:"when,omitempty" json:"when,omitempty"`
// Reconcile: true — also apply this declaration as drift correction on every
// reconcile. Equivalent to declaring the same entry under both onCreate and
// onReconcile. When false (default), only runs on onCreate (idempotent create).
Reconcile bool `yaml:"reconcile" json:"reconcile,omitempty" validate:"omitempty"`
// ForEach declares dynamic expansion over a list field.
// When set, one source declaration becomes N declarations — one per list element.
// .item and .<as> are available in template expressions within this declaration.
ForEach *ForEachSpec `yaml:"forEach,omitempty" json:"forEach,omitempty"`
// AnyOf holds OR conditions — at least one must pass for this resource to be created.
// Works alongside the existing Conditions (when:) field which uses AND semantics.
AnyOf []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`
// WorkingDirectory sets the container's working directory (container.WorkingDir).
// Useful for Git-backed pipelines where build/test commands must run inside
// a checked-out repository path.
WorkingDirectory string `yaml:"workingDirectory,omitempty" json:"workingDirectory,omitempty"`
}
JobTemplateSource declares one Job to be run by Orkestra.
Most commonly used under onDelete for cleanup tasks that must complete before Orkestra removes finalizers from the CR:
- Draining queues or buffers
- Archiving state to external storage
- Notifying external systems of deletion
- Running database migrations before removing a CRD instance
Can also be used under onCreate for one-time provisioning tasks.
Example (cleanup on delete):
onDelete:
jobs:
- name: "{{ .metadata.name }}-cleanup"
image: busybox
command: ["sh", "-c", "echo cleaning up {{ .metadata.name }}"]
backoffLimit: 3
type KatalogFile ¶
type KatalogFile struct {
APIVersion string `yaml:"apiVersion"`
Kind string `yaml:"kind"`
Metadata KatalogMeta `yaml:"metadata"`
Anchors map[string]any `yaml:"anchors,omitempty"`
Sources *KatalogSources `yaml:"sources,omitempty"`
Spec KatalogSpec `yaml:"spec"`
Security KatalogSecurity `yaml:"security"`
// Providers declares which external provider libraries this Katalog requires.
// Top-level alongside spec: and security: — providers represent a distinct
// operational concern (infrastructure dependencies) separate from CRD definitions.
//
// providers:
// - name: aws
// required: true
// auth:
// accessKeyId: "$AWS_ACCESS_KEY_ID"
// secretAccessKey: "$AWS_SECRET_ACCESS_KEY"
// region: "$AWS_REGION"
// - name: mongodb
// required: true
// auth:
// mongoUri: "$MONGODB_URL"
Providers []KatalogProviderRequirement `yaml:"providers,omitempty"`
}
KatalogFile is the top-level structure of a crd-katalog.yaml file. It contains optional sources (files and helm charts) plus inline CRDs. Orkestra's in-built merger resolves all sources and merges everything into one KatalogSpec.
type KatalogForUI ¶
type KatalogForUI struct {
APIVersion string `json:"apiVersion"` // Orkestra API version
Kind string `json:"kind"` // Always "Katalog" at runtime
Metadata KatalogMeta `json:"metadata"` // Katalog metadata (name, description, etc.)
Spec KatalogSpecForUI `json:"spec"` // CRD definitions
Security KatalogSecurity `json:"security"` // Security settings
Providers []KatalogProviderRequirement `json:"providers,omitempty"` // Provider requirements
}
KatalogForUI is a UI-friendly representation of the merged Katalog. It contains only the fields needed for display in the Control Center, excluding internal runtime fields.
type KatalogMeta ¶
type KatalogMeta struct {
Name string `yaml:"name"`
Description string `yaml:"description,omitempty"`
Version string `yaml:"version,omitempty"`
Author string `yaml:"author,omitempty"`
License string `yaml:"license,omitempty"`
}
KatalogMeta holds identifying metadata for the Katalog.
type KatalogNotification ¶
type KatalogNotification struct {
// Enabled gates all notification dispatch. Default: true when the
// notification: block is declared. Set false to silence all channels
// without removing the configuration.
Enabled *bool `yaml:"enabled,omitempty"`
// Defaults defines global notification behavior applied when a team does
// not specify its own override.
Defaults *NotificationDefaults `yaml:"defaults,omitempty"`
// Teams declares named notification targets. Conditions and rollback blocks
// reference teams by name via notify: ["platform", "oncall"].
Teams map[string]*NotificationTeam `yaml:"teams,omitempty"`
}
KatalogNotification holds the complete notification configuration for a Katalog. Declared at the same level as spec:, metadata:, and security:.
func (*KatalogNotification) EffectiveInterval ¶
func (n *KatalogNotification) EffectiveInterval(teamName string) Duration
EffectiveInterval returns the notification interval for the given team. Resolution: team.Interval → defaults.Interval → fallback (15m).
func (*KatalogNotification) EffectiveMessage ¶ added in v0.1.9
func (n *KatalogNotification) EffectiveMessage(teamName string) string
EffectiveMessage returns the notification message template for a team, falling back to the default format when none is declared.
func (*KatalogNotification) EffectiveSlackWebhook ¶ added in v0.1.9
func (n *KatalogNotification) EffectiveSlackWebhook(teamName string) string
EffectiveSlackWebhook returns the Slack webhook URL for the given team. Resolution: team.SlackWebhookUrl → defaults.SlackWebhookUrl → "".
func (*KatalogNotification) HasEmailTargets ¶
func (n *KatalogNotification) HasEmailTargets(teamName string) bool
HasEmailTargets returns true when the team has at least one email recipient.
func (*KatalogNotification) HasSlackTargets ¶
func (n *KatalogNotification) HasSlackTargets(teamName string) bool
HasSlackTargets returns true when the team has Slack channels AND a webhook URL.
func (*KatalogNotification) HasTeams ¶ added in v0.1.9
func (n *KatalogNotification) HasTeams() bool
HasTeams returns true when at least one team is declared.
func (*KatalogNotification) IsEmailEnabled ¶ added in v0.1.9
func (n *KatalogNotification) IsEmailEnabled(hasSMTPConfig bool) bool
IsEmailEnabled returns true when email is usable for at least one team. hasSMTPConfig is passed from pkg/konfig — avoids importing konfig here.
func (*KatalogNotification) IsEnabled ¶ added in v0.1.9
func (n *KatalogNotification) IsEnabled() bool
IsEnabled returns true when notifications are configured and not explicitly disabled.
func (*KatalogNotification) IsSlackEnabled ¶ added in v0.1.9
func (n *KatalogNotification) IsSlackEnabled() bool
IsSlackEnabled returns true when Slack is usable for at least one team.
type KatalogProviderRequirement ¶
type KatalogProviderRequirement struct {
// Name is the YAML block key used under operatorBox.providers.
// Must match the Name() return value of the registered Provider.
// e.g. "aws", "mongodb", "stripe"
Name string `yaml:"name"`
// Required controls whether `ork validate` hard-fails on missing registration.
// true → validation error if not registered (operator will not function correctly)
// false → validation warning only (provider blocks are skipped at runtime)
Required bool `yaml:"required"`
// Auth holds the provider credentials. Values support $ENV_VAR expansion —
// use "$MY_SECRET" and Orkestra will substitute os.Getenv("MY_SECRET") at startup.
//
// AWS example:
// auth:
// accessKeyId: "$AWS_ACCESS_KEY_ID"
// secretAccessKey: "$AWS_SECRET_ACCESS_KEY"
// region: "us-east-1"
//
// MongoDB example:
// auth:
// mongoUri: "$MONGODB_URL"
Auth map[string]string `yaml:"auth,omitempty"`
// Version is the expected provider library version.
// Used by `ork provider install` to pull the correct OCI artifact.
// Optional — if absent, the latest version is used.
Version string `yaml:"version,omitempty"`
// Library is the OCI artifact reference for this provider.
// e.g. "oci://registry.orkestra.io/providers/aws:1.8.0"
// Used by `ork provider install`. Optional for locally registered providers.
Library string `yaml:"library,omitempty"`
}
KatalogProviderRequirement declares that this Katalog uses a named provider. Declared at the top-level providers[] in the Katalog YAML.
Purpose:
- `ork validate` warns when a required provider is not registered at runtime
- Supplies credentials (with $ENV_VAR expansion) to the provider at startup
- `ork provider install` pulls the OCI artifact for this provider
- Documentation: makes explicit what external systems this Katalog touches
Only providers declared here are registered. Per-CRD provider blocks for undeclared providers are silently skipped with a warning log.
func (KatalogProviderRequirement) ResolvedAuth ¶
func (r KatalogProviderRequirement) ResolvedAuth() map[string]string
ResolvedAuth returns a copy of Auth with all $ENV_VAR values substituted. Values that do not start with "$" are returned unchanged. Called at startup before credentials are passed to the provider constructor.
type KatalogSecurity ¶
type KatalogSecurity struct {
// DeletionProtection controls whether Orkestra registers a webhook that
// blocks deletion of its managed CRDs, deployment, service, etc.
//
// When enabled (default when block is present):
// - Registers /deletion-protection endpoint on the HTTPS server
// - Creates ValidatingWebhookConfiguration "orkestra-delete-protection"
// - Entry 1: broad rule for CRDs; handler filters by ProtectedCRDNames()
// - Entry 2: ObjectSelector-gated rule for deployment, service, etc
//
// To decommission an operator with deletion protection:
// 1. Set enabled: false
// 2. Redeploy Orkestra (webhook removed on startup)
// 3. Delete resources normally
//
// nil pointer: not enabled (not declared in YAML).
DeletionProtection *DeletionProtectionConfig `yaml:"deletionProtection,omitempty"`
// Webhooks controls the admission webhook settings (ValidatingWebhookConfiguration,
// MutatingWebhookConfiguration). These apply globally — there is no per-CRD switch.
// CRDs declare validation/mutation rules; the webhook is enabled or not globally.
//
// nil pointer: admission webhooks not configured; ENV vars drive behavior.
Webhooks *WebhooksConfig `yaml:"webhooks,omitempty"`
// Conversion controls the /convert endpoint and CRD version conversion.
// Separate from admission webhooks — conversion has its own endpoint and
// configuration (window size for stats, etc.).
//
// nil pointer: conversion not configured; ENV vars drive behavior.
Conversion *ConversionConfig `yaml:"conversion,omitempty"`
// NamespaceProtection controls the optional validating webhook that prevents
// Orkestra-managed CRs from being created or updated in forbidden namespaces.
//
// This is an admission-time safeguard only. When enabled:
// - Registers /namespace-protection endpoint on the HTTPS server
// - Creates ValidatingWebhookConfiguration "orkestra-namespace-protection"
// - Enforces allowedNamespaces / restrictedNamespaces declared by each CRD
//
// If disabled or omitted, namespace rules are not enforced at apply time.
// Existing CRs in forbidden namespaces will still be reconciled normally.
//
// nil pointer: namespace protection not configured; ENV vars drive behavior.
NamespaceProtection *NamespaceProtectionConfig `yaml:"namespaceProtection,omitempty"`
}
KatalogSecurity holds the full security configuration for a Katalog.
func (*KatalogSecurity) DeletionProtectionFailurePolicy ¶
func (s *KatalogSecurity) DeletionProtectionFailurePolicy() string
DeletionProtectionFailurePolicy returns the effective failure policy string. Falls back to "Fail" when not configured — protecting by default.
func (*KatalogSecurity) DeletionProtectionServiceName ¶
func (s *KatalogSecurity) DeletionProtectionServiceName(envDefault string) string
DeletionProtectionServiceName returns the effective service name for deletion protection. Falls back to the provided ENV default.
func (*KatalogSecurity) IsAdmissionEnabled ¶
func (s *KatalogSecurity) IsAdmissionEnabled() bool
IsAdmissionEnabled returns true when admission webhooks are globally enabled.
func (*KatalogSecurity) IsConversionEnabled ¶
func (s *KatalogSecurity) IsConversionEnabled() bool
IsConversionEnabled returns true when the conversion webhook is globally enabled.
func (*KatalogSecurity) IsDeletionProtectionEnabled ¶
func (s *KatalogSecurity) IsDeletionProtectionEnabled() bool
IsDeletionProtectionEnabled returns the effective deletion protection setting.
func (*KatalogSecurity) IsNamespaceProtectionEnabled ¶ added in v0.1.9
func (s *KatalogSecurity) IsNamespaceProtectionEnabled() bool
IsNamespaceProtectionEnabled returns the effective namespace protection setting.
func (*KatalogSecurity) NamespaceProtectionFailurePolicy ¶ added in v0.1.9
func (s *KatalogSecurity) NamespaceProtectionFailurePolicy() string
NamespaceProtectionFailurePolicy returns the effective failure policy string. Falls back to "Fail" when not configured — protecting by default.
func (*KatalogSecurity) NamespaceProtectionServiceName ¶ added in v0.1.9
func (s *KatalogSecurity) NamespaceProtectionServiceName(envDefault string) string
NamespaceProtectionServiceName returns the effective service name for namespace protection. Falls back to the provided ENV default.
func (*KatalogSecurity) WebhooksFailurePolicy ¶
func (s *KatalogSecurity) WebhooksFailurePolicy(envDefault string) string
WebhooksFailurePolicy returns the effective failure policy for admission webhooks. Falls back to "Ignore" — not blocking when Orkestra is unreachable.
func (*KatalogSecurity) WebhooksServiceName ¶
func (s *KatalogSecurity) WebhooksServiceName(envDefault string) string
WebhooksServiceName returns the effective service name for admission webhooks. Falls back to the provided ENV default.
type KatalogSources ¶
type KatalogSources struct {
// Files — local paths, remote URLs, or environment variable references.
// Each entry must be a valid Katalog YAML (apiVersion, kind, spec.crds).
// Supports environment variable references: $MY_KATALOG_URL
//
// Simple form: just a path string (no auth)
// files:
// - ./katalogs/project.yaml
// - https://public.url/katalog.yaml
// - $MY_KATALOG_URL
//
// Authenticated form: a FileSource struct with auth block
// files:
// - url: https://private.url/katalog.yaml
// auth:
// type: bearer
// fromEnv: MY_TOKEN
Files []FileSource `yaml:"files,omitempty"`
// Helm — Helm chart sources. Each chart is rendered with the provided
// value files and the resulting Katalog templates are extracted and merged.
Helm []HelmSource `yaml:"helm,omitempty"`
// Registry - Registry sources.
Registry []RegistrySource `yaml:"registry,omitempty"`
}
KatalogSources declares where to load CRD definitions from. Sources are loaded before spec.crds — inline CRDs are merged last and win on name conflict (allowing local overrides of remote definitions).
Only valid on kind: Komposer documents.
type KatalogSpec ¶
type KatalogSpec struct {
// Finalizers — Katalog-level finalizers applied to all CRDs
// unless overridden at the CRD level.
Finalizers []string `yaml:"finalizers,omitempty"`
// CRDs — the CRD entries managed by this Orkestra instance.
// Map key is the CRD name; Name field is injected from the key during loading.
CRDs map[string]CRDEntry `yaml:"crds"`
}
KatalogSpec holds the actual CRD definitions. This is what the merger produces after resolving all sources.
type KatalogSpecForUI ¶
type KatalogSpecForUI struct {
CRDs map[string]CRDEntry `json:"crds"` // Map of CRD name to CRD definition
}
KatalogSpecForUI contains the CRD definitions for UI display.
type KubeReader ¶
type KubeReader interface {
// GetSecret reads a Secret's data by name in the given namespace.
// Returns the decoded data map (base64 already decoded).
GetSecret(ctx context.Context, namespace, name string) (map[string][]byte, error)
// GetConfigMap reads a ConfigMap's data by name in the given namespace.
GetConfigMap(ctx context.Context, namespace, name string) (map[string]string, error)
}
KubeReader provides read-only access to cluster resources. Providers must not write Kubernetes resources — Orkestra owns cluster state.
type MutationConfig ¶
type MutationConfig struct {
// Rules — applied in declaration order.
Rules []MutationRule `yaml:"rules,omitempty" json:"rules,omitempty"`
// MutateFirst — when true, mutation runs before validation at reconcile
// time. Default false (validate first, then mutate valid objects).
//
// At admission time, mutation always runs first — this mirrors the
// Kubernetes webhook ordering (MutatingWebhookConfiguration fires before
// ValidatingWebhookConfiguration). This field only affects reconcile ordering.
MutateFirst bool `yaml:"mutateFirst,omitempty" json:"mutateFirst,omitempty"`
}
MutationConfig holds all mutation rules for a CRD.
type MutationRule ¶
type MutationRule struct {
// Field — dot-notation path to the CR field to mutate.
Field string `yaml:"field" json:"field" validate:"required"`
// Default — set only if the field is absent or empty.
// Supports template expressions.
Default interface{} `yaml:"default,omitempty"` // accepts int, bool, string from YAML
// Override — always set, regardless of current value.
// Supports template expressions.
Override interface{} `yaml:"override,omitempty"` // accepts int, bool, string from YAML
// Value type
ValueType string `yaml:"valueType,omitempty"` // "string", "int" or "integer", "float" or "number", "bool" or "boolean"
}
MutationRule declares one field mutation.
Two mutation types:
default — set the field only if it is absent or empty.
At admission time: applied before validation runs.
At reconcile time: applied on first reconcile cycle.
override — always set the field, regardless of current value.
Use with caution — overwrites user-provided values.
Both types support Go template expressions resolved against the CR object:
default: "{{ .metadata.name }}-default"
override: "myorg/{{ .metadata.name }}:latest"
Example:
mutation:
- field: spec.replicas
default: "2"
- field: spec.logLevel
default: "info"
- field: spec.image
override: "myorg/{{ .metadata.name }}:latest"
type NamespaceProtectionConfig ¶ added in v0.1.9
type NamespaceProtectionConfig struct {
// Enabled controls whether namespace protection is active.
// Default: true when the namespaceProtection block is declared.
Enabled *bool `yaml:"enabled,omitempty"`
// ServiceName is the Kubernetes Service fronting Orkestra's HTTPS server.
// The API server sends webhook requests to this Service.
// Default: ORKESTRA_SERVICE_NAME env / "orkestra".
ServiceName string `yaml:"serviceName,omitempty"`
// FailurePolicy controls what the API server does when Orkestra is unreachable.
// "Fail" — reject the CREATE/UPDATE (recommended; this is the default).
// "Ignore" — allow the request through when Orkestra cannot be reached.
// Default: "Fail".
FailurePolicy string `yaml:"failurePolicy,omitempty"`
// RestrictedNamespaces — deny-list applied to every CRD in this Katalog.
// Merged additively with per-CRD restrictedNamespaces — more specific levels
// add to, not replace, broader levels.
RestrictedNamespaces RestrictedNamespaces `yaml:"restrictedNamespaces,omitempty" json:"restrictedNamespaces,omitempty"`
// AllowedNamespaces — allow-list applied to every CRD in this Katalog.
// Merged additively with per-CRD allowedNamespaces.
AllowedNamespaces AllowedNamespaces `yaml:"allowedNamespaces,omitempty" json:"allowedNamespaces,omitempty"`
// CleanupOnShutdown controls whether Namespace protection webhook is deleted on graceful shutdown.
// Default: false — Namespace protection webhook persists across restarts.
CleanupOnShutdown bool `yaml:"cleanupOnShutdown,omitempty"`
}
NamespaceProtectionConfig controls namespace-protection webhook behaviour.
type NamespaceTemplateSource ¶ added in v0.2.3
type NamespaceTemplateSource struct {
// Version — OrkestraRegistry implementation version. Omit for latest.
Version string `yaml:"version" json:"version,omitempty" validate:"omitempty"`
// Name — ServiceAccount name.
// Default when omitted: "{{ .metadata.name }}-sa"
Name string `yaml:"name" json:"name,omitempty" validate:"omitempty"`
Finalizers []string `yaml:"finalizers" json:"finalizers,omitempty" validate:"omitempty"`
// Labels — applied to ServiceAccount metadata. Values support template expressions.
Labels []ResourceLabel `yaml:"labels" json:"labels,omitempty" validate:"omitempty"`
Conditions []Condition `yaml:"when,omitempty" json:"when,omitempty"`
// Reconcile: true — also apply this declaration as drift correction on every
// reconcile. Equivalent to declaring the same entry under both onCreate and
// onReconcile. When false (default), only runs on onCreate (idempotent create).
Reconcile bool `yaml:"reconcile" json:"reconcile,omitempty" validate:"omitempty"`
// ForEach declares dynamic expansion over a list field.
// When set, one source declaration becomes N declarations — one per list element.
// .item and .<as> are available in template expressions within this declaration.
ForEach *ForEachSpec `yaml:"forEach,omitempty" json:"forEach,omitempty"`
// AnyOf holds OR conditions — at least one must pass for this resource to be created.
// Works alongside the existing Conditions (when:) field which uses AND semantics.
AnyOf []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`
}
NamespaceTemplateSource declares one Namespace to be managed by Orkestra.
Example:
onCreate:
namespaces:
- name: "{{ .metadata.name }}-sa"
labels:
- key: app
value: "{{ .metadata.name }}"
type NewReconcilerFunc ¶
type NewReconcilerFunc func( kube *kubeclient.Kubeclient, inf cache.SharedIndexInformer, ev *event.Event, ) domain.Reconciler
type NormalizeConfig ¶
type NormalizeConfig struct {
// Spec contains field-level normalization templates.
// Example:
//
// normalize:
// spec:
// schedule: >
// {{ if typeMap .spec.schedule }}
// {{ cronFromMap .spec.schedule }}
// {{ else }}
// {{ cronNormalize .spec.schedule }}
// {{ end }}
//
// Spec maps a dot-notation field path to a template expression.
// The template sees the raw CR (before any normalization of other fields).
// Results are coerced to the appropriate Go type via YAML parsing:
// "3" → int
// "true" → bool
// "*/5 * * * *" → string
// Empty result ("") sets the field to empty string — not nil.
Spec map[string]string `yaml:"spec,omitempty"`
}
NormalizeConfig declares template-driven spec normalization. This phase runs BEFORE mutation, validation, and reconciliation.
Purpose:
- Accept multiple user-facing shapes (string vs map, list vs scalar, etc.)
- Collapse them into a single canonical spec used internally.
- Avoid drift where the CR stores one shape but children require another.
- Provide a declarative alternative to conversion webhooks.
Behavior:
- normalize.spec is a map of field → template string.
- Each template is evaluated against the RAW CR object.
- The rendered values overwrite the corresponding fields in .spec.
- Only declared fields are overwritten; others remain untouched.
- The normalized object is passed to NewResolver() and all downstream phases.
- The stored CR in etcd is NOT modified.
Nested paths are supported:
normalize:
spec:
resources.requests.cpu: "{{ default .spec.resources.requests.cpu \"100m\" }}"
containers.0.image: "{{ .spec.image }}:{{ .spec.tag }}"
NormalizeConfig declares field normalizations that run before mutation, validation, and template rendering.
Keys are dot-notation paths into spec (e.g. "schedule", "resources.limits.cpu"). Values are template expressions evaluated against the raw CR. Results are written back into the in-memory spec copy.
type NotificationDefaults ¶
type NotificationDefaults struct {
// Interval is the minimum time between notifications for the same
// condition+team pair while the condition remains true. Default: 15m.
Interval Duration `yaml:"interval,omitempty"`
// SlackWebhookUrl is the global default Slack incoming webhook URL.
// Used when a team declares slack: channels but no slackWebhookUrl.
// Can be overridden per team.
SlackWebhookUrl string `yaml:"slackWebhookUrl,omitempty"`
}
NotificationDefaults defines global defaults applied when a team does not override specific settings.
type NotificationTeam ¶
type NotificationTeam struct {
// Email is the list of email recipients. SMTP config comes from pkg/konfig
// env vars (SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, SMTP_FROM).
Email []string `yaml:"email,omitempty"`
// Slack is the list of Slack channels to notify (e.g. "#platform-alerts").
// Requires SlackWebhookUrl (team or global default) to be configured.
Slack []string `yaml:"slack,omitempty"`
// SlackWebhookUrl is the incoming webhook URL for this team's Slack workspace.
// Overrides notification.defaults.slackWebhookUrl for this team.
// Required when Slack is non-empty and no global default is set.
SlackWebhookUrl string `yaml:"slackWebhookUrl,omitempty"`
// Interval overrides the global default for this team. Zero duration falls
// back to notification.defaults.interval or the built-in default of 15m.
Interval Duration `yaml:"interval,omitempty"`
// Message is a Go template expression evaluated against the full resolver
// data (.spec.*, .metadata.*, .status.*, .children.*, metrics.*).
// When empty, Orkestra uses a default message format:
// "[orkestra] {katalogName}/{crdKind} {crName}: {condition.Field} {op} {value}"
Message string `yaml:"message,omitempty"`
}
NotificationTeam defines channels and behavior for one named notification target.
type NotifyBlock ¶ added in v0.1.9
type NotifyBlock struct {
// Teams is the list of team names (from notification.teams) to alert.
Teams []string `yaml:"teams"`
// Message is a Go template expression for the notification body.
// Overrides the team's own message template.
// When empty, uses the team's configured message or the system default.
Message string `yaml:"message,omitempty"`
}
NotifyBlock declares notification targets and an optional message override for a specific condition.
type OperatorBoxConfig ¶
type OperatorBoxConfig struct {
// Default controls which reconciler implementation is used for this CRD.
//
// true — GenericReconciler manages the full lifecycle automatically.
// Handles: finalizer add/remove, Kubernetes events, metrics, health state.
// HookFactory is optional — set for custom business logic.
// OnCreate/OnReconcile/OnDelete templates are only valid when Default: true.
//
// false — Custom reconciler. The user provides the full reconcile implementation.
// Constructor must be declared (in YAML mode) or set directly (Go mode).
// GenericReconciler is not used — the user owns the entire lifecycle.
Default *bool `yaml:"default" json:"default,omitempty" validate:"omitempty"`
// Finalizers — per-CRD finalizer list. Overrides the Katalog-level finalizer.
// Applied by GenericReconciler when a CR is first created.
// Stripped one-by-one before delete to unblock Kubernetes garbage collection.
// If empty, falls back to the Katalog-level finalizer declaration.
Finalizers []string `yaml:"finalizers" json:"finalizers,omitempty" validate:"omitempty"`
// Hooks — declares a Go hook function for Default: true CRDs in typed or dynamic mode.
// The function at Location.Function must match: func() domain.AnyReconcileHooks
// Use this when you want full Go control over reconcile logic.
// For declarative resource management without Go code, use OnCreate/OnReconcile/OnDelete.
// Only one of Hooks or OnCreate/OnReconcile/OnDelete should be used — not both.
Hooks *HookDeclaration `yaml:"hooks" json:"hooks,omitempty" validate:"omitempty"`
// ConstructorDecl — declares a custom reconciler constructor for Default: false CRDs.
// The function at Location.Function must match: NewReconcilerFunc
// Required when Default: false in YAML mode.
ConstructorDecl *ConstructorDeclaration `yaml:"constructor" json:"constructor,omitempty" validate:"omitempty"`
// OnCreate — resources to create when the CR is first reconciled.
OnCreate *HookTemplates `yaml:"onCreate" json:"onCreate,omitempty" validate:"omitempty"`
// OnReconcile — drift correction resources applied on every reconcile.
// Omit if onCreate alone is sufficient.
OnReconcile *HookTemplates `yaml:"onReconcile" json:"onReconcile,omitempty" validate:"omitempty"`
// OnDelete — cleanup resources applied before finalizer removal.
// Omit for resources covered by owner reference cascade deletion.
OnDelete *HookTemplates `yaml:"onDelete" json:"onDelete,omitempty" validate:"omitempty"`
// HookFactory — called once at startCRDWorkers time to produce typed hooks.
// nil → GenericReconciler runs with no user hooks.
// Finalizers, events, and metrics are still handled automatically.
HookFactory func() domain.AnyReconcileHooks `yaml:"-" json:"-"`
// Constructor — called once at startCRDWorkers time to build a custom reconciler.
// Must not be nil when Default: false — enforced by Katalog validation at startup.
Constructor NewReconcilerFunc `yaml:"-" json:"-"`
// Status declares how Orkestra manages the CR's /status subresource.
// nil (default): Layer 1 only — standard Ready condition after every reconcile.
// non-nil: Layer 1 + Layer 2 declarative fields from Status.Fields.
Status *StatusConfig `yaml:"status,omitempty" json:"status,omitempty"`
// ProviderBlocks holds the parsed provider declarations from the Katalog.
// Populated during Katalog loading via ParseProviderBlocks.
// Not a YAML field — parsed from RawProviders after unmarshal.
ProviderBlocks []ProviderBlock `yaml:"-" json:"-"`
// RawProviders is the raw YAML map, populated during unmarshal.
// Converted to ProviderBlocks in the Katalog loading step.
RawProviders map[string][]map[string]interface{} `yaml:"providers,omitempty" json:"providers,omitempty"`
// Cross declares cross-CRD observations.
// Read before any resource groups — results available as .cross.<as>.status.*
Cross []CrossCRDDeclaration `yaml:"cross,omitempty" json:"cross,omitempty"`
// Autoscale declares runtime autoscale behavior for this operatorbox.
// When declared, the autoscaler evaluates conditions on a ticker and applies
// or restores worker/queue/resync overrides automatically.
// nil → no autoscaling; CRD runs with its declared static worker count.
Autoscale *AutoscaleSpec `yaml:"autoscale,omitempty" json:"autoscale,omitempty"`
// Rollback declares failure-recovery behavior for this operatorbox.
// When declared, Orkestra tracks consecutive reconcile failures and re-applies
// the last known good spec when the trigger threshold is crossed.
// nil → no rollback; failures are retried indefinitely.
Rollback *RollbackBlock `yaml:"rollback,omitempty" json:"rollback,omitempty"`
// When is an optional list of conditions that must all pass before
// this field is written. If absent or empty, the field is always written.
//
// All conditions are AND-ed together.
// To express OR logic, declare multiple StatusField entries for the same path.
//
// Conditions are evaluated against the full CR object map — the same
// map available to template expressions. This means .status.phase,
// .spec.image, .children.job.status.succeeded are all accessible.
When []Condition `yaml:"when,omitempty"`
AnyOf []Condition `yaml:"anyOf,omitempty"`
}
type PDBTemplateSource ¶ added in v0.1.9
type PDBTemplateSource struct {
Version string `yaml:"version" json:"version,omitempty"`
// Name — PDB resource name. Default: "{{ .metadata.name }}-pdb"
Name string `yaml:"name" json:"name,omitempty"`
// Namespace — target namespace. Default: CR namespace.
Namespace string `yaml:"namespace" json:"namespace,omitempty"`
// Selector — label selector identifying the pods this PDB protects.
// Keys are static; values support template expressions.
Selector SelectorMap `yaml:"selector" json:"selector,omitempty"`
// MinAvailable — minimum number of pods that must remain available.
// Accepts integer strings ("1") or percentage strings ("50%").
// Mutually exclusive with MaxUnavailable.
MinAvailable string `yaml:"minAvailable" json:"minAvailable,omitempty"`
// Accepts integer strings ("1") or percentage strings ("25%").
// Mutually exclusive with MinAvailable.
MaxUnavailable string `yaml:"maxUnavailable" json:"maxUnavailable,omitempty"`
// Labels applied to PDB metadata. Values support template expressions.
Labels []ResourceLabel `yaml:"labels" json:"labels,omitempty"`
Reconcile bool `yaml:"reconcile" json:"reconcile,omitempty"`
Conditions []Condition `yaml:"when,omitempty" json:"when,omitempty"`
AnyOf []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`
ForEach *ForEachSpec `yaml:"forEach,omitempty" json:"forEach,omitempty"`
}
PDBTemplateSource declares one PodDisruptionBudget to be managed by Orkestra.
Example:
onReconcile:
pdb:
- name: "{{ .metadata.name }}-pdb"
minAvailable: "1"
selector:
app: "{{ .metadata.name }}"
forEach:
field: spec.services
as: item
type PVCTemplateSource ¶ added in v0.1.9
type PVCTemplateSource struct {
Version string `yaml:"version" json:"version,omitempty"`
// Name — PVC name. Required.
Name string `yaml:"name" json:"name,omitempty"`
// Namespace — target namespace. Default: CR namespace.
Namespace string `yaml:"namespace" json:"namespace,omitempty"`
// StorageClassName — storage class to use. Empty means cluster default.
StorageClassName string `yaml:"storageClassName" json:"storageClassName,omitempty"`
// AccessModes — access modes. Default: ["ReadWriteOnce"].
// Supports: ReadWriteOnce, ReadOnlyMany, ReadWriteMany, ReadWriteOncePod.
AccessModes []string `yaml:"accessModes" json:"accessModes,omitempty"`
// Storage — requested storage size (e.g. "10Gi"). Required.
Storage string `yaml:"storage" json:"storage,omitempty" validate:"required"`
// VolumeMode — Filesystem or Block. Default: Filesystem.
VolumeMode string `yaml:"volumeMode" json:"volumeMode,omitempty"`
// VolumeName — bind to a specific PV by name.
VolumeName string `yaml:"volumeName" json:"volumeName,omitempty"`
Labels []ResourceLabel `yaml:"labels" json:"labels,omitempty"`
Reconcile bool `yaml:"reconcile" json:"reconcile,omitempty"`
Conditions []Condition `yaml:"when,omitempty" json:"when,omitempty"`
AnyOf []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`
ForEach *ForEachSpec `yaml:"forEach,omitempty" json:"forEach,omitempty"`
}
PVCTemplateSource declares one PersistentVolumeClaim to be managed by Orkestra.
type PVTemplateSource ¶ added in v0.1.9
type PVTemplateSource struct {
Version string `yaml:"version" json:"version,omitempty"`
// Name — PV name. Required.
Name string `yaml:"name" json:"name,omitempty"`
// StorageClassName — storage class name.
StorageClassName string `yaml:"storageClassName" json:"storageClassName,omitempty"`
// Capacity — storage capacity (e.g. "10Gi"). Required.
Capacity string `yaml:"capacity" json:"capacity,omitempty" validate:"required"`
// AccessModes — access modes. Default: ["ReadWriteOnce"].
AccessModes []string `yaml:"accessModes" json:"accessModes,omitempty"`
// ReclaimPolicy — Retain, Delete, or Recycle. Default: Retain.
ReclaimPolicy string `yaml:"reclaimPolicy" json:"reclaimPolicy,omitempty"`
// HostPath — host path for HostPath volume type. Used for local/dev PVs.
HostPath string `yaml:"hostPath" json:"hostPath,omitempty"`
// CSI driver fields for cloud/CSI volumes.
CSIDriver string `yaml:"csiDriver" json:"csiDriver,omitempty"`
CSIVolumeHandle string `yaml:"csiVolumeHandle" json:"csiVolumeHandle,omitempty"`
Labels []ResourceLabel `yaml:"labels" json:"labels,omitempty"`
Reconcile bool `yaml:"reconcile" json:"reconcile,omitempty"`
Conditions []Condition `yaml:"when,omitempty" json:"when,omitempty"`
AnyOf []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`
ForEach *ForEachSpec `yaml:"forEach,omitempty" json:"forEach,omitempty"`
}
PVTemplateSource declares one PersistentVolume to be managed by Orkestra. PersistentVolumes are cluster-scoped — Namespace is ignored.
type PlaceholderSource ¶
type PlaceholderSource struct{}
Placeholder for resources yet to be added to orkestra internal registry pkg/orkestra-registry
type PodTemplateSource ¶
type PodTemplateSource struct {
// Version — OrkestraRegistry implementation version. Omit for latest.
Version string `yaml:"version" json:"version,omitempty" validate:"omitempty"`
// Name — Pod name.
// Default when omitted: "{{ .metadata.name }}-pod"
Name string `yaml:"name" json:"name,omitempty" validate:"omitempty"`
// Image — container image. Required.
// Static: "busybox:1.35" or Dynamic: "{{ .spec.image }}"
Image string `yaml:"image" json:"image" validate:"omitempty"`
// Port — container port as a string.
// Static: "8080" or Dynamic: "{{ .spec.port }}"
Port string `yaml:"port" json:"port,omitempty" validate:"omitempty"`
// Namespace — target namespace.
// Default when omitted: "{{ .metadata.namespace }}"
Namespace string `yaml:"namespace" json:"namespace,omitempty" validate:"omitempty"`
// Labels — applied to Pod metadata. Values support template expressions.
Labels []ResourceLabel `yaml:"labels" json:"labels,omitempty" validate:"omitempty"`
// Annotations — applied to Pod metadata. Values support template expressions.
Annotations []ResourceLabel `yaml:"annotations" json:"annotations,omitempty" validate:"omitempty"`
// Resources — static CPU and memory requests/limits.
Resources *ResourceRequirements `yaml:"resources" json:"resources,omitempty" validate:"omitempty"`
Conditions []Condition `yaml:"when,omitempty" json:"when,omitempty"`
// ForEach declares dynamic expansion over a list field.
// When set, one source declaration becomes N declarations — one per list element.
// .item and .<as> are available in template expressions within this declaration.
ForEach *ForEachSpec `yaml:"forEach,omitempty" json:"forEach,omitempty"`
// AnyOf holds OR conditions — at least one must pass for this resource to be created.
// Works alongside the existing Conditions (when:) field which uses AND semantics.
AnyOf []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`
}
PodTemplateSource declares one Pod to be managed by Orkestra.
Prefer DeploymentTemplateSource for long-running workloads. Deployments manage Pod restarts, rolling updates, and replica sets automatically. Use PodTemplateSource only when you need direct, single-instance Pod control.
Example:
onCreate:
pods:
- name: "{{ .metadata.name }}-worker"
image: "{{ .spec.workerImage }}"
port: "9090"
type Provider ¶
type Provider interface {
// Name returns the YAML block key this provider handles.
// Must be unique across all registered providers.
// Convention: lowercase, no hyphens (e.g. "aws", "database", "stripe").
Name() string
// Reconcile is called after all Kubernetes resources are reconciled.
// It should bring external resources into alignment with the declared state.
// Must be idempotent — called on every resync, not just on first creation.
//
// Return nil when:
// - External resource already matches desired state (no-op)
// - External resource was successfully created or updated
// - Resource is still provisioning (check again next cycle)
// - Declaration kind is unknown (log a warning, skip, return nil)
//
// Return non-nil error when:
// - External API is unreachable
// - Credentials are invalid or expired
// - A hard quota is exceeded
// - Any condition that will not resolve on the next retry without intervention
Reconcile(ctx context.Context, req ReconcileRequest) error
// Delete is called during finalizer execution before the CR is removed.
// It should delete all external resources created for this CR.
// Must be idempotent — if the resource does not exist, return nil.
//
// The finalizer is NOT removed until Delete returns nil.
// Returning an error leaves the CR stuck in deletion — ensure
// transient errors are retried and permanent errors are surfaced clearly.
Delete(ctx context.Context, req DeleteRequest) error
}
Provider handles one named block in the Katalog's provider sections.
Implement this interface to extend Orkestra with external resource management. Register your implementation at startup via ProviderRegistry.Register.
Both Reconcile and Delete must be idempotent. They are called on every reconcile cycle and every finalizer execution respectively.
type ProviderBlock ¶
type ProviderBlock struct {
// Name is the provider block key — matches Provider.Name().
Name string
// Declarations is the ordered list of resource declarations in this block.
// Each declaration specifies one external resource to manage.
Declarations []RawProviderDeclaration
}
ProviderBlock is one named provider section from the operatorBox.providers map. The Name comes from the map key ("aws", "mongodb"). Declarations come from the list under that key.
This is the parsed, structured form used at runtime. The raw YAML map is parsed into this during Katalog loading.
func ParseProviderBlocks ¶
func ParseProviderBlocks(raw map[string][]map[string]interface{}) ([]ProviderBlock, error)
ParseProviderBlocks converts the raw YAML map from the providers: key into a structured []ProviderBlock. Called during Katalog loading after YAML unmarshal.
Input (from YAML unmarshal):
map[string][]map[string]interface{}{
"aws": [
{"s3": {"bucket": "my-bucket", "region": "us-east-1"}},
{"rds": {"instanceClass": "db.t3.micro", "engine": "postgres"}},
],
"mongodb": [
{"database": {"name": "mydb"}},
],
}
Output:
[]ProviderBlock{
{Name: "aws", Declarations: [
{Kind: "s3", Fields: {"bucket": "my-bucket", "region": "us-east-1"}},
{Kind: "rds", Fields: {"instanceClass": "db.t3.micro", "engine": "postgres"}},
]},
{Name: "mongodb", Declarations: [
{Kind: "database", Fields: {"name": "mydb"}},
]},
}
type ProviderDeclaration ¶
type ProviderDeclaration struct {
// Kind is the first key in the YAML map entry: "rds", "s3", "product", "widget".
Kind string
// Fields are the resolved key-value pairs. Values are always strings —
// template resolution produces strings; type conversion is the provider's
// responsibility.
Fields map[string]string
}
ProviderDeclaration is one resolved declaration from the YAML block.
For this Katalog block:
aws:
- rds:
instanceClass: "{{ .spec.instanceClass }}"
engine: postgres
- s3:
bucket: "my-bucket"
Orkestra produces two ProviderDeclarations:
{Kind: "rds", Fields: {"instanceClass": "db.t3.micro", "engine": "postgres"}}
{Kind: "s3", Fields: {"bucket": "my-bucket"}}
Template expressions have been resolved — Fields values are plain strings. Nested YAML maps are flattened with dot notation:
credentials: secretName: my-secret
becomes Fields["credentials.secretName"] = "my-secret"
func (ProviderDeclaration) Field ¶
func (d ProviderDeclaration) Field(key, defaultValue string) string
Field returns a field value with a default if the key is absent.
type ProviderRegistry ¶
type ProviderRegistry interface {
// Register adds a provider. Panics if a provider with the same name is
// already registered — fail fast at startup rather than silently ignoring.
Register(p Provider)
// Get returns the provider for the given block name and true, or nil and
// false if no provider is registered for that name.
Get(name string) (Provider, bool)
// Names returns all registered provider names.
// Used by the validator to warn on unknown blocks in the Katalog.
Names() []string
// Len returns the number of registered providers.
Len() int
}
ProviderRegistry holds all registered providers. Thread-safe — providers are registered at startup and read concurrently during reconcile.
func NewProviderRegistry ¶
func NewProviderRegistry() ProviderRegistry
NewProviderRegistry returns an empty ProviderRegistry.
func NoOpProviderRegistry ¶
func NoOpProviderRegistry() ProviderRegistry
NoOpProviderRegistry returns a registry with no providers registered. Used in tests and in reconcilers that do not use provider blocks.
type Queue ¶
type Queue struct {
// Default: false — each CRD gets its own isolated workqueue.
Default *bool `yaml:"default" json:"default,omitempty"`
// MaxQueueDepth — maximum number of items in the per-CRD queue.
// New items are rejected when the queue is full.
// 0 → uses Orkestra-level default set by MAX_QUEUE_DEPTH env var.
MaxQueueDepth int `yaml:"maxQueueDepth" json:"maxQueueDepth,omitempty" validate:"omitempty,gte=0"`
// DegradeThreshold — number of consecutive reconcile failures before the
// CRD health state transitions from healthy to degraded.
// 0 → uses Orkestra-level default.
DegradeThreshold int `yaml:"degradeThreshold" json:"degradeThreshold,omitempty" validate:"omitempty,gte=0"`
}
type RBACConfig ¶
type RBACConfig struct {
// Enabled controls whether RBAC is applied at startup.
// Default: true when the rbac block is declared.
Enabled *bool `yaml:"enabled,omitempty"`
// CleanupOnShutdown controls whether RBAC is deleted on graceful shutdown.
// Default: false — RBAC persists across restarts.
CleanupOnShutdown bool `yaml:"cleanupOnShutdown,omitempty"`
}
RBACConfig controls RBAC auto-apply behaviour.
type RawProviderDeclaration ¶
type RawProviderDeclaration struct {
// Kind is the resource type within the provider block.
// Derived from the single key in the YAML map entry.
// Examples: "s3", "rds", "route53", "database", "user", "collection"
Kind string
// Fields are the raw (unresolved) key-value pairs for this declaration.
// Nested YAML maps are flattened with dot notation:
// credentials:
// secretName: my-secret
// becomes Fields["credentials.secretName"] = "my-secret"
//
// Values may contain template expressions — resolved by the template
// resolver before the provider is called.
Fields map[string]string
// Conditions are the when: conditions from this declaration (AND semantics).
// Evaluated by Orkestra before calling the provider — declarations
// whose conditions fail are removed from the list before dispatch.
Conditions []Condition `yaml:"when,omitempty"`
// AnyOf holds OR conditions — at least one must pass.
AnyOf []Condition `yaml:"anyOf,omitempty"`
}
RawProviderDeclaration is one item in a provider block list. At parse time, template expressions are NOT yet resolved — they contain raw strings like "{{ .metadata.name }}" which are resolved at reconcile time.
YAML shape (one list item under aws: or mongodb:):
- s3: bucket: "{{ .metadata.name }}-assets" region: "{{ .spec.region }}" versioning: "true" when:
- field: spec.enableStorage equals: "true"
Parses into:
RawProviderDeclaration{
Kind: "s3",
Fields: map[string]string{
"bucket": "{{ .metadata.name }}-assets",
"region": "{{ .spec.region }}",
"versioning": "true",
},
Conditions: []Condition{{Field: "spec.enableStorage", Equals: "true"}},
}
type ReconcileRequest ¶
type ReconcileRequest struct {
// Object is the full CR as an unstructured map.
// Identical to the data available in Katalog template expressions.
// Access patterns:
// spec: obj["spec"].(map[string]interface{})["fieldName"]
// status: obj["status"].(map[string]interface{})["phase"]
// children: obj["children"].(map[string]interface{})["deployment"]
Object map[string]interface{}
// Declarations are the pre-resolved provider block declarations.
// Template expressions have already been evaluated against the CR.
// Conditions have already been evaluated — only passing declarations arrive.
// Each entry corresponds to one item in the YAML list.
Declarations []ProviderDeclaration
// Kube provides read-only access to cluster resources.
// Use to read Secrets for credentials and ConfigMaps for configuration.
Kube KubeReader
// Logger is a structured logger pre-tagged with crd, resource, request_id.
Logger zerolog.Logger
// OwnerName is the CR's metadata.name.
OwnerName string
// OwnerNamespace is the CR's metadata.namespace.
OwnerNamespace string
}
ReconcileRequest carries everything a provider needs for one reconcile cycle.
type RegistryRef ¶
type RegistryRef struct {
// Branch — track a branch (e.g. "main", "develop").
// The latest commit on the branch is fetched.
Branch string `yaml:"branch,omitempty"`
// Version — pin to a release tag (e.g. "v1.2.0", "v2").
// Git tags are fetched — version is used as the tag name.
Version string `yaml:"version,omitempty"`
// SHA — pin to an exact commit hash.
// The full or partial SHA works (Git resolves partial SHAs).
SHA string `yaml:"sha,omitempty"`
}
RegistryRef declares how to resolve a specific item from the registry. Exactly one of Branch, SHA, or Version should be set. When none are set, defaults to the default branch of the registry.
Example:
website: branch: main # track a branch platform-namespace: version: v1.2.0 # pin to a release tag application: sha: abc123def456 # pin to an exact commit
func (RegistryRef) IsDefault ¶
func (r RegistryRef) IsDefault() bool
IsDefault reports whether no ref is explicitly set.
func (RegistryRef) Ref ¶
func (r RegistryRef) Ref() string
Ref returns the effective git ref for this RegistryRef. Priority: SHA > Version > Branch > "main" (default).
type RegistrySource ¶
type RegistrySource struct {
// URL — the registry URL.
//
// Git: https://github.com/myorg/orkestra-registry
// OCI: ghcr.io/konduktor-io/orkestra-registry/postgres
//
// Shorthand — embed version with @:
// ghcr.io/konduktor-io/orkestra-registry/postgres@v14
// https://github.com/myorg/registry@main
//
// When @ is present, Version field is ignored.
URL string `yaml:"url" validate:"required"`
// Version — the version, tag, branch, or SHA to pull.
//
// For OCI: semantic version tag "v14", "v14.2.0"
// For Git: branch, tag, or SHA "main", "v1.0.0", "abc123"
//
// Ignored when URL contains @.
// Defaults to "main" for Git, "latest" for OCI when not set.
Version string `yaml:"version,omitempty"`
// OCI — when true, pull the pattern as an OCI artifact.
// When false (default), pull via Git clone or raw file fetch.
//
// OCI artifacts are pulled using the ORAS protocol.
// GitHub and GitLab URLs with oci: false use raw file HTTP — no clone needed.
// Other Git URLs with oci: false use git clone.
OCI bool `yaml:"oci,omitempty"`
// UseKomposer — when true, load komposer.yaml from the pulled pattern.
// When false (default), load katalog.yaml.
//
// Exactly one file is loaded — not both.
//
// UseKomposer: false (default)
// Use this when you want the CRD definitions and will override them
// inline in your own Komposer. This is the common case.
//
// UseKomposer: true
// Use this when you want to accept the upstream operator's full
// source tree as-is — their sources, their defaults, everything.
// Useful for internal teams with a canonical registry where the
// upstream Komposer is exactly what you want to run.
//
// Warning: loading a Komposer from a registry source means that
// Komposer's own sources are also resolved. A Komposer that sources
// other Katalogs will pull those too. Understand the upstream
// dependency tree before enabling this.
UseKomposer bool `yaml:"useKomposer,omitempty"`
// Auth — optional authentication for the registry.
// When empty, requests are unauthenticated.
// Auth credentials are resolved from environment variables — never literals.
Auth *FileSourceAuth `yaml:"auth,omitempty"`
// Katalog — map of katalog names to their version references.
// Key: katalog name (directory name under registry/katalogs/).
// Value: version reference (branch, sha, or version tag).
Katalog map[string]RegistryRef `yaml:"katalog,omitempty"`
}
RegistrySource is one entry in sources.registry.
func (RegistrySource) ResolvedURL ¶
func (r RegistrySource) ResolvedURL() (cleanURL, version string)
ResolvedURL returns the effective URL with the version extracted. Handles both the @ shorthand and the explicit Version field.
Returns (cleanURL, version). cleanURL is the URL without the @ suffix. version is the resolved version string (never empty).
func (RegistrySource) SourceFile ¶
func (r RegistrySource) SourceFile() string
SourceFile returns the filename Orkestra should load after pulling the pattern. Either "katalog.yaml" or "komposer.yaml" — never both.
type ReplicaSetTemplateSource ¶ added in v0.2.3
type ReplicaSetTemplateSource struct {
// Version — OrkestraRegistry implementation version to use. Omit for latest.
Version string `yaml:"version" json:"version,omitempty" validate:"omitempty"`
// Name — ReplicaSet and primary container name.
// Supports template expressions.
// Default when omitted: "{{ .metadata.name }}-replicaset"
Name string `yaml:"name" json:"name,omitempty" validate:"omitempty"`
// Image — container image. Required (must be declared here or resolvable from CR).
// Static: "nginx:1.25"
// Dynamic: "{{ .spec.image }}"
Image string `yaml:"image" json:"image" validate:"omitempty"`
// Replicas — number of pod replicas as a string.
// Static: "3"
// Dynamic: "{{ .spec.replicas }}"
// Default: "1"
Replicas string `yaml:"replicas" json:"replicas,omitempty" validate:"omitempty"`
// Port — primary container port as a string.
// Static: "8080"
// Dynamic: "{{ .spec.port }}"
// Omit to expose no port.
Port string `yaml:"port" json:"port,omitempty" validate:"omitempty"`
// Namespace — target namespace for the ReplicaSet.
// Default when omitted: "{{ .metadata.namespace }}" (same namespace as the CR).
Namespace string `yaml:"namespace" json:"namespace,omitempty" validate:"omitempty"`
// Labels — applied to the ReplicaSet ObjectMeta and the pod template.
// Label values support template expressions.
// Orkestra always adds: managed-by=orkestra, orkestra-owner=<cr-name>
Labels []ResourceLabel `yaml:"labels" json:"labels,omitempty" validate:"omitempty"`
// Annotations — applied to the ReplicaSet ObjectMeta only.
// Annotation values support template expressions.
Annotations []ResourceLabel `yaml:"annotations" json:"annotations,omitempty" validate:"omitempty"`
// Resources — CPU and memory requests/limits for the primary container.
// Values are static Kubernetes quantity strings.
// Template expressions are not supported in resource quantities.
Resources *ResourceRequirements `yaml:"resources" json:"resources,omitempty" validate:"omitempty"`
// Env — environment variables for the primary container.
// Keys are env var names. Values support template expressions.
Env map[string]EnvVarSource `yaml:"env" json:"env,omitempty"`
EnvFrom []EnvFromSource `yaml:"envFrom,omitempty" json:"envFrom,omitempty"`
// Reconcile: true — also apply this declaration as drift correction on every
// reconcile. Equivalent to declaring the same entry under both onCreate and
// onReconcile. When false (default), only runs on onCreate (idempotent create).
Reconcile bool `yaml:"reconcile" json:"reconcile,omitempty" validate:"omitempty"`
// Conditions (when) — AND semantics.
Conditions []Condition `yaml:"when,omitempty" json:"when,omitempty"`
// ForEach declares dynamic expansion over a list field.
ForEach *ForEachSpec `yaml:"forEach,omitempty" json:"forEach,omitempty"`
// AnyOf holds OR conditions — at least one must pass for this resource.
AnyOf []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`
// WorkingDirectory sets the container's working directory (container.WorkingDir).
WorkingDirectory string `yaml:"workingDirectory,omitempty" json:"workingDirectory,omitempty"`
}
ReplicaSetTemplateSource declares one ReplicaSet to be managed by Orkestra.
Declare under onCreate to create the ReplicaSet on first reconcile. Declare under onReconcile to apply drift correction on every reconcile. Declare under both to get idempotent creation and drift correction together.
Minimal example — static values only:
onCreate:
replicasets:
- image: nginx:1.25
replicas: "3"
port: "8080"
Full example — dynamic values from the CR:
onCreate:
replicasets:
- name: "{{ .metadata.name }}-app"
image: "{{ .spec.image }}"
replicas: "{{ .spec.replicas }}"
port: "{{ .spec.port }}"
namespace: "{{ .metadata.namespace }}"
labels:
- key: app
value: "{{ .metadata.name }}"
- key: managed-by
value: orkestra
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
type ResourceCheck ¶
ResourceCheck defines how to detect whether a CRD uses a given resource type.
type ResourceLabel ¶
type ResourceLabel struct {
Key string `yaml:"key" json:"key" validate:"required"`
Value string `yaml:"value" json:"value" validate:"required"`
}
ResourceLabel is a single key-value label or annotation pair. When used in hook template declarations, values support Go text/template expressions evaluated against the live CR at reconcile time. e.g. {key: "app", value: "{{ .metadata.name }}"}
func (ResourceLabel) String ¶
func (l ResourceLabel) String() string
type ResourceRequirements ¶
type ResourceRequirements struct {
Requests map[string]string `yaml:"requests" json:"requests,omitempty" validate:"omitempty"`
Limits map[string]string `yaml:"limits" json:"limits,omitempty" validate:"omitempty"`
}
ResourceRequirements mirrors Kubernetes resource requests and limits. Values are static Kubernetes quantity strings — template expressions are not supported here. e.g. requests: {cpu: "100m", memory: "128Mi"}
type ResourceSelector ¶
type ResourceSelector []ResourceLabel
type RestrictedNamespaces ¶
type RestrictedNamespaces []string
RestrictedNamespaces holds the set of restricted namespace patterns.
func (RestrictedNamespaces) IsRestricted ¶
func (r RestrictedNamespaces) IsRestricted(namespace string) bool
IsRestricted reports whether a given namespace matches any restriction. Supports exact matches and simple glob patterns (* prefix or suffix).
func (RestrictedNamespaces) Merge ¶
func (r RestrictedNamespaces) Merge(other RestrictedNamespaces) RestrictedNamespaces
Merge combines two RestrictedNamespaces sets, deduplicating entries. Used when merging Komposer-level and CRD-level restrictions. Since restrictions are additive, a namespace restricted at any level is restricted at all levels — more specific levels cannot remove restrictions.
type RollbackBlock ¶ added in v0.1.9
type RollbackBlock struct {
// Trigger declares when rollback activates.
// Both fields are optional — set one or both.
// When both are set: triggers when ConsecutiveFailures failures
// occur AND those failures all happened within WithinDuration.
Trigger RollbackTrigger `yaml:"trigger"`
// OnRollback declares the resource groups to apply when rollback is active.
// Uses the same grammar as OnReconcile — deployments, services, configMaps, etc.
// Templates may reference .previous.spec.*, .previous.metadata.*, etc.
// which are hydrated from the previous-spec annotation.
OnRollback *HookTemplates `yaml:"onRollback,omitempty"`
}
RollbackBlock declares the rollback behavior for one operatorbox. Declared inside OperatorBoxConfig as Rollback *RollbackBlock.
type RollbackPhase ¶ added in v0.1.9
type RollbackPhase string
RollbackPhase represents the reconciler's rollback state machine. Stored in status.phase — the reconciler reads this on every cycle.
const ( // RollbackPhaseNone — normal reconciliation, no rollback active. RollbackPhaseNone RollbackPhase = "" // RollbackPhaseActive — rollback is active. Normal reconciliation blocked. // The previous spec is being applied. Exits when spec generation changes. RollbackPhaseActive RollbackPhase = "RolledBack" )
type RollbackTrigger ¶ added in v0.1.9
type RollbackTrigger struct {
// ConsecutiveFailures is the number of consecutive reconcile failures
// that triggers rollback. Default: 3.
ConsecutiveFailures int `yaml:"consecutiveFailures,omitempty"`
// WithinDuration is the time window within which ConsecutiveFailures
// must occur for rollback to trigger.
// When omitted: any ConsecutiveFailures consecutive failures trigger rollback,
// regardless of how long ago the first failure occurred.
// When set: only triggers if all failures occurred within this window.
// Example: 3 failures within 5m = trigger; 3 failures over 2 hours = no trigger.
WithinDuration *Duration `yaml:"withinDuration,omitempty"`
}
RollbackTrigger declares the conditions that activate rollback.
func (*RollbackTrigger) EffectiveConsecutiveFailures ¶ added in v0.1.9
func (t *RollbackTrigger) EffectiveConsecutiveFailures() int
EffectiveConsecutiveFailures returns the consecutive failure threshold, applying the default of 3 when not declared.
func (*RollbackTrigger) ShouldTrigger ¶ added in v0.1.9
func (t *RollbackTrigger) ShouldTrigger(failureTimes []time.Time) bool
ShouldTrigger returns true when the failure history meets the rollback criteria.
failures is the list of failure timestamps in reverse chronological order (most recent first). The function checks whether the required number of consecutive failures have occurred within the configured window.
type ScaleTargetRef ¶ added in v0.2.3
type SecretKeyRef ¶
type SecretKeyRef struct {
Name string `yaml:"name" json:"name"`
Key string `yaml:"key" json:"key"`
}
SecretKeyRef selects a key from a Kubernetes Secret. Both Name and Key are required.
type SecretTemplateSource ¶
type SecretTemplateSource struct {
// Version — OrkestraRegistry implementation version. Omit for latest.
Version string `yaml:"version" json:"version,omitempty" validate:"omitempty"`
// Name — Secret name.
// Default when omitted: "{{ .metadata.name }}-secret"
Name string `yaml:"name" json:"name,omitempty" validate:"omitempty"`
// Namespace — target namespace.
// Default when omitted: "{{ .metadata.namespace }}"
Namespace string `yaml:"namespace" json:"namespace,omitempty" validate:"omitempty"`
// Type — Kubernetes Secret type.
// Default: "Opaque"
Type string `yaml:"type" json:"type,omitempty" validate:"omitempty"`
// Data — static key-value entries.
// Values are plain strings — template expressions are not supported here.
// If you need templated or dynamic values, use a custom Go hook.
Data map[string]string `yaml:"data" json:"data,omitempty" validate:"omitempty"`
// Labels — applied to Secret metadata. Values support template expressions.
Labels []ResourceLabel `yaml:"labels" json:"labels,omitempty" validate:"omitempty"`
// Annotations — applied to Secret metadata.
Annotations map[string]string `yaml:"annotations,omitempty" json:"annotations,omitempty"`
// FromSecret — name of an existing Secret to copy data from.
// Orkestra reads this at reconcile time — copies stay in sync with the source.
FromSecret string `yaml:"fromSecret" json:"fromSecret,omitempty" validate:"omitempty"`
// FromNamespace — namespace where FromSecret lives.
// Default: same namespace as the CR.
FromNamespace string `yaml:"fromNamespace" json:"fromNamespace,omitempty" validate:"omitempty"`
// ToNamespaces - a list of target namespaces
// Default when omitted: "{{ .metadata.namespace }}"
ToNamespaces []string `yaml:"toNamespaces" json:"toNamespaces,omitempty" validate:"omitempty"`
// Reconcile: true — also apply this declaration as drift correction on every
// reconcile. Equivalent to declaring the same entry under both onCreate and
// onReconcile. When false (default), only runs on onCreate (idempotent create).
Reconcile bool `yaml:"reconcile" json:"reconcile,omitempty" validate:"omitempty"`
Conditions []Condition `yaml:"when,omitempty" json:"when,omitempty"`
// Once controls idempotent secret generation.
// true — evaluate templates and create only when the Secret does not exist.
// Use with random notes (randomAlphanumeric, randomHex, randomBase64).
// false — standard create/update behavior (default).
Once bool `yaml:"once,omitempty" json:"once,omitempty"`
// ForEach declares dynamic expansion (same as other resource types)
ForEach *ForEachSpec `yaml:"forEach,omitempty" json:"forEach,omitempty"`
// AnyOf holds OR conditions (same as other resource types)
AnyOf []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`
// RotateAfter declares a time-based rotation threshold.
// When set alongside once: true, the Secret is recreated when its age
// exceeds this duration. The creation time is tracked via the annotation:
// orkestra.konductor.io/generated-at: "2026-04-06T08:00:00Z"
//
// Supported formats: 30s, 5m, 12h, 90d, 1y
// Days (d) and years (y) are extensions beyond Go's standard duration format.
//
// Example:
// secrets:
// - name: "{{ .metadata.name }}-credentials"
// once: true
// rotateAfter: 90d
// data:
// password: "{{ randomAlphanumeric 32 }}"
RotateAfter string `yaml:"rotateAfter,omitempty" json:"rotateAfter,omitempty"`
// TLS declares self-signed CA and server certificate generation.
// When set, the data: block is ignored — the Secret is created as type
// kubernetes.io/tls with fields: tls.crt, tls.key, ca.crt
//
// Default Secret name when name is empty: "orkestra-tls"
// Default validFor when empty: same as rotateAfter, or "1y"
//
// Example:
// secrets:
// - name: "{{ .metadata.name }}-tls"
// once: true
// rotateAfter: 1y
// tls:
// commonName: "{{ .metadata.name }}.{{ .metadata.namespace }}.svc"
// dnsNames:
// - "{{ .metadata.name }}"
// - "{{ .metadata.name }}.{{ .metadata.namespace }}"
// - "{{ .metadata.name }}.{{ .metadata.namespace }}.svc"
// - "{{ .metadata.name }}.{{ .metadata.namespace }}.svc.cluster.local"
// validFor: 1y
TLS *TLSSpec `yaml:"tls,omitempty" json:"tls,omitempty"`
}
SecretTemplateSource declares one Secret to be managed by Orkestra.
Secret data values are static — template expressions are not evaluated in Secret data entries. For dynamic configuration, use a custom Go hook.
Example:
onCreate:
secrets:
- name: "{{ .metadata.name }}-credentials"
type: Opaque
data:
USERNAME: admin
PASSWORD: "supersecret"
You may also copy from an existing Secret using FromSecret.
type SelectorMap ¶
Selector map
type ServiceAccountTemplateSource ¶
type ServiceAccountTemplateSource struct {
// Version — OrkestraRegistry implementation version. Omit for latest.
Version string `yaml:"version" json:"version,omitempty" validate:"omitempty"`
// Name — ServiceAccount name.
// Default when omitted: "{{ .metadata.name }}-sa"
Name string `yaml:"name" json:"name,omitempty" validate:"omitempty"`
// Namespace — target namespace.
// Default when omitted: "{{ .metadata.namespace }}"
Namespace string `yaml:"namespace" json:"namespace,omitempty" validate:"omitempty"`
// Labels — applied to ServiceAccount metadata. Values support template expressions.
Labels []ResourceLabel `yaml:"labels" json:"labels,omitempty" validate:"omitempty"`
Conditions []Condition `yaml:"when,omitempty" json:"when,omitempty"`
// Reconcile: true — also apply this declaration as drift correction on every
// reconcile. Equivalent to declaring the same entry under both onCreate and
// onReconcile. When false (default), only runs on onCreate (idempotent create).
Reconcile bool `yaml:"reconcile" json:"reconcile,omitempty" validate:"omitempty"`
// ForEach declares dynamic expansion over a list field.
// When set, one source declaration becomes N declarations — one per list element.
// .item and .<as> are available in template expressions within this declaration.
ForEach *ForEachSpec `yaml:"forEach,omitempty" json:"forEach,omitempty"`
// AnyOf holds OR conditions — at least one must pass for this resource to be created.
// Works alongside the existing Conditions (when:) field which uses AND semantics.
AnyOf []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`
}
ServiceAccountTemplateSource declares one ServiceAccount to be managed by Orkestra.
Example:
onCreate:
serviceAccounts:
- name: "{{ .metadata.name }}-sa"
namespace: "{{ .metadata.namespace }}"
labels:
- key: app
value: "{{ .metadata.name }}"
type ServiceTemplateSource ¶
type ServiceTemplateSource struct {
// Version — OrkestraRegistry implementation version. Omit for latest.
Version string `yaml:"version" json:"version,omitempty" validate:"omitempty"`
// Name — Service name.
// Default when omitted: "{{ .metadata.name }}-svc"
Name string `yaml:"name" json:"name,omitempty" validate:"omitempty"`
// Type — Kubernetes Service type.
// Accepted values: ClusterIP, NodePort, LoadBalancer.
// Default: ClusterIP.
Type string `yaml:"type" json:"type,omitempty" validate:"omitempty"`
// Port — Service port as a string.
// Static: "80" or Dynamic: "{{ .spec.servicePort }}"
Port string `yaml:"port" json:"port" validate:"omitempty"`
// TargetPort — container port the Service routes traffic to.
// Static: "8080" or Dynamic: "{{ .spec.containerPort }}"
TargetPort string `yaml:"targetPort" json:"targetPort,omitempty" validate:"omitempty"`
// Namespace — target namespace.
// Default when omitted: "{{ .metadata.namespace }}"
Namespace string `yaml:"namespace" json:"namespace,omitempty" validate:"omitempty"`
// Labels — applied to Service metadata. Values support template expressions.
Labels []ResourceLabel `yaml:"labels" json:"labels,omitempty" validate:"omitempty"`
// Selector filters which pods this service will route traffic to
// Useful in forEach situations where the labels would likely be the same
Selector SelectorMap `yaml:"selector" json:"selector,omitempty" validate:"omitempty"`
// Reconcile: true — also apply this declaration as drift correction on every
// reconcile. Equivalent to declaring the same entry under both onCreate and
// onReconcile. When false (default), only runs on onCreate (idempotent create).
Reconcile bool `yaml:"reconcile" json:"reconcile,omitempty" validate:"omitempty"`
Conditions []Condition `yaml:"when,omitempty" json:"when,omitempty"`
// ForEach declares dynamic expansion over a list field.
// When set, one source declaration becomes N declarations — one per list element.
// .item and .<as> are available in template expressions within this declaration.
ForEach *ForEachSpec `yaml:"forEach,omitempty" json:"forEach,omitempty"`
// AnyOf holds OR conditions — at least one must pass for this resource to be created.
// Works alongside the existing Conditions (when:) field which uses AND semantics.
AnyOf []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`
}
ServiceTemplateSource declares one Service to be managed by Orkestra.
Example:
onCreate:
services:
- name: "{{ .metadata.name }}-svc"
type: ClusterIP
port: "80"
targetPort: "8080"
namespace: "{{ .metadata.namespace }}"
labels:
- key: app
value: "{{ .metadata.name }}"
type StatefulSetTemplateSource ¶ added in v0.1.9
type StatefulSetTemplateSource struct {
Version string `yaml:"version" json:"version,omitempty"`
// Name — StatefulSet name. Default: "{{ .metadata.name }}".
Name string `yaml:"name" json:"name,omitempty"`
// Namespace — target namespace. Default: CR namespace.
Namespace string `yaml:"namespace" json:"namespace,omitempty"`
// Image — container image. Required.
Image string `yaml:"image" json:"image,omitempty" validate:"required"`
// Tag — image tag. Default: "latest".
Tag string `yaml:"tag" json:"tag,omitempty"`
// Replicas — number of pod replicas. Default: "1".
Replicas string `yaml:"replicas" json:"replicas,omitempty"`
// Port — container port. "0" or empty means no port exposed.
Port string `yaml:"port" json:"port,omitempty"`
// ServiceName — name of the headless Service governing the StatefulSet.
// Default: same as Name.
ServiceName string `yaml:"serviceName" json:"serviceName,omitempty"`
// StorageClass — storage class for auto-generated VolumeClaimTemplates.
StorageClass string `yaml:"storageClass" json:"storageClass,omitempty"`
// StorageSize — size of each volume claim (e.g. "10Gi"). Required when StorageClass is set.
StorageSize string `yaml:"storageSize" json:"storageSize,omitempty"`
// MountPath — mount path for the storage volume inside the container. Default: "/data".
MountPath string `yaml:"mountPath" json:"mountPath,omitempty"`
Labels []ResourceLabel `yaml:"labels" json:"labels,omitempty"`
Annotations []ResourceLabel `yaml:"annotations" json:"annotations,omitempty"`
Env map[string]EnvVarSource `yaml:"env" json:"env,omitempty"`
EnvFrom []EnvFromSource `yaml:"envFrom,omitempty" json:"envFrom,omitempty"`
Resources *ResourceRequirements `yaml:"resources" json:"resources,omitempty"`
Reconcile bool `yaml:"reconcile" json:"reconcile,omitempty"`
Conditions []Condition `yaml:"when,omitempty" json:"when,omitempty"`
AnyOf []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`
ForEach *ForEachSpec `yaml:"forEach,omitempty" json:"forEach,omitempty"`
}
StatefulSetTemplateSource declares one StatefulSet to be managed by Orkestra.
type StatusConfig ¶
type StatusConfig struct {
// Fields — list of status fields to write after every successful reconcile.
// Resolved in declaration order. Later fields win on path conflict.
Fields []StatusFieldSpec `yaml:"fields,omitempty" json:"fields,omitempty"`
// Conditions — whether to write the standard Ready condition automatically.
// Default: true. Set to false to opt out of automatic condition management.
// When true, Orkestra writes:
// status.conditions[type=Ready]:
// status: "True" | "False"
// reason: ReconcileSucceeded | ReconcileError
// message: "" | "<error message>"
// lastTransitionTime: <now>
// status.observedGeneration: <metadata.generation>
//
// Setting false is rarely needed. Do it only when your CRD's status
// schema explicitly forbids a conditions field, or when you manage
// conditions entirely via Go hooks.
Conditions *bool `yaml:"conditions,omitempty" json:"conditions,omitempty"`
}
StatusConfig declares the declarative status behavior for a CRD. Declared under spec.crds[].reconciler.status in the Katalog.
func (*StatusConfig) ConditionsEnabled ¶
func (s *StatusConfig) ConditionsEnabled() bool
ConditionsEnabled reports whether automatic standard condition management is on. Defaults to true when Conditions is nil.
func (*StatusConfig) HasFields ¶
func (s *StatusConfig) HasFields() bool
HasFields reports whether any declarative status fields are declared.
type StatusFieldSpec ¶
type StatusFieldSpec struct {
// Path — dot-notation path relative to status.
// "phase" → status.phase
// "database.host" → status.database.host
// "ready" → status.ready
Path string `yaml:"path" json:"path" validate:"required"`
// Value — the value to write. Supports template expressions.
// Resolved against the full CR object map at reconcile time.
// Empty string is written as-is — declare a static empty string to clear a field.
Value string `yaml:"value" json:"value"`
// Type — optional explicit type for the resolved value.
// If omitted, the value is written as a string.
//
// Supported values:
// "string", "str, "" (default)
// "int", "integer"
// "float"
// "bool", "boolean"
// "auto" — infer type from the resolved value
Type string `yaml:"type,omitempty" json:"type,omitempty"`
// When is an optional list of conditions that must all pass before
// this field is written. If absent or empty, the field is always written.
//
// All conditions are AND-ed together.
// To express OR logic, declare multiple StatusField entries for the same path.
//
// Conditions are evaluated against the full CR object map — the same
// map available to template expressions. This means .status.phase,
// .spec.image, .children.job.status.succeeded are all accessible.
When []Condition `yaml:"when,omitempty"`
// AnyOf — optional OR-conditions. If any condition passes, the field is written.
// Useful for multi-branch declarative state machines.
AnyOf []Condition `yaml:"anyOf,omitempty"`
}
StatusFieldSpec declares one field to write into the CR's status.
Path is relative to the status subobject. "phase" writes to status.phase. "database.host" writes to status.database.host.
Value supports Go text/template expressions evaluated against the CR:
- "{{ .spec.replicas }}" — from the CR's spec
- "{{ .metadata.name }}" — CR name
- "Running" — static string (fast path, no template parsing)
Type controls how the resolved value is written into the status patch. By default, all values are written as strings. When Type is set, the resolver will cast the resolved value into the requested type:
type: int → writes an integer (e.g., 3) type: float → writes a float64 (e.g., 3.14) type: bool → writes a boolean (e.g., true) type: string → writes a string (default behavior) type: auto → attempts to infer the type from the resolved value
Example:
- path: replicas type: int value: "{{ toInt .spec.replicas }}"
This ensures status.replicas is written as an integer, not a string.
type TLSSpec ¶
type TLSSpec struct {
// CommonName is the certificate's CN field.
// commonName: "{{ .metadata.name }}.{{ .metadata.namespace }}.svc"
CommonName string `yaml:"commonName"`
// DNSNames are the Subject Alternative Names.
// Template expressions supported per entry.
DNSNames []string `yaml:"dnsNames,omitempty"`
// ValidFor is the certificate validity period.
// Default: same as rotateAfter, or 1y if rotateAfter is not set.
// Must be >= rotateAfter to avoid immediate expiry on rotation.
ValidFor string `yaml:"validFor,omitempty"`
// Organization is the cert's O field. Default: "orkestra"
Organization string `yaml:"organization,omitempty"`
}
TLSSpec declares TLS certificate generation for a secret. When set, the secret is created as type kubernetes.io/tls with tls.crt, tls.key, and ca.crt fields.
type TimeWindow ¶
type TimeWindow struct {
// After — active after this time (format: "HH:MM" in 24h).
After string `yaml:"after,omitempty"`
// Before — active before this time (format: "HH:MM" in 24h).
Before string `yaml:"before,omitempty"`
}
TimeWindow declares a clock-based active window.
type ValidationAction ¶
type ValidationAction string
ValidationAction declares what happens when a validation rule fails.
deny (default) — at admission: synchronous rejection, kubectl sees the error
at reconcile: reconciliation halted until CR is corrected
warn — at admission: Kubernetes Warning header, CR is still stored
at reconcile: recorded as active warning on health API
Default is deny when action is omitted. Warn must be declared explicitly. This is intentional — new rules block by default.
const ( ValidationActionDeny ValidationAction = "deny" ValidationActionWarn ValidationAction = "warn" )
func EffectiveAction ¶
func EffectiveAction(a ValidationAction) ValidationAction
EffectiveAction returns the effective action, defaulting to deny.
func (ValidationAction) IsDeny ¶
func (a ValidationAction) IsDeny() bool
func (ValidationAction) IsWarn ¶
func (a ValidationAction) IsWarn() bool
type ValidationConfig ¶
type ValidationConfig struct {
// Rules — evaluated in declaration order.
// All rules are evaluated before returning — all violations are reported
// together so the user can fix everything in one cycle.
Rules []ValidationRule `yaml:"rules,omitempty" json:"rules,omitempty"`
}
ValidationConfig holds all validation rules for a CRD.
func (*ValidationConfig) HasDenyRules ¶
func (c *ValidationConfig) HasDenyRules() bool
HasDenyRules reports whether any rules use action: deny (or the default). Used to decide whether to register a ValidatingWebhookConfiguration.
func (*ValidationConfig) HasWarnRules ¶
func (c *ValidationConfig) HasWarnRules() bool
HasWarnRules reports whether any rules use action: warn.
type ValidationRule ¶
type ValidationRule struct {
// Field — dot-notation path to the CR field being validated.
// e.g. "spec.image", "metadata.labels.tier", "spec.db.engine"
Field string `yaml:"field" json:"field" validate:"required"`
// Message — shown in the Kubernetes event, webhook response, and operator
// log when this rule is violated. Make it actionable.
Message string `yaml:"message" json:"message" validate:"required"`
// Action — what happens when this rule fails.
// deny (default): block at admission, halt at reconcile.
// warn: warning at admission, advisory at reconcile.
Action ValidationAction `yaml:"action,omitempty" json:"action,omitempty"`
// Shorthands — use these for the common cases.
Equals string `yaml:"equals,omitempty" json:"equals,omitempty"`
NotEquals string `yaml:"notEquals,omitempty" json:"notEquals,omitempty"`
Prefix string `yaml:"prefix,omitempty" json:"prefix,omitempty"`
Suffix string `yaml:"suffix,omitempty" json:"suffix,omitempty"`
Contains string `yaml:"contains,omitempty" json:"contains,omitempty"`
Min string `yaml:"min,omitempty" json:"min,omitempty"` // numeric, inclusive
Max string `yaml:"max,omitempty" json:"max,omitempty"` // numeric, inclusive
GreaterThan string `yaml:"greaterThan,omitempty" json:"greaterThan,omitempty"`
LessThan string `yaml:"lessThan,omitempty" json:"lessThan,omitempty"`
// Explicit operator form — use when no shorthand covers the comparison.
Operator ConditionOperator `yaml:"operator,omitempty" json:"operator,omitempty"`
Value string `yaml:"value,omitempty" json:"value,omitempty"`
ValueType string `yaml:"valueType,omitempty"` // "string", "int", "bool"
}
ValidationRule declares one constraint on a CR field.
Shorthands (prefix, suffix, equals, etc.) exist so common rules read without boilerplate. Exactly one shorthand or an explicit operator+value pair should be set per rule.
Example — deny:
- field: spec.image prefix: "myorg/" message: "image must be from myorg registry" action: deny
Example — warn, advisory only:
- field: metadata.labels.team operator: exists message: "all resources should declare a team owner" action: warn
Example — numeric bound:
- field: spec.replicas max: "10" message: "replicas cannot exceed 10"
type WebhooksConfig ¶
type WebhooksConfig struct {
// Admission controls the ValidatingWebhookConfiguration and MutatingWebhookConfiguration.
Admission *AdmissionWebhookToggle `yaml:"admission,omitempty"`
// FailurePolicy controls what the API server does when Orkestra is unreachable
// for admission calls. "Fail" or "Ignore".
// Default: WEBHOOKS_FAILURE_POLICY env / "Ignore".
FailurePolicy string `yaml:"failurePolicy,omitempty"`
// ServiceName is the Kubernetes Service fronting Orkestra's HTTPS server.
// Shared with deletion protection when both are enabled.
// Default: ORKESTRA_SERVICE_NAME env / "orkestra".
ServiceName string `yaml:"serviceName,omitempty"`
// CleanupOnShutdown controls whether Admission webhook is deleted on graceful shutdown.
// Default: false — Admission webhook persists across restarts.
CleanupOnShutdown bool `yaml:"cleanupOnShutdown,omitempty"`
}
WebhooksConfig controls global admission webhook settings. Conversion is declared separately under security.conversion.
Source Files
¶
- admission.go
- autoscale.go
- conditions.go
- conversion.go
- cross.go
- docker.go
- enrichment.go
- external.go
- foreach.go
- func.go
- git.go
- katalog.go
- katalog_spec_providers.go
- methods.go
- normalize.go
- notification.go
- ns_allowed.go
- ns_restricted.go
- provider.go
- provider_katalog.go
- registry.go
- resource_check.go
- rollback.go
- secret_rotation.go
- security.go
- sources.go
- status.go
- types.go
- when.go