Skip to content

Add SSA conditions helpers in internal/utils#335

Open
fwiesel wants to merge 1 commit into
mainfrom
ssa-conditions-helpers
Open

Add SSA conditions helpers in internal/utils#335
fwiesel wants to merge 1 commit into
mainfrom
ssa-conditions-helpers

Conversation

@fwiesel

@fwiesel fwiesel commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Foundation for migrating all controllers to Server-Side Apply of the status subresource.

Introduces two helpers in internal/utils/conditions.go:

  • ConditionFromStatus: converts a single metav1.Condition (as stored in a status subresource) to a ConditionApplyConfiguration suitable for SSA. ObservedGeneration is preserved so gating logic (e.g. the taint controller's skip-check) keeps working.
  • SetApplyConfigurationStatusCondition: mirrors the semantics of meta.SetStatusCondition on the apply-configuration slice: append or update by Type, refresh LastTransitionTime only when Status changes, guard against nil/empty Type to prevent panics.

Together they enable per-condition seeding so each controller claims field ownership only over the conditions it actually manages, without disturbing conditions owned by other field managers on Apply.

Summary by CodeRabbit

  • New Features

    • Added utilities for converting status conditions into apply configurations.
    • Added support for safely adding and updating conditions while preserving transition timestamps and detecting changes.
  • Tests

    • Added comprehensive coverage for condition conversion, updates, no-op scenarios, timestamps, and unchanged conditions.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds utilities to convert Kubernetes status conditions into apply configurations and to append or update apply-configuration conditions with tested transition-time semantics.

Changes

Condition Utilities

Layer / File(s) Summary
Condition conversion
internal/utils/conditions.go, internal/utils/conditions_test.go
Adds ConditionFromStatus, copying condition fields including zero-valued observed generation, with corresponding tests.
Condition update semantics
internal/utils/conditions.go, internal/utils/conditions_test.go
Adds type-based append and update behavior, transition-time defaulting, nil-safe comparisons, and coverage for guard, mutation, and preservation cases.
Utils test setup
internal/utils/conditions_test.go
Adds the Ginkgo suite entrypoint for the utilities tests.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding SSA condition helpers in internal/utils.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ 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 ssa-conditions-helpers

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@fwiesel

fwiesel commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

Consumer PRs that depend on this foundation:

Final cleanup that removes internal/utils/status_patch.go once all callers are gone: #346

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
internal/utils/conditions.go (1)

118-138: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Simplify strChanged and int64Changed signatures.

Both helpers take a double-pointer (**string / **int64) for a but only read *a — they never write through it. Passing the single pointer directly removes the unnecessary indirection and makes call sites cleaner.

♻️ Proposed refactor
-func strChanged(a **string, b *string) bool {
-	if *a == nil && b == nil {
+func strChanged(a, b *string) bool {
+	if a == nil && b == nil {
 		return false
 	}
-	if *a == nil || b == nil {
+	if a == nil || b == nil {
 		return true
 	}
-	return **a != *b
+	return *a != *b
 }

-func int64Changed(a **int64, b *int64) bool {
-	if *a == nil && b == nil {
+func int64Changed(a, b *int64) bool {
+	if a == nil && b == nil {
 		return false
 	}
-	if *a == nil || b == nil {
+	if a == nil || b == nil {
 		return true
 	}
-	return **a != *b
+	return *a != *b
 }

And update call sites:

-	if strChanged(&existing.Reason, newCondition.Reason) {
+	if strChanged(existing.Reason, newCondition.Reason) {
 		existing.Reason = newCondition.Reason
 		changed = true
 	}
-	if strChanged(&existing.Message, newCondition.Message) {
+	if strChanged(existing.Message, newCondition.Message) {
 		existing.Message = newCondition.Message
 		changed = true
 	}
-	if int64Changed(&existing.ObservedGeneration, newCondition.ObservedGeneration) {
+	if int64Changed(existing.ObservedGeneration, newCondition.ObservedGeneration) {
 		existing.ObservedGeneration = newCondition.ObservedGeneration
 		changed = true
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/utils/conditions.go` around lines 118 - 138, Change strChanged and
int64Changed to accept single pointers for both arguments, preserving their nil
and value-comparison behavior. Update every call site to pass the existing
pointer value directly rather than its address, and adjust any affected comments
or type references.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@internal/utils/conditions.go`:
- Around line 118-138: Change strChanged and int64Changed to accept single
pointers for both arguments, preserving their nil and value-comparison behavior.
Update every call site to pass the existing pointer value directly rather than
its address, and adjust any affected comments or type references.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a1658255-2e6f-496a-9ede-4e8b53bbab3c

📥 Commits

Reviewing files that changed from the base of the PR and between 71421ef and 181d69b.

📒 Files selected for processing (1)
  • internal/utils/conditions.go

Introduce ConditionFromStatus and SetApplyConfigurationStatusCondition
as the foundation for migrating all controllers to server-side apply
of status subresources.

ConditionFromStatus converts a single metav1.Condition (as stored in
a status subresource) to a ConditionApplyConfiguration suitable for
SSA. ObservedGeneration is preserved so gating logic (e.g. the taint
controller's skip-check) keeps working.

SetApplyConfigurationStatusCondition mirrors the semantics of
meta.SetStatusCondition on the apply-configuration slice: append or
update by Type, refresh LastTransitionTime only when Status changes,
and guard against nil/empty Type to prevent panics.

Together they enable per-condition seeding so each controller claims
field ownership only over the conditions it actually manages, without
disturbing conditions owned by other field managers on Apply.
@fwiesel fwiesel force-pushed the ssa-conditions-helpers branch from 181d69b to 7d13627 Compare July 13, 2026 19:59
@github-actions

Copy link
Copy Markdown

Merging this branch will increase overall coverage

Impacted Packages Coverage Δ 🤖
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/utils 83.05% (+9.72%) 👍

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/utils/conditions.go 86.36% (+86.36%) 44 (+44) 38 (+38) 6 (+6) 🌟

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/utils/conditions_test.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
internal/utils/conditions_test.go (1)

130-222: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing coverage for ObservedGeneration updates and nil-field comparisons.

This block thoroughly covers Status/Reason/Message transitions, but none of the BeforeEach fixtures or new-condition builders ever set ObservedGeneration, so int64Changed is never exercised with a real value change. There's also no case for existing.Status == nil or mismatched nil Reason/Message, which the nil-safe comparison logic in SetApplyConfigurationStatusCondition is specifically designed to handle.

Consider adding cases like:

It("updates ObservedGeneration and reports changed", func() {
    gen := int64(5)
    changed := SetApplyConfigurationStatusCondition(&conditions,
        *k8sacmetav1.Condition().
            WithType("Ready").
            WithStatus(metav1.ConditionFalse).
            WithReason("NotReady").
            WithMessage("waiting").
            WithObservedGeneration(gen))
    Expect(changed).To(BeTrue())
    Expect(*conditions[0].ObservedGeneration).To(Equal(gen))
})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/utils/conditions_test.go` around lines 130 - 222, Add test coverage
in the existing “updating an existing condition” Describe block for
SetApplyConfigurationStatusCondition: include an ObservedGeneration value that
changes and assert the update is reported and stored, plus cases exercising nil
existing Status and mismatched nil/non-nil Reason or Message comparisons. Keep
the assertions focused on changed status and resulting fields, while preserving
the existing transition-time behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@internal/utils/conditions_test.go`:
- Around line 130-222: Add test coverage in the existing “updating an existing
condition” Describe block for SetApplyConfigurationStatusCondition: include an
ObservedGeneration value that changes and assert the update is reported and
stored, plus cases exercising nil existing Status and mismatched nil/non-nil
Reason or Message comparisons. Keep the assertions focused on changed status and
resulting fields, while preserving the existing transition-time behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f87c997f-4ed5-4252-b8ae-fa0b7b0e8d27

📥 Commits

Reviewing files that changed from the base of the PR and between 181d69b and 7d13627.

📒 Files selected for processing (2)
  • internal/utils/conditions.go
  • internal/utils/conditions_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/utils/conditions.go

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.

1 participant