Skip to content

Add namespace predicate and fix RBAC for HostLease controller - #3

Merged
tzumainn merged 1 commit into
osac-project:mainfrom
DanNiESh:namespace-predicate
May 13, 2026
Merged

Add namespace predicate and fix RBAC for HostLease controller#3
tzumainn merged 1 commit into
osac-project:mainfrom
DanNiESh:namespace-predicate

Conversation

@DanNiESh

@DanNiESh DanNiESh commented May 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add NamespacePredicate to restrict the controller to only reconcile HostLeases in its own namespace,
    matching the pattern used by osac-operator. The namespace is configured via the HOSTLEASE_NAMESPACE
    environment variable, defaulting to osac-hostleases when not set.
  • Fix ClusterRole to include update and patch verbs on hostleases and hostleases/finalizers, which are
    required for finalizer management.

Summary by CodeRabbit

  • New Features

    • HostLease controller can now be scoped to a specific namespace, enabling improved multi-tenant deployments.
  • Chores

    • Test infrastructure refactoring and consolidation.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 11, 2026

Copy link
Copy Markdown

Walkthrough

This PR extends the HostLeaseReconciler to operate within a single configurable Kubernetes namespace. The controller now reads HOSTLEASE_NAMESPACE from the environment at startup, exits if unset, and configures the controller-runtime manager cache to watch v1alpha1.HostLease objects only in that namespace. The deployment manifest injects this environment variable from the pod's runtime namespace, RBAC permissions are expanded to permit update/patch operations on hostleases and finalizers, and comprehensive test refactoring centralizes repeated literals into shared constants.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 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 accurately describes the main changes: adding a namespace predicate to restrict HostLease controller reconciliation and fixing RBAC permissions for the controller.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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 unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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 and usage tips.

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

Actionable comments posted: 1

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

Inline comments:
In `@internal/controller/hostlease_controller.go`:
- Around line 307-313: NamespacePredicate currently returns a predicate that
only matches objects whose namespace equals the provided namespace string, which
silently disables reconciliation when HOSTLEASE_NAMESPACE is empty; change
NamespacePredicate to detect an empty namespace and either (a) return a
predicate that always allows all objects (e.g., use
predicate.LabelChangedPredicate/TruePredicate equivalent) so the controller
watches all namespaces when namespace == "", or (b) alternatively validate the
env earlier by adding a check in NewHostLeaseReconciler to fail startup with a
clear error if the namespace is required; update NamespacePredicate (and/or
NewHostLeaseReconciler) accordingly and add a unit/test or startup log to make
the behavior explicit.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b8afc9d5-fe59-4704-bdd7-b15fe02c24c9

📥 Commits

Reviewing files that changed from the base of the PR and between e089d70 and 3455e96.

📒 Files selected for processing (5)
  • cmd/main.go
  • config/rbac/role.yaml
  • internal/controller/hostlease_controller.go
  • internal/controller/hostlease_controller_test.go
  • internal/controller/hostlease_names.go

Comment thread internal/controller/hostlease_controller.go Outdated
@DanNiESh
DanNiESh force-pushed the namespace-predicate branch 2 times, most recently from 163e718 to b2ac229 Compare May 11, 2026 23:32
@DanNiESh
DanNiESh requested review from ajamias, larsks and tzumainn May 11, 2026 23:52

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

Thanks for making this change! Two comments:

@DanNiESh
DanNiESh force-pushed the namespace-predicate branch from b2ac229 to 39a65c7 Compare May 12, 2026 13:55

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
internal/controller/hostlease_controller_test.go (1)

107-113: ⚡ Quick win

Assert namespace behavior in constructor tests.

These tests now pass a namespace but only verify interval. Add assertions for r.Namespace (provided value and empty-value default path) so the new scoping behavior is covered.

Targeted test additions
 		It("should use the provided recheck interval when positive", func() {
 			r := NewHostLeaseReconciler(nil, testScheme, mockIronic, "test-ns", 30*time.Second)
+			Expect(r.Namespace).To(Equal("test-ns"))
 			Expect(r.RecheckInterval).To(Equal(30 * time.Second))
 		})
 
 		It("should use the default recheck interval when zero", func() {
 			r := NewHostLeaseReconciler(nil, testScheme, mockIronic, "test-ns", 0)
+			Expect(r.Namespace).To(Equal("test-ns"))
 			Expect(r.RecheckInterval).To(Equal(DefaultRecheckInterval))
 		})
+
+		It("should use default namespace when namespace is empty", func() {
+			r := NewHostLeaseReconciler(nil, testScheme, mockIronic, "", 0)
+			Expect(r.Namespace).To(Equal(defaultHostLeaseNamespace))
+		})
 	})
