attachment

package
v0.0.0-...-ac943e3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 23, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package attachment holds the edge Gateway API controller's route→listener attachment resolution: parentRef matching, allowedRoutes (namespaces/kinds) admission, ReferenceGrant-gated backendRef admission, and listener/route hostname intersection. It is deliberately free of any xDS proxy/cache dependency so the attachment semantics (and their tests) stand alone from Envoy resource generation; the gatewayapi reconciler composes it.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AttachedGatewayKeys

func AttachedGatewayKeys(parentRefs []gatewayv1.ParentReference, routeNamespace string, gateways map[GatewayKey]struct{}) []string

AttachedGatewayKeys returns the "<ns>/<name>" keys of OUR Gateways a route's parentRefs attach to. Used to scope a vhost to its actual Gateways' route tables (Phase 2 assignment by attachment, not by cert).

func AttachedHostnameLookupKeys

func AttachedHostnameLookupKeys(parentRefs []gatewayv1.ParentReference, routeNamespace string, gateways map[GatewayKey]struct{}) []string

AttachedHostnameLookupKeys returns the hostname-lookup keys for EffectiveHostnames. When a parentRef specifies a sectionName the key is "ns/name/sectionName" so EffectiveHostnames uses only that listener's hostname; otherwise it uses the gateway-level "ns/name" key (union of all listener hostnames). This implements Gateway API §hostname-intersection: "If the listener section name and/or port is specified, Hostnames must match only that listener."

func AttachedToOurGateway

func AttachedToOurGateway(parentRefs []gatewayv1.ParentReference, routeNamespace string, gateways map[GatewayKey]struct{}) bool

AttachedToOurGateway reports whether the given parentRefs (belonging to a route in routeNamespace) include a reference to one of our Gateways. A parentRef's namespace defaults to the route's own namespace when unset (per the Gateway API spec), so cross-namespace attachment is matched correctly.

func BackendPermitted

func BackendPermitted(backendNamespace *gatewayv1.Namespace, routeNamespace, routeKind, name string, grants []gatewayv1beta1.ReferenceGrant) bool

BackendPermitted reports whether a backendRef is allowed onto the data plane: a same-namespace ref always is; a cross-namespace ref needs a matching ReferenceGrant in the backend's namespace whose from matches the route and whose to allows the Service. routeKind is the referring route's kind (HTTPRoute/TCPRoute/TLSRoute).

func BuildGatewayListenerHostnames

func BuildGatewayListenerHostnames(gws []gatewayv1.Gateway) map[string][]string

BuildGatewayListenerHostnames extracts the listener hostnames for each Gateway into a map keyed by "<namespace>/<name>". A listener with no hostname is represented by an empty string "". The returned value is used to compute effective route hostnames via EffectiveHostnames.

Keys: "ns/name" for the per-Gateway union (used by routes without a sectionName), and "ns/name/sectionName" for per-section lookup (used when a parentRef specifies a sectionName). The per-section value contains only that listener's hostname so EffectiveHostnames scopes the route to exactly the hostnames of the listener it attached to.

func DerefBackendNamespace

func DerefBackendNamespace(ns *gatewayv1.Namespace) string

DerefBackendNamespace returns the backendRef namespace ("" when unset).

func EffectiveHostnames

func EffectiveHostnames(routeHosts []string, gwKeys []string, gwListenerHostnames map[string][]string) []string

EffectiveHostnames computes the Gateway API effective hostname set for a route:

effective = ∪(over attached Gateways) of { route.Hostnames ∩ listenerHostnames(gw) }

Gateway API intersection rules (per spec):

  • A listener hostname "" (no hostname) admits ALL route hostnames unchanged.
  • A route hostname "" (no hostnames on the route) inherits the listener's hostname(s); a listener "" × route "" = "*" (catch-all, no constraint).
  • exact == exact: they match; result is that exact hostname.
  • listener "*.example.com" ∩ route "a.example.com": route is more specific → result "a.example.com".
  • route "*.example.com" ∩ listener "a.example.com": listener is more specific → result "a.example.com".

The return value replaces vh.Hosts in the reconciler so downstream code (the cache's buildEdgeVhostsLocked) sees only the hosts the route ACTUALLY matches. A nil/empty return means the route has no valid attachment (no listener admits any of its declared hosts) and must be discarded by the caller.

Multi-Gateway: takes the union of intersections across all attached Gateways, deduplicating. This is a correct first cut (see implementation note).

func GatewayParentPorts

func GatewayParentPorts(
	parentRefs []gatewayv1.ParentReference,
	routeNamespace string,
	gateways map[GatewayKey]struct{},
	protocol gatewayv1.ProtocolType,
	listenerKeys map[GatewayListenerKey]struct{},
) []uint32

GatewayParentPorts returns the distinct ports of our Gateway listeners that match the given protocol and are referenced by the given parentRefs (belonging to a route in routeNamespace). Used to scope TCPRoute/TLSRoute attachments to the exact Gateway listener ports. A parentRef namespace defaults to the route's own namespace when unset.

func ListenerHasInvalidRouteKinds

func ListenerHasInvalidRouteKinds(ln gatewayv1.Listener) bool

ListenerHasInvalidRouteKinds reports whether a listener's allowedRoutes.kinds names any kind the listener's protocol does not support (drives the ResolvedRefs=False / InvalidRouteKinds listener condition).

func ListenerSupportedKinds

func ListenerSupportedKinds(ln gatewayv1.Listener) []gatewayv1.RouteGroupKind

ListenerSupportedKinds returns the supportedKinds to publish on a listener's status: the protocol-default kinds, intersected with allowedRoutes.kinds when the listener sets one. A listener whose allowedRoutes.kinds names only unsupported kinds yields an empty (non-nil) slice, matching the upstream conformance expectation (supportedKinds: []).

func OurGatewayParentRefs

func OurGatewayParentRefs(parentRefs []gatewayv1.ParentReference, routeNamespace string, gateways map[GatewayKey]struct{}) []gatewayv1.ParentReference

OurGatewayParentRefs returns the parentRefs of a route (in routeNamespace) that point at one of our Gateways — the only entries we own status for. The parentRef namespace defaults to the route's namespace.

func SupportedKindsFor

func SupportedKindsFor(protocol gatewayv1.ProtocolType) []gatewayv1.RouteGroupKind

SupportedKindsFor maps a listener protocol to the Route kinds the edge serves on it: HTTPRoute for HTTP/HTTPS, TCPRoute for TCP, TLSRoute for TLS.

Types

type GatewayKey

type GatewayKey struct {
	Namespace string
	Name      string
}

GatewayKey identifies a Gateway by namespace+name. Since the edge reconciles cluster-wide, Gateway names alone are no longer unique (two namespaces may each have a Gateway "edge"), so route attachment must match on the full namespaced name.

type GatewayListenerKey

type GatewayListenerKey struct {
	Gateway  GatewayKey
	Port     uint32
	Protocol gatewayv1.ProtocolType
}

GatewayListenerKey identifies a listener within a gateway by namespace+name+protocol+port. Used to scope TCPRoute/TLSRoute parentRef port matching.

type Resolver

type Resolver struct {
	client.Reader
	Log *slog.Logger
}

Resolver resolves route→listener attachment. It needs only a Kubernetes reader (to fetch route-namespace labels for allowedRoutes.namespaces selectors) and a logger — no xDS proxy/cache types.

func (*Resolver) AttachedRoutesForListener

func (r *Resolver) AttachedRoutesForListener(
	ctx context.Context,
	gw *gatewayv1.Gateway,
	ln gatewayv1.Listener,
	httpRoutes []gatewayv1.HTTPRoute,
	tcpRoutes []gatewayv1.TCPRoute,
	tlsRoutes []gatewayv1.TLSRoute,
	gateways map[GatewayKey]struct{},
	listenerKeys map[GatewayListenerKey]struct{},
) int32

AttachedRoutesForListener counts the routes (with Accepted=True) attached to a specific listener. HTTP/HTTPS listeners accept HTTPRoutes attached to the gateway; TCP/TLS listeners accept TCP/TLSRoutes whose parentRef resolves to that listener's port (via GatewayParentPorts).

func (*Resolver) HTTPRouteAcceptance

func (r *Resolver) HTTPRouteAcceptance(ctx context.Context, hr *gatewayv1.HTTPRoute, gwByKey map[GatewayKey]*gatewayv1.Gateway) (bool, string, string)

HTTPRouteAcceptance computes the route-level Accepted condition for an HTTPRoute across all of our Gateways it references. The route is Accepted when it attaches to at least one listener of at least one of our Gateways; otherwise the most specific failure reason wins (NoMatchingListenerHostname > NotAllowedByListeners > NoMatchingParent).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL