Await manager shutdown before stopping envtest - #6179
Merged
Conversation
SuiteEnv.Stop cancelled the suite context, slept 100ms, then tore down the envtest control plane. That sleep was too short for the controller manager to finish, so its informers still held long-running watch requests when kube-apiserver got SIGTERM. kube-apiserver's graceful shutdown blocks draining those requests, overran envtest's 20s ControlPlaneStopTimeout, and failed AfterSuite with "timeout waiting for process kube-apiserver to stop". This accounted for 32 of the last 51 Operator Tests Integration failures. It concentrated in mcp-telemetry-config and mcp-group because they are the only suites with fewer specs than Ginkgo procs (5 specs, 7 procs), so their idle procs cancel the context moments after the informers establish their watches. Wait for Manager.Start to return instead of guessing at a delay. controller-runtime's Informers.Start blocks until every informer has stopped, so that return is a real guarantee the watches are closed. Bound both the manager's own graceful shutdown and the wait well under envtest's stop timeout, so a wedged runnable is reported as such rather than as an apiserver teardown failure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
aponcedeleonch
requested review from
ChrisJBurns,
JAORMX,
blkt,
jerm-dro,
jhrozek,
rdimitrov,
reyortiz3 and
tgrunnagle
as code owners
August 3, 2026 11:38
JAORMX
approved these changes
Aug 3, 2026
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6179 +/- ##
==========================================
+ Coverage 72.56% 72.57% +0.01%
==========================================
Files 736 737 +1
Lines 76391 76430 +39
==========================================
+ Hits 55430 55470 +40
+ Misses 17032 17025 -7
- Partials 3929 3935 +6 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Operator CI / Operator Tests Integrationhas a flakyAfterSuitefailure:timeout waiting for process kube-apiserver to stop. It accounts for 32 of the last 51 failures of that job, all inmcp-telemetry-config(27) andmcp-group(5).SuiteEnv.Stopcancelled the suite context, slept 100ms, then tore down the envtest control plane. 100ms is not enough for the controller manager to finish, so its informers still held long-running watch requests when kube-apiserver got SIGTERM. kube-apiserver's graceful shutdown blocks draining those requests, overruns envtest's 20sControlPlaneStopTimeout, and fails the suite. The CI logs show it directly: reflectors logFailed to watch ... connection refusedduring teardown, so the manager was demonstrably still running after the API server closed its listener.BeforeSuiteruns on every proc, so the idle procs boot a control plane and cancel the context moments after the informers established their watches — the worst case for the race.Manager.Startto return before stopping the control plane, instead of guessing at a delay. controller-runtime'sInformers.Startblocks onwaitGroup.Wait()until every informer has stopped, so that return is a real guarantee the watch connections are closed.GracefulShutdownTimeout(10s) and the wait (15s) safely under envtest's 20s stop timeout, so a genuinely wedged runnable is reported as a manager shutdown problem rather than mis-attributed to apiserver teardown.All 11 operator integration suites share this helper, so no per-suite changes are needed.
Type of change
Test plan
task test)task test-e2e)task lint-fix)Reproduced the flake locally first, then verified the fix:
ginkgo -p --repeat=6 mcp-telemetry-config20.121s/ same error as CI--repeatrunmcp-telemetry-configrunsmcp-telemetry-config+mcp-group)ginkgo -p ./cmd/thv-operator/test-integration/...(11 suites)Roughly 40 clean runs of the previously-flaky suites, against a baseline that failed twice in ~17.
task lint-fixreports one pre-existing failure unrelated to this change (cmd/thv/app/upgrade.go:204, gosec G115); confirmed present on the base commit by re-running with the change stashed.Does this introduce a user-facing change?
No. Test infrastructure only.
Special notes for reviewers
Two deliberate omissions, both open to a different call:
mcp-telemetry-configandmcp-groupeach boot 7 control planes for 5 specs and spend ~38s almost entirely on control-plane startup, because the suites useBeforeSuite(per-proc) rather thanSynchronizedBeforeSuite. That inefficiency is what makes this race so easy to hit, but fixing it means sharing one API server across procs and namespace-isolating the specs — worth a follow-up PR, and not needed to stop the flake.Fixes #.The
AddReportEntryin the timeout branch is intentional: if the manager ever does hang, teardown still proceeds and the report names the real cause instead of surfacing a second, misleading apiserver timeout.Generated with Claude Code