Skip to content

test(e2e): reproduce #219 hostname-less listener collision#221

Merged
ecv merged 1 commit into
mainfrom
test/issue-219-repro-e2e
Jun 26, 2026
Merged

test(e2e): reproduce #219 hostname-less listener collision#221
ecv merged 1 commit into
mainfrom
test/issue-219-repro-e2e

Conversation

@ecv

@ecv ecv commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Summary

End-to-end reproduction of #219 — a tenant Gateway whose listeners use the default ports/protocols (80/HTTP, 443/HTTPS) without a hostname is rejected at admission with the misleading upstream CEL message:

Combination of port, protocol and hostname must be unique for each listener

Root cause (per the issue): NSO's mutating webhook unconditionally injects hostname-less default-http (80/HTTP) and default-https (443/HTTPS) listeners. A tenant listener on those ports with no hostname produces a duplicate (port, protocol, hostname=∅) tuple, and the upstream CRD CEL rejects the whole object before NSO's own validating webhook can surface a clear reason.

This PR adds only the repro test — no production code changes. The fix lives in #220.

Test

test/e2e/gateway-listener-hostname-collision/chainsaw-test.yaml — pure admission-time reproduction on the control-plane (nso-standard) cluster; no downstream/edge wiring needed. Drives the failure exactly as the issue did, via kubectl apply --dry-run=server (runs the mutating webhook + CRD CEL without persisting).

Probes mirror the issue's investigation matrix:

Probe Listeners Expected
B (decisive) 1 — 80/HTTP, no hostname ❌ rejected must be unique
A 2 — 80/HTTP + 443/HTTPS, no hostname ❌ rejected must be unique
D (control) 1 — 80/HTTP, with hostname ✅ accepted

Probe B is decisive: a single tenant listener cannot collide with itself, so its rejection isolates the injected-default tuple collision as the cause. Probe D is the positive control — a distinguishing hostname is admitted.

Validation done

  • chainsaw lint (v0.2.15, the pinned version) → The document is valid.
  • Not executed against live clusters — this environment has no Docker/kind. Against unfixed code (main / this branch) all three probes pass and the bug reproduces.

Interaction with the fix (#220)

Once #220 merges, NSO's defaulting webhook rejects probes A/B first with a clear hostname-required message instead of the opaque "must be unique". The expected grep string in each probe will then need updating to the clear message — to be done as part of merging #220.

Refs

🤖 Generated with Claude Code

Add a chainsaw e2e test that reproduces issue #219: a tenant Gateway
whose listeners use 80/HTTP or 443/HTTPS without a hostname is rejected
at admission with the misleading upstream CEL message "Combination of
port, protocol and hostname must be unique for each listener".

The test is a pure admission-time reproduction on the control-plane
cluster (no downstream wiring), driving the failure exactly as the issue
did via kubectl apply --dry-run=server. Probes mirror the issue matrix:

  B (decisive) 1 listener  80/HTTP  no hostname  -> rejected
  A            2 listeners 80+443   no hostname  -> rejected
  D (control)  1 listener  80/HTTP  hostname     -> accepted

Probe B is decisive: a single listener cannot collide with itself, so
its rejection isolates the injected default-listener tuple collision as
the cause. Probe D confirms a distinguishing hostname is admitted.

Once #220 merges, NSO's defaulting webhook rejects A/B first with a clear
hostname-required message, so the expected message here will change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

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

Approved

@ecv
ecv merged commit 6a6a433 into main Jun 26, 2026
11 checks passed
@ecv
ecv deleted the test/issue-219-repro-e2e branch June 26, 2026 17:33
ecv added a commit that referenced this pull request Jun 26, 2026
The gateway-listener-hostname-collision e2e test (merged via #221) was
written to reproduce #219: it asserted that hostname-less tenant listeners
are rejected with the opaque upstream CEL message "Combination of port,
protocol and hostname must be unique for each listener".

This branch fixes #219 by rejecting those listeners in NSO's defaulting
webhook (before the CRD CEL stage) with a clear, actionable message. That
flips the expected error, so probes A/B failed against this branch.

Update probes A/B to grep for "a hostname must be set" and reframe the
header/descriptions from "reproduce the bug" to "verify the fix". Probe D
(listener with a hostname is admitted) is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

2 participants