Skip to content

Commit 5f5a079

Browse files
authored
feat(e2e): enhance setup-only mode and add startup banner (#673)
1 parent ec33170 commit 5f5a079

File tree

6 files changed

+148
-36
lines changed

6 files changed

+148
-36
lines changed

e2e/README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,13 @@ The following environment variables can be used to customize test execution:
189189
| `E2E_VERBOSE` | Enable verbose logging | `true` | `make e2e-test E2E_VERBOSE=false` |
190190
| `E2E_PARALLEL` | Run tests in parallel | `false` | `make e2e-test E2E_PARALLEL=true` |
191191
| `E2E_TESTS` | Specific test cases to run | (all tests) | `make e2e-test-specific E2E_TESTS="test1,test2"` |
192-
| `E2E_SETUP_ONLY` | Only setup profile without running tests | `false` | `make e2e-test E2E_SETUP_ONLY=true` |
192+
| `E2E_SETUP_ONLY` | Only setup profile without running tests (automatically keeps cluster) | `false` | `make e2e-test E2E_SETUP_ONLY=true` |
193193
| `E2E_SKIP_SETUP` | Skip setup and only run tests | `false` | `make e2e-test E2E_SKIP_SETUP=true` |
194194

195-
**Note**: When using the binary directly (`./bin/e2e`), use command-line flags instead:
195+
**Note**:
196+
197+
- When `E2E_SETUP_ONLY=true` is set, the cluster is automatically kept (no need to set `E2E_KEEP_CLUSTER=true`)
198+
- When using the binary directly (`./bin/e2e`), use command-line flags instead:
196199

197200
- `-profile` instead of `E2E_PROFILE`
198201
- `-cluster` instead of `E2E_CLUSTER_NAME`

e2e/cmd/e2e/main.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ import (
77
"os"
88
"strings"
99

10+
"github.com/vllm-project/semantic-router/e2e/pkg/banner"
1011
"github.com/vllm-project/semantic-router/e2e/pkg/framework"
1112
aigateway "github.com/vllm-project/semantic-router/e2e/profiles/ai-gateway"
1213

1314
// Import profiles to register test cases
1415
_ "github.com/vllm-project/semantic-router/e2e/profiles/ai-gateway"
1516
)
1617

18+
const version = "v1.0.0"
19+
1720
func main() {
1821
// Parse command line flags
1922
var (
@@ -31,12 +34,24 @@ func main() {
3134

3235
flag.Parse()
3336

37+
// Show banner
38+
if isInteractive() {
39+
banner.Show(version)
40+
} else {
41+
banner.ShowQuick(version)
42+
}
43+
3444
// Validate flags
3545
if *setupOnly && *skipSetup {
3646
fmt.Fprintf(os.Stderr, "Error: --setup-only and --skip-setup cannot be used together\n")
3747
os.Exit(1)
3848
}
3949

50+
// Setup-only mode always keeps the cluster
51+
if *setupOnly {
52+
*keepCluster = true
53+
}
54+
4055
// Parse test cases
4156
var testCasesList []string
4257
if *testCases != "" {
@@ -88,3 +103,17 @@ func getProfile(name string) (framework.Profile, error) {
88103
return nil, fmt.Errorf("unknown profile: %s", name)
89104
}
90105
}
106+
107+
// isInteractive checks if the program is running in an interactive terminal
108+
func isInteractive() bool {
109+
// Check if CI environment variable is set
110+
if os.Getenv("CI") != "" {
111+
return false
112+
}
113+
// Check if stdout is a terminal
114+
fileInfo, err := os.Stdout.Stat()
115+
if err != nil {
116+
return false
117+
}
118+
return (fileInfo.Mode() & os.ModeCharDevice) != 0
119+
}

e2e/pkg/banner/banner.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package banner
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
"time"
7+
)
8+
9+
// Color codes
10+
const (
11+
Reset = "\033[0m"
12+
Cyan = "\033[36m"
13+
Purple = "\033[35m"
14+
Green = "\033[32m"
15+
Yellow = "\033[33m"
16+
Bold = "\033[1m"
17+
)
18+
19+
// ASCII art for vLLM Semantic Router
20+
var logo = []string{
21+
" ██╗ ██╗██╗ ██╗ ███╗ ███╗",
22+
" ██║ ██║██║ ██║ ████╗ ████║",
23+
" ██║ ██║██║ ██║ ██╔████╔██║",
24+
" ╚██╗ ██╔╝██║ ██║ ██║╚██╔╝██║",
25+
" ╚████╔╝ ███████╗███████╗██║ ╚═╝ ██║",
26+
" ╚═══╝ ╚══════╝╚══════╝╚═╝ ╚═╝",
27+
"",
28+
" ███████╗███████╗███╗ ███╗ █████╗ ███╗ ██╗████████╗██╗ ██████╗",
29+
" ██╔════╝██╔════╝████╗ ████║██╔══██╗████╗ ██║╚══██╔══╝██║██╔════╝",
30+
" ███████╗█████╗ ██╔████╔██║███████║██╔██╗ ██║ ██║ ██║██║ ",
31+
" ╚════██║██╔══╝ ██║╚██╔╝██║██╔══██║██║╚██╗██║ ██║ ██║██║ ",
32+
" ███████║███████╗██║ ╚═╝ ██║██║ ██║██║ ╚████║ ██║ ██║╚██████╗",
33+
" ╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝",
34+
"",
35+
" ██████╗ ██████╗ ██╗ ██╗████████╗███████╗██████╗",
36+
" ██╔══██╗██╔═══██╗██║ ██║╚══██╔══╝██╔════╝██╔══██╗",
37+
" ██████╔╝██║ ██║██║ ██║ ██║ █████╗ ██████╔╝",
38+
" ██╔══██╗██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗",
39+
" ██║ ██║╚██████╔╝╚██████╔╝ ██║ ███████╗██║ ██║",
40+
" ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝",
41+
}
42+
43+
// Show displays the animated banner
44+
func Show(version string) {
45+
fmt.Println()
46+
fmt.Println()
47+
48+
// Animate logo line by line
49+
for _, line := range logo {
50+
fmt.Printf("%s%s%s%s\n", Bold, Cyan, line, Reset)
51+
time.Sleep(30 * time.Millisecond)
52+
}
53+
54+
fmt.Println()
55+
56+
// Show version and info with animation
57+
info := []string{
58+
fmt.Sprintf("%s%s E2E Testing Framework%s", Bold, Purple, Reset),
59+
fmt.Sprintf("%s Version: %s%s", Yellow, version, Reset),
60+
"",
61+
}
62+
63+
for _, line := range info {
64+
fmt.Println(line)
65+
time.Sleep(50 * time.Millisecond)
66+
}
67+
68+
// Loading animation
69+
loadingChars := []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}
70+
fmt.Print(Green + " Initializing" + Reset)
71+
for i := 0; i < 15; i++ {
72+
fmt.Printf("\r%s Initializing %s%s", Green, loadingChars[i%len(loadingChars)], Reset)
73+
time.Sleep(80 * time.Millisecond)
74+
}
75+
fmt.Printf("\r%s Initializing ✓%s\n", Green, Reset)
76+
77+
fmt.Println()
78+
fmt.Println(strings.Repeat("═", 80))
79+
fmt.Println()
80+
}
81+
82+
// ShowQuick displays a quick version without animation (for CI/non-interactive)
83+
func ShowQuick(version string) {
84+
fmt.Println()
85+
fmt.Println()
86+
87+
for _, line := range logo {
88+
fmt.Printf("%s%s%s%s\n", Bold, Cyan, line, Reset)
89+
}
90+
91+
fmt.Println()
92+
fmt.Printf("%s%s E2E Testing Framework%s\n", Bold, Purple, Reset)
93+
fmt.Printf("%s Version: %s%s\n", Yellow, version, Reset)
94+
fmt.Println()
95+
fmt.Println(strings.Repeat("═", 80))
96+
fmt.Println()
97+
}

e2e/pkg/framework/runner.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,18 @@ func (r *Runner) Run(ctx context.Context) error {
129129
return fmt.Errorf("failed to setup profile: %w", err)
130130
}
131131

132-
defer func() {
133-
teardownOpts := &TeardownOptions{
134-
KubeClient: kubeClient,
135-
KubeConfig: kubeConfig,
136-
ClusterName: r.opts.ClusterName,
137-
Verbose: r.opts.Verbose,
138-
}
139-
r.profile.Teardown(context.Background(), teardownOpts)
140-
}()
132+
// Only register teardown if not in setup-only mode
133+
if !r.opts.SetupOnly {
134+
defer func() {
135+
teardownOpts := &TeardownOptions{
136+
KubeClient: kubeClient,
137+
KubeConfig: kubeConfig,
138+
ClusterName: r.opts.ClusterName,
139+
Verbose: r.opts.Verbose,
140+
}
141+
r.profile.Teardown(context.Background(), teardownOpts)
142+
}()
143+
}
141144
} else {
142145
r.log("⏭️ Skipping profile setup (--skip-setup enabled)")
143146
}

e2e/testcases/chat_completions_progressive_stress.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ type ProgressiveStageResult struct {
3434

3535
func testProgressiveStress(ctx context.Context, client *kubernetes.Clientset, opts pkgtestcases.TestCaseOptions) error {
3636
if opts.Verbose {
37-
fmt.Println("[Test] Starting progressive stress test: 10/20 concurrent requests")
37+
fmt.Println("[Test] Starting progressive stress test: 10/20/50 concurrent requests")
3838
}
3939

4040
// Setup service connection and get local port
@@ -45,7 +45,7 @@ func testProgressiveStress(ctx context.Context, client *kubernetes.Clientset, op
4545
defer stopPortForward()
4646

4747
// Define concurrent request counts for each stage
48-
concurrencyStages := []int{10, 20}
48+
concurrencyStages := []int{10, 20, 50}
4949

5050
var stageResults []ProgressiveStageResult
5151

tools/make/e2e.mk

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -53,33 +53,13 @@ e2e-test-debug: e2e-test
5353
# Setup profile only without running tests
5454
e2e-setup: ## Setup profile only without running tests
5555
e2e-setup: E2E_SETUP_ONLY=true
56-
e2e-setup: E2E_KEEP_CLUSTER=true
57-
e2e-setup: build-e2e
58-
@$(LOG_TARGET)
59-
@echo "Setting up E2E environment with profile: $(E2E_PROFILE)"
60-
@./bin/e2e \
61-
-profile=$(E2E_PROFILE) \
62-
-cluster=$(E2E_CLUSTER_NAME) \
63-
-image-tag=$(E2E_IMAGE_TAG) \
64-
-keep-cluster=true \
65-
-verbose=$(E2E_VERBOSE) \
66-
-setup-only=true
56+
e2e-setup: e2e-test
6757

6858
# Run tests only without setup (assumes environment is already deployed)
6959
e2e-test-only: ## Run tests only without setup (assumes environment is already deployed)
70-
e2e-test-only: E2E_SKIP_SETUP=true
7160
e2e-test-only: E2E_USE_EXISTING_CLUSTER=true
72-
e2e-test-only: build-e2e
73-
@$(LOG_TARGET)
74-
@echo "Running E2E tests (skip setup) with profile: $(E2E_PROFILE)"
75-
@./bin/e2e \
76-
-profile=$(E2E_PROFILE) \
77-
-cluster=$(E2E_CLUSTER_NAME) \
78-
-use-existing-cluster=true \
79-
-verbose=$(E2E_VERBOSE) \
80-
-parallel=$(E2E_PARALLEL) \
81-
-skip-setup=true \
82-
$(if $(E2E_TESTS),-tests=$(E2E_TESTS),)
61+
e2e-test-only: E2E_SKIP_SETUP=true
62+
e2e-test-only: e2e-test
8363

8464
# Run specific E2E test cases
8565
e2e-test-specific: ## Run specific E2E test cases (E2E_TESTS="test1,test2")

0 commit comments

Comments
 (0)