Skip to content

fix(ROSAENG-64778): dvo and metrics clients leaking goroutines - #693

Open
holysoles wants to merge 3 commits into
openshift:masterfrom
holysoles:http_transport_leak
Open

fix(ROSAENG-64778): dvo and metrics clients leaking goroutines #693
holysoles wants to merge 3 commits into
openshift:masterfrom
holysoles:http_transport_leak

Conversation

@holysoles

@holysoles holysoles commented Aug 7, 2026

Copy link
Copy Markdown

What type of PR is this?

(bug/feature/cleanup/documentation/test/refactor)

Bug

What this PR does / why we need it?

Both dvoRoundTripper.RoundTrip and prometheusRoundTripper.RoundTrip create a new http.Transport on every HTTP request as a local variable.

Each transport spawns background goroutines for connection management. Since this is done in a local variable and no reference to the transport is retained, CloseIdleConnections() is never/unable to be called and the goroutines and their associated buffers become unreachable but uncollectable. The newly added tests validate that these goroutines are being leaked.

I found this issue when investigating MUO getting OOM killed on a production cluster when attempting to run upgrade preflight checks. Claude estimates each leaked transport at ~40-50KB of memory (goroutine stacks + connection buffers + TLS state). I am not able to confirm this is the root cause of that production issue, but was the only memory leak I could find and feels worth fixing.

Since the transport settings are static for the life of the client, we should be able to initialize the transport settings once and reuse it. Additionally, we this should let us benefit from connection pooling, reducing a small amount of cpu overhead of a new TLS handshake for every client request.

additional fixes

checkPodDisruptionBudgets namespace filter is using strings.HasPrefix(ns, "openshift-*"), but * will be treated as a literal character, not a wildcard. No namespace will ever match that, so all PDBs are being checked regardless of namespace.

Per coderabbit review, I also added request-level timeouts to these clients since we could block the reconciliation loop if a server hung while responding.

Which Jira/Github issue(s) this PR fixes?

Fixes Jira https://redhat.atlassian.net/browse/ROSAENG-64778

Special notes for your reviewer:

Pre-checks (if applicable):

  • Tested latest changes against a cluster
  • Included documentation changes with PR

Summary by CodeRabbit

  • Bug Fixes
    • Corrected namespace matching for disruption budget health checks.
    • Improved reliability of metrics and DVO requests with consistent connection, proxy, and timeout settings.
    • Prevented potential goroutine leaks during metrics and DVO operations.
  • Testing
    • Added coverage for response handling, authorization, TLS configuration, and request behavior.

