Repository: istio/istio (go)

Issue:
K8s Gateway should set ResolvedRefs condition to false for incompatible route type
### Bug Description

A Gateway should fail to become ready if it explicitly supports any route type incompatible with the protocol type and the gateway listener should have a false ResolvedRefs condition with reason InvalidRouteKinds.

https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io%2fv1beta1.ListenerStatus


### Version

```prose
latest
```


### Additional Information

_No response_

### Affected product area

- [ ] Docs
- [ ] Installation
- [ ] Networking
- [ ] Performance and Scalability
- [ ] Extensions and Telemetry
- [ ] Security
- [ ] Test and Release
- [ ] User Experience
- [ ] Developer Infrastructure
- [ ] Upgrade
- [ ] Multi Cluster
- [ ] Virtual Machine
- [ ] Control Plane Revisions

### Is this the right place to submit this?

- [X] This is not a security vulnerability
- [X] This is not a question about how to use Istio

Pull request description:
Gateway api route kind status fixes
**Please provide a description of this PR:**

Fixes #40675 

Patch:
diff --git a/pilot/pkg/config/kube/gateway/conditions.go b/pilot/pkg/config/kube/gateway/conditions.go
index 511b55d352..403b404314 100644
--- a/pilot/pkg/config/kube/gateway/conditions.go
+++ b/pilot/pkg/config/kube/gateway/conditions.go
@@ -257,17 +257,25 @@ func reportListenerCondition(index int, l k8s.Listener, obj config.Config, condi
 			gs.Listeners = append(gs.Listeners, k8s.ListenerStatus{})
 		}
 		cond := gs.Listeners[index].Conditions
+		supported, valid := generateSupportedKinds(l)
+		if !valid {
+			conditions[string(k8s.ListenerConditionResolvedRefs)] = &condition{
+				reason:  string(k8s.ListenerReasonInvalidRouteKinds),
+				status:  metav1.ConditionFalse,
+				message: "Invalid route kinds",
+			}
+		}
 		gs.Listeners[index] = k8s.ListenerStatus{
 			Name:           l.Name,
 			AttachedRoutes: 0, // this will be reported later
-			SupportedKinds: generateSupportedKinds(l),
+			SupportedKinds: supported,
 			Conditions:     setConditions(obj.Generation, cond, conditions),
 		}
 		return gs
 	})
 }
 
-func generateSupportedKinds(l k8s.Listener) []k8s.RouteGroupKind {
+func generateSupportedKinds(l k8s.Listener) ([]k8s.RouteGroupKind, bool) {
 	supported := []k8s.RouteGroupKind{}
 	switch l.Protocol {
 	case k8s.HTTPProtocolType, k8s.HTTPSProtocolType:
@@ -288,13 +296,25 @@ func generateSupportedKinds(l k8s.Listener) []k8s.RouteGroupKind {
 		intersection := []k8s.RouteGroupKind{}
 		for _, s := range supported {
 			for _, kind := range l.AllowedRoutes.Kinds {
-				if s == kind {
+				if routeGroupKindEqual(s, kind) {
 					intersection = append(intersection, s)
 					break
 				}
 			}
 		}
-		return intersection
+		return intersection, len(intersection) == len(l.AllowedRoutes.Kinds)
+	}
+	return supported, true
+}
+
+// This and the following function really belongs in some gateway-api lib
+func routeGroupKindEqual(rgk1, rgk2 k8s.RouteGroupKind) bool {
+	return rgk1.Kind == rgk2.Kind && getGroup(rgk1) == getGroup(rgk2)
+}
+
+func getGroup(rgk k8s.RouteGroupKind) k8s.Group {
+	if rgk.Group != nil {
+		return *rgk.Group
 	}
-	return supported
+	return "gateway.networking.k8s.io"
 }
diff --git a/pilot/pkg/config/kube/gateway/conversion.go b/pilot/pkg/config/kube/gateway/conversion.go
index e3aa33fb18..aae3cf5f7b 100644
--- a/pilot/pkg/config/kube/gateway/conversion.go
+++ b/pilot/pkg/config/kube/gateway/conversion.go
@@ -1337,9 +1337,10 @@ func convertGateways(r ConfigContext) ([]config.Config, map[parentKey]map[k8s.Se
 				gwMap[ref] = map[k8s.SectionName]*parentInfo{}
 			}
 
+			allowed, _ := generateSupportedKinds(l)
 			pri := &parentInfo{
 				InternalName:     obj.Namespace + "/" + gatewayConfig.Name,
-				AllowedKinds:     generateSupportedKinds(l),
+				AllowedKinds:     allowed,
 				Hostnames:        server.Hosts,
 				OriginalHostname: emptyIfNil((*string)(l.Hostname)),
 			}


Test patch:
diff --git a/pilot/pkg/config/kube/gateway/testdata/route-binding.status.yaml.golden b/pilot/pkg/config/kube/gateway/testdata/route-binding.status.yaml.golden
index 7f46de944e..4470d664a2 100644
--- a/pilot/pkg/config/kube/gateway/testdata/route-binding.status.yaml.golden
+++ b/pilot/pkg/config/kube/gateway/testdata/route-binding.status.yaml.golden
@@ -132,9 +132,9 @@ status:
       status: "True"
       type: Ready
     - lastTransitionTime: fake
-      message: No errors found
-      reason: ResolvedRefs
-      status: "True"
+      message: Invalid route kinds
+      reason: InvalidRouteKinds
+      status: "False"
       type: ResolvedRefs
     name: scope-route
     supportedKinds: []
diff --git a/pilot/pkg/config/kube/gateway/testdata/route-binding.yaml b/pilot/pkg/config/kube/gateway/testdata/route-binding.yaml
index dd2d0ddea5..f7b5034c09 100644
--- a/pilot/pkg/config/kube/gateway/testdata/route-binding.yaml
+++ b/pilot/pkg/config/kube/gateway/testdata/route-binding.yaml
@@ -30,6 +30,8 @@ spec:
     allowedRoutes:
       namespaces:
         from: All
+      kinds:
+      - kind: HTTPRoute
   - name: same-namespace
     hostname: "*.same-namespace.example"
     port: 80