Skip to content

fix/code issues#295

Merged
fwiesel merged 24 commits intomainfrom
fix/code-issues
May 5, 2026
Merged

fix/code issues#295
fwiesel merged 24 commits intomainfrom
fix/code-issues

Conversation

@notandy
Copy link
Copy Markdown
Contributor

@notandy notandy commented Apr 28, 2026

Multiple reruns of agentic code issue inspections, paired with individual fixes.
Includes 2-3 serious fixes, but mostly minor stuff - still worthy.
Commits have been reviewed and are pretty small individually.

  • Fix strings.SplitN with n=1 being a no-op
  • Move flag validation after flag.Parse()
  • Add 30-second timeout to HA service HTTP client
  • Add retry-on-conflict for eviction status updates
  • Copy transferLabels slice before appending to avoid mutation
  • Fix PeriodSeconds(0) on startup probe
  • Fix missing URL path separator in HA service URL
  • Fix wrong error message (image vs network)
  • Fix missing "not" in error message
  • Consolidate duplicate difference functions into utils package
  • Remove dead code - unused logger in SetupWithManager functions
  • Remove unused logger imports in aggregates and traits controllers
  • Fix eviction updateStatus to re-fetch resource on conflict retry
  • Fix evictNext: add explicit return after deleting branch and fix error typo
  • Return early when Hypervisor not found in GardenerNodeLifecycleController
  • Fix --version flag to print version info and check it before validation
  • Remove dead code: unused functions, constants, and types
  • Fix typo: SanitzeReconcileErrorEncoder -> SanitizeReconcileErrorEncoder
  • Rename moveToBack to deprioritize for clarity
  • Fix Clone() to preserve cfg field in SanitizeReconcileErrorEncoder
  • Fix FindNodeStatusCondition to return pointer to slice element, not copy
  • Narrow RBAC annotations on status subresources to get;update;patch
  • Remove unused base parameter from eviction updateStatus and handleNotFound

Summary by CodeRabbit

  • New Features

    • Added --version flag to display application version and build information.
  • Bug Fixes

    • Corrected error messages in certificate creation and image lookup workflows.
    • Improved HTTP request handling with configured timeout support.
  • Security

    • Refined Kubernetes RBAC permissions to enforce principle of least privilege for status subresources.
  • Chores

    • Fixed internal spelling inconsistencies.
    • Removed unused utility functions and simplified internal code.
    • Enhanced status update resilience with optimistic locking.

notandy added 18 commits April 27, 2026 23:27
SplitN(s, ".", 1) returns the original string unsplit since n=1 returns
a single-element slice containing the whole string. Changed to n=2 to
correctly extract the short hostname (everything before the first ".").

This fixes hypervisor hostname comparisons that were incorrectly
comparing full FQDNs against short hostnames, which could block
onboarding or cause false "could not find exact match" errors.
The validation checks for certificate-issuer-name and certificate-namespace
were running before flag.Parse(), meaning user-provided values were not
yet parsed. This made the validation ineffective - it would always pass
since the variables had non-empty defaults.

Moving the validation after flag.Parse() ensures that if a user passes
an empty value (e.g., --certificate-issuer-name=""), it will be caught.
The HA service HTTP call was using the default HTTP client with no
timeout, which could hang indefinitely and block the reconciliation
goroutine. Added a 30-second timeout to prevent this.
Unlike the Hypervisor status patches which use PatchHypervisorStatusWithRetry
with exponential backoff retries, the Eviction status patches were using a
direct optimistic-lock patch with no retry. Under contention this would fail
with a conflict and require a full re-reconciliation.

Added retry logic using the same StatusPatchBackoff configuration used by
the Hypervisor controller. Also added PatchEvictionStatusWithRetry helper
for future use.
The transferLabels slice is a package-level variable that was being
mutated during SetupWithManager by appending custom label selector keys.
While this is called only once during initialization, it could cause
data races if tests run in parallel with -race flag.

