Skip to content

Commit 561db7d

Browse files
committed
update
Signed-off-by: bitliu <[email protected]>
1 parent c4b7e46 commit 561db7d

File tree

18 files changed

+219
-193
lines changed

18 files changed

+219
-193
lines changed

.github/workflows/integration-test-ai-gateway.yml renamed to .github/workflows/integration-test-k8s.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Integration Test [AI Gateway]
1+
name: Integration Test [Kubernetes]
22

33
on:
44
pull_request:

e2e/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/vllm-project/semantic-router/e2e
33
go 1.24
44

55
require (
6+
k8s.io/api v0.31.0
67
k8s.io/apimachinery v0.31.0
78
k8s.io/client-go v0.31.0
89
)
@@ -43,7 +44,6 @@ require (
4344
gopkg.in/inf.v0 v0.9.1 // indirect
4445
gopkg.in/yaml.v2 v2.4.0 // indirect
4546
gopkg.in/yaml.v3 v3.0.1 // indirect
46-
k8s.io/api v0.31.0 // indirect
4747
k8s.io/klog/v2 v2.130.1 // indirect
4848
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
4949
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect

e2e/pkg/framework/runner.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,11 +263,20 @@ func (r *Runner) runSingleTest(ctx context.Context, kubeClient *kubernetes.Clien
263263

264264
start := time.Now()
265265

266+
// Get service configuration from profile
267+
svcConfig := r.profile.GetServiceConfig()
268+
266269
opts := testcases.TestCaseOptions{
267270
Verbose: r.opts.Verbose,
268271
Namespace: "default",
269272
Timeout: "5m",
270273
RestConfig: r.restConfig,
274+
ServiceConfig: testcases.ServiceConfig{
275+
LabelSelector: svcConfig.LabelSelector,
276+
Namespace: svcConfig.Namespace,
277+
Name: svcConfig.Name,
278+
PortMapping: svcConfig.PortMapping,
279+
},
271280
}
272281

273282
err := tc.Fn(ctx, kubeClient, opts)

e2e/pkg/framework/types.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ type Profile interface {
2222

2323
// GetTestCases returns the list of test cases to run for this profile
2424
GetTestCases() []string
25+
26+
// GetServiceConfig returns the service configuration for accessing the deployed service
27+
GetServiceConfig() ServiceConfig
28+
}
29+
30+
// ServiceConfig contains configuration for accessing a service
31+
type ServiceConfig struct {
32+
LabelSelector string // e.g., "gateway.envoyproxy.io/owning-gateway-namespace=default,..."
33+
Namespace string
34+
Name string // optional, if empty will use LabelSelector to find service
35+
PortMapping string // e.g., "8080:80"
2536
}
2637

2738
// SetupOptions contains options for profile setup

e2e/pkg/helpers/kubernetes.go

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,12 @@ func VerifyServicePodsRunning(ctx context.Context, client *kubernetes.Clientset,
122122
// The ports parameter should be in format "localPort:servicePort" (e.g., "8080:80")
123123
// Note: Kubernetes API doesn't support port-forward directly to services, only to pods.
124124
// This function mimics kubectl's behavior by finding a pod behind the service.
125-
func StartPortForward(ctx context.Context, client *kubernetes.Clientset, restConfig *rest.Config, namespace, service, ports string, verbose bool) error {
125+
// Returns a stop function that should be called to clean up the port forwarding.
126+
func StartPortForward(ctx context.Context, client *kubernetes.Clientset, restConfig *rest.Config, namespace, service, ports string, verbose bool) (func(), error) {
126127
// Parse ports (e.g., "8080:80" -> local=8080, service=80)
127128
portParts := strings.Split(ports, ":")
128129
if len(portParts) != 2 {
129-
return fmt.Errorf("invalid port format: %s (expected format: localPort:servicePort)", ports)
130+
return nil, fmt.Errorf("invalid port format: %s (expected format: localPort:servicePort)", ports)
130131
}
131132
localPort := portParts[0]
132133
servicePort := portParts[1]
@@ -138,7 +139,7 @@ func StartPortForward(ctx context.Context, client *kubernetes.Clientset, restCon
138139
// Get the service to find its selector
139140
svc, err := client.CoreV1().Services(namespace).Get(ctx, service, metav1.GetOptions{})
140141
if err != nil {
141-
return fmt.Errorf("failed to get service: %w", err)
142+
return nil, fmt.Errorf("failed to get service: %w", err)
142143
}
143144

144145
// Build label selector from service selector
@@ -153,11 +154,11 @@ func StartPortForward(ctx context.Context, client *kubernetes.Clientset, restCon
153154
LabelSelector: labelSelector,
154155
})
155156
if err != nil {
156-
return fmt.Errorf("failed to list pods for service: %w", err)
157+
return nil, fmt.Errorf("failed to list pods for service: %w", err)
157158
}
158159

159160
if len(pods.Items) == 0 {
160-
return fmt.Errorf("no pods found for service %s/%s", namespace, service)
161+
return nil, fmt.Errorf("no pods found for service %s/%s", namespace, service)
161162
}
162163

163164
// Use the first running pod
@@ -171,7 +172,7 @@ func StartPortForward(ctx context.Context, client *kubernetes.Clientset, restCon
171172
}
172173

173174
if targetPod == nil {
174-
return fmt.Errorf("no running pods found for service %s/%s", namespace, service)
175+
return nil, fmt.Errorf("no running pods found for service %s/%s", namespace, service)
175176
}
176177

177178
if verbose {
@@ -197,7 +198,7 @@ func StartPortForward(ctx context.Context, client *kubernetes.Clientset, restCon
197198
// Create SPDY transport
198199
transport, upgrader, err := spdy.RoundTripperFor(restConfig)
199200
if err != nil {
200-
return fmt.Errorf("failed to create SPDY transport: %w", err)
201+
return nil, fmt.Errorf("failed to create SPDY transport: %w", err)
201202
}
202203

203204
// Build the URL for port forwarding to pod
@@ -224,7 +225,7 @@ func StartPortForward(ctx context.Context, client *kubernetes.Clientset, restCon
224225
// Create port forwarder (forward localPort to containerPort on the pod)
225226
forwarder, err := portforward.New(dialer, []string{fmt.Sprintf("%s:%s", localPort, containerPort)}, stopChan, readyChan, out, errOut)
226227
if err != nil {
227-
return fmt.Errorf("failed to create port forwarder: %w", err)
228+
return nil, fmt.Errorf("failed to create port forwarder: %w", err)
228229
}
229230

230231
// Start port forwarding in background
@@ -242,12 +243,19 @@ func StartPortForward(ctx context.Context, client *kubernetes.Clientset, restCon
242243
if verbose {
243244
fmt.Printf("[Helper] Port forwarding is ready\n")
244245
}
245-
return nil
246+
// Return stop function
247+
stopFunc := func() {
248+
if verbose {
249+
fmt.Printf("[Helper] Stopping port forwarding to %s/%s\n", namespace, service)
250+
}
251+
close(stopChan)
252+
}
253+
return stopFunc, nil
246254
case <-time.After(30 * time.Second):
247255
close(stopChan)
248-
return fmt.Errorf("timeout waiting for port forward to be ready")
256+
return nil, fmt.Errorf("timeout waiting for port forward to be ready")
249257
case <-ctx.Done():
250258
close(stopChan)
251-
return ctx.Err()
259+
return nil, ctx.Err()
252260
}
253261
}

e2e/pkg/testcases/registry.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,26 @@ type TestCaseOptions struct {
4040

4141
// RestConfig is the Kubernetes REST config
4242
RestConfig *rest.Config
43+
44+
// ServiceConfig contains service-specific configuration
45+
ServiceConfig ServiceConfig
46+
}
47+
48+
// ServiceConfig contains configuration for accessing a service
49+
type ServiceConfig struct {
50+
// LabelSelector is the label selector to find the service
51+
// Example: "gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=semantic-router"
52+
LabelSelector string
53+
54+
// Namespace is the namespace where the service is located
55+
Namespace string
56+
57+
// Name is the service name (optional, if not using label selector)
58+
Name string
59+
60+
// PortMapping is the port mapping for port-forwarding
61+
// Format: "localPort:servicePort" (e.g., "8080:80")
62+
PortMapping string
4363
}
4464

4565
var (

e2e/profiles/ai-gateway/basic_health_check.go

Lines changed: 0 additions & 46 deletions
This file was deleted.

e2e/profiles/ai-gateway/profile.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import (
1313
"github.com/vllm-project/semantic-router/e2e/pkg/framework"
1414
"github.com/vllm-project/semantic-router/e2e/pkg/helm"
1515
"github.com/vllm-project/semantic-router/e2e/pkg/helpers"
16+
17+
// Import testcases package to register all test cases via their init() functions
18+
_ "github.com/vllm-project/semantic-router/e2e/testcases"
1619
)
1720

1821
// Profile implements the AI Gateway test profile
@@ -104,7 +107,6 @@ func (p *Profile) Teardown(ctx context.Context, opts *framework.TeardownOptions)
104107
// GetTestCases returns the list of test cases for this profile
105108
func (p *Profile) GetTestCases() []string {
106109
return []string{
107-
"basic-health-check",
108110
"chat-completions-request",
109111
"domain-classify",
110112
"cache",
@@ -113,6 +115,15 @@ func (p *Profile) GetTestCases() []string {
113115
}
114116
}
115117

118+
// GetServiceConfig returns the service configuration for accessing the deployed service
119+
func (p *Profile) GetServiceConfig() framework.ServiceConfig {
120+
return framework.ServiceConfig{
121+
LabelSelector: "gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=semantic-router",
122+
Namespace: "envoy-gateway-system",
123+
PortMapping: "8080:80",
124+
}
125+
}
126+
116127
func (p *Profile) deploySemanticRouter(ctx context.Context, deployer *helm.Deployer, opts *framework.SetupOptions) error {
117128
// Use local Helm chart instead of remote OCI registry
118129
chartPath := "deploy/helm/semantic-router"
@@ -263,6 +274,26 @@ func (p *Profile) verifyEnvironment(ctx context.Context, opts *framework.SetupOp
263274
}
264275
}
265276

277+
// Check all deployments are healthy
278+
p.log("Verifying all deployments are healthy...")
279+
280+
// Check semantic-router deployment
281+
if err := helpers.CheckDeployment(ctx, client, "vllm-semantic-router-system", "semantic-router", p.verbose); err != nil {
282+
return fmt.Errorf("semantic-router deployment not healthy: %w", err)
283+
}
284+
285+
// Check envoy-gateway deployment
286+
if err := helpers.CheckDeployment(ctx, client, "envoy-gateway-system", "envoy-gateway", p.verbose); err != nil {
287+
return fmt.Errorf("envoy-gateway deployment not healthy: %w", err)
288+
}
289+
290+
// Check ai-gateway-controller deployment
291+
if err := helpers.CheckDeployment(ctx, client, "envoy-ai-gateway-system", "ai-gateway-controller", p.verbose); err != nil {
292+
return fmt.Errorf("ai-gateway-controller deployment not healthy: %w", err)
293+
}
294+
295+
p.log("All deployments are healthy")
296+
266297
return nil
267298
}
268299

0 commit comments

Comments
 (0)