Skip to content

tests/snr: add 5 destructive remediation tests (worker + master) - #52

Merged
openshift-merge-bot[bot] merged 8 commits into
medik8s:mainfrom
gamado:feat/snr-worker-master-remediation
Jul 13, 2026
Merged

tests/snr: add 5 destructive remediation tests (worker + master)#52
openshift-merge-bot[bot] merged 8 commits into
medik8s:mainfrom
gamado:feat/snr-worker-master-remediation

Conversation

@gamado

@gamado gamado commented Jul 8, 2026

Copy link
Copy Markdown

Summary

Port SNR worker and master remediation tests from Python (ocp-edge-auto) to Go/Ginkgo. These tests stop kubelet on nodes, NHC detects unhealthy state, SNR creates remediation CRs, nodes reboot and recover.

Tests added

  • OCP-52416: Worker kubelet stop with NHC detection
  • OCP-50772: ResourceDeletion strategy -- workload pod eviction
  • OCP-61594: OutOfServiceTaint strategy -- workload pod eviction
  • OCP-55059: Master kubelet stop with NHC detection
  • OCP-56069: Simultaneous master + worker kubelet stop

Key implementation details

  • waitForRemediationComplete handles both fast flow (remediation completes during oc debug timeout) and normal flow (test observes SNR CR lifecycle)
  • stopKubeletForRemediation wraps helpers.StopKubelet with error suppression for oc debug timeout and debug pod teardown races
  • deleteRemediationCR uses retry-safe get-delete-confirm pattern (aligned with FAR PR Add 6 standalone FAR destructive tests and improve test resiliency #49)
  • selectMasterNode / countReadyMasterNodes try both master and control-plane role labels for OCP 4.14+ compatibility
  • NHC CRs include minHealthy: 51% required by NHC admission webhook
  • Workload pods use registry.k8s.io/pause:3.9 (multi-arch: x86 + ARM64)
  • GVK declarations refactored from functions to package-level vars (aligned with FAR PR Add 6 standalone FAR destructive tests and improve test resiliency #49)

Files changed

  • New: tests/snr-operator/tests/worker_remediation.go (3 tests)
  • New: tests/snr-operator/tests/master_remediation.go (2 tests)
  • Modified: tests/snr-operator/tests/helpers.go (+493 lines of remediation helpers)
  • Modified: tests/snr-operator/internal/snrparams/const.go (+65 lines of constants)
  • Modified: tests/snr-operator/README.md (destructive test documentation)
  • Modified: config_lifecycle.go, processing_conditions.go (snrGVK() -> snrGVK var)

Test plan

  • go build ./tests/snr-operator/... -- passes
  • go vet ./tests/snr-operator/... -- passes
  • gofmt -l tests/snr-operator/ -- no changes needed
  • All 5 tests pass on AWS x86 OCP 4.22 (31m 47s)
  • All 5 tests pass on nvd-srv-16 ARM64 OCP 4.22 (31m 29s)
  • Negative validation: all 5 tests correctly fail with bogus SNRT
  • /review-checklist -- 0 violations across 48 rules

Jira: RHWA-1077

Summary by CodeRabbit

  • New Features

    • Added destructive remediation coverage for worker and master nodes.
    • Added scenarios validating automatic, resource-deletion, and out-of-service-taint remediation strategies.
    • Added verification for node reboot, recovery, workload eviction, and simultaneous master/worker remediation.
  • Documentation

    • Expanded test prerequisites, commands, labels, and pass criteria for destructive test execution.

@openshift-ci
openshift-ci Bot requested review from lyfofvipin and razo7 July 8, 2026 06:52
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Changes

SNR destructive remediation coverage

Layer / File(s) Summary
Destructive test documentation
tests/snr-operator/README.md
Documents destructive prerequisites, label-filtered commands, and worker/master remediation scenarios.
Remediation constants and GVK wiring
tests/snr-operator/internal/snrparams/const.go, tests/snr-operator/tests/helpers.go, tests/snr-operator/tests/config_lifecycle.go, tests/snr-operator/tests/processing_conditions.go
Adds remediation constants and changes SNR GVK helpers to package-level values used by existing tests.
Remediation helper workflow
tests/snr-operator/tests/helpers.go
Adds log search, kubelet stopping, NHC/SNRT construction, node selection, remediation polling, workload eviction, and cleanup helpers.
Worker remediation suite
tests/snr-operator/tests/worker_remediation.go
Tests automatic, ResourceDeletion, and OutOfServiceTaint remediation after worker kubelet disruption.
Master remediation suite
tests/snr-operator/tests/master_remediation.go
Tests master-only and simultaneous master/worker remediation, reboot detection, recovery, and resource cleanup.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested labels: lgtm

Suggested reviewers: ugreener, razo7, slintes, mshitrit

🚥 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 summarizes the main change: five destructive remediation tests covering worker and master nodes.
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 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.

@gamado

gamado commented Jul 8, 2026

Copy link
Copy Markdown
Author

/test 4.22-konflux-e2e-snr-aws

@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)
tests/snr-operator/tests/helpers.go (1)

206-245: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

findMessageInControllerLogs duplicates findMessageInDSPodLogs.

This function is a near-verbatim copy of findMessageInDSPodLogs (lines 170-205), differing only in the label selector and two error strings. Consider extracting a shared helper to avoid drift.

♻️ Suggested shared helper
// findMessageInPodLogs lists pods matching labelSelector and searches
// their recent logs for message. podKind is used only in error text.
func findMessageInPodLogs(labelSelector, podKind, message string, logWindow time.Duration) error {
	pods, listErr := pod.List(APIClient, medik8sparams.OperatorNs, metav1.ListOptions{
		LabelSelector: labelSelector,
	})
	if listErr != nil {
		return fmt.Errorf("failed to list SNR %s pods: %w", podKind, listErr)
	}
	if len(pods) == 0 {
		return fmt.Errorf("no SNR %s pods found", podKind)
	}

	var lastLogErr error
	for _, p := range pods {
		logStr, logErr := p.GetLog(logWindow, "")
		if logErr != nil {
			lastLogErr = fmt.Errorf("pod %s: %w", p.Object.Name, logErr)
			continue
		}
		if strings.Contains(logStr, message) {
			return nil
		}
	}
	if lastLogErr != nil {
		return fmt.Errorf("message %q not found; last log error: %w", message, lastLogErr)
	}
	return fmt.Errorf("message %q not found in any SNR %s pod logs (last %s)", message, podKind, logWindow)
}

Then have both callers delegate, e.g. findMessageInControllerLogsfindMessageInPodLogs(snrparams.OperatorControllerPodLabelSelector, "controller", message, logWindow).

🤖 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 `@tests/snr-operator/tests/helpers.go` around lines 206 - 245,
`findMessageInControllerLogs` is a near-duplicate of `findMessageInDSPodLogs`,
so it should delegate to a shared helper instead of maintaining separate
copy-pasted logic. Extract the common pod log search flow into a helper such as
`findMessageInPodLogs`, parameterized by label selector and pod kind/error text,
and have `findMessageInControllerLogs` and `findMessageInDSPodLogs` call it with
their respective selectors and names. Keep the existing behavior for listing
pods, checking `GetLog`, and returning the same error shapes, but centralize the
implementation to prevent drift.
🤖 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 `@tests/snr-operator/tests/master_remediation.go`:
- Around line 263-286: The simultaneous remediation test in
master_remediation.go is missing the node creation timestamp guard used by the
single-node test. Before triggering remediation, record the creation timestamps
for both targetMasterName and targetWorkerName using the same pattern as the
earlier test, then after waitForRemediationComplete and the WaitForNodeReady
checks, verify each node’s creation timestamp is unchanged to confirm reboot
rather than recreation. Use the existing remediation flow and helpers in the
test case where currentNHCNames is cleaned up, and keep the new assertions
alongside the boot ID-based recovery checks.

---

Nitpick comments:
In `@tests/snr-operator/tests/helpers.go`:
- Around line 206-245: `findMessageInControllerLogs` is a near-duplicate of
`findMessageInDSPodLogs`, so it should delegate to a shared helper instead of
maintaining separate copy-pasted logic. Extract the common pod log search flow
into a helper such as `findMessageInPodLogs`, parameterized by label selector
and pod kind/error text, and have `findMessageInControllerLogs` and
`findMessageInDSPodLogs` call it with their respective selectors and names. Keep
the existing behavior for listing pods, checking `GetLog`, and returning the
same error shapes, but centralize the implementation to prevent drift.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 05ce87cc-2b2b-418b-8fe8-d74d474602e9

📥 Commits

Reviewing files that changed from the base of the PR and between 1534e0d and 9009bad.

📒 Files selected for processing (8)
  • tests/mdr-operator/README.md
  • tests/snr-operator/README.md
  • tests/snr-operator/internal/snrparams/const.go
  • tests/snr-operator/tests/config_lifecycle.go
  • tests/snr-operator/tests/helpers.go
  • tests/snr-operator/tests/master_remediation.go
  • tests/snr-operator/tests/processing_conditions.go
  • tests/snr-operator/tests/worker_remediation.go

Comment thread tests/snr-operator/tests/master_remediation.go
Comment thread tests/snr-operator/tests/helpers.go
Comment thread tests/snr-operator/README.md Outdated
Comment thread tests/snr-operator/tests/helpers.go Outdated
Comment thread tests/snr-operator/tests/master_remediation.go Outdated
Comment thread tests/snr-operator/tests/helpers.go
Comment thread tests/snr-operator/tests/master_remediation.go Outdated
Comment thread tests/snr-operator/tests/worker_remediation.go Outdated
Comment thread tests/snr-operator/tests/master_remediation.go
Comment thread tests/snr-operator/tests/master_remediation.go Outdated
@gamado
gamado requested a review from ugreener July 8, 2026 11:16
Comment thread tests/snr-operator/tests/helpers.go Outdated
Comment thread tests/snr-operator/tests/helpers.go Outdated
Comment thread tests/snr-operator/tests/worker_remediation.go Outdated
Comment thread tests/snr-operator/internal/snrparams/const.go Outdated
Comment thread tests/snr-operator/tests/worker_remediation.go Outdated
@gamado
gamado requested a review from ugreener July 8, 2026 13:08
Comment thread tests/snr-operator/tests/master_remediation.go Outdated
Comment thread tests/snr-operator/internal/snrparams/const.go
Comment thread tests/snr-operator/README.md Outdated
Comment thread tests/snr-operator/README.md Outdated
@gamado
gamado requested a review from ugreener July 8, 2026 15:34
@gamado

gamado commented Jul 8, 2026

Copy link
Copy Markdown
Author

/test 4.22-konflux-e2e-snr-aws

@ugreener

ugreener commented Jul 9, 2026

Copy link
Copy Markdown

/lgtm

@openshift-ci openshift-ci Bot added the lgtm label Jul 9, 2026
@gamado
gamado requested review from razo7 and removed request for razo7 July 9, 2026 08:09
Comment thread tests/snr-operator/tests/helpers.go Outdated
Comment thread tests/snr-operator/tests/helpers.go Outdated
Comment thread tests/snr-operator/tests/helpers.go
Comment thread tests/snr-operator/tests/master_remediation.go Outdated
)

