fix: Skip landing page registration on NewLandingPage error#2937
fix: Skip landing page registration on NewLandingPage error#2937carterpewpew wants to merge 1 commit into
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: carterpewpew The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
This issue is currently awaiting triage. If kube-state-metrics contributors determine this is a relevant issue, they will accept it by applying the The DetailsInstructions 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. |
|
Welcome @carterpewpew! |
6b039b3 to
8f01c12
Compare
There was a problem hiding this comment.
Pull request overview
This PR prevents kube-state-metrics from registering a nil landing page handler when web.NewLandingPage() returns an error, avoiding a runtime panic on requests to / while keeping other endpoints functional.
Changes:
- Return early (after logging) from
buildTelemetryServer()andbuildMetricsServer()when landing page creation fails, skippingmux.Handle("/", landingPage). - Add tests for the landing page success path and a regression-style test illustrating the nil-handler panic scenario.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| pkg/app/server.go | Returns the mux without registering / when landing page construction fails. |
| pkg/app/server_test.go | Adds landing page tests and a regression-style panic test for a nil landing page handler. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| func TestNilLandingPageHandlerPanicsOnRequest(t *testing.T) { | ||
| t.Parallel() | ||
| // Simulate the unfixed bug: web.NewLandingPage returns (nil, err) and | ||
| // the nil *LandingPageHandler is registered on the mux without an early | ||
| // return. In Go, a nil concrete pointer assigned to an interface is | ||
| // non-nil, so mux.Handle succeeds. But ServeHTTP dereferences the nil | ||
| // receiver (h.routePrefix), causing a panic. | ||
| var nilHandler *web.LandingPageHandler | ||
|
|
||
| mux := http.NewServeMux() | ||
| mux.Handle("/", nilHandler) | ||
|
|
c31cc82 to
d39d4f3
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
pkg/app/server_test.go:1063
- Same issue as above: overriding the global
newLandingPagecan run concurrently with othert.Parallel()tests in this package and lead to data races/flakes. Use synchronization to guard overrides (or refactor to inject the landing page factory per server build) so tests remain safe under parallel execution andgo test -race.
func TestBuildMetricsServerLandingPageError(t *testing.T) {
original := newLandingPage
t.Cleanup(func() { newLandingPage = original })
newLandingPage = func(_ web.LandingConfig) (*web.LandingPageHandler, error) {
return nil, fmt.Errorf("injected landing page error")
}
| // Overridable in tests to simulate NewLandingPage failures. | ||
| var newLandingPage = web.NewLandingPage |
| func TestBuildTelemetryServerLandingPageError(t *testing.T) { | ||
| original := newLandingPage | ||
| t.Cleanup(func() { newLandingPage = original }) | ||
| newLandingPage = func(_ web.LandingConfig) (*web.LandingPageHandler, error) { | ||
| return nil, fmt.Errorf("injected landing page error") | ||
| } |
When web.NewLandingPage returns an error, the previous code logged it but still registered a nil *LandingPageHandler for "/", which can panic on GET / because ServeHTTP dereferences the receiver. Accept the landing page factory as a parameter in buildTelemetryServer and buildMetricsServer so tests can inject a failing factory without mutable global state or data races. Return the mux without registering the root handler when the factory fails. Add tests that inject a failing factory and assert "/" returns 404 while other routes (/metrics, /healthz) continue to serve 200. Add happy-path tests that verify "/" returns 200 under normal conditions. Signed-off-by: Jathavedhan M <jathavedhan.m@ibm.com>
d39d4f3 to
b12fbce
Compare
What this PR does / why we need it:
When
web.NewLandingPage()returns an error, the handler value is nil and the API is telling us not to use it. The previous code logged the error but still calledmux.Handle("/", landingPage), registering a nil*web.LandingPageHandler. Because a nil pointer stored in anhttp.Handlerinterface is non-nil in Go, the default mux accepts it silently. The firstGET /then panics whenServeHTTPdereferences the nil receiver (e.g. readingroutePrefix).This change:
newLandingPagefunction parameter tobuildTelemetryServer()andbuildMetricsServer()so the landing page factory is injected per call. Production code passesweb.NewLandingPage; tests can inject a failing factory without mutable global state or data races./handler, when the factory returns an error. The rest of the server (metrics, health, pprof, etc.) continues to work and the process does not crash on the root path if landing page construction fails./returns 200) and the error path (landing page skipped,/returns 404, other routes like/metricsand/healthzstill work). All tests are safe to run witht.Parallel()and passgo test -race.How does this change affect the cardinality of KSM: does not change cardinality
Which issue(s) this PR fixes: N/A