Skip to content

CNTRLPLANE-400: feat(remediationAlloowed in NP): propagate MHC RemediationAllowed to NodePool Ready condition#9019

Open
sdminonne wants to merge 1 commit into
openshift:mainfrom
sdminonne:CNTRLPLANE-400
Open

CNTRLPLANE-400: feat(remediationAlloowed in NP): propagate MHC RemediationAllowed to NodePool Ready condition#9019
sdminonne wants to merge 1 commit into
openshift:mainfrom
sdminonne:CNTRLPLANE-400

Conversation

@sdminonne

@sdminonne sdminonne commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Bubble up the CAPI MachineHealthCheck RemediationAllowed condition into the NodePool Ready condition. When RemediationAllowed=False (too many unhealthy machines exceed maxUnhealthy), the NodePool Ready condition is overridden to False with reason TooManyUnhealthy and the MHC's original message preserved.
  • Add a MachineHealthCheck watch with a predicate filter so only RemediationAllowed condition changes (Status, Reason, or Message) trigger NodePool reconciliation, avoiding unnecessary reconciliations from unrelated MHC status field updates.
  • Set nodePoolAnnotation on the MHC so the existing enqueueParentNodePool watch handler can map MHC events back to the parent NodePool.

Test plan

  • TestMHCRemediationAllowedBubbledUpToReady — verifies Ready is overridden when RemediationAllowed=False, left untouched when True or absent
  • TestMHCRemediationAllowedChangedPredicate — verifies predicate filters Update events correctly (8 cases: Status changes, Reason-only change, Message-only change, condition appearing/disappearing, no-change cases)
  • TestReconcileMachineHealthCheckAnnotation — verifies nodePoolAnnotation is set on MHC
  • Full nodepool controller test suite passes
  • make verify passes (lint, gitlint, CRD schema check)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • NodePool readiness now reflects whether MachineHealthCheck remediation is currently allowed.
    • MachineHealthCheck updates can automatically trigger NodePool reconciliation when remediation status details change.
    • MachineHealthChecks are linked to their corresponding NodePools for improved update tracking.
  • Bug Fixes

    • Prevented NodePools from reporting ready when required remediation is blocked.

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@openshift-ci openshift-ci Bot added do-not-merge/needs-area area/hypershift-operator Indicates the PR includes changes for the hypershift operator and API - outside an OCP release labels Jul 16, 2026
@openshift-ci

openshift-ci Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: sdminonne
Once this PR has been reviewed and has the lgtm label, please assign muraee for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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 Jul 16, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The nodepool controller annotates MachineHealthChecks with their parent NodePool key and filters MHC updates to relevant RemediationAllowed changes. During auto-repair reconciliation, a non-true remediation condition sets the NodePool Ready condition to false with the MHC’s reason and message. Tests cover annotation assignment, readiness propagation, and predicate behavior.

Sequence Diagram(s)

sequenceDiagram
  participant MachineHealthCheck
  participant NodePoolController
  participant CAPIReconcile
  participant NodePool
  MachineHealthCheck->>NodePoolController: Change RemediationAllowed
  NodePoolController->>CAPIReconcile: Enqueue associated NodePool
  CAPIReconcile->>NodePool: Set Ready false with reason and message
Loading

Suggested reviewers: clebs, jparrill