Now we copy the slice before appending to avoid mutating the original.
PeriodSeconds of 0 is technically invalid in the Kubernetes API - the
minimum is 1 second. Kubernetes would silently default it to 10 seconds,
which may not be the intended behavior. Changed to explicit 1 second.
If KVM_HA_SERVICE_URL doesn't end with a "/", the URL would be malformed
(e.g., "https://exampleapi/hypervisors/host" instead of
"https://example/api/hypervisors/host"). Now we ensure a trailing slash
exists before appending the path.
The error message said "could not list networks" but it was about
finding the test image. Changed to "could not find test image".
Changed "could create certificate" to "could not create certificate".
Also added missing colon before the error wrapping placeholder.
Both internal/controller/utils.go and internal/openstack/aggregates.go
had their own implementations of a set-difference function. The
controller version used generics while the openstack version was
string-specific.

Moved the generic version to internal/utils/slices.go so it can be
shared by both packages without circular imports.
Several SetupWithManager functions were fetching a logger from context
and then immediately discarding it with `_`. Removed these unnecessary
lines.
The updateStatus method used a stale base object across retry attempts,
meaning retries would always fail with the same conflict. Now re-fetches
the latest eviction on each retry attempt, matching the pattern used by
PatchHypervisorStatusWithRetry.
…r typo

- Add explicit return after the 'deleting' branch so control flow does
  not fall through to the final return statement. Previously it worked by
  coincidence (err was always nil), but was fragile for future changes.
- Fix typo: 'could update status' -> 'could not update status'
- Replace dangling err reference at final return with explicit nil
- Simplify if/else blocks by removing unnecessary else after return
…ller

Previously, when the Hypervisor was not found, the controller continued
with a zero-value struct and relied on LifecycleEnabled defaulting to
false to exit early. Now explicitly returns when the Hypervisor is not
found, making the intent clear and avoiding fragile zero-value reliance.
The --version flag previously printed nothing and was checked after
required flag validation, so running with --version and missing flags
would error instead of printing the version.
Remove the following unused symbols:
- ErrRetry variable (utils.go)
- HasStatusCondition function (utils.go)
- IsNodeConditionTrue function (utils.go)
- labelEvictionRequired constant (constants.go)
- labelEvictionApproved constant (constants.go)
- PatchEvictionStatusWithRetry function (status_patch.go)
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 2026

📝 Walkthrough

Walkthrough

The PR refactors RBAC permissions to restrict hypervisors/status access across multiple controllers to only get;update;patch, centralizes a Difference utility function, corrects the logger encoder name spelling, and refactors the eviction controller's status-patching mechanism to use optimistic locking with conflict retries.

Changes

Cohort / File(s) Summary
Startup Flow & Logger Spelling
cmd/main.go, internal/logger/logger.go
Reorders startup validation to defer certificate issuer/namespace checks until after --version flag handling; adds --version output with component name, version, OS/arch, and commit. Corrects logger encoder function name from NewSanitzeReconcileErrorEncoder to NewSanitizeReconcileErrorEncoder and updates Clone() to preserve encoder config.
RBAC Permission Tightening
internal/controller/{aggregates,hypervisor_maintenance,hypervisor_taint,traits}_controller.go, config/rbac/role.yaml
Restricts hypervisors/status RBAC permissions across controllers from broader CRUD verbs to only get;update;patch. Removes list;watch;create;delete capabilities while preserving status read/write access.
Logger Initialization Cleanup
internal/controller/hypervisor_instance_ha_controller.go
Removes unused background context creation and logger.FromContext() call from controller setup.
Eviction Controller Status Refactor
internal/controller/eviction_controller.go
Reworked updateStatus to re-fetch latest Eviction resource, deep-copy desired status, overlay onto fresh object, and apply merge patch with optimistic locking. Wraps patch in retry.RetryOnConflict. Updates all call sites and simplifies handleNotFound by removing its base parameter.
Hypervisor Label Handling
internal/controller/hypervisor_controller.go
Refactors transferLabels initialization to reset to fresh copy of defaultTransferLabels and avoid duplicates via slices.Contains check before appending keys from LabelSelector.
Utility Functions Refactoring
internal/controller/utils.go, internal/utils/slices.go, internal/controller/utils_test.go
Moves generic Difference function to centralized internal/utils/slices.go; removes unused helpers IsNodeConditionTrue, HasStatusCondition, and ErrRetry from controller utils. Updates FindNodeStatusCondition to return pointer to slice element instead of loop-variable copy. Updates InstanceHaUrl to normalize URL with trailing slash and updateInstanceHA to use dedicated http.Client with 30-second timeout.
Minor Controller Updates
internal/controller/{gardener_node_lifecycle,node_certificate,onboarding}_controller.go
Treats missing Hypervisor as no-op in gardener_node_lifecycle; adjusts signalling Deployment probe period from 0 to 1 seconds. Corrects error message wrapping in node_certificate. Fixes hostname-shortening logic in ensureNovaProperties and corrects error message from "could not list networks" to "could not find test image" in onboarding.
Constants & Aggregates Cleanup
internal/controller/constants.go, internal/openstack/aggregates.go
Removes labelEvictionRequired and labelEvictionApproved constants. Replaces local difference helper with utils.Difference in aggregates logic.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~35 minutes

Possibly related PRs

Suggested reviewers

  • fwiesel
  • mchristianl

Poem

🐰 A rabbit's refrain on tighter rules,
RBAC bounds now govern the tools,
Status patches locked with retry precision,
Utils centralized—a cleaner vision,
Spelling fixed, and logs laid to rest,
This code refresh stands the test!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 54.55% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title 'fix/code issues' is vague and generic, using non-descriptive terms that do not convey meaningful information about the changeset. Use a more specific title that highlights the primary change, such as 'Fix RBAC restrictions, eviction status handling, and utility consolidation' or focus on the most impactful change.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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.

✏️ 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 fix/code-issues

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
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

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

notandy added 4 commits April 29, 2026 11:24
The Clone() method was not copying the cfg field, violating the Clone
contract by returning an encoder with a zero-valued EncoderConfig.
Previously returned a pointer to the range loop variable (a copy),
meaning mutations through the pointer would not affect the original
slice. Now indexes directly into the slice to return a stable pointer.
Status subresources don't support create, delete, list, or watch verbs.
Remove over-broad permissions from hypervisor/status RBAC annotations
across all controllers.
…Found

After the updateStatus refactor to re-fetch resources on retry, the base
parameter is no longer used. Remove it along with the now-unnecessary
DeepCopy calls at each call site. Also remove unused gosec nolint
directive in utils.go.
@notandy notandy marked this pull request as ready for review April 29, 2026 19:06
Copy link
Copy Markdown

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
internal/controller/node_certificate_controller.go (2)

147-150: Minor: use structured logging instead of fmt.Sprintf (optional).

