pkg/configrefs/gateway.go
Rama main · réplica de lectura del repositorio original.
package configrefs
// Gateway API reference defaults: an omitted backendRef group/kind names a core
// Service, an omitted parentRef group/kind names a Gateway, and an omitted
// namespace is the route's own. An explicit group or kind always wins, so a
// mesh parentRef to a Service or a backendRef to a same-named custom kind must
// never be joined to a Gateway or core Service that happens to share the name.
const gatewayAPIGroup = "gateway.networking.k8s.io"
// GatewayBackendIsService reports whether a route backendRef names a core Service.
func GatewayBackendIsService(ref map[string]any) bool {
group, _ := ref["group"].(string)
kind, _ := ref["kind"].(string)
return group == "" && (kind == "" || kind == "Service")
}
// GatewayParentIsGateway reports whether a route parentRef names a Gateway.
func GatewayParentIsGateway(ref map[string]any) bool {
group, hasGroup := ref["group"].(string)
kind, _ := ref["kind"].(string)
return (!hasGroup || group == gatewayAPIGroup) && (kind == "" || kind == "Gateway")
}
// GatewayRefNamespace returns the reference's namespace, defaulting to the route's.
func GatewayRefNamespace(ref map[string]any, routeNamespace string) string {
if ns, _ := ref["namespace"].(string); ns != "" {
return ns
}
return routeNamespace
}
// GatewayParentRefInSpec reports whether a status.parents[].parentRef still
// names one of the route's spec.parentRefs, by exact reference identity after
// Gateway API defaulting: group, kind, namespace, name, sectionName and port
// must all agree. sectionName and port are part of that identity and are NOT
// wildcarded — an unset field matches only an unset field — so narrowing or
// widening a parentRef's scope retires the status entry recorded for the old
// scope. routeNamespace defaults an omitted namespace on EITHER side, resolved
// independently, so an omitted status namespace never inherits an explicit spec
// namespace. A status entry that matches no spec parentRef is stale and the
// caller should ignore it.
func GatewayParentRefInSpec(statusRef map[string]any, specParentRefs []any, routeNamespace string) bool {
if len(statusRef) == 0 {
return false
}
for _, sp := range specParentRefs {
specRef, ok := sp.(map[string]any)
if !ok {
continue
}
if gatewayParentRefsEqual(statusRef, specRef, routeNamespace) {
return true
}
}
return false
}
func gatewayParentRefsEqual(a, b map[string]any, routeNamespace string) bool {
if gatewayRefGroup(a) != gatewayRefGroup(b) {
return false
}
if gatewayRefKind(a) != gatewayRefKind(b) {
return false
}
if GatewayRefNamespace(a, routeNamespace) != GatewayRefNamespace(b, routeNamespace) {
return false
}
an, _ := a["name"].(string)
bn, _ := b["name"].(string)
if an != bn {
return false
}
as, _ := a["sectionName"].(string)
bs, _ := b["sectionName"].(string)
if as != bs {
return false
}
return gatewayRefPortEqual(a, b)
}
// gatewayRefGroup returns the parentRef's API group, distinguishing an omitted
// group (defaults to the Gateway group) from an explicit empty group (the core
// group) — mirroring GatewayParentIsGateway, and deliberately NOT collapsing ""
// into the Gateway group the way the display-only detector helper does.
func gatewayRefGroup(ref map[string]any) string {
if g, ok := ref["group"].(string); ok {
return g
}
return gatewayAPIGroup
}
// gatewayRefKind returns the parentRef's kind. Kind defaults to Gateway
// independently of group; an absent or empty kind is Gateway.
func gatewayRefKind(ref map[string]any) string {
if k, ok := ref["kind"].(string); ok && k != "" {
return k
}
return "Gateway"
}
// gatewayRefPortEqual compares the optional port of two parentRefs. Presence is
// compared separately from value: both absent is equal, one absent is not, and
// a present-but-unparseable port never compares equal (so schema-invalid data
// cannot accidentally match).
func gatewayRefPortEqual(a, b map[string]any) bool {
av, aPresent := a["port"]
bv, bPresent := b["port"]
if aPresent != bPresent {
return false
}
if !aPresent {
return true
}
an, aok := gatewayPortValue(av)
bn, bok := gatewayPortValue(bv)
if !aok || !bok {
return false
}
return an == bn
}
func gatewayPortValue(v any) (int64, bool) {
switch t := v.(type) {
case int64:
return t, true
case int32:
return int64(t), true
case int:
return int64(t), true
case float64:
return int64(t), true
default:
return 0, false
}
}