Skip to content

fix(issues): correlate missing admission webhook services - #1391

Open
nadaverell wants to merge 1 commit into
fix/rad-346-onset-provenancefrom
fix/rad-346-webhook-missing-service
Open

fix(issues): correlate missing admission webhook services#1391
nadaverell wants to merge 1 commit into
fix/rad-346-onset-provenancefrom
fix/rad-346-webhook-missing-service

Conversation

@nadaverell

@nadaverell nadaverell commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • classify API-server admission failures when a webhook Service is missing, using strict webhook name and in-cluster Service URL parsing
  • correlate blocked workloads to the exact webhook configuration and missing backend Service fingerprint
  • keep the real webhook configuration as the root issue without inventing a synthetic Service resource
  • preserve ambiguity boundaries and failurePolicy semantics

Validation

  • make build
  • make test
  • go test ./internal/k8s ./internal/issues -count=1
  • live EKS test on radar-test-nonprod: reproduced the exact service not found FailedCreate event, verified the configuration-to-workload incident edge in API and UI, installed a TLS webhook backend, and verified both workload recovery and issue disappearance
  • Cursor Opus cross-review: no findings

Stacked on #1390; retarget to main after that PR lands.

RAD-346


Note

Medium Risk
Changes admission webhook incident correlation and parsing of API-server failure messages; incorrect matching could mis-parent workloads or miss real outages, though ambiguity guards and broad tests limit exposure.

Overview
Extends admission webhook failure handling beyond no ready endpoints to service not found API errors, using strict parsing of webhook name and in-cluster Service URL so scheduling failures classify as WebhookUnavailable.

Missing webhook backend detections now use shared MissingWebhookBackendReason and WebhookBackendFingerprint so each configuration root is keyed to an exact backend Service identity. Diagnostic enrichment treats those missing-ref webhook configuration issues as roots (no synthetic Service row), resolves webhooks via AdmissionWebhookRefsForConfiguration, and links blocked workloads only when the parsed failure matches failurePolicy=Fail, webhook name, service identity, and failure kind (missing service vs no endpoints).

Existing Service-backend webhook correlation is tightened the same way: ParseAdmissionWebhookBackendFailure replaces the no-endpoints-only parser, and incident edges require an exact webhook reference match rather than service name alone.

Reviewed by Cursor Bugbot for commit e5161cd. Bugbot is set up for automated code reviews on this repo. Configure here.

@nadaverell
nadaverell requested a review from hisco as a code owner August 9, 2026 03:23
nadaverell added a commit that referenced this pull request Aug 9, 2026
## Summary
- detect Gateways that reference a missing GatewayClass after a
two-minute reconciliation grace
- detect HTTPRoute, GRPCRoute, TCPRoute, and TLSRoute parentRefs that
target a missing Gateway
- require authoritative cluster or exact-namespace informer coverage
before asserting absence
- preserve unrelated Gateway controller conditions while deduplicating
exact structural echoes, including Envoy Gateway PortNotFound
- apply the same authority check to KEDA Rollout scaleTargetRefs so
partial caches cannot produce false missing-target issues

## Validation
- `make build`
- `make test`
- `make tsc`
- `go test ./internal/issues ./internal/k8s`
- `go test ./...` from `pkg/k8score/`
- live EKS smoke on `radar-test-nonprod`: grace suppression, both
findings present, target creation recovery, and fixture cleanup
- Playwright Issues-page smoke with both findings rendered and zero
console errors
- visual-test skipped: no UI delta

## Stack
- stacked on #1391
- #1391 is stacked on #1390

