types

package
v0.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 11, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

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/motif.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.orkspace.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:

  1. Deletion protection — webhook that blocks deletion of managed CRDs and the operator itself.
  2. Admission webhooks — ValidatingWebhookConfiguration and MutatingWebhookConfiguration.
  3. Conversion — CRD version conversion via /convert (separate from webhooks).

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 KomposeRuntimeKatalog.

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

View Source
const (
	// AnnotationGeneratedAt is the RFC3339 timestamp when the secret was last generated.
	AnnotationGeneratedAt = "orkestra.orkspace.io/generated-at"

	// AnnotationRotateAfter stores the declared rotation duration.
	AnnotationRotateAfter = "orkestra.orkspace.io/rotate-after"
)
View Source
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"
)
View Source
const PreviousSpecAnnotation = "orkestra.orkspace.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.

View Source
const RollbackGenerationAnnotation = "orkestra.orkspace.io/rollback-at-generation"

RollbackGenerationAnnotation records the generation at which rollback was last triggered. Used to detect spec changes that should exit rollback.

Variables

View Source
var HookRegistry = map[schema.GroupVersionKind]func() domain.AnyReconcileHooks{}
View Source
var ListRegistry = map[schema.GroupVersionKind]func() runtime.Object{}
View Source
var ObjectRegistry = map[schema.GroupVersionKind]func() runtime.Object{}
View Source
var ReconcilerRegistry = map[schema.GroupVersionKind]NewReconcilerFunc{}
View Source
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.