🤖 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/controller/hostlease_controller_test.go` around lines 107 - 113, The
constructor tests currently only verify RecheckInterval; update both cases that
call NewHostLeaseReconciler to also assert the reconciler's Namespace field:
when calling NewHostLeaseReconciler(nil, testScheme, mockIronic, "test-ns",
30*time.Second) expect r.Namespace to equal "test-ns", and when calling it with
an empty namespace string (0 interval case) expect r.Namespace to equal the
default/empty behavior (e.g., DefaultNamespace or "" depending on constructor
semantics) so the new scoping behavior is covered; reference
NewHostLeaseReconciler and r.Namespace when adding these assertions and keep
existing RecheckInterval checks.
🤖 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.

Inline comments:
In `@config/manager/manager.yaml`:
- Around line 68-72: The manifest currently hard-sets HOSTLEASE_NAMESPACE via
env.fieldRef to metadata.namespace, forcing the manager into the Pod namespace;
remove this env entry so the manager's constructor fallback can determine the
intended HostLease scope. Locate the env block that defines HOSTLEASE_NAMESPACE
(the env -> - name: HOSTLEASE_NAMESPACE -> valueFrom -> fieldRef -> fieldPath:
metadata.namespace) and delete that whole env variable (or replace it with an
explicit empty/default value if you need an explicit unset), leaving the manager
code to read configuration or fall back as implemented.

---

Nitpick comments:
In `@internal/controller/hostlease_controller_test.go`:
- Around line 107-113: The constructor tests currently only verify
RecheckInterval; update both cases that call NewHostLeaseReconciler to also
assert the reconciler's Namespace field: when calling
NewHostLeaseReconciler(nil, testScheme, mockIronic, "test-ns", 30*time.Second)
expect r.Namespace to equal "test-ns", and when calling it with an empty
namespace string (0 interval case) expect r.Namespace to equal the default/empty
behavior (e.g., DefaultNamespace or "" depending on constructor semantics) so
the new scoping behavior is covered; reference NewHostLeaseReconciler and
r.Namespace when adding these assertions and keep existing RecheckInterval
checks.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2364f045-854e-49d7-9ea2-5d197fe41c5c

📥 Commits

Reviewing files that changed from the base of the PR and between 3455e96 and 39a65c7.

📒 Files selected for processing (6)
  • cmd/main.go
  • config/manager/manager.yaml
  • config/rbac/role.yaml
  • internal/controller/hostlease_controller.go
  • internal/controller/hostlease_controller_test.go
  • internal/controller/hostlease_names.go
✅ Files skipped from review due to trivial changes (1)
  • internal/controller/hostlease_names.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • config/rbac/role.yaml
  • internal/controller/hostlease_controller.go

Comment on lines +68 to +72
env:
- name: HOSTLEASE_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace

@coderabbitai coderabbitai Bot May 12, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid hard-binding HostLease scope to the manager Pod namespace.

Line 69 forces HOSTLEASE_NAMESPACE to metadata.namespace (system here), which bypasses constructor fallback and can silently exclude HostLeases if they live in another intended namespace.

Suggested adjustment
-        env:
-          - name: HOSTLEASE_NAMESPACE
-            valueFrom:
-              fieldRef:
-                fieldPath: metadata.namespace
+        # Keep unset to use controller default, or set explicitly via overlay/config.
+        env: []
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
env:
- name: HOSTLEASE_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
# Keep unset to use controller default, or set explicitly via overlay/config.
env: []
🤖 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 `@config/manager/manager.yaml` around lines 68 - 72, The manifest currently
hard-sets HOSTLEASE_NAMESPACE via env.fieldRef to metadata.namespace, forcing
the manager into the Pod namespace; remove this env entry so the manager's
constructor fallback can determine the intended HostLease scope. Locate the env
block that defines HOSTLEASE_NAMESPACE (the env -> - name: HOSTLEASE_NAMESPACE
-> valueFrom -> fieldRef -> fieldPath: metadata.namespace) and delete that whole
env variable (or replace it with an explicit empty/default value if you need an
explicit unset), leaving the manager code to read configuration or fall back as
implemented.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Following the pattern here https://github.com/osac-project/osac-operator/blob/main/config/manager/manager.yaml#L77-L80. HostLeases in other namespaces should be excluded as intended.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@DanNiESh, understood — thanks for the context. Using the Kubernetes Downward API to inject metadata.namespace as an env var is a well-established pattern (also used by the Operator SDK, OLM, and others) to namespace-scope a controller to its own deployment namespace. Since the explicit design goal is for the controller to only reconcile HostLeases in its own namespace (mirroring the osac-operator pattern), the current implementation is correct. I'll withdraw my earlier concern.


✏️ Learnings added
Learnt from: DanNiESh
Repo: osac-project/host-management-openstack PR: 3
File: config/manager/manager.yaml:68-72
Timestamp: 2026-05-12T14:21:18.642Z
Learning: In `config/manager/manager.yaml` of the `host-management-openstack` project, the `HOSTLEASE_NAMESPACE` env var is intentionally set via Kubernetes Downward API (`fieldRef: fieldPath: metadata.namespace`) to scope the HostLease controller to its own Pod namespace. This mirrors the pattern used by `osac-operator`. Excluding HostLeases in other namespaces is the intended behavior — do not flag this as an issue.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@DanNiESh

Copy link
Copy Markdown
Contributor Author

Member

Done!

Comment thread cmd/main.go Outdated
mgr.GetClient(),
mgr.GetScheme(),
ironicClient,
os.Getenv(envHostLeaseNamespace),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I know we provide a default if this is unset, but I wonder if it makes more sense to just make this a required setting and exit with an error if it is unset. What do you think? @DanNiESh @tzumainn

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The HOSTLEASE_NAMESPACE is set in config/manager/manager.yaml. Does that guarantee that the environment variable is always set?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

On the one hand, osac-operator has a default. On the other hand, I've never thought the default made much sense, since we never use it. I guess there could be an argument for having defaults in an environment where we only expect to install a single OSAC?

return obj.GetNamespace() == namespace
},
)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Using a namespace predicate works, but we can do better. See larsks@af76bdc, which shows an alternative approach that is more efficient in terms of memory usage and api event processing. If that seems like a reasonable approach we can update this PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think watching namespace using cache is reasonble.

Use controller-runtime cache configuration to restrict the HostLease watch
to a single namespace (from HOSTLEASE_NAMESPACE env var) instead of using a
namespace predicate. This reduces memory usage and event notifications since
the controller no longer watches HostLease resources across all namespaces.

Also adds RBAC for pods and configures the HOSTLEASE_NAMESPACE env var in
the manager deployment via downward API.

Co-Authored-By: Lars Kellogg-Stedman <lars@redhat.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@DanNiESh
DanNiESh force-pushed the namespace-predicate branch from 39a65c7 to 31236ea Compare May 12, 2026 18:37

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

♻️ Duplicate comments (1)
cmd/main.go (1)

186-190: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid hard-failing when HOSTLEASE_NAMESPACE is unset; use the documented default.

Line 186 to Line 190 exits the process on empty env var, but this PR’s stated behavior is to default to osac-hostleases. Current behavior can cause avoidable startup failures when env injection is misconfigured.

Suggested patch
-import (
+import (
 	"crypto/tls"
 	"flag"
-	"fmt"
 	"os"
 	"path/filepath"
@@
-const envHostLeaseNamespace = "HOSTLEASE_NAMESPACE"
+const (
+	envHostLeaseNamespace     = "HOSTLEASE_NAMESPACE"
+	defaultHostLeaseNamespace = "osac-hostleases"
+)
@@
 	controllerNamespace := os.Getenv(envHostLeaseNamespace)
 	if controllerNamespace == "" {
-		setupLog.Error(nil, fmt.Sprintf("%s environment variable must be set", envHostLeaseNamespace))
-		os.Exit(1)
+		controllerNamespace = defaultHostLeaseNamespace
+		setupLog.Info("HOSTLEASE_NAMESPACE not set; using default namespace", "namespace", controllerNamespace)
 	}
🤖 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 `@cmd/main.go` around lines 186 - 190, The code currently exits when
controllerNamespace := os.Getenv(envHostLeaseNamespace) is empty; instead, set
controllerNamespace to the documented default "osac-hostleases" if the env var
is unset and log a warning rather than calling setupLog.Error(nil, ...) and
os.Exit(1); update the logic around controllerNamespace and the
envHostLeaseNamespace usage so it assigns "osac-hostleases" when empty and emits
a clear warning via setupLog (e.g., setupLog.Info or setupLog.Warn) mentioning
the default being used.
🤖 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.

Duplicate comments:
In `@cmd/main.go`:
- Around line 186-190: The code currently exits when controllerNamespace :=
os.Getenv(envHostLeaseNamespace) is empty; instead, set controllerNamespace to
the documented default "osac-hostleases" if the env var is unset and log a
warning rather than calling setupLog.Error(nil, ...) and os.Exit(1); update the
logic around controllerNamespace and the envHostLeaseNamespace usage so it
assigns "osac-hostleases" when empty and emits a clear warning via setupLog
(e.g., setupLog.Info or setupLog.Warn) mentioning the default being used.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 70a987e1-c0f1-450c-881b-379091e03fca

📥 Commits

Reviewing files that changed from the base of the PR and between 39a65c7 and 31236ea.

📒 Files selected for processing (4)
  • cmd/main.go
  • config/manager/manager.yaml
  • config/rbac/role.yaml
  • internal/controller/hostlease_controller_test.go
✅ Files skipped from review due to trivial changes (2)
  • config/manager/manager.yaml
  • internal/controller/hostlease_controller_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • config/rbac/role.yaml

@DanNiESh

Copy link
Copy Markdown
Contributor Author

Squashed @larsks commit into this commit.

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

Thanks for the changes!

@tzumainn
tzumainn merged commit d206b73 into osac-project:main May 13, 2026
5 checks passed
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.

3 participants