🚥 Pre-merge checks | ✅ 10 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Test Structure And Quality ⚠️ Warning The new tests are well-scoped, but their Gomega assertions still use bare expectations (e.g. NotTo(HaveOccurred())) without failure context. Add brief context strings to the new expectations in the three tests, especially around MHC annotation and Ready/predicate checks.
✅ Passed checks (10 passed)
Check name Status Explanation
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.
Stable And Deterministic Test Names ✅ Passed The added test/subtest names are fixed strings; no fmt.Sprintf, timestamps, UUIDs, IPs, or generated suffixes appear in the new titles.
Topology-Aware Scheduling Compatibility ✅ Passed Patch only changes MHC annotation/Ready gating and watch predicates; no affinity, spread, nodeSelector, replica, or topology assumptions were added.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed PASS: The PR adds only testing.T unit tests and controller code; no new Ginkgo e2e tests, IPv4 literals, or external connectivity were added.
No-Weak-Crypto ✅ Passed Changed files only add MHC condition/predicate and annotation logic; no weak-crypto APIs or secret comparisons appear in the touched code.
Container-Privileges ✅ Passed Diff only touches Go controller/tests; no K8s manifests or privileged/securityContext fields (privileged, hostPID, hostNetwork, allowPrivilegeEscalation, SYS_ADMIN) were added.
No-Sensitive-Data-In-Logs ✅ Passed The PR only adds MHC condition/predicate logic and annotation wiring; no new logs print secrets, tokens, PII, or other sensitive values.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: propagating MHC RemediationAllowed into the NodePool Ready condition.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@sdminonne

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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)
hypershift-operator/controllers/nodepool/capi_test.go (1)

3829-3846: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Exercise CAPI.Reconcile instead of duplicating its new branch.

This reproduces the production condition logic, so it can pass if CAPI.Reconcile stops invoking that logic. Drive the MHC status through the existing reconciliation fixture and assert the resulting NodePool condition.

As per coding guidelines, unit test any code changes and additions.

🤖 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 `@hypershift-operator/controllers/nodepool/capi_test.go` around lines 3829 -
3846, Replace the duplicated condition-handling block in the test with an
invocation of CAPI.Reconcile using the existing reconciliation fixture,
configuring the fixture’s MachineHealthCheck status with tt.mhcConditions.
Assert the resulting NodePool condition produced by reconciliation, preserving
coverage of the remediation-allowed behavior without directly calling
findMHCRemediationAllowedCondition or SetStatusCondition. Add or update unit
assertions for the reconciled outcomes.

Source: Coding guidelines

🤖 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 `@hypershift-operator/controllers/nodepool/capi.go`:
- Around line 1458-1466: The MHC condition change detection only compares
Status, so same-status Reason or Message updates do not trigger reconciliation.
In hypershift-operator/controllers/nodepool/capi.go lines 1458-1466, update the
comparison in the findMHCRemediationAllowedCondition flow to also detect Reason
and Message changes. In hypershift-operator/controllers/nodepool/capi_test.go
lines 3895-3898, add a test case with unchanged Status but changed Reason and/or
Message that expects reconciliation.

---

Nitpick comments:
In `@hypershift-operator/controllers/nodepool/capi_test.go`:
- Around line 3829-3846: Replace the duplicated condition-handling block in the
test with an invocation of CAPI.Reconcile using the existing reconciliation
fixture, configuring the fixture’s MachineHealthCheck status with
tt.mhcConditions. Assert the resulting NodePool condition produced by
reconciliation, preserving coverage of the remediation-allowed behavior without
directly calling findMHCRemediationAllowedCondition or SetStatusCondition. Add
or update unit assertions for the reconciled outcomes.
🪄 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: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: fbc73ca4-b40a-4d1d-8510-f6bd6114cd38

📥 Commits

Reviewing files that changed from the base of the PR and between 3eefe36 and 5a73424.

📒 Files selected for processing (3)
  • hypershift-operator/controllers/nodepool/capi.go
  • hypershift-operator/controllers/nodepool/capi_test.go
  • hypershift-operator/controllers/nodepool/nodepool_controller.go

Comment on lines +1458 to +1466
oldCond := findMHCRemediationAllowedCondition(oldMHC.Status.Conditions)
newCond := findMHCRemediationAllowedCondition(newMHC.Status.Conditions)
if oldCond == nil && newCond == nil {
return false
}
if oldCond == nil || newCond == nil {
return true
}
return oldCond.Status != newCond.Status

