Skip to content

v0.9.0

Choose a tag to compare

@github-actions github-actions released this 24 Mar 09:23
· 38 commits to main since this release

πŸ”† Highlights

Cluster-Scoped Instance CRDs (KREP-10)

RGDs can now generate cluster-scoped instance CRDs. Add scope: Cluster to your schema and kro produces a non-namespaced CRD. Namespaced child resources must explicitly declare metadata.namespace when the instance is cluster-scoped. The field defaults to Namespaced and is immutable after creation. Docs

includeWhen Can Reference Upstream Resources

includeWhen expressions are no longer limited to schema fields - they can now reference other resources in the graph. kro treats these references as real dependencies that participate in DAG construction and cycle detection. Docs.

Decorators - External Collections (KREP-008)

ExternalRef previously only supported name and namespace for scalar lookups. They now support full matchLabels and matchExpressions selectors, so a single externalRef can match multiple resources dynamically. Selector values accept CEL expressions. Docs

Reactive Watches on External References and Decorators (KREP-003)

kro now watches external references - both scalar and collections β€” and re-reconciles instances instantly when an external resource is created, updated, or deleted. (Docs)

omit() CEL Function ( ⚠️ feature-gated: CELOmitFunction)

A new CEL omit() function lets you conditionally remove fields from rendered templates. Use ${schema.spec.kmsKeyID != "" ? schema.spec.kmsKeyID : omit()} and the field is dropped entirely from the SSA payload - important for APIs that distinguish between field absence and an empty value. omit() is rejected on required metadata fields (name, namespace, apiVersion, kind). Alpha, default off. Docs

Instance Status Condition Events (⚠️ feature-gated: InstanceConditionEvents)

kro can now emit Kubernetes Events when instance status conditions transition between reconciliation cycles. Events show the transition as "False β†’ True: ResourcesReady" and are typed Normal for transitions to True, Warning for everything else. Visible via kubectl describe on any instance. Alpha, default off. Docs

CEL Libraries Enrichment

The CEL environment gained nine new capabilities:

  • json: json.marshal() and json.unmarshal() for working with JSON payloads directly in expressions
  • maps: map.merge() to combine two maps with second-map-wins semantics
  • lists: lists.setAtIndex(), lists.insertAtIndex(), lists.removeAtIndex() for immutable list mutations; k8s Lists library for lists.concat() and friends
  • quantity: parse and manipulate Kubernetes Quantities ("500m", "2Gi") natively
  • bind: cel.bind(varName, init, body) to name intermediate values and reduce repetition
  • comprehensions: TwoVarComprehensions (transformMap, transformList) and sortBy for stable ordering by arbitrary expressions
  • random: random.seededInt(min, max, seed) for deterministic integer generation from resource UIDs

Graph Revisions (KREP-013)

RGD specs are now versioned. Each spec change creates an immutable GraphRevision snapshot (kubectl get gr) that is compiled and validated independently before instances can use it. If a new spec breaks compilation, instances block with a clear status instead of failing silently β€” you see exactly which revision failed and why via kubectl describe gr. kro retains the last 5 revisions per RGD (configurable), giving you an audit trail of every spec change. More importantly, Graph Revisions lay the foundation for progressive rollouts and revision pinning in future releases. Docs. Docs

✨ Features

  • feat: implement KREP-10 - support cluster-scoped instance CRDs by @antcybersec in #1152
  • feat: external ref watches and external ref collections by @jakobmoellerdev in #1079
  • feat: support CEL expressions in LabelSelectors for external collections by @jakobmoellerdev in #1079
  • feat: disable instance reconciliation when a kro.run/reconcile:"disabled" label is present by @NickKeller in #1062
  • feat(cel): add omit() for conditional field omission in templates by @michaelhtm in #1139
  • feat(events): Add events for instance status condition transition by @spattk in #1151
  • feat(#510): implement standard Kubernetes feature gates via component-base by @jakobmoellerdev in #1172
  • feat(helm): expose feature gates in chart values by @a-hilaly in #1187
  • feat(graph): gate omit() behind CELOmitFunction feature flag by @a-hilaly in #1185
  • feat(graph): reject omit() on required resource metadata fields by @michaelhtm in #1167
  • feat: allow includeWhen to reference other resources by @a-hilaly in #1104
  • feat(cel): add json.marshal and json.unmarshal CEL functions by @NicholasBlaskey in #1033
  • feat(cel): add map library with merge functionality by @a-hilaly in #1068
  • feat(cel): add index-mutation functions to the lists library by @pnz1990 in #1148
  • feat(cel): add k8s Lists library support by @NicholasBlaskey in #1178
  • feat(cel): add k8s Quantity library support by @NicholasBlaskey in #1177
  • feat(cel): add cel.bind() support to default environment and AST inspector by @pnz1990 in #1145
  • feat(cel): add support for TwoVarComprehensions in CEL environment by @jakobmoellerdev in #1136
  • feat(cel/ast): improve loop variable scoping and support sortBy comprehension by @jakobmoellerdev in #1136
  • feat(cel): add deterministic seeded integer generation function by @a-hilaly in #1108
  • feat(cel): add version support for the cel json library by @NicholasBlaskey in #1033
  • feat(compat): detect default value changes as non-breaking in schema comparison by @michaelhtm in #1098
  • feat(instance): block graph propagation on terminating managed resources by @a-hilaly in #1132
  • feat(helm): add topologySpreadConstraints in deployment by @QuentinBtd in #1137
  • feat: Add opt-in pprof profiling support via build tags by @a-hilaly in #922
  • feat: make instance requeue interval configurable by @a-hilaly in #1184
  • feat: expose leader election tuning flags in helm chart by @a-hilaly in #1205
  • feat: add metrics for pkg/runtime by @NicholasBlaskey in #1053
  • feat: Add RGD controller metrics by @NicholasBlaskey in #1063
  • feat: Add instance controller metrics by @NicholasBlaskey in #1056
  • feat(cel): add metrics for CEL cache hit/miss tracking by @a-hilaly in #1142
  • feat: Add client-go and reflector metrics registration by @a-hilaly in #1143
  • feat: Use expressive histogram buckets for controller reconciliation metrics by @a-hilaly in #1157
  • feat: Implementation of Graph Revisions (KREP-013) by @a-hilaly in #1085
  • feat: Watch owned GraphRevisions from the RGD controller by @a-hilaly in #1200
  • feat: watch graph revisions by spec.snapshot.name for orphan adoption by @a-hilaly in #1206
  • feat: Limit collection size to 1000 to protect cluster performance by @NicholasBlaskey in #1036
  • feat: limit collection dimension to 5 by @michaelhtm in #1045
  • feat: disable instance reconciliation with annotation instead of label by @michaelhtm in #1191
  • feat: KREP-15 label/annotation migration to internal.kro.run/ prefix by @michaelhtm in #1094

πŸ› Bug Fixes

  • fix: flaky validate RGD status test by @michaelhtm in #1034
  • fix: flaky validate RGD status integration test by @Aman-Cool in #1041
  • fix(docs): Wrong schema apiVersion definition in RGD chaining by @gagahsyuja in #1050
  • fix: properly return error in simpleschema parsing when the marker does by @NickKeller in #1073
  • fix: remove the rgd labels from managed resources by @jakobmoellerdev in #1075
  • fix(applyset): preserve prune scope on UID conflicts and requeue retry by @a-hilaly in #1081
  • fix: pass up expressive error by @fabianburth in #1078
  • fix(runtime): schema-aware CEL value conversion by @jakobmoellerdev in #1080
  • fix: show root cause error by @fabianburth in #1160
  • fix(dynamic): skip parent instance events with unchanged generation by @jakobmoellerdev in #1173
  • fix(metadata): skip instance-namespace label for cluster-scoped instances by @a-hilaly in #1175
  • fix(docs): correct RGD conditions by @a-hilaly in #1181
  • fix(collections): register collection watch for all expanded resources by @a-hilaly in #1182
  • fix(cel): handle oneOf string|number schemas in UnstructuredToVal by @a-hilaly in #1179
  • fix: return a requeue error when waiting for readiness by @fabianburth in #1090
  • fix: do not count requeue signals as handler errors in dynamic_controller_handler_errors_total by @Avr8 in #1059
  • fix(cel): sort transformList result before comparison in TwoVar test by @a-hilaly in #1141
  • fix: add instance state in progress case by @fabianburth in #1090
  • fix(graph/resolver): expose schema resolver metrics on controller-runtime registry by @a-hilaly in #1113
  • fix: ResourceGraphDefinition delete predicate handling by @a-hilaly in #1097
  • fix(externalref): allow external collections to list across all namespaces by @a-hilaly in #1180
  • fix: tighten cluster-scoped instance namespace validation by @a-hilaly in #1152
  • fix: handle cluster-scoped instances in reconciliation and SSA patches by @a-hilaly in #1152
  • fix(instance): surface graph resolution failures in conditions and metrics by @a-hilaly in #1201
  • fix: get rid of cel build caches due to problems during stabilization by @jakobmoellerdev in #1195
  • fix: missing dynamic controller registration, and wire up missing metrics by @jakobmoellerdev in #1146

⚑ Performance

  • perf(graph): eliminate duplicate CEL type building during RGD construction by @jakobmoellerdev in #1116
  • perf(cel): cache base declarations and environment with sync.Once by @jakobmoellerdev in #1119
  • perf(cel): add caching for CEL compilation artifacts to optimize performance by @jakobmoellerdev in #1129
  • perf: removes the lock convoy during large RGD bursts by @a-hilaly in #1192
  • perf: Make string templates compile to concatenation by @NicholasBlaskey in #1131
  • perf: use DefaultUnstructuredConverter to eliminate JSON round-trips in conditions by @spattk in #1204

πŸ”§ Refactoring

  • refactor(cel): Move cel conversion functions to separate package by @NicholasBlaskey in #1043
  • refactor(dag): use a heap-based topological sort by @a-hilaly in #1122
  • refactor(api): move InstanceState and NodeState to api/v1alpha1 by @NicholasBlaskey in #1134
  • refactor(runtime,instance): split large files and simplify state management by @jakobmoellerdev in #1165
  • refactor(cel/ast): derive known functions from CEL environment by @a-hilaly in #1109
  • refactor(apis): add condition prune mechanism for upgrades by @a-hilaly in #1198
  • dynamiccontroller: retain parent informers for shared GVR watches by @a-hilaly in #1105
  • dynamiccontroller: rollback provisional watches on failed reconciles by @a-hilaly in #1106
  • commit watches on requeue signals, not just on success by @a-hilaly in #1158

πŸ“– Documentation

πŸ§ͺ Testing

  • test: harden pkg/runtime coverage by @a-hilaly in #1099
  • test(instance): harden instance reconciler coverage by @a-hilaly in #1103
  • test(rgd): harden rgd controller unit tests by @a-hilaly in #1102
  • test(pkg/graph): harden unit tests for graph builder and friends by @a-hilaly in #1120
  • test: verify externalref integration cases reconcile on watched updates by @a-hilaly in #1123
  • test: integration test case, omit() removes field by @michaelhtm in #1168
  • test: add webhook denial integration tests with ValidatingAdmissionPolicy by @NicholasBlaskey in #1154
  • test: Add an upgrade test framework that validates kro upgrades don't break by @a-hilaly in #1197
  • test: Add verify-codegen ci entrypoint by @a-hilaly in #1196

🧹 Chores

New Contributors

Full Changelog: v0.8.5...v0.9.0