Skip to content

feat: reflect EC2 backend discovery failures in Backend status conditions#14173

Merged
puertomontt merged 5 commits into
kgateway-dev:mainfrom
puertomontt:ec2-status
Jun 25, 2026
Merged

feat: reflect EC2 backend discovery failures in Backend status conditions#14173
puertomontt merged 5 commits into
kgateway-dev:mainfrom
puertomontt:ec2-status

Conversation

@puertomontt

@puertomontt puertomontt commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Description

The EC2 backend's EDS polling loop runs asynchronously after translation, so credential and discovery failures (bad credentials, IAM denial, AWS API errors, zero matching instances) produced only a log line and never surfaced on the Backend resource. Operators had no Kubernetes-native signal that discovery was broken.

This PR adds an EndpointsDiscovered status condition that is written back to the Backend after every refresh cycle.

What changed

  • New condition + reasons (api/v1alpha1/kgateway/backend_types.go): EndpointsDiscovered with reasons Discovered, NoMatchingInstances, CredentialError, AuthorizationError, DiscoveryError.
  • EC2 discovery (ec2.go): each refresh records a per-backend ec2DiscoveryStatus (part of state equality, so the condition is recomputed on every poll — including transient failures that preserve carried-forward endpoints per NFR-3). A new DiscoveryStatus KRT collection exposes it. Errors are classified: locally-detected credential problems → CredentialError; AWS auth/authz codes → AuthorizationError; everything else → DiscoveryError. Backends with an unresolved secretRef (filtered out before discovery runs) report CredentialError synchronously.
  • Plumbing: ir.BackendObjectStatus carries plugin-contributed conditions; BackendPlugin.ExtraConditions exposes the collection; GenerateBackendStatusReport merges them alongside Accepted so a single writer owns all Backend conditions.
  • Stale-condition handling (pkg/reports/status.go): a kgateway-managed condition absent from a fresh report is now dropped rather than preserved forever, so a backend that stops doing discovery (or is no longer an EC2 backend) doesn't retain stale state.

Condition mapping

State Status Reason Message
Poll succeeded, ≥1 endpoint True Discovered N endpoints active
Poll succeeded, 0 matches False NoMatchingInstances describes the filters in use
Missing/unresolved/malformed credentials False CredentialError description without secret values
AWS auth/authz rejection False AuthorizationError AWS error message
Transient/other AWS error False DiscoveryError AWS error message

Note on classification

The issue lists "invalid keys" under CredentialError, but AWS rejects well-formed-but-wrong keys server-side (AuthFailure/InvalidClientTokenId), which this PR maps to AuthorizationError. CredentialError covers locally-detectable problems (unresolved secret, malformed secret data); AuthorizationError covers AWS-side rejections — consistent with the table's "AWS error message" vs. "description without exposing secret values" split. Happy to fold those AWS codes into CredentialError if preferred.

Change Type

/kind feature

Changelog

EC2 backends now report an `EndpointsDiscovered` status condition reflecting whether runtime endpoint discovery succeeded, including credential, authorization, and zero-match failures.

Additional Notes

Discovery against live AWS is not exercised by e2e here; coverage is via unit tests for the success/no-match/auth-failure/credential-error paths, the report merge, and stale-condition dropping.