View Source
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) []RoleTemplateSource { return t.Roles }) ||
				usesTemplates(rc.OnReconcile, func(t *HookTemplates) []RoleTemplateSource { return t.Roles }) ||
				usesTemplates(rc.OnDelete, func(t *HookTemplates) []RoleTemplateSource { return t.Roles })
		},
	},

	"rolebindings": {
		Get: func(crd CRDEntry) bool {
			rc := crd.OperatorBox
			return usesTemplates(rc.OnCreate, func(t *HookTemplates) []RoleBindingTemplateSource { return t.RoleBindings }) ||
				usesTemplates(rc.OnReconcile, func(t *HookTemplates) []RoleBindingTemplateSource { return t.RoleBindings }) ||
				usesTemplates(rc.OnDelete, func(t *HookTemplates) []RoleBindingTemplateSource { 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.

View Source
var SchemeAdderFns []func(*runtime.Scheme) error

SchemeAdderFns holds AddToScheme functions collected from generated init() calls. Each generated zz_generated_runtime_registry.go appends to this slice in its init(); NewSchemeRegistry drains it via RegisterTypedScheme. This is the bridge between the user's generated package and the Orkestra internal pkg/runtime stub — no explicit call needed beyond the blank import.

Functions

func EvaluateOneCond

func EvaluateOneCond(data map[string]interface{}, cond Condition) bool

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

func EvaluateWhen(data map[string]interface{}, allOf []Condition, anyOf []Condition) bool

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 IsValidProtocol added in v0.3.9

func IsValidProtocol(p string) bool

IsValidProtocol reports whether the provided protocol is valid. Accepted values (case‑insensitive):

  • TCP
  • UDP
  • SCTP

func IsValidServiceType added in v0.3.9

func IsValidServiceType(t string) bool

IsValidServiceType reports whether the provided service type is valid. Accepted values (case‑insensitive):

  • ClusterIP
  • NodePort
  • LoadBalancer
func NavigateDotPath(m map[string]interface{}, path string) string

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(m map[string]interface{}, path string) interface{}

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

func NeedsRotation(generatedAt, rotateAfter string) bool

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 ParseTimeDuration added in v0.4.2

func ParseTimeDuration(s string) (time.Duration, error)

ParseTimeDuration 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. "Platform"
	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 Admission added in v0.3.9

type Admission struct {
	Validation *ValidationConfig
	Mutation   *MutationConfig
}

Admission holds validation and mutation configuration for a CRD.

func (*Admission) HasMutationRules added in v0.4.0

func (a *Admission) HasMutationRules() bool

Separate helpers for hasMutationRules and hasValidationRules

func (*Admission) HasValidationOrMutationRules added in v0.4.0

func (a *Admission) HasValidationOrMutationRules() bool

Returns true when either validation or mutation rules are declared.

func (*Admission) HasValidationRules added in v0.4.0

func (a *Admission) HasValidationRules() bool

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" json:"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

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" json:"workers,omitempty"`

	// QueueDepth — maximum queue depth before backpressure.
	QueueDepth *int `yaml:"queueDepth,omitempty" json:"queueDepth,omitempty"`

	// Resync — resync interval override. How frequently all CRs are
	// re-enqueued regardless of changes.
	Resync *Duration `yaml:"resync,omitempty" json:"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

type AutoscaleBaseline struct {
	Workers    int
	QueueDepth int
	Resync     time.Duration
}

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" json:"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" json:"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" json:"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" json:"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" json:"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" json:"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" json:"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 {
	// Participant marks this CRD as a conversion participant without declaring
	// conversion paths. Use this on the stable/storage-version CRD when the
	// conversion paths are declared on the other version. Both CRDs need to
	// be marked (one with paths, one with participant: true) for conversion
	// stats to appear for each in the Control Center.
	Participant bool `yaml:"participant,omitempty" json:"participant,omitempty"`

	// StorageVersion — the version all objects are stored as internally.
	// All conversion paths route through this version.
	StorageVersion string `yaml:"storageVersion,omitempty" json:"storageVersion,omitempty"`

	// 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,omitempty" json:"paths,omitempty"`

	// 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" json:"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"`

	// Imports declares Motif imports for this operatorBox.
	// Each import references a Motif by OCI reference, file path, or short name,
	// and binds its inputs via with:. Resources from imported Motifs are merged
	// into OnReconcile at Katalog load time.
	// Required inputs not provided in with: are a validation error.
	Imports []MotifImport `yaml:"imports,omitempty" json:"imports,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

func (c *CRDEntry) AllowedNamespacesOnly() bool

AllowedNamespacesOnly reports if only allowedNamespaces is defined for this crd.

func (*CRDEntry) AutoScaleProfile

func (c *CRDEntry) AutoScaleProfile() string

AutoScaleProfile returns the string value of the autoscale profile

func (*CRDEntry) AutoscaleEnabled

func (c *CRDEntry) AutoscaleEnabled() bool

AutoscaleEnabled reports whether this CRD declares the autoscale block

func (*CRDEntry) CollectProbeProfileEntries added in v0.4.2

func (c *CRDEntry) CollectProbeProfileEntries() []ProbeProfileEntry

CollectProbeProfileEntries returns all probe profile references declared for this CRD across OnCreate, OnReconcile, and OnDelete. Only entries with a non-empty Profile string are returned — omitted profiles (which fall back to "standard") are not surfaced for validation.

func (*CRDEntry) CollectResourceProfileEntries added in v0.4.2

func (c *CRDEntry) CollectResourceProfileEntries() []ResourceProfileEntry

CollectResourceProfileEntries returns all resources.profile references declared for this CRD across OnCreate, OnReconcile, and OnDelete. Only entries with a non-empty Profile string are returned.

func (*CRDEntry) CollectSleepEntries added in v0.4.2

func (c *CRDEntry) CollectSleepEntries() []SleepEntry

CollectSleepEntries returns all SleepEntry items declared for this CRD across OnCreate, OnReconcile and OnDelete. This is the canonical discovery method callers should use for validation, diagnostics, or runtime wiring.

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

func (c *CRDEntry) ConstructorEnabled() bool

ConstructorEnabled reports whether the reconcile behaviour uses a constructor. Defaults to false when omitted.

func (*CRDEntry) ConstructorManagedResources added in v0.4.1

func (c *CRDEntry) ConstructorManagedResources() []ManagedResource

ConstructorManagedResources returns the list of managed resources declared under the constructor block. Returns nil if constructor is not declared or no resources exist.

func (*CRDEntry) CustomHooksEnabled added in v0.2.0

func (c *CRDEntry) CustomHooksEnabled() bool

CustomHooksEnabled reports whether the reconcile behaviour uses custom hooks. Defaults to false when omitted.

func (*CRDEntry) DefaultQueue

func (c *CRDEntry) DefaultQueue() bool

DefaultQueue reports whether this CRD uses the default queue configuration. Defaults to false when omitted.

func (*CRDEntry) DefaultReconcile

func (c *CRDEntry) DefaultReconcile() bool

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

func (c *CRDEntry) GVKString() string

GVKString returns the fully resolved GroupVersionKind for this CRD as a string.

func (*CRDEntry) GVR

GVR returns the fully resolved GroupVersionResource for this CRD. Used for dynamic client list/watch operations.

func (*CRDEntry) GVRString

func (c *CRDEntry) GVRString() string

GVRString returns the fully resolved GroupVersionResource for this CRD as a string.

func (*CRDEntry) GetDependencies

func (c *CRDEntry) GetDependencies() []string

GetDependencies returns the dependency names for this CRD in sorted order.

func (*CRDEntry) GetRuntimeObjects

func (c *CRDEntry) GetRuntimeObjects() (runtime.Object, runtime.Object)

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

func (c *CRDEntry) HasAllowedNamespaces() bool

HasAllowedNamespaces reports if allowedNamespaces is defined for this crd.

func (*CRDEntry) HasAnyClusterRoleBindings added in v0.4.2

func (c *CRDEntry) HasAnyClusterRoleBindings() bool

HasAnyClusterRoleBindings reports whether this CRD defines any ClusterRoleBindings in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyClusterRoles added in v0.4.2

func (c *CRDEntry) HasAnyClusterRoles() bool

HasAnyClusterRoles reports whether this CRD defines any ClusterRoles in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyConfigMaps added in v0.4.2

func (c *CRDEntry) HasAnyConfigMaps() bool

HasAnyConfigMaps reports whether this CRD defines any ConfigMaps in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyDaemonSets added in v0.4.2

func (c *CRDEntry) HasAnyDaemonSets() bool

HasAnyDaemonSets reports whether this CRD defines any DaemonSets in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyDeployments added in v0.3.8

func (c *CRDEntry) HasAnyDeployments() bool

HasAnyDeployments reports whether this CRD defines any Deployments in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyHPA added in v0.2.3

func (c *CRDEntry) HasAnyHPA() bool

HasAnyHPA reports whether this CRD defines any HPA defined in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyHooks added in v0.1.9

func (c *CRDEntry) HasAnyHooks() bool

HasAnyHooks reports whether this CRD declares any onCreate, onReconcile, or onDelete hooks.

func (*CRDEntry) HasAnyIngresses added in v0.4.2

func (c *CRDEntry) HasAnyIngresses() bool

HasAnyIngresses reports whether this CRD defines any Ingresses in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyLimitRanges added in v0.4.2

func (c *CRDEntry) HasAnyLimitRanges() bool

HasAnyLimitRanges reports whether this CRD defines any LimitRanges in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyNamespaces added in v0.4.2

func (c *CRDEntry) HasAnyNamespaces() bool

HasAnyNamespaces reports whether this CRD defines any Namespaces in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyNetworkPolicies added in v0.4.2

func (c *CRDEntry) HasAnyNetworkPolicies() bool

HasAnyNetworkPolicies reports whether this CRD defines any NetworkPolicies in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyPersistentVolumeClaims added in v0.4.2

func (c *CRDEntry) HasAnyPersistentVolumeClaims() bool

HasAnyPersistentVolumeClaims reports whether this CRD defines any PVCs in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyPersistentVolumes added in v0.4.2

func (c *CRDEntry) HasAnyPersistentVolumes() bool

HasAnyPersistentVolumes reports whether this CRD defines any PersistentVolumes in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyPodDisruptionBudgets added in v0.4.2

func (c *CRDEntry) HasAnyPodDisruptionBudgets() bool

HasAnyPodDisruptionBudgets reports whether this CRD defines any PDBs in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyPodSecurityPolicies added in v0.4.2

func (c *CRDEntry) HasAnyPodSecurityPolicies() bool

HasAnyPodSecurityPolicies reports whether this CRD defines any PSPs in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyPodTemplates added in v0.4.2

func (c *CRDEntry) HasAnyPodTemplates() bool

HasAnyPodTemplates reports whether this CRD defines any PodTemplates in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyPods added in v0.4.2

func (c *CRDEntry) HasAnyPods() bool

HasAnyPods reports whether this CRD defines any Pods in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyPriorityClasses added in v0.4.2

func (c *CRDEntry) HasAnyPriorityClasses() bool

HasAnyPriorityClasses reports whether this CRD defines any PriorityClasses in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyPriorityLevelConfigurations added in v0.4.2

func (c *CRDEntry) HasAnyPriorityLevelConfigurations() bool

HasAnyPriorityLevelConfigurations reports whether this CRD defines any PL configs in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyReplicaSets added in v0.3.8

func (c *CRDEntry) HasAnyReplicaSets() bool

HasAnyReplicaSets reports whether this CRD defines any ReplicaSets in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyResourceQuotas added in v0.4.2

func (c *CRDEntry) HasAnyResourceQuotas() bool

HasAnyResourceQuotas reports whether this CRD defines any ResourceQuotas in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyRoleBindings added in v0.4.2

func (c *CRDEntry) HasAnyRoleBindings() bool

HasAnyRoleBindings reports whether this CRD defines any RoleBindings in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyRoles added in v0.4.2

func (c *CRDEntry) HasAnyRoles() bool

HasAnyRoles reports whether this CRD defines any Roles in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyRuntimeClasses added in v0.4.2

func (c *CRDEntry) HasAnyRuntimeClasses() bool

HasAnyRuntimeClasses reports whether this CRD defines any RuntimeClasses in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnySecrets added in v0.2.3

func (c *CRDEntry) HasAnySecrets() bool

HasAnySecrets reports whether this CRD defines any secrets in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyServiceAccounts added in v0.4.2

func (c *CRDEntry) HasAnyServiceAccounts() bool

HasAnyServiceAccounts reports whether this CRD defines any ServiceAccounts in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyServiceMonitors added in v0.4.2

func (c *CRDEntry) HasAnyServiceMonitors() bool

HasAnyServiceMonitors reports whether this CRD defines any ServiceMonitors in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyServices added in v0.3.9

func (c *CRDEntry) HasAnyServices() bool

HasAnyServices reports whether this CRD defines any Services in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyStatefulSets added in v0.3.8

func (c *CRDEntry) HasAnyStatefulSets() bool

HasAnyStatefulSets reports whether this CRD defines any StatefulSets in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyStorageBackups added in v0.4.2

func (c *CRDEntry) HasAnyStorageBackups() bool

HasAnyStorageBackups reports whether this CRD defines any StorageBackups in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyStorageClasses added in v0.4.2

func (c *CRDEntry) HasAnyStorageClasses() bool

HasAnyStorageClasses reports whether this CRD defines any StorageClasses in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyStorageLocations added in v0.4.2

func (c *CRDEntry) HasAnyStorageLocations() bool

HasAnyStorageLocations reports whether this CRD defines any StorageLocations in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyStoragePools added in v0.4.2

func (c *CRDEntry) HasAnyStoragePools() bool

HasAnyStoragePools reports whether this CRD defines any StoragePools in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyStorageSnapshots added in v0.4.2

func (c *CRDEntry) HasAnyStorageSnapshots() bool

HasAnyStorageSnapshots reports whether this CRD defines any StorageSnapshots in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyStorageVolumes added in v0.4.2

func (c *CRDEntry) HasAnyStorageVolumes() bool

HasAnyStorageVolumes reports whether this CRD defines any StorageVolumes in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyTLSSecrets added in v0.2.3

func (c *CRDEntry) HasAnyTLSSecrets() bool

HasAnyTLSSecrets reports whether any secret in either phase defines a TLS configuration.

func (*CRDEntry) HasAnyVolumeMounts added in v0.4.2

func (c *CRDEntry) HasAnyVolumeMounts() bool

HasAnyVolumeMounts reports whether this CRD defines any VolumeMounts (placeholder) in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAnyVolumes added in v0.4.2

func (c *CRDEntry) HasAnyVolumes() bool

HasAnyVolumes reports whether this CRD defines any Volumes (placeholder) in either OnCreate or OnReconcile phases.

func (*CRDEntry) HasAutoscaleProfile

func (c *CRDEntry) HasAutoscaleProfile() bool

HasAutoscaleProfile reports whether this crd defined autoscale profile

func (*CRDEntry) HasMutationRules

func (c *CRDEntry) HasMutationRules() bool

Separate helpers for hasMutationRules and hasValidationRules

func (*CRDEntry) HasNamespaceRules added in v0.1.9

func (c *CRDEntry) HasNamespaceRules() bool

HasNamespaceRules reports whether this CRD declares any namespace rules.

func (*CRDEntry) HasOnCreate added in v0.1.9

func (c *CRDEntry) HasOnCreate() bool

HasOnCreate reports whether this CRD declares any onCreate hooks.

func (*CRDEntry) HasOnDelete added in v0.1.9

func (c *CRDEntry) HasOnDelete() bool

HasOnDelete reports whether this CRD declares any onDelete hooks.

func (*CRDEntry) HasOnReconcile added in v0.1.9

func (c *CRDEntry) HasOnReconcile() bool

HasOnReconcile reports whether this CRD declares any onReconcile hooks.

func (*CRDEntry) HasProviders

func (c *CRDEntry) HasProviders() bool

HasProviders reports whether this CRD declares any provider blocks.

func (*CRDEntry) HasRestrictedNamespaces added in v0.1.9

func (c *CRDEntry) HasRestrictedNamespaces() bool

HasRestrictedNamespaces reports if restrictedNamespaces is defined for this crd.

func (*CRDEntry) HasRollbackRules added in v0.1.9

func (c *CRDEntry) HasRollbackRules() bool

HasRollbackRules reports whether this CRD has any rollback behavior configured — either via an explicit rollback: block or the rollBackOnError: true shorthand.

func (*CRDEntry) HasSleep added in v0.4.2

func (c *CRDEntry) HasSleep() bool

HasSleep reports whether any sleep declarations exist for this CRD. It is a thin convenience wrapper around CollectSleepEntries.

func (*CRDEntry) HasStatusFields added in v0.4.0

func (c *CRDEntry) HasStatusFields() bool

HasStatusFields reports whether this CRD declares any status fields.

func (*CRDEntry) HasTemplates

func (c *CRDEntry) HasTemplates() bool

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

func (c *CRDEntry) HasValidationOrMutationRules() bool

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 (c *CRDEntry) HasValidationRules() bool

func (*CRDEntry) HookManagedResources added in v0.4.1

func (c *CRDEntry) HookManagedResources() []ManagedResource

HookManagedResources returns the list of managed resources declared under the hooks block. Returns nil if hooks are not declared or no resources exist.

func (*CRDEntry) InvolvedInConversion added in v0.3.1

func (c *CRDEntry) InvolvedInConversion() bool

InvolvedInConversion reports whether this CRD is involved in version conversion. A CRD is involved when it either declares conversion paths (the CRD that hosts the /convert logic) or explicitly opts in with participant: true (the stable/ storage-version CRD on the other side of the pair).

func (*CRDEntry) IsBuiltInType

func (c *CRDEntry) IsBuiltInType() bool

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

func (c *CRDEntry) IsDynamic() bool

IsDynamic determines whether this CRD should operate in dynamic mode. Resolution order (first match wins):

  1. mode: dynamic explicitly declared → true
  2. mode: typed explicitly declared → false
  3. APITypes.Location is empty → true (no compiled types available)
  4. APITypes.Location is set → false (compiled types available)

func (*CRDEntry) IsEnabled

func (c *CRDEntry) IsEnabled() bool

IsEnabled reports whether this CRD is enabled. Defaults to true when omitted.

func (*CRDEntry) IsEnabledAllEndpoints

func (c *CRDEntry) IsEnabledAllEndpoints() bool

IsEnabledAllEndpoints reports whether the all endpoints are disabled for this CRD. Defaults to false when omitted.

func (*CRDEntry) IsHealthEnabled

func (c *CRDEntry) IsHealthEnabled() bool

IsHealthEnabled reports whether the /health endpoint is enabled for this CRD. Defaults to true when omitted.

func (*CRDEntry) IsInfoEnabled

func (c *CRDEntry) IsInfoEnabled() bool

IsInfoEnabled reports whether the /info endpoint is enabled for this CRD. Defaults to true when omitted.

func (*CRDEntry) IsNamespaced

func (c *CRDEntry) IsNamespaced() bool

IsNamespaced reports whether this CRD is namespaced. Defaults to true unless explicitly overridden or determined by enrichment.

func (*CRDEntry) IsNotificationEnabled

func (c *CRDEntry) IsNotificationEnabled() bool

NotificationEnabled reports whether this CRD declares the notification block Enabled by default

func (*CRDEntry) IsStatuslessType

func (c *CRDEntry) IsStatuslessType() bool

IsStatusless reports whether this CRD has no meaningful readiness semantics. These resources become "Ready" immediately upon creation.

func (*CRDEntry) NeedsResourceDecl added in v0.3.8

func (c *CRDEntry) NeedsResourceDecl() bool

NeedsResourceDecl reports whether this CRD defines any workload resources (Deployments, StatefulSets, or ReplicaSets) in either OnCreate or OnReconcile.

func (*CRDEntry) ResourceDecl added in v0.3.8

func (c *CRDEntry) ResourceDecl() *ResourceRequirements

ResourceDecl returns the first ResourceRequirements defined for this CRD. It checks OnCreate first, then OnReconcile, and searches Deployments, StatefulSets, and ReplicaSets in that order. Returns nil if none exist.

func (*CRDEntry) RestrictedNamespacesOnly added in v0.1.9

func (c *CRDEntry) RestrictedNamespacesOnly() bool

RestrictedNamespacesOnly reports if only restrictedNamespaces is defined for this crd.

func (*CRDEntry) SetMaxQueueDepth

func (c *CRDEntry) SetMaxQueueDepth(def int) int

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

func (c *CRDEntry) SetWorkers(def int) int

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

func (c *CRDEntry) SkipObservedGeneration() bool

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

func (c *CRDEntry) SkipStatusSubresource() bool

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

func (c *CRDEntry) UpdateCRDCaBundle() bool

UpdateCRDCaBundle reports whether this CRD declares an updateCRD field Used to update the crd when certificate is autogenerted by orkestra

func (*CRDEntry) ValidateMetricField

func (c *CRDEntry) ValidateMetricField(field string) error

ValidateMetricField returns an error if the field is not a known autoscale metric.

func (*CRDEntry) WithAnyManagedResources added in v0.4.1

func (c *CRDEntry) WithAnyManagedResources() bool

WithAnyManagedResources reports whether hooks or constructor declare resources.

func (*CRDEntry) WithConstructorDecl added in v0.2.8

func (c *CRDEntry) WithConstructorDecl() bool

WithConstructorDecl returns true if the CRD has a constructor declaration. Required when Default: false in the Katalog. The generated registry will emit a ReconcilerRegistry entry for this CRD.

func (*CRDEntry) WithConstructorManagedResources added in v0.4.1

func (c *CRDEntry) WithConstructorManagedResources() bool

WithConstructorManagedResources reports whether this CRD has a constructor that declares managed resources for RBAC generation.

func (*CRDEntry) WithHookManagedResources added in v0.4.1

func (c *CRDEntry) WithHookManagedResources() bool

WithHookManagedResources reports whether this CRD has hooks that declare managed resources for RBAC generation.

func (*CRDEntry) WithHooksDecl added in v0.2.8

func (c *CRDEntry) WithHooksDecl() bool

WithHooksDecl returns true if the CRD has a hooks declaration (HookDeclaration). Used to determine whether to generate registry entries for the HookRegistry. Does not imply anything about Default: true/false — a typed CRD can have hooks even when Default: true (generic reconciler) or false (custom reconciler).

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

func (CRDMode) String

func (m CRDMode) String() string

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" json:"field"`

	// Operator — how to compare the field value.
	// See ConditionOperator constants below.
	Operator ConditionOperator `yaml:"operator,omitempty" json:"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" json:"value,omitempty"`

	// Equals is a shorthand for operator: equals.
	Equals string `yaml:"equals,omitempty" json:"equals,omitempty"`

	// NotEquals is a shorthand for operator: notEquals.
	NotEquals string `yaml:"notEquals,omitempty" json:"notEquals,omitempty"`

	// Contains is a shorthand for operator: contains.
	Contains string `yaml:"contains,omitempty" json:"contains,omitempty"`

	// Prefix is a shorthand for operator: prefix.
	Prefix string `yaml:"prefix,omitempty" json:"prefix,omitempty"`

	// Suffix is a shorthand for operator: suffix.
	Suffix string `yaml:"suffix,omitempty" json:"suffix,omitempty"`

	// Exists is a shorthand for operator: exists.
	// When true, the condition passes when the field is present and non-empty.
	Exists *bool `yaml:"exists,omitempty" json:"exists,omitempty"`

	// NotExists is a shorthand for operator: notExists.
	// When true, the condition passes when the field is absent or empty.
	NotExists *bool `yaml:"notExists,omitempty" json:"notExists,omitempty"`

	// Numeric shorthands
	GreaterThan string `yaml:"greaterThan,omitempty" json:"greaterThan,omitempty"`
	LessThan    string `yaml:"lessThan,omitempty" json:"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" json:"time,omitempty"`

	// DayOfWeek — active on the specified days of the week.
	//   anyOf:
	//     - dayOfWeek:
	//         in: [Monday, Tuesday, Wednesday, Thursday, Friday]
	DayOfWeek *DayOfWeekCondition `yaml:"dayOfWeek,omitempty" json:"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" json:"cron,omitempty"`

	// Duration — how long a cron-opened window remains active.
	Duration Duration `yaml:"duration,omitempty" json:"duration,omitempty"`

	// Notify declares teams to alert when this condition is true.
	Notify *NotifyBlock `yaml:"notify,omitempty" json:"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" json:"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"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,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"

func (ConfigMapTemplateSource) GetName added in v0.4.2

func (t ConfigMapTemplateSource) GetName() string

func (ConfigMapTemplateSource) GetSleep added in v0.4.2

func (t ConfigMapTemplateSource) GetSleep() string

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"`

	// Resources — Kubernetes resource types this constructor manages (used for RBAC generation).
	Resources []ManagedResource `json:"resources,omitempty" yaml:"resources,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" json:"enabled,omitempty"`

	// ConversionWindow is the rolling window size for latency/throughput stats.
	// Default: CONVERSION_WINDOW env / 100.
	ConversionWindow int `yaml:"conversionWindow,omitempty" json:"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" json:"from"`

	// To — the target version (bare, e.g. "v1")
	To string `yaml:"to" validate:"required" json:"to"`

	// 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" json:"spec"`
}

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" yaml:"kind"`
	StorageVersion string           `json:"storageVersion" yaml:"storageVersion"`
	Paths          []ConversionPath `json:"paths" yaml:"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 ConversionVersionSpec struct {
	Version string                 `json:"version" yaml:"version"`
	Spec    map[string]interface{} `json:"spec" yaml:"spec"`
}

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"`

	// ImagePullSecrets is an optional list of references to secrets in the same namespace to use
	// for pulling any of the images used by this PodSpec.
	// If specified, these secrets will be passed to individual puller implementations for them to use.
	ImagePullSecrets []string `yaml:"imagePullSecrets" json:"imagePullSecrets" 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"`

	// NodeSelector is a selector which must be true for the pod to fit on a node.
	// Selector which must match a node's labels for the pod to be scheduled on that node.
	// More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
	// +optional
	// +mapType=atomic
	NodeSelector map[string]string `yaml:"nodeSelector,omitempty" json:"nodeSelector,omitempty"`

	// ServiceAccountName is the name of the ServiceAccount to use to run this pod.
	// More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
	// +optional
	ServiceAccountName string `yaml:"serviceAccountName,omitempty" json:"serviceAccountName,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"`

	// Resources — CPU and memory requests/limits for the container.
	// Set resources.profile for a named preset, or resources.requests/limits for
	// explicit values. Profile and explicit values are mutually exclusive.
	Resources *ResourceRequirements `yaml:"resources" json:"resources,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"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,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"]

func (CronJobTemplateSource) GetName added in v0.4.2

func (t CronJobTemplateSource) GetName() string

func (CronJobTemplateSource) GetResources added in v0.4.2

func (t CronJobTemplateSource) GetResources() *ResourceRequirements

func (CronJobTemplateSource) GetSleep added in v0.4.2

func (t CronJobTemplateSource) GetSleep() string

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" json:"crd"`

	// LabelSelector is a label key/value pair for label-based informer lookup.
	// Mutually exclusive with Kind.
	LabelSelector map[string]string `yaml:"labelSelector,omitempty" json:"labelSelector,omitempty"`

	// Selector identifies which CR instance to observe.
	Selector CrossSelector `yaml:"selector" json:"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" json:"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" json:"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" json:"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" json:"name,omitempty"`

	// Namespace is the CR namespace. Template expressions supported.
	// Default: same namespace as the current CR.
	Namespace string `yaml:"namespace,omitempty" json:"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" json:"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" json:"endpoint"`

	// Token is a bearer token for the endpoint. $ENV_VAR syntax supported.
	Token string `yaml:"token,omitempty" json:"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" json:"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" json:"in,omitempty"`

	// NotIn — active on all days except these.
	NotIn []string `yaml:"notIn,omitempty" json:"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" json:"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" json:"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" json:"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" json:"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"`

	// ImagePullSecrets is an optional list of references to secrets in the same namespace to use
	// for pulling any of the images used by this PodSpec.
	// If specified, these secrets will be passed to individual puller implementations for them to use.
	ImagePullSecrets []string `yaml:"imagePullSecrets" json:"imagePullSecrets" 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.
	// Set resources.profile for a named preset, or resources.requests/limits for
	// explicit values. Profile and explicit values are mutually exclusive.
	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"`

	// NodeSelector is a selector which must be true for the pod to fit on a node.
	// Selector which must match a node's labels for the pod to be scheduled on that node.
	// More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
	// +optional
	// +mapType=atomic
	NodeSelector map[string]string `yaml:"nodeSelector,omitempty" json:"nodeSelector,omitempty"`

	// ServiceAccountName is the name of the ServiceAccount to use to run this pod.
	// More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
	// +optional
	ServiceAccountName string `yaml:"serviceAccountName,omitempty" json:"serviceAccountName,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"`

	// Probes — startup, liveness, and readiness probe configuration.
	Probes *ProbesConfig `yaml:"probes,omitempty" json:"probes,omitempty"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,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"
      resources:
        profile: burst      # Use orkestra's burst resource configuration

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

func (DeploymentTemplateSource) GetName added in v0.4.2

func (t DeploymentTemplateSource) GetName() string

func (DeploymentTemplateSource) GetProbes added in v0.4.2

func (t DeploymentTemplateSource) GetProbes() *ProbesConfig

GetProbes returns the probe configuration for each supported workload type. Value receivers so the method is available on both values and pointers.

func (DeploymentTemplateSource) GetResources added in v0.4.2

GetResources returns the resource requirements for each supported workload type.

func (DeploymentTemplateSource) GetSleep added in v0.4.2

func (t DeploymentTemplateSource) GetSleep() string

Core workload resources

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"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,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

type Duration struct {
	time.Duration
}

Duration is a time.Duration that unmarshals from YAML strings like "15s", "2m", "1h".

func (Duration) MarshalYAML

func (d Duration) MarshalYAML() (interface{}, error)

func (*Duration) UnmarshalYAML

func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error

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 EnvFromSource struct {
	ConfigMapRef string `yaml:"configMapRef,omitempty" json:"configMapRef,omitempty"`
	SecretRef    string `yaml:"secretRef,omitempty" json:"secretRef,omitempty"`
}

type EnvVar added in v0.3.9

type EnvVar struct {
	Key   string
	Value string
	IsCfg bool // true when line carries "# ork:cfg"
}

EnvVar is a single variable parsed from a .env file.

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" yaml:"status"`

	// Body is the first 4096 bytes of the response body.
	// Truncated to avoid unbounded memory use.
	Body string `json:"body" yaml:"body"`

	// Error is the error message when the call failed.
	// Empty on success.
	Error string `json:"error" yaml:"error"`

	// Called is "true" when the call was made, "false" when skipped (conditions failed).
	Called string `json:"called" yaml:"called"`

	// Additional values for metrics
	StatusCode      int     `json:"statusCode" yaml:"statusCode"`
	DurationSeconds float64 `json:"durationSeconds" yaml:"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" json:"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" json:"url"`

	// Method is the HTTP method. Default: GET.
	Method string `yaml:"method,omitempty" json:"method,omitempty"`

	// Body is the request body for POST/PUT/PATCH requests.
	// Template expressions supported.
	//   body: '{"name": "{{ .metadata.name }}"}'
	Body string `yaml:"body,omitempty" json:"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" json:"token,omitempty"`

	// Headers are additional HTTP headers to include.
	Headers map[string]string `yaml:"headers,omitempty" json:"headers,omitempty"`

	// Timeout is the maximum duration for this call.
	// Default: 10s. Format: "5s", "1m", "500ms"
	Timeout string `yaml:"timeout,omitempty" json:"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" json:"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" json:"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" json:"when,omitempty"`
	AnyOf      []Condition `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,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:

Struct with auth:

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.

func (*FileSourceAuth) Resolve

func (a *FileSourceAuth) Resolve() (*utils.FileAuth, error)

Resolve resolves the FileSourceAuth to a utils.FileAuth. Reads environment variables and returns the resolved credentials. Returns nil if the auth block is nil (unauthenticated source).

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" json:"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" json:"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"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,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"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,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

func (HPATemplateSource) GetName added in v0.4.2

func (t HPATemplateSource) GetName() string

func (HPATemplateSource) GetSleep added in v0.4.2

func (t HPATemplateSource) GetSleep() string

Autoscaling, disruption, scheduling

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.orkspace.io/v1
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"`

	// Resources — Kubernetes resource types this hook manages (used for RBAC generation).
	Resources []ManagedResource `json:"resources,omitempty" yaml:"resources,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"`
	Roles                    []RoleTemplateSource           `yaml:"roles" json:"roles,omitempty" validate:"omitempty"`
	RoleBindings             []RoleBindingTemplateSource    `yaml:"roleBindings" json:"roleBindings,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"`
	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

func (*HookTemplates) VisitResources added in v0.4.2

func (h *HookTemplates) VisitResources(fn func(res interface{}))

VisitResources calls fn for every resource template in this HookTemplates. It abstracts over all resource slices (Deployments, Services, Jobs, etc.) so callers can perform generic operations like detecting Sleep, validating fields, or scanning for managed-resource contracts.

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"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,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"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,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 }}"

func (IngressTemplateSource) GetName added in v0.4.2

func (t IngressTemplateSource) GetName() string

func (IngressTemplateSource) GetSleep added in v0.4.2

func (t IngressTemplateSource) GetSleep() string

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"`

	// ImagePullSecrets is an optional list of references to secrets in the same namespace to use
	// for pulling any of the images used by this PodSpec.
	// If specified, these secrets will be passed to individual puller implementations for them to use.
	ImagePullSecrets []string `yaml:"imagePullSecrets" json:"imagePullSecrets" 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"`

	// NodeSelector is a selector which must be true for the pod to fit on a node.
	// Selector which must match a node's labels for the pod to be scheduled on that node.
	// More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
	// +optional
	// +mapType=atomic
	NodeSelector map[string]string `yaml:"nodeSelector,omitempty" json:"nodeSelector,omitempty"`

	// ServiceAccountName is the name of the ServiceAccount to use to run this pod.
	// More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
	// +optional
	ServiceAccountName string `yaml:"serviceAccountName,omitempty" json:"serviceAccountName,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"`

	// Resources — CPU and memory requests/limits for the container.
	// Set resources.profile for a named preset, or resources.requests/limits for
	// explicit values. Profile and explicit values are mutually exclusive.
	Resources *ResourceRequirements `yaml:"resources" json:"resources,omitempty" validate:"omitempty"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,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

func (JobTemplateSource) GetName added in v0.4.2

func (t JobTemplateSource) GetName() string

func (t NetworkPolicyTemplateSource) GetName() string { return t.Name }

func (JobTemplateSource) GetResources added in v0.4.2

func (t JobTemplateSource) GetResources() *ResourceRequirements

func (JobTemplateSource) GetSleep added in v0.4.2

func (t JobTemplateSource) GetSleep() string

Batch

type KatalogFile

type KatalogFile struct {
	APIVersion string          `yaml:"apiVersion"`
	Kind       string          `yaml:"kind"`
	Metadata   KatalogMeta     `yaml:"metadata"`
	Anchors    map[string]any  `yaml:"anchors,omitempty"`
	Imports    *KatalogSources `yaml:"imports,omitempty"`
	Spec       KatalogSpec     `yaml:"spec"`
	Security   KatalogSecurity `yaml:"security"`

	// Notification holds the top-level alerting configuration for this Katalog.
	// Defines channels (email, Slack) and per-team routing rules that fire when
	// a managed CRD's conditions transition. When a Komposer references multiple
	// source Katalogs, notification blocks are merged — source teams are inherited
	// and the Komposer's own teams win on name conflict.
	Notification *KatalogNotification `yaml:"notification,omitempty"`

	// 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 is the required unique identifier of the Katalog.
	Name string `yaml:"name" json:"name,omitempty"`

	// Description provides a human-readable explanation of the Katalog's purpose.
	Description string `yaml:"description,omitempty" json:"description,omitempty"`

	// Version follows semantic versioning (e.g., "1.2.3") for the Katalog schema or content.
	Version string `yaml:"version,omitempty" json:"version,omitempty"`

	// Author identifies the creator or maintainer of the Katalog.
	Author string `yaml:"author,omitempty" json:"author,omitempty"`

	// License describes the licensing terms under which the Katalog is distributed.
	License string `yaml:"license,omitempty" json:"license,omitempty"`

	// Tags are optional keywords for categorising the Katalog in the Orkestra Registry.
	// They aid discovery (e.g., "database", "stateful", "security") when using
	// `ork registry list --tag <tag>` and for indexing in Artifact Hub.
	// Tags have no effect on runtime behaviour.
	Tags []string `yaml:"tags,omitempty" json:"tags,omitempty"`

	// CreatedBy indicates which client or command generated this Katalog metadata.
	// It influences the UI presented by the Control Center:
	//   - If empty or "operator" (default) → shows an operator‑focused UI with
	//     detailed infrastructure and workload controls.
	//   - If "orkdoctor" → indicates a developer context; the Control Center
	//     shows a simplified, developer‑oriented UI with only the terminology
	//     and actions relevant to application developers (hides low‑level operator details).
	// Other values may be introduced in the future for different workflows.
	CreatedBy string `yaml:"createdBy,omitempty" json:"createdBy,omitempty"`

	// Projects holds the aggregated ProjectInfo entries for every application
	// participating in this Komposer workspace. Each entry represents the
	// developer‑side metadata discovered by 'ork doctor' for a single project.
	//
	// Unlike a Katalog—which contains only the ProjectInfo for its own app—the
	// Komposer acts as the multi‑project orchestrator and therefore exposes a
	// map of project name → ProjectInfo. This enables the Orkestra Control Center
	// to present a unified, workspace‑level developer view (languages, ports,
	// Dockerfile presence, env breakdowns, frontend detection, etc.) without
	// needing access to the original source directories.
	//
	// The operator and runtime ignore this field entirely; it is purely developer
	// metadata used for persona‑aware UI and tooling.
	// For today, Only 'ork doctor' populates it.
	Projects map[string]ProjectInfo `yaml:"projects,omitempty" json:"projects,omitempty"`
}

KatalogMeta holds identifying metadata for a 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" json:"enabled,omitempty"`

	// Defaults defines global notification behavior applied when a team does
	// not specify its own override.
	Defaults *NotificationDefaults `yaml:"defaults,omitempty" json:"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" json:"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" json:"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" json:"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" json:"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" json:"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.
	//
	// Future
	Library string `yaml:"library,omitempty" json:"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 {
	// ServiceName is the name of the kubernetes service where orkestra
	// is deployed
	ServiceName string `yaml:"serviceName,omitempty" json:"serviceName,omitempty"`

	// 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-deletion-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" json:"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" json:"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" json:"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" json:"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) OrkestraServiceName added in v0.2.5

func (s *KatalogSecurity) OrkestraServiceName(envDefault string) string

OrkestraServiceName returns the effective service name for orkestra. 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 Language added in v0.3.9

type Language string

Language represents the primary language detected in the project.

const (
	LangGo      Language = "Go"
	LangNode    Language = "Node.js"
	LangJava    Language = "Java"
	LangPython  Language = "Python"
	LangRuby    Language = "Ruby"
	LangRust    Language = "Rust"
	LangUnknown Language = "Unknown"
)

type ManagedResource added in v0.4.1

type ManagedResource struct {
	// Kind is the Kubernetes Kind of the resource (e.g. "StatefulSet",
	// "Service", "CronJob"). This is the primary identifier and is required.
	Kind string `json:"kind,omitempty" yaml:"kind,omitempty"`

	// APIVersion is optional and only needed when the Kind cannot be resolved
	// from Orkestra's built‑in registry. Example: "apps/v1", "batch/v1",
	// "widgets.example.com/v1alpha1".
	APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"`

	// Group is optional and used for custom resources or non‑core API groups
	// when you want to fully specify the GroupVersionResource explicitly.
	// Example: "widgets.example.com".
	Group string `json:"group,omitempty" yaml:"group,omitempty"`

	// Version is optional and used together with Group for custom resources.
	// Example: "v1alpha1".
	Version string `json:"version,omitempty" yaml:"version,omitempty"`

	// Plural is optional and used when the plural name cannot be inferred
	// from Orkestra's built‑in registry or CRD metadata. Example: "widgets".
	Plural string `json:"plural,omitempty" yaml:"plural,omitempty"`
}

ManagedResource describes a Kubernetes resource type that a typed extension (either a hook or a constructor) will manage.

Orkestra uses this information to generate RBAC rules for the operator ServiceAccount. Each declared resource results in permissions to get/list/watch/create/update/patch/delete that resource type.

For built‑in Kubernetes resources, Kind alone is sufficient because Orkestra resolves the full GroupVersionResource from its internal registry.

For custom resources or non‑core API groups, APIVersion and/or explicit group/version/plural may be provided.

Example (in katalog.yaml):

hooks:
  resources:
    - kind: StatefulSet
    - kind: Service
    - kind: CronJob
    - kind: Widget
      group: widgets.example.com
      version: v1alpha1
      plural: widgets

type Motif added in v0.3.9

type Motif struct {
	APIVersion string         `yaml:"apiVersion" json:"apiVersion"`
	Kind       string         `yaml:"kind" json:"kind"`
	Metadata   MotifMeta      `yaml:"metadata" json:"metadata"`
	Inputs     []MotifInput   `yaml:"inputs,omitempty" json:"inputs,omitempty"`
	Resources  *HookTemplates `yaml:"resources,omitempty" json:"resources,omitempty"`
	Status     *StatusConfig  `yaml:"status,omitempty" json:"status,omitempty"`
	Admission  *Admission     `yaml:"admission,omitempty" json:"admission,omitempty"`
}

Motif is the smallest reusable primitive in Orkestra's composition model. A Motif declares named inputs and resource blocks. It cannot run alone — it must be imported by a Katalog that provides its inputs via with:.

YAML:

apiVersion: orkestra.orkspace.io/v1
kind: Motif
metadata:
  name: postgres
inputs:
  - name: image
  - name: volumeSize
resources: ...
status: ...
admission:
  validation:
    rules:
      - field: spec.image
        prefix: "myregistry.com/"
        action: deny
  mutation:
    rules:
      - field: spec.replicas
        default: "2"

type MotifImport added in v0.3.9

type MotifImport struct {
	// Motif is the registry URL, file path, or short name.
	// Same formats as RegistrySource.URL:
	//   File:  ./postgres/motif.yaml
	//   OCI:   ghcr.io/orkspace/orkestra-registry/postgres@v16
	//   Git:   https://github.com/myorg/postgres-motif@main
	// @ shorthand encodes the version inline: url@version
	Motif string `yaml:"motif" json:"motif,omitempty"`

	// Version — explicit version (tag, branch, or SHA).
	// Ignored when @ shorthand is used in Motif.
	// Defaults to "latest" for OCI, "main" for Git.
	Version string `yaml:"version,omitempty" json:"version,omitempty"`

	// OCI — when true, pull the Motif artifact via OCI/ORAS protocol.
	// When false (default), pull via Git (GitHub raw URL, GitLab, or git clone).
	OCI bool `yaml:"oci,omitempty" json:"oci,omitempty"`

	// Auth — optional credentials for the registry.
	// Same auth model as RegistrySource.Auth — resolved from environment variables.
	Auth *FileSourceAuth `yaml:"auth,omitempty" json:"auth,omitempty"`

	// With binds the Motif's declared inputs to values.
	// Values are template expressions evaluated in the CRD's reconcile context.
	// Required inputs not provided here are a validation error.
	// Optional inputs not provided use their Motif-declared defaults.
	With map[string]string `yaml:"with,omitempty" json:"with,omitempty"`
}

MotifImport declares one Motif import inside an operatorBox. Follows the same resolution semantics as RegistrySource in a Komposer — if you know how to pull a pattern, you already know how to pull a Motif.

YAML inside operatorBox:

File (developer path):

imports:
  - motif: ./motifs/postgres/motif.yaml
    with:
      image: "postgres:16"

OCI registry (the Orkestra registry houses both patterns and motifs):

imports:
  - motif: ghcr.io/orkspace/orkestra-registry/postgres@v16
    oci: true
    with:
      image: "{{ .spec.postgresImage }}"

Git registry:

imports:
  - motif: https://github.com/myorg/postgres-motif@main
    with:
      image: "{{ .spec.postgresImage }}"

type MotifInput added in v0.3.9

type MotifInput struct {
	// Name is the input identifier referenced in templates as inputs.Name.
	Name string `yaml:"name" json:"name"`

	// Description explains what this input controls.
	Description string `yaml:"description,omitempty" json:"description,omitempty"`

	// Required — when true, the importing Katalog must provide this input
	// in its with: block. Validation fails if required inputs are missing.
	Required bool `yaml:"required,omitempty" json:"required,omitempty"`

	// Type hints at the expected type of the input value. Not currently enforced,
	// but reserved for future type checking or schema generation.
	Type string `yaml:"type,omitempty" json:"type,omitempty"`

	// Default is the value used when the input is not provided in with:.
	// Only valid when Required is false.
	Default string `yaml:"default,omitempty" json:"default,omitempty"`
}

MotifInput declares one input parameter for a Motif.

type MotifMeta added in v0.3.9

type MotifMeta struct {
	Name        string `yaml:"name" json:"name"`
	Version     string `yaml:"version,omitempty" json:"version,omitempty"`
	Description string `yaml:"description,omitempty" json:"description,omitempty"`
	Author      string `yaml:"author,omitempty" json:"author,omitempty"`
	License     string `yaml:"license,omitempty" json:"license,omitempty"`
}

MotifMeta holds Motif identity fields.

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" json:"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" json:"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" json:"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" json:"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"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,omitempty"`
}

NamespaceTemplateSource declares one Namespace to be managed by Orkestra.

Example:

onCreate:
  namespaces:
    - name: "{{ .metadata.name }}-sa"
      labels:
        - key: app
          value: "{{ .metadata.name }}"

func (NamespaceTemplateSource) GetName added in v0.4.2

func (t NamespaceTemplateSource) GetName() string

func (NamespaceTemplateSource) GetSleep added in v0.4.2

func (t NamespaceTemplateSource) GetSleep() string

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" json:"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" json:"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" json:"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" json:"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" json:"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" json:"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" json:"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" json:"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" json:"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" json:"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"`

	// RollBackOnError is a zero-config rollback shorthand.
	//
	// When true, Orkestra automatically rolls back to the previous spec whenever
	// the default trigger threshold is reached (3 consecutive failures), without
	// requiring a separate rollback: block.
	//
	// The rollback templates are derived from all resource declarations that have
	// reconcile: true in onCreate: and onReconcile:. Those same templates are
	// re-applied using the previous spec as the base context — .spec.* resolves
	// to the previous spec values, so no .previous.spec.* references are needed.
	//
	// Resources with once: true are excluded — they are never regenerated by rollback.
	//
	// Combine with an explicit rollback.trigger to adjust the threshold without
	// redeclaring the rollback templates:
	//
	//	operatorBox:
	//	  rollBackOnError: true
	//	  rollback:
	//	    trigger:
	//	      consecutiveFailures: 5
	//	      withinDuration: 10m
	//
	// Declare rollback.onRollback alongside rollBackOnError: true to override the
	// derived templates for specific resources while keeping the shorthand trigger.
	RollBackOnError bool `yaml:"rollBackOnError,omitempty" json:"rollBackOnError,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"`
}

func (*OperatorBoxConfig) DerivedRollback added in v0.3.2

func (c *OperatorBoxConfig) DerivedRollback() *RollbackBlock

DerivedRollback returns the effective RollbackBlock for this operatorbox, merging rollBackOnError: true shorthand with any explicit rollback: declaration.

Resolution order:

  1. Neither rollBackOnError nor rollback set → nil (no rollback)
  2. rollBackOnError: false, rollback set → explicit block returned as-is
  3. rollBackOnError: true → synthetic block derived from reconcile:true resources; explicit rollback.trigger and rollback.onRollback take precedence when set

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"`

	// MaxUnavailable — maximum number of pods that may be unavailable.
	// 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"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,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

func (PDBTemplateSource) GetName added in v0.4.2

func (t PDBTemplateSource) GetName() string

func (PDBTemplateSource) GetSleep added in v0.4.2

func (t PDBTemplateSource) GetSleep() string

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"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,omitempty"`
}

PVCTemplateSource declares one PersistentVolumeClaim to be managed by Orkestra.

func (PVCTemplateSource) GetName added in v0.4.2

func (t PVCTemplateSource) GetName() string

func (PVCTemplateSource) GetSleep added in v0.4.2

func (t PVCTemplateSource) GetSleep() string

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"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,omitempty"`
}