strings.HasPrefix with "openshift-*" never matches, so all PDBs were
validated including core openshift platform PDBs
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (2)
  • build/Dockerfile is excluded by !build/**
  • build/Dockerfile.olm-registry is excluded by !build/**

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 64aa7178-35ba-4fd6-b417-38e843392534

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

The PR configures reusable HTTP transports for DVO and Prometheus clients, adds request and goroutine behavior tests, and corrects OpenShift namespace prefix matching in the PDB filter.

Changes

Client transport and validation

Layer / File(s) Summary
DVO transport configuration and validation
pkg/dvo/builder.go, pkg/dvo/client.go, pkg/dvo/client_test.go, pkg/dvo/dvo_suite_test.go
The DVO client now reuses a configured transport with proxy and timeout settings. Tests cover request paths, response bodies, authorization, and goroutine counts.
Prometheus transport configuration and validation
pkg/metrics/metrics.go, pkg/metrics/metrics_test.go, pkg/metrics/metrics_suite_test.go
The Prometheus client now reuses a configured transport with proxy, timeout, and TLS settings. Tests cover TLS setup, query results, authorization, and goroutine counts.

PDB namespace filtering

Layer / File(s) Summary
PDB namespace prefix correction
pkg/upgraders/healthcheck_pdb.go
The namespace filter now matches namespaces beginning with openshift- while retaining configured exceptions.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: charlesgong, ravitri

🚥 Pre-merge checks | ✅ 14 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Test Structure And Quality ⚠️ Warning The added DVO and metrics specs contain many assertions without failure messages and create mock clients inside each It; only HTTP servers use AfterEach cleanup, unlike the repository lifecycle pat... Add diagnostic messages to assertions, move shared fixture setup to BeforeEach, and explicitly clean up mock controllers and HTTP servers in AfterEach.
✅ Passed checks (14 passed)
Check name Status Explanation
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.
Stable And Deterministic Test Names ✅ Passed The added Ginkgo titles in pkg/dvo and pkg/metrics are literal, descriptive strings and contain no generated names, timestamps, namespaces, nodes, IPs, or other run-dependent values.
Microshift Test Compatibility ✅ Passed Added Ginkgo specs are package unit tests using gomock and httptest; they do not run against a cluster or add MicroShift-incompatible e2e API assumptions.
Single Node Openshift (Sno) Test Compatibility ✅ Passed New Ginkgo specs use httptest servers and mocked Kubernetes clients. They do not schedule pods, inspect nodes, or assume multi-node or HA topology.
Topology-Aware Scheduling Compatibility ✅ Passed The commit changes HTTP clients and tests only; it adds no deployment, controller, manifest, replica, affinity, topology, node-selection, toleration, or PDB scheduling constraints.
Ote Binary Stdout Contract ✅ Passed This operator PR is not an OTE binary, and its only process-level additions are Ginkgo RunSpecs calls; no changed code writes non-JSON data to stdout.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The new Ginkgo specs are package unit tests using local httptest servers; they add no IPv4 literals, preserve parsed host brackets, and require no external or public network access.
No-Weak-Crypto ✅ Passed Changed code uses standard TLS 1.2, x509, and HTTP transports; scans found no MD5, SHA1, DES, RC4, Blowfish, ECB, custom crypto, or secret comparisons.
Container-Privileges ✅ Passed The PR changes only Go source and tests. Scans found no privileged:true, hostPID, hostNetwork, hostIPC, SYS_ADMIN, or allowPrivilegeEscalation:true; images use non-root users where declared.
No-Sensitive-Data-In-Logs ✅ Passed The added implementation and tests contain no logging calls; tokens and pull secrets are used only in Authorization headers and test assertions, not emitted to logs.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: fixing goroutine leaks in the DVO and metrics clients.
✨ 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.

@openshift-ci
openshift-ci Bot requested review from charlesgong and ravitri August 7, 2026 20:33

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

🤖 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 `@pkg/dvo/builder.go`:
- Around line 47-57: The reusable transports in pkg/dvo/builder.go lines 47-57
and pkg/metrics/metrics.go lines 161-173 need bounded full-request cancellation:
add an appropriate overall transport timeout and ensure the HTTP requests
created by the DVO GetMetrics() and Prometheus Query() flows use
deadline-bearing contexts. Preserve the existing connection, keep-alive, proxy,
and TLS timeout settings while applying the same protection at both sites.

In `@pkg/dvo/client_test.go`:
- Around line 27-28: Check URL parsing and port conversion errors in the test
helper at pkg/dvo/client_test.go:27-28 and apply the same validation at
pkg/metrics/metrics_test.go:26-28. In each helper, handle url.Parse errors
before accessing the parsed URL, then handle strconv.Atoi errors before using
the port, reporting failures through the existing test context.
- Line 82: Migrate the four DVO scenarios in pkg/dvo/client_test.go at lines
82-82, 111-111, and 133-133, and the three metrics scenarios in
pkg/metrics/metrics_test.go at lines 94-94, 123-123, and 151-151 from standalone
Test* functions into Ginkgo v2 Describe/It blocks. Replace their assertions with
Gomega assertions and preserve each scenario’s existing behavior.
🪄 Autofix

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: Pro Plus

Run ID: a0916b1d-feb9-41b5-92e5-2a05603242fd

📥 Commits

Reviewing files that changed from the base of the PR and between 2e1644b and 13bb02c.

📒 Files selected for processing (6)
  • pkg/dvo/builder.go
  • pkg/dvo/client.go
  • pkg/dvo/client_test.go
  • pkg/metrics/metrics.go
  • pkg/metrics/metrics_test.go
  • pkg/upgraders/healthcheck_pdb.go

Comment thread pkg/dvo/builder.go
Comment thread pkg/dvo/client_test.go
Comment thread pkg/dvo/client_test.go Outdated
@codecov-commenter

codecov-commenter commented Aug 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 55.77%. Comparing base (2e1644b) to head (e0197fc).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #693      +/-   ##
==========================================
+ Coverage   54.33%   55.77%   +1.44%     
==========================================
  Files         123      123              
  Lines        6212     6218       +6     
==========================================
+ Hits         3375     3468      +93     
+ Misses       2631     2533      -98     
- Partials      206      217      +11     
Files with missing lines Coverage Δ
pkg/dvo/builder.go 85.18% <100.00%> (+85.18%) ⬆️
pkg/dvo/client.go 64.70% <100.00%> (+64.70%) ⬆️
pkg/metrics/metrics.go 31.56% <100.00%> (+18.35%) ⬆️
pkg/upgraders/healthcheck_pdb.go 88.15% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Creating a new http.Transport per request in RoundTrip leaks ~3
goroutines per call. Move transport construction to the dvo
and metrics client builders so it's created once and reused.

Tests Generated by: Claude Code (opus 4.6)
@holysoles
holysoles force-pushed the http_transport_leak branch from 13bb02c to 720e8cd Compare August 10, 2026 17:47

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

🧹 Nitpick comments (1)
pkg/dvo/dvo_suite_test.go (1)

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

Use Ginkgo v2 in the updated suite files.

Update the consolidated suite imports for the V2 tests:

  • pkg/dvo/dvo_suite_test.go#L6-L6
  • pkg/metrics/metrics_suite_test.go#L6-L6

Use github.com/onsi/ginkgo/v2 instead of github.com/onsi/ginkgo, and remove the unused legacy github.com/onsi/ginkgo module requirement.

🤖 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 `@pkg/dvo/dvo_suite_test.go` at line 6, Update the Ginkgo imports in
pkg/dvo/dvo_suite_test.go (line 6) and pkg/metrics/metrics_suite_test.go (line
6) to use github.com/onsi/ginkgo/v2 instead of the legacy package, then remove
the unused github.com/onsi/ginkgo module requirement.

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.

Nitpick comments:
In `@pkg/dvo/dvo_suite_test.go`:
- Line 6: Update the Ginkgo imports in pkg/dvo/dvo_suite_test.go (line 6) and
pkg/metrics/metrics_suite_test.go (line 6) to use github.com/onsi/ginkgo/v2
instead of the legacy package, then remove the unused github.com/onsi/ginkgo
module requirement.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: d7d4ced6-bab6-4c7b-bfc5-dd484b8fbd7c

📥 Commits

Reviewing files that changed from the base of the PR and between 13bb02c and 720e8cd.

📒 Files selected for processing (6)
  • pkg/dvo/builder.go
  • pkg/dvo/client_test.go
  • pkg/dvo/dvo_suite_test.go
  • pkg/metrics/metrics.go
  • pkg/metrics/metrics_suite_test.go
  • pkg/metrics/metrics_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/dvo/builder.go
  • pkg/metrics/metrics.go

@holysoles
holysoles force-pushed the http_transport_leak branch 2 times, most recently from 36933bf to 720e8cd Compare August 10, 2026 19:53
@openshift-ci

openshift-ci Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

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

@joshbranham

Copy link
Copy Markdown
Contributor

/lgtm
/hold

Looks good to me, holding to give SMEs a chance to review if they want.

@openshift-ci openshift-ci Bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Aug 11, 2026
@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Aug 11, 2026
@openshift-ci

openshift-ci Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: holysoles, joshbranham

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

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. lgtm Indicates that a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants