Skip to content

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

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c859896
copy from existing test to start with
SinaChavoshi May 14, 2025
fe540a7
update test and add gateway to main manifest
SinaChavoshi May 15, 2025
63fedab
fix spelling error
SinaChavoshi May 19, 2025
68812d7
check RouteConditionResolvedRefs instead of Reconciled
SinaChavoshi May 20, 2025
5efaeb2
add new line at the end of yaml files.
SinaChavoshi May 27, 2025
2cd8dab
delete blank lines in yaml files.
SinaChavoshi May 27, 2025
26704a1
change variable names to use primary / secondary
SinaChavoshi May 27, 2025
bb62da7
add to do for name change across the project.
SinaChavoshi May 27, 2025
796b584
fix comment
SinaChavoshi May 27, 2025
403b588
Merge branch 'main' into inf_pool_tests_12
SinaChavoshi May 27, 2025
6506d44
change all variable names to use primary/secondary consistantly
SinaChavoshi May 27, 2025
dafd21e
add to do for http route testing
SinaChavoshi May 27, 2025
ecf11e4
HTTPRouteMustBeAcceptedAndResolved
SinaChavoshi May 27, 2025
f1ce162
add helper method.
SinaChavoshi May 27, 2025
f3d8e8c
using helper method for pool route accepted.
SinaChavoshi May 28, 2025
1cd8790
combline pool and route accpetnace
SinaChavoshi May 28, 2025
44b1427
add http route validation
SinaChavoshi May 28, 2025
d15c25e
Merge branch 'main' into inf_pool_tests_12
SinaChavoshi May 28, 2025
1451a90
remove extra comments and yaml fields.
SinaChavoshi May 28, 2025
adcc104
Merge branch 'main' into inf_pool_tests_12
SinaChavoshi May 28, 2025
1535ccc
remove duplicate method
SinaChavoshi May 28, 2025
ff25051
fix timeout
SinaChavoshi May 28, 2025
cf587a6
remove modifiedTimeoutConfig.HTTPRouteMustHaveCondition per review co…
SinaChavoshi May 28, 2025
afc8bc3
remove excessive logging from conformance.go
SinaChavoshi May 28, 2025
8588183
Update conformance/tests/basic/httproute_multiple_gateways_different_…
SinaChavoshi May 28, 2025
8b6a873
Update conformance/tests/basic/httproute_multiple_gateways_different_…
SinaChavoshi May 28, 2025
efe3990
Update conformance/tests/basic/httproute_multiple_gateways_different_…
SinaChavoshi May 28, 2025
b63459d
Update conformance/tests/basic/httproute_multiple_gateways_different_…
SinaChavoshi May 28, 2025
b903d8f
Update conformance/tests/basic/httproute_multiple_gateways_different_…
SinaChavoshi May 28, 2025
2d52812
Remove unecessary logs for accpeted reason.
SinaChavoshi May 28, 2025
939ae57
Remove all comments from yaml and go files and fix yaml
SinaChavoshi May 29, 2025
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
16 changes: 10 additions & 6 deletions conformance/conformance.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ import (
"sigs.k8s.io/yaml"

// Import necessary types and utilities from the core Gateway API conformance suite.
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" // Import core Gateway API types
confapis "sigs.k8s.io/gateway-api/conformance/apis/v1" // Report struct definition
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
confapis "sigs.k8s.io/gateway-api/conformance/apis/v1"
confconfig "sigs.k8s.io/gateway-api/conformance/utils/config"
confflags "sigs.k8s.io/gateway-api/conformance/utils/flags"
apikubernetes "sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
Expand All @@ -68,8 +68,9 @@ import (

// Constants for the shared Gateway
const (
SharedGatewayName = "conformance-gateway" // Name of the Gateway in manifests.yaml
SharedGatewayNamespace = "gateway-conformance-infra" // Namespace of the Gateway
PrimaryGatewayName = "conformance-gateway"
SharedGatewayNamespace = "gateway-conformance-infra"
SecondaryGatewayName = "conformance-secondary-gateway"
)

// GatewayLayerProfileName defines the name for the conformance profile that tests
Expand Down Expand Up @@ -221,10 +222,13 @@ func RunConformanceWithOptions(t *testing.T, opts confsuite.ConformanceOptions)

cSuite.Setup(t, tests.ConformanceTests)

sharedGwNN := types.NamespacedName{Name: SharedGatewayName, Namespace: SharedGatewayNamespace}
sharedGwNN := types.NamespacedName{Name: PrimaryGatewayName, Namespace: SharedGatewayNamespace}
secondaryGwNN := types.NamespacedName{Name: SecondaryGatewayName, Namespace: SharedGatewayNamespace}

// Validate Gateway setup.
// Validate Gateway setup for both Gateways.
ensureGatewayAvailableAndReady(t, cSuite.Client, opts, sharedGwNN)
ensureGatewayAvailableAndReady(t, cSuite.Client, opts, secondaryGwNN)

t.Log("Running Inference Extension conformance tests against all registered tests")
err = cSuite.Run(t, tests.ConformanceTests)
require.NoError(t, err, "error running conformance tests")
Expand Down
134 changes: 134 additions & 0 deletions conformance/tests/basic/httproute_multiple_gateways_different_pools.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
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 (
"net/http"
"testing"

"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-inference-extension/conformance/tests"
k8utils "sigs.k8s.io/gateway-api-inference-extension/conformance/utils/kubernetes"
trafficutils "sigs.k8s.io/gateway-api-inference-extension/conformance/utils/traffic"
)

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 and routes traffic accordingly.",
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"
primaryGatewayName = "conformance-gateway"
secondaryGatewayName = "conformance-secondary-gateway"
routeForPrimaryGWName = "route-for-primary-gateway"
routeForSecondaryGWName = "route-for-secondary-gateway"
primaryPoolName = "primary-pool"
secondaryPoolName = "secondary-pool"
primaryBackendDeploymentName = "multi-gw-primary-backend-deployment"
secondaryBackendDeploymentName = "multi-gw-secondary-backend-deployment"
primaryRouteHostname = "primary.example.com"
primaryRoutePath = "/test-primary-gateway"
secondaryRouteHostname = "secondary.example.com"
secondaryRoutePath = "/test-secondary-gateway"
)

routeForPrimaryGWNN := types.NamespacedName{Name: routeForPrimaryGWName, Namespace: appBackendNamespace}
routeForSecondaryGWNN := types.NamespacedName{Name: routeForSecondaryGWName, Namespace: appBackendNamespace}
primaryPoolNN := types.NamespacedName{Name: primaryPoolName, Namespace: appBackendNamespace}
secondaryPoolNN := types.NamespacedName{Name: secondaryPoolName, Namespace: appBackendNamespace}
primaryGatewayNN := types.NamespacedName{Name: primaryGatewayName, Namespace: infraNamespace}
secondaryGatewayNN := types.NamespacedName{Name: secondaryGatewayName, Namespace: infraNamespace}

t.Run("Primary HTTPRoute, InferencePool, and Gateway path: verify status and traffic", func(t *testing.T) {
k8utils.HTTPRouteAndInferencePoolMustBeAcceptedAndRouteAccepted(
t,
s.Client,
routeForPrimaryGWNN,
primaryGatewayNN,
primaryPoolNN,
)
t.Logf("Primary path: HTTPRoute %s -> Gateway %s -> InferencePool %s status verified.",
routeForPrimaryGWNN.String(), primaryGatewayNN.String(), primaryPoolNN.String())
t.Logf("Fetching Gateway Endpoint for Primary Gateway...")
primaryGwAddr := k8utils.GetGatewayEndpoint(t, s.Client, s.TimeoutConfig, primaryGatewayNN)

t.Logf("Testing traffic to Primary Gateway: %s, expecting pod to start with: %s",
primaryGwAddr, primaryBackendDeploymentName)

primaryExpectedResponse := trafficutils.BuildExpectedHTTPResponse(
primaryRouteHostname,
primaryRoutePath,
http.StatusOK,
primaryBackendDeploymentName,
appBackendNamespace,
)

gwhttp.MakeRequestAndExpectEventuallyConsistentResponse(
t,
s.RoundTripper,
s.TimeoutConfig,
primaryGwAddr,
primaryExpectedResponse,
)
t.Logf("Successfully routed traffic via Primary Gateway, response from pod starting with %s", primaryBackendDeploymentName)
})

t.Run("Secondary HTTPRoute, InferencePool, and Gateway path: verify status and traffic", func(t *testing.T) {
k8utils.HTTPRouteAndInferencePoolMustBeAcceptedAndRouteAccepted(
t,
s.Client,
routeForSecondaryGWNN,
secondaryGatewayNN,
secondaryPoolNN,
)
t.Logf("Secondary path: HTTPRoute %s -> Gateway %s -> InferencePool %s status verified.",
routeForSecondaryGWNN.String(), secondaryGatewayNN.String(), secondaryPoolNN.String())

t.Logf("Fetching Gateway Endpoint for Secondary Gateway...")
secondaryGwAddr := k8utils.GetGatewayEndpoint(t, s.Client, s.TimeoutConfig, secondaryGatewayNN)

t.Logf("Testing traffic to Secondary Gateway: %s, expecting pod to start with: %s",
secondaryGwAddr, secondaryBackendDeploymentName)

secondaryExpectedResponse := trafficutils.BuildExpectedHTTPResponse(
secondaryRouteHostname,
secondaryRoutePath,
http.StatusOK,
secondaryBackendDeploymentName,
appBackendNamespace,
)

gwhttp.MakeRequestAndExpectEventuallyConsistentResponse(
t,
s.RoundTripper,
s.TimeoutConfig,
secondaryGwAddr,
secondaryExpectedResponse,
)
t.Logf("Successfully routed traffic via Secondary Gateway, response from pod starting with %s", secondaryBackendDeploymentName)
})
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: multi-gw-primary-backend-deployment
namespace: gateway-conformance-app-backend
labels:
app: multi-gw-primary-backend
spec:
selector:
matchLabels:
app: multi-gw-primary-backend
template:
metadata:
labels:
app: multi-gw-primary-backend
spec:
containers:
- name: echoserver-primary
image: gcr.io/k8s-staging-gateway-api/echo-basic:v20240412-v1.0.0-394-g40c666fd
ports:
- containerPort: 3000
readinessProbe:
httpGet:
path: /
port: 3000
initialDelaySeconds: 3
periodSeconds: 5
failureThreshold: 2
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
---
apiVersion: v1
kind: Service
metadata:
name: primary-pool-epp
namespace: gateway-conformance-app-backend
spec:
selector:
app: multi-gw-primary-backend
ports:
- name: http
port: 3000
targetPort: 3000
- name: epp
port: 9002
targetPort: 9002
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: multi-gw-secondary-backend-deployment
namespace: gateway-conformance-app-backend
labels:
app: multi-gw-secondary-backend
spec:
selector:
matchLabels:
app: multi-gw-secondary-backend
template:
metadata:
labels:
app: multi-gw-secondary-backend
spec:
containers:
- name: echoserver-secondary
image: gcr.io/k8s-staging-gateway-api/echo-basic:v20240412-v1.0.0-394-g40c666fd
ports:
- containerPort: 3000
readinessProbe:
httpGet:
path: /
port: 3000
initialDelaySeconds: 3
periodSeconds: 5
failureThreshold: 2
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
---
apiVersion: v1
kind: Service
metadata:
name: secondary-pool-epp
namespace: gateway-conformance-app-backend
spec:
selector:
app: multi-gw-secondary-backend
ports:
- name: http
port: 3000
targetPort: 3000
- name: epp
port: 9002
targetPort: 9002
---
apiVersion: inference.networking.x-k8s.io/v1alpha2
kind: InferencePool
metadata:
name: primary-pool
namespace: gateway-conformance-app-backend
spec:
selector:
app: "multi-gw-primary-backend"
targetPortNumber: 3000
extensionRef:
name: primary-pool-epp
---
apiVersion: inference.networking.x-k8s.io/v1alpha2
kind: InferencePool
metadata:
name: secondary-pool
namespace: gateway-conformance-app-backend
spec:
selector:
app: "multi-gw-secondary-backend"
targetPortNumber: 3000
extensionRef:
name: secondary-pool-epp
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: route-for-primary-gateway
namespace: gateway-conformance-app-backend
spec:
parentRefs:
- kind: Gateway
name: conformance-gateway
namespace: gateway-conformance-infra
sectionName: http
hostnames:
- "primary.example.com"
rules:
- backendRefs:
- group: inference.networking.x-k8s.io
kind: InferencePool
name: primary-pool
port: 3000
matches:
- path:
value: /test-primary-gateway
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: route-for-secondary-gateway
namespace: gateway-conformance-app-backend
spec:
parentRefs:
- 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: secondary-pool
port: 3000
matches:
- path:
value: /test-secondary-gateway
10 changes: 7 additions & 3 deletions conformance/utils/config/timing.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,22 @@ type InferenceExtensionTimeoutConfig struct {
// GatewayObjectPollInterval is the polling interval used when waiting for a Gateway object to appear.
GatewayObjectPollInterval time.Duration

// HTTPRouteConditionTimeout represents the maximum time to wait for an HTTPRoute to have a specific condition.
HTTPRouteDeletionReconciliationTimeout time.Duration

// HTTPRouteDeletionReconciliationTimeout is the time to wait for controllers to reconcile
// state after an HTTPRoute is deleted, before checking dependent resources or traffic.
HTTPRouteDeletionReconciliationTimeout time.Duration
HTTPRouteConditionTimeout time.Duration
}

// DefaultInferenceExtensionTimeoutConfig returns a new InferenceExtensionTimeoutConfig with default values.
func DefaultInferenceExtensionTimeoutConfig() InferenceExtensionTimeoutConfig {

return InferenceExtensionTimeoutConfig{
TimeoutConfig: gatewayconfig.DefaultTimeoutConfig(), // Initialize embedded struct
TimeoutConfig: gatewayconfig.DefaultTimeoutConfig(),
InferencePoolMustHaveConditionTimeout: 300 * time.Second,
InferencePoolMustHaveConditionInterval: 10 * time.Second,
GatewayObjectPollInterval: 5 * time.Second,
HTTPRouteDeletionReconciliationTimeout: 5 * time.Second,
HTTPRouteConditionTimeout: 300 * time.Second,
}
}
Loading