@coderabbitai coderabbitai Bot Jul 16, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reconcile when the blocked-remediation reason or message changes.

A RemediationAllowed=False update with unchanged status but a new reason/message is filtered out, leaving the NodePool Ready condition stale.

  • hypershift-operator/controllers/nodepool/capi.go#L1458-L1466: compare Reason and Message in addition to Status.
  • hypershift-operator/controllers/nodepool/capi_test.go#L3895-L3898: add a same-status reason/message-change case that expects reconciliation.
Proposed fix
- return oldCond.Status != newCond.Status
+ return oldCond.Status != newCond.Status ||
+   oldCond.Reason != newCond.Reason ||
+   oldCond.Message != newCond.Message

The PR objective explicitly requires preserving the MHC message. As per coding guidelines, unit test code changes and additions.

📝 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
oldCond := findMHCRemediationAllowedCondition(oldMHC.Status.Conditions)
newCond := findMHCRemediationAllowedCondition(newMHC.Status.Conditions)
if oldCond == nil && newCond == nil {
return false
}
if oldCond == nil || newCond == nil {
return true
}
return oldCond.Status != newCond.Status
oldCond := findMHCRemediationAllowedCondition(oldMHC.Status.Conditions)
newCond := findMHCRemediationAllowedCondition(newMHC.Status.Conditions)
if oldCond == nil && newCond == nil {
return false
}
if oldCond == nil || newCond == nil {
return true
}
return oldCond.Status != newCond.Status ||
oldCond.Reason != newCond.Reason ||
oldCond.Message != newCond.Message
📍 Affects 2 files
  • hypershift-operator/controllers/nodepool/capi.go#L1458-L1466 (this comment)
  • hypershift-operator/controllers/nodepool/capi_test.go#L3895-L3898
🤖 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 `@hypershift-operator/controllers/nodepool/capi.go` around lines 1458 - 1466,
The MHC condition change detection only compares Status, so same-status Reason
or Message updates do not trigger reconciliation. In
hypershift-operator/controllers/nodepool/capi.go lines 1458-1466, update the
comparison in the findMHCRemediationAllowedCondition flow to also detect Reason
and Message changes. In hypershift-operator/controllers/nodepool/capi_test.go
lines 3895-3898, add a test case with unchanged Status but changed Reason and/or
Message that expects reconciliation.

Source: Coding guidelines

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.

Fixed in the latest force-push. The predicate now also compares Reason and Message:

return oldCond.Status != newCond.Status ||
    oldCond.Reason != newCond.Reason ||
    oldCond.Message != newCond.Message

Added two new test cases covering Reason-only and Message-only changes (8 total).

@sdminonne
sdminonne marked this pull request as draft July 16, 2026 15:25
@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 16, 2026
…odePool status

Bubble up the CAPI MachineHealthCheck RemediationAllowed condition into
the NodePool Ready condition. When more machines are unhealthy than
maxUnhealthy allows, CAPI sets RemediationAllowed=False with reason
TooManyUnhealthy and stops remediating. This state was previously only
visible by inspecting the MHC object directly in the control plane
namespace. Now, when RemediationAllowed=False, the NodePool Ready
condition is overridden to False with the MHC's original reason and
message preserved. When remediation is allowed or the condition is
absent, Ready is left as set by MachineDeployment/MachineSet
reconciliation.

- Set nodePoolAnnotation on the MHC so the existing
  enqueueParentNodePool watch handler can map it back to its parent
  NodePool.
- After MHC create/update, read its RemediationAllowed condition and
  override Ready=False when remediation is blocked, preserving the
  MHC's reason and message.
- Add a MachineHealthCheck watch in SetupWithManager so MHC status
  changes trigger NodePool reconciliation.
