Skip to content

Add DRA node labeling via unified PodNodeLabel reconciler#1832

Merged
openshift-merge-bot[bot] merged 1 commit into
rh-ecosystem-edge:mainfrom
TomerNewman:add-node-lable
Jun 24, 2026
Merged

Add DRA node labeling via unified PodNodeLabel reconciler#1832
openshift-merge-bot[bot] merged 1 commit into
rh-ecosystem-edge:mainfrom
TomerNewman:add-node-lable

Conversation

@TomerNewman

@TomerNewman TomerNewman commented Jun 24, 2026

Copy link
Copy Markdown
Member

Merge DevicePluginPodReconciler and the new DRA pod labeling logic into a single PodNodeLabelReconciler that handles both roles. The reconciler watches DaemonSet pods with a ModuleNameLabel, determines the role from the DaemonSetRole label, and manages the corresponding node label (device-plugin-ready or dra-ready) based on pod readiness.


/cc @ybettan @yevgeny-shnaidman
/assign @ybettan @yevgeny-shnaidman


fix #1826

Summary by CodeRabbit

  • New Features

    • Added support for DRA-specific node labels alongside existing pod-to-node labeling behavior.
    • Updated controller handling so pod status and node labels are managed with role-aware logic.
  • Bug Fixes

    • Improved label removal checks so a node is only unlabelled when no other ready pod for the same module and role is running.
    • Preserved finalizer cleanup during pod deletion, even when node assignment is missing.
  • Tests

    • Added and updated coverage for device-plugin and DRA labeling, unlabeling, and deletion scenarios.

Merge DevicePluginPodReconciler and the new DRA pod labeling logic into
a single PodNodeLabelReconciler that handles both roles. The reconciler
watches DaemonSet pods with a ModuleNameLabel, determines the role from
the DaemonSetRole label, and manages the corresponding node label
(device-plugin-ready or dra-ready) based on pod readiness.
@netlify

netlify Bot commented Jun 24, 2026

Copy link
Copy Markdown

Deploy Preview for openshift-kmm ready!

Name Link
🔨 Latest commit de0ae49
🔍 Latest deploy log https://app.netlify.com/projects/openshift-kmm/deploys/6a3bc64db8e62500080e329e
😎 Deploy Preview https://deploy-preview-1832--openshift-kmm.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@openshift-ci

openshift-ci Bot commented Jun 24, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: TomerNewman

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Renames DevicePluginPodReconciler to PodNodeLabelReconciler, extending its reconcile logic to detect the pod's DaemonSetRole label and select the appropriate node label (device-plugin-ready or dra-ready). The role-scoped "other running pod" check and all helpers are updated to the new type. A GetDRANodeLabel utility is added with a public wrapper. The manager wiring and test suite are updated accordingly.

Changes

PodNodeLabelReconciler unification and DRA labeling

Layer / File(s) Summary
GetDRANodeLabel utility and public wrapper
internal/utils/kmmlabels.go, internal/utils/kmmlabels_test.go, pkg/labels/labels.go, pkg/labels/labels_test.go
Adds GetDRANodeLabel(namespace, moduleName) returning kmm.node.kubernetes.io/<ns>.<name>.dra-ready; exposes it via the public pkg/labels package; tests both.
PodNodeLabelReconciler type, reconcile logic, and helpers
internal/controllers/pod_node_label_reconciler.go
Replaces DevicePluginPodReconciler with PodNodeLabelReconciler; reconcile path now reads DaemonSetRole to choose labelName and roleLabelValue; scopes the "other running pod" check to module+role; adds addLabel, deleteLabel, deleteFinalizer helpers on the new type; renames the readiness predicate logger and updates SetupWithManager.
Manager wiring update
cmd/manager/main.go
Registers NewPodNodeLabelReconciler instead of NewDevicePluginPodReconciler and updates the fatal-error controller name constant.
Reconciler test suite replacement
internal/controllers/pod_node_label_reconciler_test.go, internal/controllers/device_plugin_pod_reconciler_test.go
Removes the old device-plugin-only test suite; introduces a new gomock-based suite covering both device-plugin and DRA pod roles across all reconcile scenarios (errors, labeling, unlabeling, finalizer removal).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

approved, lgtm

Suggested reviewers

  • ybettan
  • yevgeny-shnaidman
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 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: introducing unified PodNodeLabel reconciliation for DRA node labeling.
Linked Issues check ✅ Passed The changes match #1826 by unifying device-plugin and DRA pod labeling and updating node labels based on pod readiness.
Out of Scope Changes check ✅ Passed The diff stays focused on the unified reconciler, related label helpers, and matching tests without obvious unrelated additions.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@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: 2

🧹 Nitpick comments (1)
internal/controllers/pod_node_label_reconciler_test.go (1)

98-134: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add mixed-role regression coverage for the replacement-pod lookup.

Lines 107-122 and Lines 311-326 only prove the happy path where the same role keeps the label. This PR’s key contract is that device-plugin and DRA pods must not keep each other’s node labels alive, so please add the inverse cases too: a ready DRA pod must not block removal of device-plugin-ready, and a ready device-plugin pod must not block removal of dra-ready. Otherwise a future change that drops constants.DaemonSetRole from the List selector will still pass this suite.

Also applies to: 302-341

🤖 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/controllers/pod_node_label_reconciler_test.go` around lines 98 -
134, Add inverse mixed-role regression tests around PodNodeLabelReconciler’s
replacement-pod lookup so the suite covers cross-role behavior, not just the
same-role happy path. In the test blocks around Reconcile and the
kubeClient.List expectation, add cases where a ready DRA pod exists while
checking removal of device-plugin-ready, and where a ready device-plugin pod
exists while checking removal of dra-ready; assert the node label is still
removed in both cases. Use the existing constants.DaemonSetRole,
constants.DevicePluginRoleLabelValue, and the Reconcile flow in
pod_node_label_reconciler_test.go to locate the right spots.
🤖 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/controllers/pod_node_label_reconciler.go`:
- Around line 69-79: The sibling-pod lookup in PodNodeLabelReconciler is too
broad because r.client.List only filters by module name, role, and node, so pods
from other namespaces can block label cleanup for the current pod. Update the
lookup in the pod node label reconciler to scope the List call to the current
pod’s namespace by adding a namespace filter such as
client.InNamespace(pod.Namespace), alongside the existing MatchingLabels and
MatchingFields selectors.
- Around line 40-47: The role selection logic in PodNodeLabelReconciler
currently treats any non-"dra" DaemonSetRole value as device-plugin, which can
incorrectly reconcile pods with missing or invalid labels. Update the label
handling in the reconciler flow to explicitly validate
pod.Labels[constants.DaemonSetRole] before choosing roleLabelValue and
labelName, and return early from the reconcile path for missing or unknown
values instead of defaulting to constants.DevicePluginRoleLabelValue. Keep the
existing DRA/device-plugin branching, but only after the role label has been
confirmed valid.

---

Nitpick comments:
In `@internal/controllers/pod_node_label_reconciler_test.go`:
- Around line 98-134: Add inverse mixed-role regression tests around
PodNodeLabelReconciler’s replacement-pod lookup so the suite covers cross-role
behavior, not just the same-role happy path. In the test blocks around Reconcile
and the kubeClient.List expectation, add cases where a ready DRA pod exists
while checking removal of device-plugin-ready, and where a ready device-plugin
pod exists while checking removal of dra-ready; assert the node label is still
removed in both cases. Use the existing constants.DaemonSetRole,
constants.DevicePluginRoleLabelValue, and the Reconcile flow in
pod_node_label_reconciler_test.go to locate the right spots.
🪄 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: 06ca9e8a-ebe5-47d8-9800-37b0998d49dc

📥 Commits

Reviewing files that changed from the base of the PR and between 53251bd and de0ae49.

📒 Files selected for processing (8)
  • cmd/manager/main.go
  • internal/controllers/device_plugin_pod_reconciler_test.go
  • internal/controllers/pod_node_label_reconciler.go
  • internal/controllers/pod_node_label_reconciler_test.go
  • internal/utils/kmmlabels.go
  • internal/utils/kmmlabels_test.go
  • pkg/labels/labels.go
  • pkg/labels/labels_test.go
💤 Files with no reviewable changes (1)
  • internal/controllers/device_plugin_pod_reconciler_test.go

Comment on lines +40 to +47
isDRA := pod.Labels[constants.DaemonSetRole] == constants.DRARoleLabelValue

roleLabelValue := constants.DevicePluginRoleLabelValue
labelName := utils.GetDevicePluginNodeLabel(pod.Namespace, moduleName)
if isDRA {
roleLabelValue = constants.DRARoleLabelValue
labelName = utils.GetDRANodeLabel(pod.Namespace, moduleName)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject missing or unknown DaemonSetRole values instead of defaulting to device-plugin.

Anything other than "dra" currently falls through to the device-plugin path. Because the controller only filters on ModuleNameLabel, a DaemonSet pod with a missing or typoed role will still reconcile and toggle the device-plugin node label incorrectly. Validate the label explicitly and return early on unknown values.

🤖 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/controllers/pod_node_label_reconciler.go` around lines 40 - 47, The
role selection logic in PodNodeLabelReconciler currently treats any non-"dra"
DaemonSetRole value as device-plugin, which can incorrectly reconcile pods with
missing or invalid labels. Update the label handling in the reconciler flow to
explicitly validate pod.Labels[constants.DaemonSetRole] before choosing
roleLabelValue and labelName, and return early from the reconcile path for
missing or unknown values instead of defaulting to
constants.DevicePluginRoleLabelValue. Keep the existing DRA/device-plugin
branching, but only after the role label has been confirmed valid.

Comment on lines +69 to 79
// Making sure there is no other pod of the same role already running
labelSelector := client.MatchingLabels{
constants.ModuleNameLabel: moduleName,
constants.DaemonSetRole: roleLabelValue,
}
fieldSelector := client.MatchingFields{"spec.nodeName": nodeName}
var modulePodsList v1.PodList
err := dppr.client.List(ctx, &modulePodsList, labelSelector, fieldSelector)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to get list of all pods for module %s on node %s: %v", moduleName, nodeName, err)

var podsList v1.PodList
if err := r.client.List(ctx, &podsList, labelSelector, fieldSelector); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to get list of pods for module %s on node %s: %v", moduleName, nodeName, err)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Scope the sibling-pod lookup to the pod namespace.

The node label key is namespace-qualified, but this List is cluster-wide and only filters by module name + role. If ns-a/foo and ns-b/foo land on the same node, a ready pod in ns-b will prevent removing the stale label for ns-a. Add client.InNamespace(pod.Namespace) (or an equivalent namespace filter) to the lookup.

🤖 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/controllers/pod_node_label_reconciler.go` around lines 69 - 79, The
sibling-pod lookup in PodNodeLabelReconciler is too broad because r.client.List
only filters by module name, role, and node, so pods from other namespaces can
block label cleanup for the current pod. Update the lookup in the pod node label
reconciler to scope the List call to the current pod’s namespace by adding a
namespace filter such as client.InNamespace(pod.Namespace), alongside the
existing MatchingLabels and MatchingFields selectors.

@yevgeny-shnaidman

Copy link
Copy Markdown
Member

/lgtm

@openshift-ci openshift-ci Bot added the lgtm label Jun 24, 2026
@openshift-merge-bot openshift-merge-bot Bot merged commit 89084d7 into rh-ecosystem-edge:main Jun 24, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cherry-picking error for 9547ce640701fd5bc76d7083807ac6d1cb68e5ab

3 participants