Skip to content

Commit 1708386

Browse files
committed
feat(conformance): add conformance test for endpoint served.
1 parent 0e4a99d commit 1708386

File tree

3 files changed

+136
-2
lines changed

3 files changed

+136
-2
lines changed

conformance/resources/base.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ spec:
200200
terminationGracePeriodSeconds: 130
201201
containers:
202202
- name: epp
203-
image: us-central1-docker.pkg.dev/k8s-staging-images/gateway-api-inference-extension/epp:v1.0.0
203+
image: us-central1-docker.pkg.dev/bobzetian-gke-dev/gateway-api-inference-extension/epp:latest
204204
imagePullPolicy: Always
205205
args:
206206
- --pool-name
@@ -298,7 +298,7 @@ spec:
298298
terminationGracePeriodSeconds: 130
299299
containers:
300300
- name: epp
301-
image: us-central1-docker.pkg.dev/k8s-staging-images/gateway-api-inference-extension/epp:v1.0.0
301+
image: us-central1-docker.pkg.dev/bobzetian-gke-dev/gateway-api-inference-extension/epp:latest
302302
imagePullPolicy: Always
303303
args:
304304
- --pool-name
@@ -351,6 +351,7 @@ data:
351351
kind: EndpointPickerConfig
352352
plugins:
353353
- type: header-based-testing-filter
354+
- type: destination-endpoint-served-verifier
354355
schedulingProfiles:
355356
- name: conformance-profile
356357
plugins:
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package tests
18+
19+
import (
20+
"fmt"
21+
"net/http"
22+
"testing"
23+
24+
"github.com/stretchr/testify/require"
25+
"k8s.io/apimachinery/pkg/types"
26+
gwhttp "sigs.k8s.io/gateway-api/conformance/utils/http"
27+
"sigs.k8s.io/gateway-api/conformance/utils/suite"
28+
"sigs.k8s.io/gateway-api/pkg/features"
29+
30+
"sigs.k8s.io/gateway-api-inference-extension/conformance/resources"
31+
k8sutils "sigs.k8s.io/gateway-api-inference-extension/conformance/utils/kubernetes"
32+
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/requestcontrol/plugins/test"
33+
testscheduling "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework/plugins/test"
34+
)
35+
36+
func init() {
37+
ConformanceTests = append(ConformanceTests, GatewayDestinationEndpointServed)
38+
}
39+
40+
var GatewayDestinationEndpointServed = suite.ConformanceTest{
41+
ShortName: "GatewayDestinationEndpointServed",
42+
Description: "A conformance test to verify that the gateway correctly reports the endpoint that served the request.",
43+
Manifests: []string{"tests/gateway_destination_endpoint_served.yaml"},
44+
Features: []features.FeatureName{
45+
features.FeatureName("SupportInferencePool"),
46+
features.SupportGateway,
47+
},
48+
Test: func(t *testing.T, s *suite.ConformanceTestSuite) {
49+
const (
50+
hostname = "primary.example.com"
51+
path = "/destination-endpoint-served-test"
52+
)
53+
54+
httpRouteNN := types.NamespacedName{Name: "httproute-for-destination-endpoint-served", Namespace: resources.AppBackendNamespace}
55+
gatewayNN := resources.PrimaryGatewayNN
56+
poolNN := resources.PrimaryInferencePoolNN
57+
backendPodLabels := map[string]string{"app": resources.PrimaryModelServerAppLabel}
58+
59+
t.Log("Verifying HTTPRoute and InferencePool are accepted and the Gateway has an address.")
60+
k8sutils.HTTPRouteMustBeAcceptedAndResolved(t, s.Client, s.TimeoutConfig, httpRouteNN, gatewayNN)
61+
k8sutils.InferencePoolMustBeAcceptedByParent(t, s.Client, poolNN, gatewayNN)
62+
gwAddr := k8sutils.GetGatewayEndpoint(t, s.Client, s.TimeoutConfig, gatewayNN)
63+
64+
t.Logf("Fetching backend pods with labels: %v", backendPodLabels)
65+
pods, err := k8sutils.GetPodsWithLabel(t, s.Client, resources.AppBackendNamespace, backendPodLabels, s.TimeoutConfig)
66+
require.NoError(t, err, "Failed to get backend pods")
67+
require.Len(t, pods, resources.ModelServerPodReplicas, "Expected to find %d backend pods, but found %d.", resources.ModelServerPodReplicas, len(pods))
68+
69+
podIPs := make([]string, len(pods))
70+
podNames := make([]string, len(pods))
71+
for i, pod := range pods {
72+
podIPs[i] = pod.Status.PodIP
73+
podNames[i] = pod.Name
74+
}
75+
76+
requestBody := `{
77+
"model": "conformance-fake-model",
78+
"prompt": "Write as if you were a critic: San Francisco"
79+
}`
80+
t.Run("Request is served by the selected backend pod", func(t *testing.T) {
81+
for i := 0; i < len(pods); i++ {
82+
gwhttp.MakeRequestAndExpectEventuallyConsistentResponse(
83+
t,
84+
s.RoundTripper,
85+
s.TimeoutConfig,
86+
gwAddr,
87+
gwhttp.ExpectedResponse{
88+
Request: gwhttp.Request{
89+
Host: hostname,
90+
Path: path,
91+
Method: http.MethodPost,
92+
Body: requestBody,
93+
Headers: map[string]string{
94+
testscheduling.HeaderTestEppEndPointSelectionKey: podIPs[i],
95+
},
96+
},
97+
Response: gwhttp.Response{
98+
StatusCodes: []int{http.StatusOK},
99+
Headers: map[string]string{
100+
test.ConformanceTestResultHeader: fmt.Sprintf("%s:3000", podIPs[i]), // The echo server's port is 3000.
101+
},
102+
},
103+
Backend: podNames[i],
104+
Namespace: resources.AppBackendNamespace,
105+
},
106+
)
107+
}
108+
})
109+
},
110+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
apiVersion: gateway.networking.k8s.io/v1
2+
kind: HTTPRoute
3+
metadata:
4+
name: httproute-for-destination-endpoint-served
5+
namespace: inference-conformance-app-backend
6+
spec:
7+
parentRefs:
8+
- group: gateway.networking.k8s.io
9+
kind: Gateway
10+
name: conformance-primary
11+
namespace: inference-conformance-infra
12+
sectionName: http
13+
hostnames:
14+
- "primary.example.com"
15+
rules:
16+
- backendRefs:
17+
- group: inference.networking.k8s.io
18+
kind: InferencePool
19+
name: primary-inference-pool
20+
matches:
21+
- path:
22+
type: PathPrefix
23+
value: /destination-endpoint-served-test

0 commit comments

Comments
 (0)