- Add a predicate filter on the MHC watch so only RemediationAllowed
  condition changes (Status, Reason, or Message) trigger
  reconciliation, avoiding unnecessary reconciliations from unrelated
  MHC status field updates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 63.82979% with 17 lines in your changes missing coverage. Please review.
✅ Project coverage is 44.16%. Comparing base (3d0980b) to head (bb23dd6).
⚠️ Report is 18 commits behind head on main.

Files with missing lines Patch % Lines
hypershift-operator/controllers/nodepool/capi.go 65.21% 13 Missing and 3 partials ⚠️
...erator/controllers/nodepool/nodepool_controller.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9019      +/-   ##
==========================================
+ Coverage   44.15%   44.16%   +0.01%     
==========================================
  Files         772      772              
  Lines       96260    96307      +47     
==========================================
+ Hits        42503    42537      +34     
- Misses      50816    50825       +9     
- Partials     2941     2945       +4     
Files with missing lines Coverage Δ
...erator/controllers/nodepool/nodepool_controller.go 43.30% <0.00%> (-0.05%) ⬇️
hypershift-operator/controllers/nodepool/capi.go 71.68% <65.21%> (-0.28%) ⬇️

... and 1 file with indirect coverage changes

Flag Coverage Δ
cmd-support 38.26% <ø> (ø)
cpo-hostedcontrolplane 46.17% <ø> (ø)
cpo-other 45.21% <ø> (ø)
hypershift-operator 54.13% <63.82%> (+0.03%) ⬆️
other 32.34% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@sdminonne
sdminonne marked this pull request as ready for review July 17, 2026 06:08
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 17, 2026
@openshift-ci
openshift-ci Bot requested review from Nirshal and bryan-cox July 17, 2026 06:08
@openshift-ci

openshift-ci Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

@sdminonne: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@sdminonne sdminonne changed the title feat(CNTRLPLANE-400): propagate MHC RemediationAllowed to NodePool Ready condition CNTRLPLANE-400: feat(remediationAlloowed in NP): propagate MHC RemediationAllowed to NodePool Ready condition Jul 17, 2026
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jul 17, 2026
@openshift-ci-robot

openshift-ci-robot commented Jul 17, 2026

Copy link
Copy Markdown

@sdminonne: This pull request references CNTRLPLANE-400 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the epic to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Summary

  • Bubble up the CAPI MachineHealthCheck RemediationAllowed condition into the NodePool Ready condition. When RemediationAllowed=False (too many unhealthy machines exceed maxUnhealthy), the NodePool Ready condition is overridden to False with reason TooManyUnhealthy and the MHC's original message preserved.
  • Add a MachineHealthCheck watch with a predicate filter so only RemediationAllowed condition changes (Status, Reason, or Message) trigger NodePool reconciliation, avoiding unnecessary reconciliations from unrelated MHC status field updates.
  • Set nodePoolAnnotation on the MHC so the existing enqueueParentNodePool watch handler can map MHC events back to the parent NodePool.

Test plan

  • TestMHCRemediationAllowedBubbledUpToReady — verifies Ready is overridden when RemediationAllowed=False, left untouched when True or absent
  • TestMHCRemediationAllowedChangedPredicate — verifies predicate filters Update events correctly (8 cases: Status changes, Reason-only change, Message-only change, condition appearing/disappearing, no-change cases)
  • TestReconcileMachineHealthCheckAnnotation — verifies nodePoolAnnotation is set on MHC
  • Full nodepool controller test suite passes
  • make verify passes (lint, gitlint, CRD schema check)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

  • NodePool readiness now reflects whether MachineHealthCheck remediation is currently allowed.

  • MachineHealthCheck updates can automatically trigger NodePool reconciliation when remediation status details change.

  • MachineHealthChecks are linked to their corresponding NodePools for improved update tracking.

  • Bug Fixes

  • Prevented NodePools from reporting ready when required remediation is blocked.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/hypershift-operator Indicates the PR includes changes for the hypershift operator and API - outside an OCP release jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants