Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions conformance/resources/base.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ spec:
terminationGracePeriodSeconds: 130
containers:
- name: epp
image: us-central1-docker.pkg.dev/k8s-staging-images/gateway-api-inference-extension/epp:v20251105-cbb8928
image: us-central1-docker.pkg.dev/k8s-staging-images/gateway-api-inference-extension/epp:v20251119-2aaf2a6
imagePullPolicy: Always
args:
- --pool-name
Expand Down Expand Up @@ -298,7 +298,7 @@ spec:
terminationGracePeriodSeconds: 130
containers:
- name: epp
image: us-central1-docker.pkg.dev/k8s-staging-images/gateway-api-inference-extension/epp:v20251105-cbb8928
image: us-central1-docker.pkg.dev/k8s-staging-images/gateway-api-inference-extension/epp:v20251119-2aaf2a6
imagePullPolicy: Always
args:
- --pool-name
Expand Down Expand Up @@ -507,7 +507,7 @@ spec:
terminationGracePeriodSeconds: 130
containers:
- name: epp
image: us-central1-docker.pkg.dev/k8s-staging-images/gateway-api-inference-extension/epp:v20251105-cbb8928
image: us-central1-docker.pkg.dev/k8s-staging-images/gateway-api-inference-extension/epp:v20251119-2aaf2a6
imagePullPolicy: Always
args:
- --pool-name
Expand Down Expand Up @@ -560,6 +560,7 @@ data:
kind: EndpointPickerConfig
plugins:
- type: header-based-testing-filter
- type: destination-endpoint-served-verifier
schedulingProfiles:
- name: conformance-profile
plugins:
Expand Down
109 changes: 109 additions & 0 deletions conformance/tests/gateway_destination_endpoint_served.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
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 tests

import (
"net/http"
"testing"

"github.com/stretchr/testify/require"
"k8s.io/apimachinery/pkg/types"
gwhttp "sigs.k8s.io/gateway-api/conformance/utils/http"
"sigs.k8s.io/gateway-api/conformance/utils/suite"
"sigs.k8s.io/gateway-api/pkg/features"

"sigs.k8s.io/gateway-api-inference-extension/conformance/resources"
k8sutils "sigs.k8s.io/gateway-api-inference-extension/conformance/utils/kubernetes"
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/requestcontrol/plugins/test"
testscheduling "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework/plugins/test"
)

func init() {
ConformanceTests = append(ConformanceTests, GatewayDestinationEndpointServed)
}

var GatewayDestinationEndpointServed = suite.ConformanceTest{
ShortName: "GatewayDestinationEndpointServed",
Description: "A conformance test to verify that the gateway correctly reports the endpoint that served the request.",
Manifests: []string{"tests/gateway_destination_endpoint_served.yaml"},
Features: []features.FeatureName{
features.FeatureName("SupportInferencePool"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like something that needs a const (similar to SupportGateway)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll have a separate PR for this change to fix #863

features.SupportGateway,
},
Test: func(t *testing.T, s *suite.ConformanceTestSuite) {
const (
hostname = "primary.example.com"
path = "/destination-endpoint-served-test"
)

httpRouteNN := types.NamespacedName{Name: "httproute-for-destination-endpoint-served", Namespace: resources.AppBackendNamespace}
gatewayNN := resources.PrimaryGatewayNN
poolNN := resources.PrimaryInferencePoolNN
backendPodLabels := map[string]string{"app": resources.PrimaryModelServerAppLabel}

t.Log("Verifying HTTPRoute and InferencePool are accepted and the Gateway has an address.")
k8sutils.HTTPRouteMustBeAcceptedAndResolved(t, s.Client, s.TimeoutConfig, httpRouteNN, gatewayNN)
k8sutils.InferencePoolMustBeAcceptedByParent(t, s.Client, poolNN, gatewayNN)
gwAddr := k8sutils.GetGatewayEndpoint(t, s.Client, s.TimeoutConfig, gatewayNN)

t.Logf("Fetching backend pods with labels: %v", backendPodLabels)
pods, err := k8sutils.GetPodsWithLabel(t, s.Client, resources.AppBackendNamespace, backendPodLabels, s.TimeoutConfig)
require.NoError(t, err, "Failed to get backend pods")
require.Len(t, pods, resources.ModelServerPodReplicas, "Expected to find %d backend pods, but found %d.", resources.ModelServerPodReplicas, len(pods))

podIPs := make([]string, len(pods))
podNames := make([]string, len(pods))
for i, pod := range pods {
podIPs[i] = pod.Status.PodIP
podNames[i] = pod.Name
}

requestBody := `{
"model": "conformance-fake-model",
"prompt": "Write as if you were a critic: San Francisco"
}`
t.Run("Request is served by the selected backend pod", func(t *testing.T) {
for i := 0; i < len(pods); i++ {
gwhttp.MakeRequestAndExpectEventuallyConsistentResponse(
t,
s.RoundTripper,
s.TimeoutConfig,
gwAddr,
gwhttp.ExpectedResponse{
Request: gwhttp.Request{
Host: hostname,
Path: path,
Method: http.MethodPost,
Body: requestBody,
Headers: map[string]string{
testscheduling.HeaderTestEppEndPointSelectionKey: podIPs[i],
},
},
Response: gwhttp.Response{
StatusCodes: []int{http.StatusOK},
Headers: map[string]string{
test.ConformanceTestResultHeader: podIPs[i] + ":3000", // The echo server's port is 3000.
},
},
Backend: podNames[i],
Namespace: resources.AppBackendNamespace,
},
)
}
})
},
}
23 changes: 23 additions & 0 deletions conformance/tests/gateway_destination_endpoint_served.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httproute-for-destination-endpoint-served
namespace: inference-conformance-app-backend
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: conformance-primary
namespace: inference-conformance-infra
sectionName: http
hostnames:
- "primary.example.com"
rules:
- backendRefs:
- group: inference.networking.k8s.io
kind: InferencePool
name: primary-inference-pool
matches:
- path:
type: PathPrefix
value: /destination-endpoint-served-test