Linear: RAD-346

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes live issue detection for Gateway networking and dynamic-cache
“absence” semantics; incorrect authority or dedupe could hide real
problems or briefly miss issues during informer sync, but behavior is
heavily tested and biased toward silence when coverage is incomplete.
> 
> **Overview**
> Extends **Gateway API missing-reference detection** beyond route
backend Services: after a **2-minute grace**, it flags **Gateways** with
a non-existent `spec.gatewayClassName` and **routes** (`HTTPRoute`,
`GRPCRoute`, `TCPRoute`, `TLSRoute`) whose `parentRefs` point at a
**missing Gateway** (same- or cross-namespace). **Backend Service / port
/ ReferenceGrant** checks still require the Service lister; **topology**
checks (class + parent) run even when Services aren’t available.
> 
> **Issue taxonomy** maps `Missing GatewayClass` to
**gateway_not_ready** and `Missing Gateway parent` to
**gateway_route_invalid**; user-facing catalog copy is updated
accordingly.
> 
> **Dedupe** no longer drops every `ResolvedRefs:*` condition when any
structural missing-ref exists on the route. It only hides **matching**
controller echoes (e.g. backend missing → `BackendNotFound` /
`PortNotFound`; ReferenceGrant → `RefNotPermitted`). A **missing
parent** structural row does **not** suppress unrelated `ResolvedRefs`
conditions.
> 
> **Dynamic cache authority**: new `HasWatchedInSyncedNamespace` returns
“missing” only when the relevant informer has **synced** for that
namespace (including during informer scope replacement). **KEDA
`Rollout` scaleTargetRefs** use the same rule so partial watches don’t
emit false **missing scaleTargetRef** issues. Initial add-event
suppression is renamed/clarified so it isn’t confused with sync
authority.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
93ee479. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
nadaverell added a commit that referenced this pull request Aug 9, 2026
## Summary
- detect Gateways that reference a missing GatewayClass after a
two-minute reconciliation grace
- detect HTTPRoute, GRPCRoute, TCPRoute, and TLSRoute parentRefs that
target a missing Gateway
- require authoritative cluster or exact-namespace informer coverage
before asserting absence
- preserve unrelated Gateway controller conditions while deduplicating
exact structural echoes, including Envoy Gateway PortNotFound
- apply the same authority check to KEDA Rollout scaleTargetRefs so
partial caches cannot produce false missing-target issues

## Validation
- `make build`
- `make test`
- `make tsc`
- `go test ./internal/issues ./internal/k8s`
- `go test ./...` from `pkg/k8score/`
- live EKS smoke on `radar-test-nonprod`: grace suppression, both
findings present, target creation recovery, and fixture cleanup
- Playwright Issues-page smoke with both findings rendered and zero
console errors
- visual-test skipped: no UI delta

## Stack
- stacked on #1391
- #1391 is stacked on #1390

Linear: RAD-346

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes live issue detection for Gateway networking and dynamic-cache
“absence” semantics; incorrect authority or dedupe could hide real
problems or briefly miss issues during informer sync, but behavior is
heavily tested and biased toward silence when coverage is incomplete.
> 
> **Overview**
> Extends **Gateway API missing-reference detection** beyond route
backend Services: after a **2-minute grace**, it flags **Gateways** with
a non-existent `spec.gatewayClassName` and **routes** (`HTTPRoute`,
`GRPCRoute`, `TCPRoute`, `TLSRoute`) whose `parentRefs` point at a
**missing Gateway** (same- or cross-namespace). **Backend Service / port
/ ReferenceGrant** checks still require the Service lister; **topology**
checks (class + parent) run even when Services aren’t available.
> 
> **Issue taxonomy** maps `Missing GatewayClass` to
**gateway_not_ready** and `Missing Gateway parent` to
**gateway_route_invalid**; user-facing catalog copy is updated
accordingly.
> 
> **Dedupe** no longer drops every `ResolvedRefs:*` condition when any
structural missing-ref exists on the route. It only hides **matching**
controller echoes (e.g. backend missing → `BackendNotFound` /
`PortNotFound`; ReferenceGrant → `RefNotPermitted`). A **missing
parent** structural row does **not** suppress unrelated `ResolvedRefs`
conditions.
> 
> **Dynamic cache authority**: new `HasWatchedInSyncedNamespace` returns
“missing” only when the relevant informer has **synced** for that
namespace (including during informer scope replacement). **KEDA
`Rollout` scaleTargetRefs** use the same rule so partial watches don’t
emit false **missing scaleTargetRef** issues. Initial add-event
suppression is renamed/clarified so it isn’t confused with sync
authority.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
93ee479. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@nadaverell
nadaverell force-pushed the fix/rad-346-webhook-missing-service branch from 2da1e04 to 3588d3d Compare August 9, 2026 13:03
@nadaverell
nadaverell force-pushed the fix/rad-346-onset-provenance branch from a2fce69 to e2c2e3d Compare August 9, 2026 13:03
@nadaverell
nadaverell force-pushed the fix/rad-346-webhook-missing-service branch 2 times, most recently from dc1547c to 572085b Compare August 10, 2026 00:24
@nadaverell
nadaverell force-pushed the fix/rad-346-webhook-missing-service branch from 572085b to e5161cd Compare August 10, 2026 00:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant