Skip to content

Add aggregate metadata#274

Open
PhilippMatthes wants to merge 1 commit intomainfrom
add-aggregate-metadata
Open

Add aggregate metadata#274
PhilippMatthes wants to merge 1 commit intomainfrom
add-aggregate-metadata

Conversation

@PhilippMatthes
Copy link
Member

@PhilippMatthes PhilippMatthes commented Mar 24, 2026

This change adds aggregate metadata to the type kvmv1.Aggregate struct, and passes it in the aggregates controller.

Summary by CodeRabbit

  • New Features

    • Hypervisor aggregates now support optional metadata represented as key-value pairs, enabling custom tagging and enhanced resource organization.
  • Tests

    • Enhanced test coverage for metadata functionality in aggregates.

@coderabbitai
Copy link

coderabbitai bot commented Mar 24, 2026

📝 Walkthrough

Walkthrough

Metadata support is added to the Aggregate type across the codebase, including type definitions, deep copy logic, apply configurations, CRD schema, and OpenStack integration. The Metadata field stores key-value pairs representing aggregate metadata from OpenStack.

Changes

Cohort / File(s) Summary
Type definition and generated code
api/v1/hypervisor_types.go, api/v1/zz_generated.deepcopy.go, applyconfigurations/api/v1/aggregate.go
Added Metadata field to Aggregate type; updated deep copy logic to properly copy metadata maps and aggregate slices; added WithMetadata fluent builder method to apply configuration.
CRD schema
charts/openstack-hypervisor-operator/crds/kvm.cloud.sap_hypervisors.yaml
Extended status schema for aggregates.items with new optional metadata object field (type: object with string-valued properties).
OpenStack integration
internal/openstack/aggregates.go
Updated ApplyAggregates to populate Metadata field from OpenStack aggregate data.
Test coverage
internal/openstack/aggregates_test.go
Extended test fixture and assertions to verify metadata handling across aggregates with populated, nil, and empty metadata values.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A hop, a skip, through code so neat,
Metadata added, a treat so sweet,
Keys and values in pairs they go,
Aggregates enriched with data's glow!
WithMetadata bounds with joy!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add aggregate metadata' directly and concisely describes the main change: adding a metadata field to the Aggregate struct across all related files (types, deepcopy, apply configurations, CRD, and implementation).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-aggregate-metadata

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

Merging this branch will not change overall coverage

Impacted Packages Coverage Δ 🤖
github.com/cobaltcore-dev/openstack-hypervisor-operator/api/v1 0.00% (ø)
github.com/cobaltcore-dev/openstack-hypervisor-operator/applyconfigurations/api/v1 0.00% (ø)
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/openstack 77.44% (ø)

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/cobaltcore-dev/openstack-hypervisor-operator/api/v1/hypervisor_types.go 0.00% (ø) 0 0 0
github.com/cobaltcore-dev/openstack-hypervisor-operator/api/v1/zz_generated.deepcopy.go 0.00% (ø) 0 0 0
github.com/cobaltcore-dev/openstack-hypervisor-operator/applyconfigurations/api/v1/aggregate.go 0.00% (ø) 0 0 0
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/openstack/aggregates.go 98.11% (ø) 53 52 1

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

Changed unit test files

  • github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/openstack/aggregates_test.go

@PhilippMatthes
Copy link
Member Author

I validated this is not a breaking change.

minikube start

Apply the crd before this change without the field:

git checkout 0c0978 && kubectl apply -f charts/openstack-hypervisor-operator/crds/

Create example hypervisor resource:

cat <<EOF | kubectl apply -f -
apiVersion: kvm.cloud.sap/v1
kind: Hypervisor
metadata:
  name: example-hypervisor
EOF

Add some aggregate into the status:

kubectl patch hypervisor example-hypervisor --type=merge --subresource status --patch 'status: {aggregates: [{"name": "example-name", "uuid": "example-uuid"}]}'

Now apply the new crd:

git checkout add-aggregate-metadata && kubectl apply -f charts/openstack-hypervisor-operator/crds/

That succeeds and keeps the status:

kubectl get hypervisor example-hypervisor -o yaml
#...
status:
  aggregates:
  - name: example-name
    uuid: example-uuid

And I can populate the metadata field:

kubectl patch hypervisor example-hypervisor --type=merge --subresource status --patch 'status: {aggregates: [{"name": "example-name", "uuid": "example-uuid", "metadata": {"a": "b"}}]}'
# ...
status:
  aggregates:
  - metadata:
      a: b
    name: example-name
    uuid: example-uuid