Add an EndpointsDiscovered status condition to the Backend resource so
operators get a Kubernetes-native signal for EC2 runtime discovery
outcomes (gloo-gateway#2283, FR-8/NFR-2).

The EC2 EDS controller now records a per-backend discovery status after
every refresh cycle and exposes it via a DiscoveryStatus KRT collection:

- success with >=1 endpoint -> True/Discovered ("N endpoints active")
- success with 0 matches    -> False/NoMatchingInstances (describes filters)
- unresolved/malformed creds -> False/CredentialError
- AWS auth/authz rejection   -> False/AuthorizationError
- transient/other AWS error  -> False/DiscoveryError

Failures preserve carried-forward endpoints (NFR-3); the condition is
recomputed on every poll because the discovery status participates in
state equality. Backends with an unresolved secretRef are surfaced
synchronously even though they are filtered out before discovery runs.

Conditions are merged into the single backendStatusReport writer
alongside Accepted, and a managed condition absent from a fresh report
is now dropped (instead of preserved) so a backend that stops doing
discovery does not retain stale state.

Fixes solo-io/gloo-gateway#2283

Signed-off-by: omar <[email protected]>
Copilot AI review requested due to automatic review settings June 4, 2026 20:46
@puertomontt
puertomontt requested a review from a team as a code owner June 4, 2026 20:46
@gateway-bot gateway-bot added do-not-merge/description-invalid kind/feature Categorizes issue or PR as related to a new feature. release-note labels Jun 4, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a Kubernetes-native signal for runtime AWS EC2 backend discovery by introducing an EndpointsDiscovered Backend status condition, plumbing plugin-contributed conditions into the core backend status writer, and ensuring stale kgateway-managed Backend conditions are dropped when no longer produced.

Changes:

  • Introduces BackendConditionEndpointsDiscovered plus standardized reason enums for discovery outcomes.
  • Adds EC2 discovery status production (including error classification) and wires it into Backend status reporting via a plugin “extra conditions” collection.
  • Updates Backend status building to drop stale kgateway-owned condition types that are absent from the latest report, and adds/extends unit tests for merging and stale-condition behavior.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
api/v1alpha1/kgateway/backend_types.go Defines EndpointsDiscovered condition type and reason constants for discovery outcomes.
pkg/kgateway/extensions2/plugins/backend/ec2.go Tracks per-backend EC2 discovery status and exposes it as a KRT collection for status reporting.
pkg/kgateway/extensions2/plugins/backend/ec2_test.go Adds unit tests for discovery status generation and error classification.
pkg/kgateway/extensions2/plugins/backend/plugin.go Wires EC2 discovery status collection into the backend plugin’s ExtraConditions.
pkg/pluginsdk/ir/backend.go Adds ir.BackendObjectStatus for plugin-contributed Backend conditions and equality semantics.
pkg/pluginsdk/types.go Extends BackendPlugin to optionally expose ExtraConditions and includes it in sync gating.
pkg/kgateway/proxy_syncer/status.go Merges plugin-contributed Backend conditions into the single Backend status report writer.
pkg/kgateway/proxy_syncer/proxy_syncer.go Fetches plugin ExtraConditions and passes them into backend status report generation.
pkg/kgateway/proxy_syncer/backend_status_test.go Adds coverage validating extra-condition merging behavior.
pkg/reports/status.go Drops stale kgateway-owned Backend condition types that are absent from a fresh report.
pkg/reports/observed_generation_test.go Adds a regression test ensuring stale managed Backend conditions are dropped while foreign ones are preserved.

Comment on lines 305 to +311
if source.secret != nil {
derived, err := deriveStaticSecret(source.secret)
if err != nil {
return nil, fmt.Errorf("invalid aws secret: %w", err)
// Malformed credential data is a credential problem, not an AWS-side
// rejection; classify it so the Backend reports CredentialError. The
// wrapped error never includes secret values (see deriveStaticSecret).
return nil, &ec2CredentialError{err: fmt.Errorf("invalid aws secret: %w", err)}

@andy-fong andy-fong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

commented on slack.

When an EC2 discovery poll fails but endpoints carried forward from a
previous successful poll are still being served, report the
EndpointsDiscovered condition with reason Degraded instead of the raw
failure reason. This lets operators tell a degraded-but-serving backend
apart from one that is hard down (no endpoints), e.g. to alert on the two
cases differently. The underlying failure cause is preserved in the
condition message, which now also states how many endpoints are still
served (or that none are available).

Also fix TestDiscoveryStatusForBackendReportsCredentialErrorForUnresolvedSecret,
which built a backend with no auth set and so never exercised the
secret-credential branch it claimed to, falling through to a nil-trigger
panic. It now configures Secret auth with an unresolved secret.

Signed-off-by: omar <[email protected]>
@puertomontt
puertomontt enabled auto-merge June 25, 2026 09:02
@puertomontt
puertomontt added this pull request to the merge queue Jun 25, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 25, 2026
@puertomontt
puertomontt added this pull request to the merge queue Jun 25, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 25, 2026
@puertomontt
puertomontt added this pull request to the merge queue Jun 25, 2026
Merged via the queue into kgateway-dev:main with commit b65fdb8 Jun 25, 2026
32 checks passed
@puertomontt
puertomontt deleted the ec2-status branch June 25, 2026 10:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/feature Categorizes issue or PR as related to a new feature. release-note

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants