Skip to content
Merged
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
23 changes: 21 additions & 2 deletions conformance/resources/manifests/manifests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -50,8 +50,27 @@ 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
5 changes: 4 additions & 1 deletion conformance/tests/basic/inferencepool_accepted.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ var InferencePoolAccepted = suite.ConformanceTest{
ShortName: "InferencePoolAccepted",
Description: "A minimal InferencePool resource should be accepted by the controller and report an Accepted condition",
Manifests: []string{"tests/basic/inferencepool_accepted.yaml"},
Features: []features.FeatureName{},
Features: []features.FeatureName{
features.FeatureName("SupportInferencePool"),
features.SupportGateway,
},
Test: func(t *testing.T, s *suite.ConformanceTestSuite) {
// created by the associated manifest file.
poolNN := types.NamespacedName{Name: "inferencepool-basic-accepted", Namespace: "gateway-conformance-app-backend"}
Expand Down
104 changes: 104 additions & 0 deletions conformance/tests/basic/inferencepool_resolvedrefs_condition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
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 (
"context"
"testing"
"time"

"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
"sigs.k8s.io/gateway-api/conformance/utils/suite"
"sigs.k8s.io/gateway-api/pkg/features"

"sigs.k8s.io/gateway-api-inference-extension/conformance/tests"
k8sutils "sigs.k8s.io/gateway-api-inference-extension/conformance/utils/kubernetes"
)

func init() {
tests.ConformanceTests = append(tests.ConformanceTests, InferencePoolParentStatus)
}

var InferencePoolParentStatus = suite.ConformanceTest{
ShortName: "InferencePoolResolvedRefsCondition",
Description: "Verify that an InferencePool correctly updates its parent-specific status (e.g., Accepted condition) when referenced by HTTPRoutes attached to shared Gateways, and clears parent statuses when no longer referenced.",
Manifests: []string{"tests/basic/inferencepool_resolvedrefs_condition.yaml"},
Features: []features.FeatureName{
features.FeatureName("SupportInferencePool"),
features.SupportGateway,
},
Test: func(t *testing.T, s *suite.ConformanceTestSuite) {
const (
appBackendNamespace = "gateway-conformance-app-backend"
infraNamespace = "gateway-conformance-infra"
poolName = "multi-gateway-pool"
sharedGateway1Name = "conformance-gateway"
sharedGateway2Name = "conformance-secondary-gateway"
httpRoute1Name = "httproute-for-gw1"
httpRoute2Name = "httproute-for-gw2"
)

poolNN := types.NamespacedName{Name: poolName, Namespace: appBackendNamespace}
httpRoute1NN := types.NamespacedName{Name: httpRoute1Name, Namespace: appBackendNamespace}
httpRoute2NN := types.NamespacedName{Name: httpRoute2Name, Namespace: appBackendNamespace}
gateway1NN := types.NamespacedName{Name: sharedGateway1Name, Namespace: infraNamespace}
gateway2NN := types.NamespacedName{Name: sharedGateway2Name, Namespace: infraNamespace}

k8sutils.HTTPRouteMustBeAcceptedAndResolved(t, s.Client, s.TimeoutConfig, httpRoute1NN, gateway1NN)
k8sutils.HTTPRouteMustBeAcceptedAndResolved(t, s.Client, s.TimeoutConfig, httpRoute2NN, gateway2NN)

t.Run("InferencePool should show Accepted:True by parents when referenced by multiple HTTPRoutes", func(t *testing.T) {
k8sutils.InferencePoolMustBeAcceptedByParent(t, s.Client, poolNN)
// TODO(#865) ensure requests are correctly routed to this InferencePool.
t.Logf("InferencePool %s has parent status Accepted:True as expected with two references.", poolNN.String())
})

t.Run("Delete httproute-for-gw1", func(t *testing.T) {
httproute1 := &gatewayv1.HTTPRoute{
ObjectMeta: metav1.ObjectMeta{Name: httpRoute1NN.Name, Namespace: httpRoute1NN.Namespace},
}
t.Logf("Deleting HTTPRoute %s", httpRoute1NN.String())
require.NoError(t, s.Client.Delete(context.TODO(), httproute1), "failed to delete httproute-for-gw1")
time.Sleep(s.TimeoutConfig.GatewayMustHaveCondition)
})

t.Run("InferencePool should still show Accepted:True by parent after one HTTPRoute is deleted", func(t *testing.T) {
k8sutils.InferencePoolMustBeAcceptedByParent(t, s.Client, poolNN)
// TODO(#865) ensure requests are correctly routed to this InferencePool.
t.Logf("InferencePool %s still has parent status Accepted:True as expected with one reference remaining.", poolNN.String())
})

t.Run("Delete httproute-for-gw2", func(t *testing.T) {
httproute2 := &gatewayv1.HTTPRoute{
ObjectMeta: metav1.ObjectMeta{Name: httpRoute2NN.Name, Namespace: httpRoute2NN.Namespace},
}
t.Logf("Deleting HTTPRoute %s", httpRoute2NN.String())
require.NoError(t, s.Client.Delete(context.TODO(), httproute2), "failed to delete httproute-for-gw2")
})

t.Run("InferencePool should have no parent statuses after all HTTPRoutes are deleted", func(t *testing.T) {
t.Logf("Waiting for InferencePool %s to have no parent statuses.", poolNN.String())
k8sutils.InferencePoolMustHaveNoParents(t, s.Client, poolNN)
t.Logf("InferencePool %s correctly shows no parent statuses, indicating it's no longer referenced.", poolNN.String())
})

t.Logf("InferencePoolResolvedRefsCondition completed.")
},
}
131 changes: 131 additions & 0 deletions conformance/tests/basic/inferencepool_resolvedrefs_condition.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# conformance/tests/basic/inferencepool_resolvedrefs_condition.yaml

# This manifest defines the initial resources for the
# inferencepool_resolvedrefs_condition.go conformance test.

# --- Backend Deployment (using agnhost echo server) ---
# This Deployment provides Pods for the InferencePool to select.
apiVersion: apps/v1
kind: Deployment
metadata:
name: infra-backend-deployment
namespace: gateway-conformance-app-backend
labels:
app: infra-backend
spec:
replicas: 1
selector:
matchLabels:
app: infra-backend
template:
metadata:
labels:
app: infra-backend
spec:
containers:
- name: agnhost-echo
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

---
# --- Backend Service ---
# Service for the infra-backend-deployment.
apiVersion: v1
kind: Service
metadata:
name: infra-backend-svc
namespace: gateway-conformance-app-backend
spec:
selector:
app: infra-backend
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
- name: epp
port: 9002
targetPort: 9002

---
# --- InferencePool Definition ---
apiVersion: inference.networking.x-k8s.io/v1alpha2
kind: InferencePool
metadata:
name: multi-gateway-pool # Name used in the Go test
namespace: gateway-conformance-app-backend # Defined in base manifests.yaml
spec:
# --- Selector (Required) ---
# Selects the Pods belonging to this pool.
selector:
app: "infra-backend"
# --- Target Port (Required) ---
targetPortNumber: 8080
extensionRef:
name: infra-backend-svc

---
# --- HTTPRoute for Gateway 1 (conformance-gateway) ---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httproute-for-gw1
namespace: gateway-conformance-app-backend
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: conformance-gateway
namespace: gateway-conformance-infra
sectionName: http
hostnames:
- "gw1.example.com"
rules:
- backendRefs:
- group: inference.networking.x-k8s.io
kind: InferencePool
name: multi-gateway-pool
port: 8080
matches:
- path:
type: PathPrefix
value: /conformance-gateway-test

---
# --- HTTPRoute for Gateway 2 (conformance-secondary-gateway) ---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httproute-for-gw2
namespace: gateway-conformance-app-backend
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: conformance-secondary-gateway
namespace: gateway-conformance-infra
sectionName: http
hostnames:
- "secondary.example.com"
rules:
- backendRefs:
- group: inference.networking.x-k8s.io
kind: InferencePool
name: multi-gateway-pool
port: 8080
matches:
- path:
type: PathPrefix
value: /gateway-2-test
Loading