PVTemplateSource declares one PersistentVolume to be managed by Orkestra. PersistentVolumes are cluster-scoped — Namespace is ignored.

func (PVTemplateSource) GetName added in v0.4.2

func (t PVTemplateSource) GetName() string

func (PVTemplateSource) GetSleep added in v0.4.2

func (t PVTemplateSource) GetSleep() string

Storage

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"`

	// ImagePullSecrets is an optional list of references to secrets in the same namespace to use
	// for pulling any of the images used by this PodSpec.
	// If specified, these secrets will be passed to individual puller implementations for them to use.
	ImagePullSecrets []string `yaml:"imagePullSecrets" json:"imagePullSecrets" 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 — CPU and memory requests/limits for the primary container.
	// Set resources.profile for a named preset, or resources.requests/limits for
	// explicit values. Profile and explicit values are mutually exclusive.
	Resources *ResourceRequirements `yaml:"resources" json:"resources,omitempty" validate:"omitempty"`

	// NodeSelector is a selector which must be true for the pod to fit on a node.
	// Selector which must match a node's labels for the pod to be scheduled on that node.
	// More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
	// +optional
	// +mapType=atomic
	NodeSelector map[string]string `yaml:"nodeSelector,omitempty" json:"nodeSelector,omitempty"`

	// ServiceAccountName is the name of the ServiceAccount to use to run this pod.
	// More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
	// +optional
	ServiceAccountName string `yaml:"serviceAccountName,omitempty" json:"serviceAccountName,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"`

	// Probes — startup, liveness, and readiness probe configuration.
	Probes *ProbesConfig `yaml:"probes,omitempty" json:"probes,omitempty"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,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"