In ensureCertificate, log.Info(fmt.Sprintf("Certificate %s %s", certName, update)) could be replaced with structured fields (e.g., "certName", "operation"). This makes log filtering/aggregation easier and is idiomatic for controller-runtime loggers.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/controller/node_certificate_controller.go` around lines 147 - 150,
Replace the fmt.Sprintf usage in ensureCertificate with structured logging:
instead of log.Info(fmt.Sprintf("Certificate %s %s", certName, update)), call
log.Info with message and key/value fields (e.g., log.Info("Certificate
operation", "certName", certName, "operation", update)) so the
controller-runtime logger emits structured fields; ensure the conditional still
checks controllerutil.OperationResultNone and retain the same message semantics.

169-171: Minor: consider including more reconciliation context in the wrapped error (optional).

Right now the retry wrapper preserves the underlying err, but the final reconciler error doesn’t include identifiers like node.Name / req.Name (even though ensureCertificate has them locally). If this error ever shows up in cluster logs/events, adding those fields would speed up debugging.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/controller/node_certificate_controller.go` around lines 169 - 171,
The retry wrapper call to retry.RetryOnConflict currently returns the underlying
error without identifying which node failed; capture the returned err and wrap
it with context including the node identifier (e.g., node.Name or req.Name)
before returning from the reconciler. Concretely, after calling
retry.RetryOnConflict(func() error { return r.ensureCertificate(ctx, node,
node.Name) }), check the error and return a wrapped error such as using
fmt.Errorf("reconcile certificate for node %s: %w", node.Name, err) (or
errors.Wrapf) so the final reconciler error includes the node name and aids
debugging.
internal/logger/logger.go (1)

25-27: Constructor rename is correct; consider named fields for resilience.

Good fix. Optional: at Line 26, use named fields in the struct literal to avoid field-order coupling.