var _ = Describe("SNR Functional - Worker Node Remediation",
Serial, Ordered, ContinueOnFailure,

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.

Consider adding a BeforeEach that verifies the controller deployment is Ready before each destructive test:

BeforeEach(func() {
    By("Verifying FAR controller is Ready before test")
    farDeployment, err := deployment.Pull(
        APIClient, farparams.OperatorDeploymentName, medik8sparams.OperatorNs)
    Expect(err).ToNot(HaveOccurred())
    Expect(farDeployment.IsReady(medik8sparams.DefaultTimeout)).To(BeTrue(),
        "FAR controller is not Ready - webhook will be unreachable")
})

With ContinueOnFailure, if a prior test leaves the cluster degraded, the SNR controller may not be ready when the next test starts. Adding an equivalent BeforeEach for snrparams.OperatorDeploymentName would catch this early instead of timing out 15 minutes into the test.

Same applies to master_remediation.go:23.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 4c5f289

Comment thread tests/snr-operator/tests/worker_remediation.go Outdated
Comment thread tests/snr-operator/README.md Outdated
Comment thread tests/snr-operator/README.md Outdated
Comment thread tests/snr-operator/tests/worker_remediation.go Outdated
Comment thread tests/mdr-operator/README.md
gamado and others added 6 commits July 12, 2026 12:39
Port SNR worker and master remediation tests from Python (ocp-edge-auto)
to Go/Ginkgo. These tests stop kubelet on nodes, NHC detects unhealthy
state, SNR creates remediation CRs, nodes reboot and recover.

Tests added:
- OCP-52416: Worker kubelet stop with NHC detection
- OCP-50772: ResourceDeletion strategy -- workload pod eviction
- OCP-61594: OutOfServiceTaint strategy -- workload pod eviction
- OCP-55059: Master kubelet stop with NHC detection
- OCP-56069: Simultaneous master + worker kubelet stop

New files:
- tests/snr-operator/tests/worker_remediation.go (Tests 7, 8, 9)
- tests/snr-operator/tests/master_remediation.go (Tests 10, 11)

Key helpers added to helpers.go:
- waitForRemediationComplete: handles both fast and normal remediation
  flows (boot ID + SNR CR lifecycle check)
- stopKubeletForRemediation: wraps StopKubelet with oc debug error
  suppression for timeout and debug pod teardown races
- buildNHC/buildNHCForWorkers/buildNHCForMasters: NHC CR builders
- buildSNRT: SelfNodeRemediationTemplate CR builder
- createWorkloadPodOnNode/waitForPodEvictedFromNode: workload pod helpers
- deleteRemediationCR: retry-safe CR deletion (aligned with FAR PR medik8s#49)
- selectMasterNode/countReadyMasterNodes: master node selection with
  control-plane label fallback

Refactored snrGVK/snrcGVK from functions to package-level vars
(aligned with FAR PR medik8s#49 naming convention).

Updated README with destructive test documentation (Tests 15-19).

Validated on:
- AWS x86 OCP 4.22: 5/5 passed (31m 47s total)
- nvd-srv-16 ARM64 OCP 4.22: 5/5 passed (31m 29s total)
- Negative tests (bogus SNRT): 5/5 correctly failed

Jira: RHWA-1077

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
Add ContainerStatuses[].Ready check to createWorkloadPodOnNode,
not just Phase==Running. Catches CrashLoopBackOff edge case (R-08).

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Use control-plane label in buildNHCForMasters for OCP 4.14+ compat
- Move DeferCleanup after Create in createWorkloadPodOnNode (per FAR pattern)
- Fix stale sbrparams comment reference on nhcGVK
- Replace "Test 11" with OCP-56069 Polarion reference
- Add worker count check in master BeforeAll for simultaneous test
- Add CreationTimestamp verification to eviction tests (OCP-50772, OCP-61594)
- Add CreationTimestamp verification to simultaneous test (OCP-56069)
- Fix README: remove "etcd cluster healthy" claim (not verified by code)
- Document sequential stopKubelet limitation in simultaneous test

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Add stale SNR CR pre-cleanup before each test (R-03)
- Rename DSLogSearchWindow to LogSearchWindow (used for controller too)
- Replace stale "Tests 8/9" with Polarion IDs (OCP-50772, OCP-61594)
- Change minHealthy from "51%" to "1" (avoids ceil rounding on 2-worker)
- Add "manager" container name to findMessageInControllerLogs
- Add ManagerContainerName constant (matches FAR/SBR/NHC/MDR/NMO)

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Add stale SNR CR pre-cleanup to eviction tests (OCP-50772, OCP-61594)
- README: split worker/master prereqs for worker count clarity
- README: mark eviction tests as Connected (pause image needs registry.k8s.io)
- README: add CreationTimestamp to Test 19 pass criteria

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
Structural refactoring:
- Extract shared BeforeEach for deployment readiness check (razo7 medik8s#5)
- Extract shared BeforeEach for boot ID + creation timestamp recording (razo7 medik8s#9)
- Extract verifyRemediationAndRecovery shared function (razo7 medik8s#6)
- Extract runStrategyTest for ResourceDeletion/OutOfServiceTaint dedup (razo7 medik8s#6)
- Wrap strategy tests in Context("strategy-specific remediation")
- Move worker count check + selection into OCP-56069 body (razo7 medik8s#4)

Bug fixes:
- Tighten stopKubeletForRemediation error matching to oc debug patterns (razo7 medik8s#1)
- Use direct map assignment instead of SetNestedField in buildNHC (razo7 medik8s#2)
- Add Unschedulable filter to selectMasterNode (razo7 medik8s#3)
- Fix README --focus strings to be unique per test (razo7 medik8s#8)
- Fix README "3+ masters and 2+ workers" -> "1+ workers" for OCP-56069 (razo7 medik8s#7)

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
@gamado
gamado force-pushed the feat/snr-worker-master-remediation branch from 531f0ab to 4c5f289 Compare July 12, 2026 09:40
@openshift-ci openshift-ci Bot removed the lgtm label Jul 12, 2026
@gamado
gamado requested review from mshitrit and razo7 July 12, 2026 09:43
Comment thread tests/snr-operator/tests/worker_remediation.go Outdated
Replace log message check with direct taint verification on the node
during remediation. The taint is more reliable than log parsing and
verifies the actual remediation mechanism. (mshitrit review feedback)

- Add OutOfServiceTaintKey constant
- Remove unused findMessageInControllerLogs, OutOfServiceAutoSelectedMsg,
  LogSearchWindow

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
@gamado
gamado requested a review from mshitrit July 12, 2026 10:41
@gamado

gamado commented Jul 12, 2026

Copy link
Copy Markdown
Author

/test 4.22-konflux-e2e-snr-aws

@gamado

gamado commented Jul 12, 2026

Copy link
Copy Markdown
Author

/retest

1 similar comment
@gamado

gamado commented Jul 12, 2026

Copy link
Copy Markdown
Author

/retest

- Change minHealthy from string "1" to int64(1) in NHC CR builder.
  NHC's IntOrString parser rejects bare string "1" (not a percentage,
  not a number). This caused NHC to silently fail reconciliation,
  never creating the SNR CR.

- Add boot ID fallback to taint verification. On slow oc debug
  environments (ARM64, remote clusters), the entire remediation
  cycle completes before the taint check starts. Boot ID change
  proves the taint was applied and removed.

- Rename DSLogSearchWindow to LogSearchWindow (used for controller
  logs too, not just DS).

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
@gamado

gamado commented Jul 12, 2026

Copy link
Copy Markdown
Author

/test 4.22-konflux-e2e-snr-aws

@openshift-ci

openshift-ci Bot commented Jul 13, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: gamado, mshitrit

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

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.

4 participants