func (PodTemplateSource) GetName added in v0.4.2

func (t PodTemplateSource) GetName() string

Additional common types

func (PodTemplateSource) GetProbes added in v0.4.2

func (t PodTemplateSource) GetProbes() *ProbesConfig

func (PodTemplateSource) GetResources added in v0.4.2

func (t PodTemplateSource) GetResources() *ResourceRequirements

func (PodTemplateSource) GetSleep added in v0.4.2

func (t PodTemplateSource) GetSleep() string

func (t DaemonSetTemplateSource) GetSleep() string { return t.Sleep }

type PolicyRuleSpec added in v0.3.9

type PolicyRuleSpec struct {
	APIGroups     []string `yaml:"apiGroups" json:"apiGroups,omitempty"`
	Resources     []string `yaml:"resources" json:"resources,omitempty"`
	Verbs         []string `yaml:"verbs" json:"verbs,omitempty"`
	ResourceNames []string `yaml:"resourceNames" json:"resourceNames,omitempty"`
}

PolicyRuleSpec declares one RBAC policy rule. String values within slices support template expressions.

type ProbeConfig added in v0.4.2

type ProbeConfig struct {
	// Type — probe mechanism. "http" uses an HTTP GET, "tcp" opens a TCP socket.
	// When path is set and type is omitted, http is assumed.
	Type string `yaml:"type,omitempty" json:"type,omitempty"`

	// Path — HTTP GET path. Required when type is "http".
	Path string `yaml:"path,omitempty" json:"path,omitempty"`

	// Port — override port for the probe. Defaults to the container's declared port.
	Port int32 `yaml:"port,omitempty" json:"port,omitempty"`

	// Profile — timing profile name. Allowed values: fast, standard, patient, slow-start.
	// Defaults to "standard" when omitted.
	Profile string `yaml:"profile,omitempty" json:"profile,omitempty"`

	// Explicit timing overrides — use when profiles are not granular enough.
	InitialDelaySeconds *int32 `yaml:"initialDelaySeconds,omitempty" json:"initialDelaySeconds,omitempty"`
	PeriodSeconds       *int32 `yaml:"periodSeconds,omitempty" json:"periodSeconds,omitempty"`
	FailureThreshold    *int32 `yaml:"failureThreshold,omitempty" json:"failureThreshold,omitempty"`
	SuccessThreshold    *int32 `yaml:"successThreshold,omitempty" json:"successThreshold,omitempty"`
	TimeoutSeconds      *int32 `yaml:"timeoutSeconds,omitempty" json:"timeoutSeconds,omitempty"`
}

ProbeConfig configures a single Kubernetes probe (startup, liveness, or readiness). Supports HTTP GET and TCP socket checks, with timing driven by named profiles or explicit field overrides.

Examples:

probes:
  startup:
    type: http
    path: /health
    profile: slow-start
  liveness:
    type: http
    path: /health
    profile: standard
  readiness:
    type: http
    path: /ready
    profile: standard

probes:
  liveness:
    type: tcp
    profile: standard

type ProbeProfileEntry added in v0.4.2

type ProbeProfileEntry struct {
	Phase        string // "onCreate", "onReconcile", "onDelete"
	Resource     string // e.g. "Deployment", "StatefulSet"
	ResourceName string // template name field (may be empty)
	ProbeType    string // "startup", "liveness", "readiness"
	Profile      string // raw profile name as written in the katalog
	Mixed        bool   // true when profile is set alongside explicit timing overrides
}

ProbeProfileEntry describes a single probe profile reference found in a HookTemplates resource. Used by validation to fail fast on unknown profiles and to enforce mutual exclusivity between profile and explicit timing fields.

type ProbesConfig added in v0.4.2

type ProbesConfig struct {
	Startup   *ProbeConfig `yaml:"startup,omitempty" json:"startup,omitempty"`
	Liveness  *ProbeConfig `yaml:"liveness,omitempty" json:"liveness,omitempty"`
	Readiness *ProbeConfig `yaml:"readiness,omitempty" json:"readiness,omitempty"`
}

ProbesConfig groups startup, liveness, and readiness probe declarations.

type ProjectInfo added in v0.3.9

type ProjectInfo struct {
	// Name is the project name as written into the katalog.
	// Derived from AppName.
	Name string `yaml:"name,omitempty" json:"name,omitempty"`

	// AppName is the derived application name from the directory.
	AppName string `yaml:"appName,omitempty" json:"appName,omitempty"`

	// Dir is the absolute path to the project directory.
	Dir string `yaml:"dir,omitempty" json:"dir,omitempty"`

	// HasDockerfile indicates whether a Dockerfile exists in the project.
	HasDockerfile bool `yaml:"hasDockerfile,omitempty" json:"hasDockerfile,omitempty"`

	// DockerfilePath is the full path to the Dockerfile if present.
	DockerfilePath string `yaml:"dockerfilePath,omitempty" json:"dockerfilePath,omitempty"`

	// GitCommit is the short SHA of the current git commit, empty if not a repo.
	GitCommit string `yaml:"gitCommit,omitempty" json:"gitCommit,omitempty"`

	// Language is the detected project language (Python, Go, Node, etc.).
	Language Language `yaml:"language,omitempty" json:"language,omitempty"`

	// LangMarker is the file that triggered language detection (e.g. requirements.txt).
	LangMarker string `yaml:"langMarker,omitempty" json:"langMarker,omitempty"`

	// Port is the detected application port (from .env or language defaults).
	Port string `yaml:"port,omitempty" json:"port,omitempty"`

	// EnvVars contains all parsed .env variables.
	EnvVars []EnvVar `yaml:"-" json:"-"`

	// Secrets contains all env vars classified as secrets (IsCfg == false).
	Secrets []EnvVar `yaml:"-" json:"-"`

	// Config contains all env vars classified as config (IsCfg == true).
	Config []EnvVar `yaml:"-" json:"-"`

	// HasFrontend indicates whether a frontend was detected in the project.
	HasFrontend bool `yaml:"hasFrontend,omitempty" json:"hasFrontend,omitempty"`

	// HasSMTP is true if SMTP‑related variables were found in .env.
	HasSMTP bool `yaml:"hasSMTP,omitempty" json:"hasSMTP,omitempty"`

	// HasSlack is true if Slack webhook variables were found in .env.
	HasSlack bool `yaml:"hasSlack,omitempty" json:"hasSlack,omitempty"`

	// License is the detected project license from standard license files.
	License string `yaml:"license,omitempty" json:"license,omitempty"`

	// HasCompose indicates whether a docker-compose.yaml file exists.
	HasCompose bool `yaml:"hasCompose,omitempty" json:"hasCompose,omitempty"`

	// UseCompose indicates whether the user chose to use the compose file.
	UseCompose bool `yaml:"useCompose,omitempty" json:"useCompose,omitempty"`

	// ComposePath is the path to the docker-compose.yaml file.
	ComposePath string `yaml:"composePath,omitempty" json:"composePath,omitempty"`

	// SecretCount is the number of secret variables (derived).
	SecretCount int `yaml:"secretCount,omitempty" json:"secretCount,omitempty"`

	// ConfigCount is the number of config variables (derived).
	ConfigCount int `yaml:"configCount,omitempty" json:"configCount,omitempty"`

	// Namespace is the Kubernetes namespace this project is deployed into.
	// Written by ork doctor at deploy time so the Control Center can
	// display the internal service URL without an additional API call.
	Namespace string `yaml:"namespace,omitempty" json:"namespace,omitempty"`

	// CurrentImage is the fully-qualified image reference that was last
	// deployed for this project (e.g. docker.io/myorg/app:abc123).
	// Written by ork doctor after a successful deploy.
	CurrentImage string `yaml:"currentImage,omitempty" json:"currentImage,omitempty"`
}

ProjectInfo captures everything ork doctor discovers about a project directory. It is used directly in a Katalog (single project) and reused inside a Komposer (multiple projects). Only ork doctor populates this.

func (*ProjectInfo) HasConfig added in v0.4.2

func (p *ProjectInfo) HasConfig() bool

HasConfig reports whether ork doctor discovered any config environment variables in the project (.env where IsCfg == true).

func (*ProjectInfo) HasCreds added in v0.4.2

func (p *ProjectInfo) HasCreds() bool

HasCreds reports whether the project contains *either* secrets or config. Useful for high‑level checks (e.g., does this project need a ConfigMap or Secret?).

func (*ProjectInfo) HasSecrets added in v0.4.2

func (p *ProjectInfo) HasSecrets() bool

HasSecrets reports whether ork doctor discovered any secret environment variables in the project (.env where IsCfg == false).

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.

func (ProviderDeclaration) Require

func (d ProviderDeclaration) Require(key string) (string, error)

Require returns a field value or an error if the key is absent or empty. Use for required fields that must be present for the provider to proceed.

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 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" json:"when,omitempty"`

	// AnyOf holds OR conditions — at least one must pass.
	AnyOf []Condition `yaml:"anyOf,omitempty" json:"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" json:"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" json:"version,omitempty"`

	// SHA — pin to an exact commit hash.
	// The full or partial SHA works (Git resolves partial SHAs).
	SHA string `yaml:"sha,omitempty" json:"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/orkspace/orkestra-registry/postgres
	//
	// Shorthand — embed version with @:
	//   ghcr.io/orkspace/orkestra-registry/postgres@v14
	//   https://github.com/myorg/registry@main
	//
	// When @ is present, Version field is ignored.
	URL string `yaml:"url" validate:"required" json:"url"`

	// 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" json:"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" json:"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" json:"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" json:"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" json:"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"`

	// ImagePullSecrets is an optional list of references to secrets in the same namespace to use
	// for pulling any of the images used by this PodSpec.
	// If specified, these secrets will be passed to individual puller implementations for them to use.
	ImagePullSecrets []string `yaml:"imagePullSecrets" json:"imagePullSecrets" 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.
	// Set resources.profile for a named preset, or resources.requests/limits for
	// explicit values. Profile and explicit values are mutually exclusive.
	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"`

	// NodeSelector is a selector which must be true for the pod to fit on a node.
	// Selector which must match a node's labels for the pod to be scheduled on that node.
	// More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
	// +optional
	// +mapType=atomic
	NodeSelector map[string]string `yaml:"nodeSelector,omitempty" json:"nodeSelector,omitempty"`

	// ServiceAccountName is the name of the ServiceAccount to use to run this pod.
	// More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
	// +optional
	ServiceAccountName string `yaml:"serviceAccountName,omitempty" json:"serviceAccountName,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"`

	// Probes — startup, liveness, and readiness probe configuration.
	Probes *ProbesConfig `yaml:"probes,omitempty" json:"probes,omitempty"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,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

func (ReplicaSetTemplateSource) GetName added in v0.4.2

func (t ReplicaSetTemplateSource) GetName() string

func (ReplicaSetTemplateSource) GetProbes added in v0.4.2

func (t ReplicaSetTemplateSource) GetProbes() *ProbesConfig

func (ReplicaSetTemplateSource) GetResources added in v0.4.2

func (ReplicaSetTemplateSource) GetSleep added in v0.4.2

func (t ReplicaSetTemplateSource) GetSleep() string

type ResourceCheck

type ResourceCheck struct {
	Get func(crd CRDEntry) bool
}

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 ResourceProfileEntry added in v0.4.2

type ResourceProfileEntry struct {
	Phase        string // "onCreate", "onReconcile", "onDelete"
	Resource     string // e.g. "Deployment", "StatefulSet"
	ResourceName string // template name field (may be empty)
	Profile      string // raw profile name as written in the katalog
	Mixed        bool   // true when profile is set alongside explicit requests/limits
}

ResourceProfileEntry describes a single resources.profile reference found in a HookTemplates resource. Used by validation to fail fast on unknown profiles and to enforce mutual exclusivity between profile and explicit resource fields.

type ResourceRequirements

type ResourceRequirements struct {
	Profile  string            `yaml:"profile,omitempty" json:"profile,omitempty" validate:"omitempty"`
	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"}

Profile is mutually exclusive with Requests and Limits. When Profile is set, it expands into a complete ResourceRequirements at reconcile time.

type ResourceSelector

type ResourceSelector []ResourceLabel

func (ResourceSelector) String

func (s ResourceSelector) String() string

Stringifier

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

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 RoleBindingTemplateSource added in v0.3.9

type RoleBindingTemplateSource struct {
	Version    string          `yaml:"version" json:"version,omitempty"`
	Name       string          `yaml:"name" json:"name,omitempty"`
	Namespace  string          `yaml:"namespace" json:"namespace,omitempty"`
	Labels     []ResourceLabel `yaml:"labels" json:"labels,omitempty"`
	RoleRef    RoleRefSpec     `yaml:"roleRef" json:"roleRef,omitempty"`
	Subjects   []SubjectSpec   `yaml:"subjects" json:"subjects,omitempty"`
	Conditions []Condition     `yaml:"when,omitempty" json:"when,omitempty"`
	Reconcile  bool            `yaml:"reconcile" json:"reconcile,omitempty"`
	ForEach    *ForEachSpec    `yaml:"forEach,omitempty" json:"forEach,omitempty"`
	AnyOf      []Condition     `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,omitempty"`
}

RoleBindingTemplateSource declares one RoleBinding to be managed by Orkestra.

Example:

onCreate:
  roleBindings:
    - name: "{{ .metadata.name }}-rolebinding"
      namespace: "{{ .metadata.name }}-ns"
      roleRef:
        name: "{{ .metadata.name }}-role"
      subjects:
        - kind: ServiceAccount
          name: "{{ .metadata.name }}-sa"
          namespace: "{{ .metadata.name }}-ns"

func (RoleBindingTemplateSource) GetName added in v0.4.2

func (t RoleBindingTemplateSource) GetName() string

func (RoleBindingTemplateSource) GetSleep added in v0.4.2