Optional tidy-up
 func NewSanitizeReconcileErrorEncoder(cfg zapcore.EncoderConfig) zapcore.Encoder {
-	return &SanitizeReconcileErrorEncoder{zapcore.NewConsoleEncoder(cfg), cfg}
+	return &SanitizeReconcileErrorEncoder{
+		Encoder: zapcore.NewConsoleEncoder(cfg),
+		cfg:     cfg,
+	}
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/logger/logger.go` around lines 25 - 27, The constructor
NewSanitizeReconcileErrorEncoder currently returns a
SanitizeReconcileErrorEncoder using a positional struct literal; change it to
use named fields to prevent field-order coupling by constructing
&SanitizeReconcileErrorEncoder{Encoder: zapcore.NewConsoleEncoder(cfg), Config:
cfg} (match the actual field names on SanitizeReconcileErrorEncoder) so future
field reorders won't break this initializer.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/controller/eviction_controller.go`:
- Around line 172-185: The current updateStatus implementation captures a stale
full-status snapshot in desiredStatus and then overwrites freshEviction.Status
with that snapshot inside the retry, which can revert concurrent status updates;
modify EvictionReconciler.updateStatus so the mutation of freshEviction.Status
happens inside the RetryOnConflict closure and is derived from the freshly
fetched freshEviction (e.g., copy only the intended fields from the previously
computed desired state rather than assigning the whole desiredStatus), then
compute freshBase := freshEviction.DeepCopy() and call r.Status().Patch(ctx,
freshEviction, client.MergeFromWithOptions(freshBase,
client.MergeFromWithOptimisticLock{}),
client.FieldOwner(EvictionControllerName)) so each retry generates a patch
against the latest resourceVersion instead of reapplying a stale snapshot.

In `@internal/controller/hypervisor_controller.go`:
- Around line 198-202: The package-level slice transferLabels is being
reassigned and can leak state across repeated SetupWithManager runs; in the
SetupWithManager path rebuild a local labels slice from an immutable base (do
not reassign the package-level transferLabels), append requirement.Key() values
from requirements into that local slice, and deduplicate entries (e.g., via a
temporary map) before using it — update any code that currently does
transferLabels = append([]string{}, transferLabels...) to instead create a fresh
localLabels := append([]string{}, baseTransferLabels...) then append
requirement.Key() for each requirement and remove duplicates prior to using
localLabels.

---

Nitpick comments:
In `@internal/controller/node_certificate_controller.go`:
- Around line 147-150: Replace the fmt.Sprintf usage in ensureCertificate with
structured logging: instead of log.Info(fmt.Sprintf("Certificate %s %s",
certName, update)), call log.Info with message and key/value fields (e.g.,
log.Info("Certificate operation", "certName", certName, "operation", update)) so
the controller-runtime logger emits structured fields; ensure the conditional
still checks controllerutil.OperationResultNone and retain the same message
semantics.
- Around line 169-171: The retry wrapper call to retry.RetryOnConflict currently
returns the underlying error without identifying which node failed; capture the
returned err and wrap it with context including the node identifier (e.g.,
node.Name or req.Name) before returning from the reconciler. Concretely, after
calling retry.RetryOnConflict(func() error { return r.ensureCertificate(ctx,
node, node.Name) }), check the error and return a wrapped error such as using
fmt.Errorf("reconcile certificate for node %s: %w", node.Name, err) (or
errors.Wrapf) so the final reconciler error includes the node name and aids
debugging.

In `@internal/logger/logger.go`:
- Around line 25-27: The constructor NewSanitizeReconcileErrorEncoder currently
returns a SanitizeReconcileErrorEncoder using a positional struct literal;
change it to use named fields to prevent field-order coupling by constructing
&SanitizeReconcileErrorEncoder{Encoder: zapcore.NewConsoleEncoder(cfg), Config:
cfg} (match the actual field names on SanitizeReconcileErrorEncoder) so future
field reorders won't break this initializer.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a10f3535-cbaa-474a-8f3c-fe041149a1f7

📥 Commits

Reviewing files that changed from the base of the PR and between 38c9868 and 2fc05c6.

📒 Files selected for processing (17)
  • cmd/main.go
  • internal/controller/aggregates_controller.go
  • internal/controller/constants.go
  • internal/controller/eviction_controller.go
  • internal/controller/gardener_node_lifecycle_controller.go
  • internal/controller/hypervisor_controller.go
  • internal/controller/hypervisor_instance_ha_controller.go
  • internal/controller/hypervisor_maintenance_controller.go
  • internal/controller/hypervisor_taint_controller.go
  • internal/controller/node_certificate_controller.go
  • internal/controller/onboarding_controller.go
  • internal/controller/traits_controller.go
  • internal/controller/utils.go
  • internal/controller/utils_test.go
  • internal/logger/logger.go
  • internal/openstack/aggregates.go
  • internal/utils/slices.go
💤 Files with no reviewable changes (1)
  • internal/controller/hypervisor_instance_ha_controller.go

Comment thread internal/controller/eviction_controller.go
Comment thread internal/controller/hypervisor_controller.go Outdated
notandy added 2 commits April 29, 2026 22:28
Prevents accumulation of stale label selector keys when SetupWithManager
is called multiple times (e.g., in tests with multiple managers).
Apply desired status fields individually onto the freshly-fetched object
in the retry closure instead of overwriting the entire status, preventing
concurrent condition changes from being reverted. Add deduplication when
appending label selector keys to transferLabels.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 1, 2026

Merging this branch changes the coverage (1 decrease, 2 increase)

Impacted Packages Coverage Δ 🤖
github.com/cobaltcore-dev/openstack-hypervisor-operator/cmd 0.00% (ø)
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller 66.49% (+0.83%) 👍
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/logger 0.00% (ø)
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/openstack 78.29% (-0.81%) 👎
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/utils 73.33% (+13.33%) 🎉

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/cobaltcore-dev/openstack-hypervisor-operator/cmd/main.go 0.00% (ø) 0 0 0
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/aggregates_controller.go 85.94% (+1.32%) 64 (-1) 55 9 (-1) 👍
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/constants.go 0.00% (ø) 0 0 0
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/eviction_controller.go 39.38% (+3.48%) 160 (+4) 63 (+7) 97 (-3) 👍
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/gardener_node_lifecycle_controller.go 72.41% (+0.99%) 58 (+2) 42 (+2) 16 👍
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/hypervisor_controller.go 75.68% (-3.20%) 74 (+3) 56 18 (+3) 👎
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/hypervisor_instance_ha_controller.go 90.91% (+3.95%) 44 (-2) 40 4 (-2) 👍
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/hypervisor_maintenance_controller.go 79.07% (+0.91%) 86 (-1) 68 18 (-1) 👍
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/hypervisor_taint_controller.go 92.86% (ø) 14 13 1
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/node_certificate_controller.go 81.63% (ø) 49 40 9
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/onboarding_controller.go 55.14% (ø) 243 134 109
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/traits_controller.go 74.60% (+1.17%) 63 (-1) 47 16 (-1) 👍
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/utils.go 84.62% (+6.35%) 39 (-7) 33 (-3) 6 (-4) 👍
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/logger/logger.go 0.00% (ø) 0 0 0
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/openstack/aggregates.go 97.92% (-0.20%) 48 (-5) 47 (-5) 1 👎
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/utils/slices.go 100.00% (+100.00%) 5 (+5) 5 (+5) 0 🌟

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/controller/utils_test.go

Copy link
Copy Markdown

@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 (1)
config/rbac/role.yaml (1)

73-82: 💤 Low value

Consider removing list and watch from hypervisors/status for tighter least-privilege.

The /status subresource endpoint is typically only used for get, update, and patch operations. Controllers watch/list the main resource (not the status subresource) and receive the status as part of the object. The context snippet from aggregates_controller.go confirms only get;update;patch is declared.

If this file is generated via controller-gen, verify that no controller annotation actually requests list or watch on hypervisors/status. If none do, these verbs may be safely removed.

🔧 Suggested narrowing
 - apiGroups:
   - kvm.cloud.sap
   resources:
   - hypervisors/status
   verbs:
   - get
-  - list
   - patch
   - update
-  - watch
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@config/rbac/role.yaml` around lines 73 - 82, The RBAC rule grants unnecessary
verbs on the status subresource: remove "list" and "watch" from the resources
entry for "hypervisors/status" in role.yaml to follow least-privilege (keep only
get, patch, update); confirm no controller annotations request list/watch for
the status subresource (check aggregates_controller.go and any +kubebuilder:rbac
annotations) and regenerate the role if the manifest is produced by
controller-gen.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@config/rbac/role.yaml`:
- Around line 73-82: The RBAC rule grants unnecessary verbs on the status
subresource: remove "list" and "watch" from the resources entry for
"hypervisors/status" in role.yaml to follow least-privilege (keep only get,
patch, update); confirm no controller annotations request list/watch for the
status subresource (check aggregates_controller.go and any +kubebuilder:rbac
annotations) and regenerate the role if the manifest is produced by
controller-gen.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ede49ea4-38e0-42ba-84a5-329f9abade20

📥 Commits

Reviewing files that changed from the base of the PR and between 2fc05c6 and 82ce512.

📒 Files selected for processing (3)
  • config/rbac/role.yaml
  • internal/controller/eviction_controller.go
  • internal/controller/hypervisor_controller.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/controller/hypervisor_controller.go

Copy link
Copy Markdown
Contributor

@fwiesel fwiesel left a comment

Choose a reason for hiding this comment

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

Can you move the changes to the eviction controller to its own PR?
Most of the changes are clear cleanup improvements, but from my perspective the changes to the eviction controller have some side-effects that maybe could be discussed separately.

Copy link
Copy Markdown
Contributor

@fwiesel fwiesel left a comment

Choose a reason for hiding this comment

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

Okay, I read up on it a bit.

Since

  • only the eviction-controller is modifying the eviction status,
  • and the controller-runtime ensures that even with multiple threads, only one reconciliation is running per object,

we are not at risk of having the same controller modifying the same object in an "ABBA" manner.
So, it should work, but I'd prefer then using Patch without Lock with a comment pointing that out why (i.e only one controller, per object locking in controller-runtime).

It is not a must from my side to change it that way. I am looking at SSA, and that might solve that for us quite elegantly.

@fwiesel fwiesel merged commit 098d444 into main May 5, 2026
7 checks passed
@fwiesel fwiesel deleted the fix/code-issues branch May 5, 2026 09:15
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