@PhilippMatthes PhilippMatthes marked this pull request as ready for review March 24, 2026 16:15
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
applyconfigurations/api/v1/aggregate.go (1)

35-47: Minor typo in comment.

Line 36: "build" should be "built" for grammatical correctness.

📝 Suggested fix
 // WithMetadata puts the entries into the Metadata field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
 // If called multiple times, the entries provided by each call will be put on the Metadata field,
 // overwriting an existing map entries in Metadata field with the same key.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@applyconfigurations/api/v1/aggregate.go` around lines 35 - 47, The comment on
the WithMetadata method has a grammatical typo: change "objects can be build by
chaining" to "objects can be built by chaining" in the doc comment for
AggregateApplyConfiguration.WithMetadata so the documentation is correct and
reads "built" instead of "build".
internal/openstack/aggregates_test.go (1)

122-134: Consider using a map-based assertion for metadata to avoid order dependency.

The current test collects metadata into a slice by index, then asserts on specific indices. While this works because ApplyAggregates preserves the order of desiredAggregates, the earlier assertions for names and uuids use ConsistOf which is order-independent.

For consistency and robustness, consider asserting metadata by aggregate name:

💡 Suggested improvement
-			metadata := make([]map[string]string, len(aggregates))
 			for i, agg := range aggregates {
 				names[i] = agg.Name
 				uuids[i] = agg.UUID
-				metadata[i] = agg.Metadata
 			}
 			Expect(names).To(ConsistOf("agg1", "agg2", "agg3"))
 			Expect(uuids).To(ConsistOf("uuid-agg1", "uuid-agg2", "uuid-agg3"))
-			Expect(metadata[0]).To(Equal(map[string]string{"key1": "value1", "key2": "value2"})) // agg1 metadata should be preserved
-			Expect(metadata[1]).To(BeNil())                                                      // agg2 has no metadata field, should be nil
-			Expect(metadata[2]).To(BeEmpty())                                                    // agg3 has empty metadata, should be preserved
+			// Assert metadata by name to avoid order dependency
+			metadataByName := make(map[string]map[string]string)
+			for _, agg := range aggregates {
+				metadataByName[agg.Name] = agg.Metadata
+			}
+			Expect(metadataByName["agg1"]).To(Equal(map[string]string{"key1": "value1", "key2": "value2"}))
+			Expect(metadataByName["agg2"]).To(BeNil())
+			Expect(metadataByName["agg3"]).To(BeEmpty())
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/openstack/aggregates_test.go` around lines 122 - 134, The test
currently indexes metadata by position which assumes order; instead, map the
returned aggregates by their Name (e.g., build a map[string]map[string]string
from the aggregates slice produced by ApplyAggregates) and assert each
aggregate's metadata by looking up metadataByName["agg1"],
metadataByName["agg2"], metadataByName["agg3"]; update the Expect assertions to
reference the map lookups (preserving the same expectations: agg1 equals the
map, agg2 is nil, agg3 is empty) so the test no longer depends on slice ordering
while keeping the existing names/uuids ConsistOf checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@applyconfigurations/api/v1/aggregate.go`:
- Around line 35-47: The comment on the WithMetadata method has a grammatical
typo: change "objects can be build by chaining" to "objects can be built by
chaining" in the doc comment for AggregateApplyConfiguration.WithMetadata so the
documentation is correct and reads "built" instead of "build".

In `@internal/openstack/aggregates_test.go`:
- Around line 122-134: The test currently indexes metadata by position which
assumes order; instead, map the returned aggregates by their Name (e.g., build a
map[string]map[string]string from the aggregates slice produced by
ApplyAggregates) and assert each aggregate's metadata by looking up
metadataByName["agg1"], metadataByName["agg2"], metadataByName["agg3"]; update
the Expect assertions to reference the map lookups (preserving the same
expectations: agg1 equals the map, agg2 is nil, agg3 is empty) so the test no
longer depends on slice ordering while keeping the existing names/uuids
ConsistOf checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a2d38d88-1ddd-405f-b164-2e60aa78987a

📥 Commits

Reviewing files that changed from the base of the PR and between 0c09786 and 56b40c7.

📒 Files selected for processing (6)
  • api/v1/hypervisor_types.go
  • api/v1/zz_generated.deepcopy.go
  • applyconfigurations/api/v1/aggregate.go
  • charts/openstack-hypervisor-operator/crds/kvm.cloud.sap_hypervisors.yaml
  • internal/openstack/aggregates.go
  • internal/openstack/aggregates_test.go

@PhilippMatthes PhilippMatthes requested a review from notandy March 24, 2026 16:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants