Add spec.groups field with typed group memberships#292
Merged
PhilippMatthes merged 3 commits intomainfrom Apr 30, 2026
Merged
Conversation
Introduce a new spec.groups field on the Hypervisor CRD that unifies traits and aggregates as typed group entries using the field-presence union pattern. Each entry populates exactly one type-specific sub-field (trait or aggregate), enforced by a CEL validation rule. Includes library helper functions (HasTrait, GetTraits, HasAggregate, GetAggregates) following the meta.IsStatusConditionTrue pattern, reusable across the shim, operator, and scheduler. Existing spec.customTraits and spec.aggregates fields remain untouched.
This comment was marked as spam.
This comment was marked as spam.
Member
Author
- Replace MinLength=1 with RFC 4122 UUID pattern validation on AggregateGroup.UUID to reject malformed UUIDs at the CRD level. - Tighten negative validation test assertions to check specific field paths in error messages (trait.name, aggregate.name, aggregate.uuid). - Add round-trip assertion verifying aggregate metadata survives serialization after creation. - Update all test UUIDs to valid RFC 4122 format.
The "union rule" tests still used "abc-123" which doesn't match the new RFC 4122 pattern validation. Replace with valid UUIDs.
This comment was marked as low quality.
This comment was marked as low quality.
mchristianl
approved these changes
Apr 29, 2026
notandy
approved these changes
Apr 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Cortex Placement Shim replaces OpenStack Placement for kvm and reads scheduling information directly from the Hypervisor CRD. This is an opportunity to rethink how traits and aggregates are modeled on the CRD.
Today, trait and aggregate data is split across spec and status. Controllers reconcile between the two, merging sources and pushing state to OpenStack Placement. With the shim reading the CRD directly, there is no external system to observe or merge from, making this indirection unnecessary. The existing spec fields are also flat string lists tied to OpenStack naming, unable to carry the structured data like UUIDs and metadata that the shim needs to serve a compatible Placement API.
Both traits and aggregates are forms of grouping: traits group hypervisors by capability, aggregates group them by administrative assignment. This proposal unifies them under a new spec.groups field as the single source of truth. Rather than using Kubernetes labels, which are flat key-value strings without schema validation, spec.groups models each group kind as a well-typed substruct that can carry structured data such as UUIDs and metadata.
The field is a list of typed group entries following the field-presence union pattern from core Kubernetes, as used by PodSpec.volumes. Each entry populates exactly one type-specific sub-field:
Each group type has its own struct with only the fields relevant to it. A CEL validation rule enforces that exactly one sub-field is populated per entry. The existing spec.customTraits and spec.aggregates fields remain untouched to not interfere with existing controller logic, separating this api change from the controller refactor. They can be deprecated and removed in a future release once the shim is fully integrated.
Library helper functions like HasTrait, GetTraits, HasAggregate, and GetAggregates follow the meta.IsStatusConditionTrue pattern and are reusable across the shim, operator, and scheduler.
The design is extensible: adding a new grouping concept means adding one optional pointer field to the Group struct and a corresponding type-specific struct. No changes to existing fields or consumers are required.