func (t RoleBindingTemplateSource) GetSleep() string

type RoleRefSpec added in v0.3.9

type RoleRefSpec struct {
	Name string `yaml:"name" json:"name,omitempty"`
	Kind string `yaml:"kind" json:"kind,omitempty"` // Role | ClusterRole; defaults to Role
}

RoleRefSpec names the Role (or ClusterRole) being bound. Name supports template expressions. Kind defaults to "Role".

type RoleTemplateSource added in v0.3.9

type RoleTemplateSource struct {
	Version    string           `yaml:"version" json:"version,omitempty"`
	Name       string           `yaml:"name" json:"name,omitempty"`
	Namespace  string           `yaml:"namespace" json:"namespace,omitempty"`
	Labels     []ResourceLabel  `yaml:"labels" json:"labels,omitempty"`
	Rules      []PolicyRuleSpec `yaml:"rules" json:"rules,omitempty"`
	Conditions []Condition      `yaml:"when,omitempty" json:"when,omitempty"`
	Reconcile  bool             `yaml:"reconcile" json:"reconcile,omitempty"`
	ForEach    *ForEachSpec     `yaml:"forEach,omitempty" json:"forEach,omitempty"`
	AnyOf      []Condition      `yaml:"anyOf,omitempty" json:"anyOf,omitempty"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,omitempty"`
}

RoleTemplateSource declares one namespaced Role to be managed by Orkestra.

Example:

onCreate:
  roles:
    - name: "{{ .metadata.name }}-role"
      namespace: "{{ .metadata.name }}-ns"
      rules:
        - apiGroups: ["apps"]
          resources: ["deployments"]
          verbs: ["get", "list", "watch", "update", "patch"]
          resourceNames: ["{{ .metadata.name }}"]

func (RoleTemplateSource) GetName added in v0.4.2

func (t RoleTemplateSource) GetName() string

func (RoleTemplateSource) GetSleep added in v0.4.2

func (t RoleTemplateSource) GetSleep() string

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" json:"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" json:"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" json:"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" json:"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 ScaleTargetRef struct {
	APIVersion string `yaml:"apiVersion" json:"apiVersion"`
	Kind       string `yaml:"kind" json:"kind"`
	Name       string `yaml:"name" json:"name"`
}

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.orkspace.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"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,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.

func (SecretTemplateSource) GetName added in v0.4.2

func (t SecretTemplateSource) GetName() string

func (SecretTemplateSource) GetSleep added in v0.4.2

func (t SecretTemplateSource) GetSleep() string

Config & identity

type SelectorMap

type SelectorMap map[string]string

Selector map

func (SelectorMap) String

func (m SelectorMap) String() string

Stringifier

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"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,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 }}"

func (ServiceAccountTemplateSource) GetName added in v0.4.2

func (ServiceAccountTemplateSource) GetSleep added in v0.4.2

func (t ServiceAccountTemplateSource) GetSleep() string

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"`

	// Headless — when true, the Service is created without a clusterIP (clusterIP: None).
	// Used primarily for StatefulSets to enable stable network identities and per‑pod DNS:
	//   <podname>.<service>.<namespace>.svc.cluster.local
	// Set this to true when the Service is meant to back a StatefulSet or provide
	// direct pod‑to‑pod addressing rather than load‑balanced traffic.
	Headless bool `yaml:"headless" json:"headless,omitempty" validate:"omitempty"`

	// Protocol defines network protocols supported for things like container ports.
	// "TCP", "UDP", "SCTP"
	Protocol string `yaml:"protocol" json:"protocol,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"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,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 }}"

func (ServiceTemplateSource) GetName added in v0.4.2

func (t ServiceTemplateSource) GetName() string

func (t DaemonSetTemplateSource) GetName() string { return t.Name }

func (ServiceTemplateSource) GetSleep added in v0.4.2

func (t ServiceTemplateSource) GetSleep() string

Services & networking

type SleepEntry added in v0.4.2

type SleepEntry struct {
	Phase        string // "onCreate", "onReconcile", "onDelete"
	Resource     string // e.g., "Deployment", "Service", "Job"
	ResourceName string // template name field if available (may be empty)
	Duration     string // raw duration string as written in the katalog
}

SleepEntry describes a single sleep declaration found in a HookTemplates resource. It includes the phase (onCreate/onReconcile/onDelete), the resource type (for human diagnostics), an optional resource name (if present in the template), and the raw duration string.

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" validate:"omitempty"`

	// ImagePullSecrets is an optional list of references to secrets in the same namespace to use
	// for pulling any of the images used by this PodSpec.
	// If specified, these secrets will be passed to individual puller implementations for them to use.
	ImagePullSecrets []string `yaml:"imagePullSecrets" json:"imagePullSecrets" validate:"omitempty"`

	// 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"`

	// VolumeClaimTemplates — one or more PVC templates; each pod gets its own volume per entry.
	VolumeClaimTemplates []VolumeClaimTemplateSource `yaml:"volumeClaimTemplates" json:"volumeClaimTemplates,omitempty"`

	// NodeSelector is a selector which must be true for the pod to fit on a node.
	// Selector which must match a node's labels for the pod to be scheduled on that node.
	// More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
	// +optional
	// +mapType=atomic
	NodeSelector map[string]string `yaml:"nodeSelector,omitempty" json:"nodeSelector,omitempty"`

	// ServiceAccountName is the name of the ServiceAccount to use to run this pod.
	// More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
	// +optional
	ServiceAccountName string `yaml:"serviceAccountName,omitempty" json:"serviceAccountName,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 — CPU and memory requests/limits for the primary container.
	// Set resources.profile for a named preset, or resources.requests/limits for
	// explicit values. Profile and explicit values are mutually exclusive.
	Resources *ResourceRequirements `yaml:"resources" json:"resources,omitempty" validate:"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"`

	// Probes — startup, liveness, and readiness probe configuration.
	Probes *ProbesConfig `yaml:"probes,omitempty" json:"probes,omitempty"`

	// Sleep injects an artificial delay into the reconcile of this resource.
	// Useful for autoscale testing, latency simulation, and chaos engineering.
	// Accepts extended duration units (s, m, h, d, w, mo, y).
	Sleep string `json:"sleep,omitempty" yaml:"sleep,omitempty"`
}

func (StatefulSetTemplateSource) GetName added in v0.4.2

func (t StatefulSetTemplateSource) GetName() string

func (StatefulSetTemplateSource) GetProbes added in v0.4.2

func (t StatefulSetTemplateSource) GetProbes() *ProbesConfig

func (StatefulSetTemplateSource) GetResources added in v0.4.2

func (StatefulSetTemplateSource) GetSleep added in v0.4.2

func (t StatefulSetTemplateSource) GetSleep() string

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 SubjectSpec added in v0.3.9

type SubjectSpec struct {
	Kind      string `yaml:"kind" json:"kind,omitempty"`
	Name      string `yaml:"name" json:"name,omitempty"`
	Namespace string `yaml:"namespace" json:"namespace,omitempty"`
}

SubjectSpec declares one RBAC subject for a RoleBinding. Name and Namespace support template expressions.

type TLSSpec

type TLSSpec struct {
	// CommonName is the certificate's CN field.
	//   commonName: "{{ .metadata.name }}.{{ .metadata.namespace }}.svc"
	CommonName string `yaml:"commonName" json:"commonName"`

	// DNSNames are the Subject Alternative Names.
	// Template expressions supported per entry.
	DNSNames []string `yaml:"dnsNames,omitempty" json:"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" json:"validFor,omitempty"`

	// Organization is the cert's O field. Default: "orkestra"
	Organization string `yaml:"organization,omitempty" json:"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" json:"after,omitempty"`

	// Before — active before this time (format: "HH:MM" in 24h).
	Before string `yaml:"before,omitempty" json:"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" or "integer", "float" or "number", "bool" or "boolean"
}

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 VolumeClaimTemplateSource added in v0.4.2

type VolumeClaimTemplateSource struct {
	// Name — PVC template name. Default: "data".
	Name string `yaml:"name" json:"name,omitempty"`

	// StorageClass — storage class to provision from. Required.
	StorageClass string `yaml:"storageClass" json:"storageClass"`

	// StorageSize — requested storage size (e.g. "10Gi"). Required.
	StorageSize string `yaml:"storageSize" json:"storageSize"`

	// MountPath — path inside the container to mount this volume. Default: "/data".
	MountPath string `yaml:"mountPath" json:"mountPath,omitempty"`

	// AccessModes — defaults to ["ReadWriteOnce"].
	AccessModes []string `yaml:"accessModes" json:"accessModes,omitempty"`
}

StatefulSetTemplateSource declares one StatefulSet to be managed by Orkestra. VolumeClaimTemplateSource declares one PersistentVolumeClaim template for a StatefulSet. Each StatefulSet pod receives its own PVC created from this template.

type WebhooksConfig

type WebhooksConfig struct {
	// Admission controls the ValidatingWebhookConfiguration and MutatingWebhookConfiguration.
	Admission *AdmissionWebhookToggle `yaml:"admission,omitempty" json:"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" json:"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" json:"serviceName,omitempty"`

	// CleanupOnShutdown controls whether Admission webhook is deleted on graceful shutdown.
	// Default: false — Admission webhook persists across restarts.
	CleanupOnShutdown bool `yaml:"cleanupOnShutdown,omitempty" json:"cleanupOnShutdown,omitempty"`
}

WebhooksConfig controls global admission webhook settings. Conversion is declared separately under security.conversion.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL