-
Notifications
You must be signed in to change notification settings - Fork 88
feat(conformance): Add HTTPRouteMultipleGatewaysDifferentPools test #838
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,7 +23,7 @@ metadata: | |
gateway-conformance: backend | ||
|
||
--- | ||
# Namespace for simple web server backends. This is expected by | ||
# Namespace for simple web server backends. This is expected by | ||
# the upstream conformance suite's Setup method. | ||
apiVersion: v1 | ||
kind: Namespace | ||
|
@@ -50,8 +50,30 @@ spec: | |
protocol: HTTP | ||
allowedRoutes: | ||
namespaces: | ||
from: All | ||
from: All | ||
kinds: | ||
# Allows HTTPRoutes to attach, which can then reference InferencePools. | ||
- group: gateway.networking.k8s.io | ||
kind: HTTPRoute | ||
|
||
--- | ||
# --- Conformance Secondary Gateway Definition --- | ||
# A second generic Gateway resource for tests requiring multiple Gateways. | ||
apiVersion: gateway.networking.k8s.io/v1 | ||
kind: Gateway | ||
metadata: | ||
name: conformance-secondary-gateway | ||
namespace: gateway-conformance-infra | ||
spec: | ||
gatewayClassName: "{GATEWAY_CLASS_NAME}" | ||
listeners: | ||
- name: http | ||
port: 80 | ||
protocol: HTTP | ||
hostname: "secondary.example.com" # Distinct hostname to differentiate from conformance-gateway | ||
allowedRoutes: | ||
namespaces: | ||
from: All | ||
kinds: | ||
- group: gateway.networking.k8s.io | ||
kind: HTTPRoute | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't forget trailing new lines in these files |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
/* | ||
Copyright 2025 The Kubernetes Authors. | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package basic | ||
|
||
import ( | ||
"testing" | ||
|
||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/types" | ||
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" | ||
gatewayk8utils "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" | ||
"sigs.k8s.io/gateway-api/conformance/utils/suite" | ||
|
||
// Import the tests package to append to ConformanceTests | ||
"sigs.k8s.io/gateway-api-inference-extension/conformance/tests" | ||
"sigs.k8s.io/gateway-api-inference-extension/conformance/utils/config" | ||
infrakubernetes "sigs.k8s.io/gateway-api-inference-extension/conformance/utils/kubernetes" | ||
) | ||
|
||
func init() { | ||
tests.ConformanceTests = append(tests.ConformanceTests, HTTPRouteMultipleGatewaysDifferentPools) | ||
} | ||
|
||
var HTTPRouteMultipleGatewaysDifferentPools = suite.ConformanceTest{ | ||
ShortName: "HTTPRouteMultipleGatewaysDifferentPools", | ||
Description: "Validates two HTTPRoutes on different Gateways successfully referencing different InferencePools.", | ||
Manifests: []string{"tests/basic/httproute_multiple_gateways_different_pools.yaml"}, | ||
Test: func(t *testing.T, s *suite.ConformanceTestSuite) { | ||
const ( | ||
appBackendNamespace = "gateway-conformance-app-backend" | ||
infraNamespace = "gateway-conformance-infra" | ||
gateway1Name = "conformance-gateway" | ||
gateway2Name = "conformance-secondary-gateway" | ||
routeForGW1Name = "route-for-gw1" | ||
routeForGW2Name = "route-for-gw2" | ||
poolAName = "pool-a" | ||
poolBName = "pool-b" | ||
) | ||
|
||
routeForGW1NN := types.NamespacedName{Name: routeForGW1Name, Namespace: appBackendNamespace} | ||
routeForGW2NN := types.NamespacedName{Name: routeForGW2Name, Namespace: appBackendNamespace} | ||
poolANN := types.NamespacedName{Name: poolAName, Namespace: appBackendNamespace} | ||
poolBNN := types.NamespacedName{Name: poolBName, Namespace: appBackendNamespace} | ||
gateway1NN := types.NamespacedName{Name: gateway1Name, Namespace: infraNamespace} | ||
gateway2NN := types.NamespacedName{Name: gateway2Name, Namespace: infraNamespace} | ||
|
||
var timeoutConfig config.InferenceExtensionTimeoutConfig = config.DefaultInferenceExtensionTimeoutConfig() | ||
|
||
t.Run("HTTPRoute for Gateway 1 should be Accepted and have ResolvedRefs", func(t *testing.T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It feels like a lot of what's in this test is going to get repeated in almost every conformance test. I'd recommend having some helpers that turn the wait for an HTTPRoute and InferencePool to be accepted into single line function calls for each resource. |
||
acceptedCondition := metav1.Condition{ | ||
Type: string(gatewayv1.RouteConditionAccepted), | ||
Status: metav1.ConditionTrue, | ||
Reason: string(gatewayv1.RouteReasonAccepted), | ||
} | ||
gatewayk8utils.HTTPRouteMustHaveCondition(t, s.Client, timeoutConfig.TimeoutConfig, routeForGW1NN, gateway1NN, acceptedCondition) | ||
t.Logf("HTTPRoute %s is Accepted by Gateway %s", routeForGW1NN.String(), gateway1NN.String()) | ||
|
||
resolvedRefsCondition := metav1.Condition{ | ||
Type: string(gatewayv1.RouteConditionResolvedRefs), | ||
Status: metav1.ConditionTrue, | ||
Reason: string(gatewayv1.RouteReasonResolvedRefs), | ||
} | ||
gatewayk8utils.HTTPRouteMustHaveCondition(t, s.Client, timeoutConfig.TimeoutConfig, routeForGW1NN, gateway1NN, resolvedRefsCondition) | ||
t.Logf("HTTPRoute %s has all references resolved by Gateway %s", routeForGW1NN.String(), gateway1NN.String()) | ||
}) | ||
|
||
t.Run("InferencePool A (pool-a) should be Accepted", func(t *testing.T) { | ||
acceptedCondition := metav1.Condition{ | ||
Type: string(gatewayv1.RouteConditionAccepted), | ||
Status: metav1.ConditionTrue, | ||
Reason: string(gatewayv1.RouteReasonAccepted), | ||
} | ||
infrakubernetes.InferencePoolMustHaveCondition(t, s.Client, poolANN, acceptedCondition) | ||
t.Logf("InferencePool %s parent status shows Accepted by Gateway %s (via HTTPRoute %s)", poolANN.String(), gateway1NN.String(), routeForGW1NN.String()) | ||
}) | ||
|
||
t.Run("HTTPRoute for Gateway 2 should be Accepted and have ResolvedRefs", func(t *testing.T) { | ||
acceptedCondition := metav1.Condition{ | ||
Type: string(gatewayv1.RouteConditionAccepted), | ||
Status: metav1.ConditionTrue, | ||
Reason: string(gatewayv1.RouteReasonAccepted), | ||
} | ||
gatewayk8utils.HTTPRouteMustHaveCondition(t, s.Client, timeoutConfig.TimeoutConfig, routeForGW2NN, gateway2NN, acceptedCondition) | ||
t.Logf("HTTPRoute %s is Accepted by Gateway %s", routeForGW2NN.String(), gateway2NN.String()) | ||
|
||
resolvedRefsCondition := metav1.Condition{ | ||
Type: string(gatewayv1.RouteConditionResolvedRefs), | ||
Status: metav1.ConditionTrue, | ||
Reason: string(gatewayv1.RouteReasonResolvedRefs), | ||
} | ||
gatewayk8utils.HTTPRouteMustHaveCondition(t, s.Client, timeoutConfig.TimeoutConfig, routeForGW2NN, gateway2NN, resolvedRefsCondition) | ||
t.Logf("HTTPRoute %s has all references resolved by Gateway %s", routeForGW2NN.String(), gateway2NN.String()) | ||
}) | ||
|
||
t.Run("InferencePool B (pool-b) should be Accepted", func(t *testing.T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On further thought, I'd expect these tests to go further. To really ensure that this is working as expected, we should try to send a request and ensure it gets routed to the appropriate InferencePool. |
||
acceptedCondition := metav1.Condition{ | ||
Type: string(gatewayv1.RouteConditionAccepted), | ||
Status: metav1.ConditionTrue, | ||
Reason: string(gatewayv1.RouteReasonAccepted), | ||
} | ||
infrakubernetes.InferencePoolMustHaveCondition(t, s.Client, poolBNN, acceptedCondition) | ||
t.Logf("InferencePool %s parent status shows Accepted by Gateway %s (via HTTPRoute %s)", poolBNN.String(), gateway2NN.String(), routeForGW2NN.String()) | ||
}) | ||
}, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
# httproute_multiple_gateways_different_pools.yaml | ||
# This manifest defines resources for the httproute_multiple_gateways_different_pools conformance test. | ||
# It includes two distinct backend deployments, their EPP services, two InferencePools, | ||
# and two HTTPRoutes, each linking to one of the two shared Gateways from the base manifests. | ||
|
||
# --- Backend Deployment A --- | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: multi-gw-backend-a-deployment | ||
namespace: gateway-conformance-app-backend | ||
labels: | ||
app: multi-gw-backend-a | ||
spec: | ||
replicas: 1 | ||
selector: | ||
matchLabels: | ||
app: multi-gw-backend-a | ||
template: | ||
metadata: | ||
labels: | ||
app: multi-gw-backend-a | ||
spec: | ||
containers: | ||
- name: agnhost-echo-a | ||
image: k8s.gcr.io/e2e-test-images/agnhost:2.39 | ||
args: | ||
- serve-hostname | ||
- --port=8080 | ||
ports: | ||
- name: http | ||
containerPort: 8080 | ||
readinessProbe: | ||
httpGet: | ||
path: / | ||
port: 8080 | ||
initialDelaySeconds: 3 | ||
periodSeconds: 5 | ||
failureThreshold: 2 | ||
|
||
--- | ||
# --- Service for Backend Deployment A (EPP for pool-a) --- | ||
apiVersion: v1 | ||
kind: Service | ||
metadata: | ||
name: pool-a-epp | ||
namespace: gateway-conformance-app-backend | ||
spec: | ||
selector: | ||
app: multi-gw-backend-a | ||
ports: | ||
- name: http | ||
protocol: TCP | ||
port: 8080 | ||
targetPort: 8080 | ||
- name: epp | ||
protocol: TCP | ||
port: 9002 | ||
targetPort: 9002 | ||
|
||
--- | ||
# --- Backend Deployment B --- | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: multi-gw-backend-b-deployment | ||
namespace: gateway-conformance-app-backend | ||
labels: | ||
app: multi-gw-backend-b | ||
spec: | ||
replicas: 1 | ||
selector: | ||
matchLabels: | ||
app: multi-gw-backend-b | ||
template: | ||
metadata: | ||
labels: | ||
app: multi-gw-backend-b | ||
spec: | ||
containers: | ||
- name: agnhost-echo-b | ||
image: k8s.gcr.io/e2e-test-images/agnhost:2.39 | ||
args: | ||
- serve-hostname | ||
- --port=8080 | ||
ports: | ||
- name: http | ||
containerPort: 8080 | ||
readinessProbe: | ||
httpGet: | ||
path: / | ||
port: 8080 | ||
initialDelaySeconds: 3 | ||
periodSeconds: 5 | ||
failureThreshold: 2 | ||
|
||
--- | ||
# --- Service for Backend Deployment B (EPP for pool-b) --- | ||
apiVersion: v1 | ||
kind: Service | ||
metadata: | ||
name: pool-b-epp | ||
namespace: gateway-conformance-app-backend | ||
spec: | ||
selector: | ||
app: multi-gw-backend-b | ||
ports: | ||
- name: http | ||
protocol: TCP | ||
port: 8080 | ||
targetPort: 8080 | ||
- name: epp | ||
protocol: TCP | ||
port: 9002 | ||
targetPort: 9002 | ||
|
||
--- | ||
# --- InferencePool A Definition --- | ||
apiVersion: inference.networking.x-k8s.io/v1alpha2 | ||
kind: InferencePool | ||
metadata: | ||
name: pool-a | ||
namespace: gateway-conformance-app-backend | ||
spec: | ||
selector: | ||
app: "multi-gw-backend-a" | ||
targetPortNumber: 8080 | ||
extensionRef: | ||
name: pool-a-epp | ||
|
||
--- | ||
# --- InferencePool B Definition --- | ||
apiVersion: inference.networking.x-k8s.io/v1alpha2 | ||
kind: InferencePool | ||
metadata: | ||
name: pool-b | ||
namespace: gateway-conformance-app-backend | ||
spec: | ||
selector: | ||
app: "multi-gw-backend-b" | ||
targetPortNumber: 8080 | ||
extensionRef: | ||
name: pool-b-epp | ||
|
||
--- | ||
# --- HTTPRoute for Gateway 1 (conformance-gateway) --- | ||
apiVersion: gateway.networking.k8s.io/v1 | ||
kind: HTTPRoute | ||
metadata: | ||
name: route-for-gw1 | ||
namespace: gateway-conformance-app-backend | ||
spec: | ||
parentRefs: | ||
- group: gateway.networking.k8s.io | ||
kind: Gateway | ||
name: conformance-gateway # Referencing shared conformance-gateway | ||
namespace: gateway-conformance-infra # Gateway is in infra namespace | ||
sectionName: http | ||
hostnames: | ||
- "gw1.example.com" # Specific hostname for this route | ||
rules: | ||
- backendRefs: | ||
- group: inference.networking.x-k8s.io | ||
kind: InferencePool | ||
name: pool-a | ||
port: 8080 | ||
weight: 1 | ||
matches: | ||
- path: | ||
type: PathPrefix | ||
value: /test-gw1 | ||
|
||
--- | ||
# --- HTTPRoute for Gateway 2 (conformance-secondary-gateway) --- | ||
apiVersion: gateway.networking.k8s.io/v1 | ||
kind: HTTPRoute | ||
metadata: | ||
name: route-for-gw2 | ||
namespace: gateway-conformance-app-backend | ||
spec: | ||
parentRefs: | ||
- group: gateway.networking.k8s.io | ||
kind: Gateway | ||
name: conformance-secondary-gateway # Referencing shared conformance-secondary-gateway | ||
namespace: gateway-conformance-infra # Gateway is in infra namespace | ||
sectionName: http | ||
hostnames: | ||
- "secondary.example.com" # Matching hostname of conformance-secondary-gateway | ||
rules: | ||
- backendRefs: | ||
- group: inference.networking.x-k8s.io | ||
kind: InferencePool | ||
name: pool-b | ||
port: 8080 | ||
weight: 1 | ||
matches: | ||
- path: | ||
type: PathPrefix | ||
value: /test-gw2 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment here |
Uh oh!
There was an error while loading. Please reload this page.