Skip to content

test: add E2E tests for payload processor with Kind cluster CI - #31

Merged
nirrozenbaum merged 1 commit into
llm-d:mainfrom
asaadbalum:feat/issue-14-add-e2e-tests
Jul 9, 2026
Merged

test: add E2E tests for payload processor with Kind cluster CI#31
nirrozenbaum merged 1 commit into
llm-d:mainfrom
asaadbalum:feat/issue-14-add-e2e-tests

Conversation

@asaadbalum

@asaadbalum asaadbalum commented May 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Add end-to-end tests that deploy a complete Envoy + Payload Processor + model-server-simulator stack on a Kind cluster and validate core functionality through the actual ext_proc gRPC pipeline.

  • Base model routing: Verifies that model field extraction from /v1/chat/completions and /v1/completions bodies routes Llama and DeepSeek requests to the correct pools via X-Gateway-Base-Model-Name header.
  • LoRA adapter routing: Verifies that adapter names are resolved to base models through ConfigMap reconciliation and routed to the correct pool.
  • Streaming: Verifies that streaming requests ("stream": true) return SSE text/event-stream chunks through the full Envoy → Payload Processor → model-server pipeline.
  • Metrics: Verifies that ipp_info and ipp_success_total Prometheus metrics are populated after traffic flows.
  • CI integration: E2E job added to ci-pr-checks.yaml — delegates all orchestration to make test-e2e / hack/test-e2e.sh.

Manifest structure

Kubernetes manifests live under deploy/ following the llm-d-router pattern: shared components (deploy/components/) and environment-specific infrastructure (deploy/environments/dev/e2e-infra/). Test code references these manifests via relative paths with ${VAR} substitution, enabling reuse for both E2E tests and local Kind development.

The E2E Envoy configuration mirrors production:

  • Envoy distroless-v1.33.2 with request_body_mode: FULL_DUPLEX_STREAMED
  • allow_mode_override: true, failure_mode_allow: false
  • request_trailer_mode: SEND, response_trailer_mode: SKIP

Model server simulators use fake model names (ipp-test-llama, ipp-test-deepseek) with --mode=echo, matching the llm-d-router's standard E2E pattern. The sim image is pinned to v0.9.0 for reproducibility.

New files

File Purpose
deploy/components/ipp/deployment.yaml IPP Deployment (imagePullPolicy: IfNotPresent)
deploy/components/ipp/service.yaml IPP Service (NodePort 30090 for metrics)
deploy/components/ipp/rbac.yaml ServiceAccount + ClusterRole + ClusterRoleBinding
deploy/components/model-server/llama/deployment.yaml Llama simulator + Service + adapter ConfigMap
deploy/components/model-server/deepseek/deployment.yaml DeepSeek simulator + Service + adapter ConfigMap
deploy/environments/dev/e2e-infra/envoy.yaml Envoy proxy with ext_proc filter config (NodePort 30080)
test/e2e/e2e_suite_test.go Ginkgo BeforeSuite/AfterSuite — deploys stack, waits for readiness
test/e2e/e2e_test.go 7 test cases covering all scenarios above
test/e2e/README.md Developer quickstart guide
test/e2e/TROUBLESHOOTING.md Troubleshooting guide (Kind multi-cluster, image issues)
hack/test-e2e.sh Orchestration script (Kind + image build + test + auto-cleanup)

Modified files

File Change
.github/workflows/ci-pr-checks.yaml Added e2e job (calls make test-e2e)
Makefile Added test-e2e, image-build-local, image-kind targets + E2E config vars
go.mod / go.sum Added github.com/onsi/ginkgo/v2, github.com/onsi/gomega, github.com/openai/openai-go + transitive deps

What's NOT included

  • No changes to core IPP logic (pkg/, internal/, cmd/)
  • No changes to existing tests or CI jobs
  • No Helm chart modifications
  • No production deployment manifests (these are test-only)

Test plan

  • All 7 E2E tests pass on Kind (7 Passed | 0 Failed)
  • All unit tests pass with race detector
  • golangci-lint 0 issues (standard + E2E build tags)
  • CI workflow YAML validated (syntax + job dependency graph)

@github-actions

github-actions Bot commented May 4, 2026

Copy link
Copy Markdown

Unsigned commits detected! Please sign your commits.

For instructions on how to set up GPG/SSH signing and verify your commits, please see GitHub Documentation.

@asaadbalum
asaadbalum force-pushed the feat/issue-14-add-e2e-tests branch 3 times, most recently from 9da84d3 to 1b2b395 Compare May 4, 2026 11:54

@aradhalevy aradhalevy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good, some minor comments (and we will need the new added check to run and pass first)

Comment thread test/testdata/e2e-deployment.yaml Outdated
name: llama-adapters
namespace: $E2E_NS
labels:
inference.llm-d.io/ipp-managed: "true"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I believe it supposed to be llm-d.ai instead of llm-d.io as per #28.

After this fix the test pass for me locally

Comment thread test/testdata/e2e-deployment.yaml Outdated
name: deepseek-adapters
namespace: $E2E_NS
labels:
inference.llm-d.io/ipp-managed: "true"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

same llm-d.ai instead of llm-d.io

Comment thread test/e2e/README.md
| Streaming routing | SSE chunks returned |
| Metrics | `bbr_info`, `bbr_success_total` |

## Troubleshooting

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

When I had a couple of other clusters set up in kind, Envoy tried to route requests to them. Please add a suggestion / troubleshooting to use kind delete clusters --all first to clean your kind environment first.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added

Comment thread deploy/components/ipp/deployment.yaml Outdated
containers:
- name: payload-processor
image: $E2E_IMAGE
imagePullPolicy: Never

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should be IfNotPresent if we want to test on a different cluster other than kind. But that requires pushing an image to ghcr.io and might require some more changes, and can be dealt with in another issue / PR if you prefer to keep this PR for kind only

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Keeping it for now, will address it in a follow-up pr

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please fix it now

Comment thread .github/workflows/ci-e2e.yaml Outdated

- name: Run E2E tests
run: |
E2E_IMAGE=ghcr.io/llm-d/llm-d-inference-payload-processor:e2e \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You don't use the Makefile / script here, I think it would be better to use them to have a single source of truth.

@asaadbalum
asaadbalum force-pushed the feat/issue-14-add-e2e-tests branch from 1b2b395 to 9de9955 Compare May 6, 2026 07:57
@github-actions github-actions Bot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. labels May 6, 2026
@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown

⚠️ Large PR detected

Your PR is large. Please consider breaking it into multiple PRs.

The do-not-merge/hold label has been added and can be removed by the reviewers based on their judgement.

@aradhalevy aradhalevy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM.
I think this is fine even tough it is a large PR as all the code is needed and relevant to this minimal e2e test suite.

Comment thread test/e2e/e2e_suite_test.go Outdated

var (
testConfig *testutils.TestConfig
ppImage string

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: it would be better to align the name on ipp rather than pp (that was the agreed acronym).

Comment thread test/e2e/README.md Outdated
| Base model routing | Pool routing via header |
| LoRA adapter routing | ConfigMap adapter lookup |
| Streaming routing | SSE chunks returned |
| Metrics | `bbr_info`, `bbr_success_total` |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

as a follow up, we should update all metrics to be named ipp instead of bbr.

not a blocker

Comment thread test/e2e/README.md
| Streaming routing | SSE chunks returned |
| Metrics | `bbr_info`, `bbr_success_total` |

## Troubleshooting

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this should probably go to a separate troubleshot guide.
quickstart guide should be quick, and simple :)
in other words, the simplest explanation of the green path.

Comment thread test/testdata/e2e-deployment.yaml Outdated
@@ -0,0 +1,164 @@
# Llama model server simulator
apiVersion: apps/v1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

can you explain the separation between e2e-deployment and deepseek-model-server?
I see deepseek has deployment + svc.
here I see deployment + svc for a llama plus adapter of deepseek + llama + many other CRs.
not sure I understand the separation.

Comment thread .github/workflows/ci-e2e.yaml Outdated
- '!**/*.md'
- '!LICENSE'
- '!OWNERS'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

can you move this logic to the file "ci-pr-checks.yaml" (and on the way to clean from it the lint python and build at the end)?

@asaadbalum
asaadbalum force-pushed the feat/issue-14-add-e2e-tests branch from 9de9955 to 3c561d1 Compare May 11, 2026 07:13
@github-actions

Copy link
Copy Markdown

⚠️ Large PR detected

Your PR is large. Please consider breaking it into multiple PRs.

The do-not-merge/hold label has been added and can be removed by the reviewers based on their judgement.

@asaadbalum
asaadbalum requested a review from nirrozenbaum May 11, 2026 07:17
@nirrozenbaum

Copy link
Copy Markdown
Collaborator

@shmuelk can you please review this PR when you have time?
would be good to validate the tests structure is aligned with scheduler.

@shmuelk

shmuelk commented May 13, 2026

Copy link
Copy Markdown
Collaborator

@nirrozenbaum I took a very quick look at this PR.

I don't like it's structure. This E2E test looks a lot more like the old IGW E2E test and not like the scheduler's E2E test.

@roytman restructured the End to End test and the development environment on Kind to use the same K8S YAML and config YAML files where possible. Following that idea here will make it easier to put together a development environment on Kind.

@nirrozenbaum

Copy link
Copy Markdown
Collaborator

@nirrozenbaum I took a very quick look at this PR.

I don't like it's structure. This E2E test looks a lot more like the old IGW E2E test and not like the scheduler's E2E test.

@roytman restructured the End to End test and the development environment on Kind to use the same K8S YAML and config YAML files where possible. Following that idea here will make it easier to put together a development environment on Kind.

@asaadbalum can you please take a look on @shmuelk's feedback and work towards setting the e2e to work like they do in llm-d scheduler? (or the new name llm-d router).

@asaadbalum
asaadbalum force-pushed the feat/issue-14-add-e2e-tests branch from 3c561d1 to 2a0668c Compare May 17, 2026 07:12
@github-actions

Copy link
Copy Markdown

⚠️ Large PR detected

Your PR is large. Please consider breaking it into multiple PRs.

The do-not-merge/hold label has been added and can be removed by the reviewers based on their judgement.

@nirrozenbaum

Copy link
Copy Markdown
Collaborator

cc for another pair of eyes: @noyitz

Comment thread test/e2e/e2e_suite_test.go Outdated
Comment thread deploy/components/model-server/llama/deployment.yaml Outdated
@asaadbalum
asaadbalum force-pushed the feat/issue-14-add-e2e-tests branch from 2a0668c to 1732c7b Compare May 31, 2026 12:59
@github-actions

Copy link
Copy Markdown

⚠️ Large PR detected

Your PR is large. Please consider breaking it into multiple PRs.

The do-not-merge/hold label has been added and can be removed by the reviewers based on their judgement.

@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown

⚠️ Large PR detected

Your PR is large. Please consider breaking it into multiple PRs.

The do-not-merge/hold label has been added and can be removed by the reviewers based on their judgement.

@asaadbalum
asaadbalum force-pushed the feat/issue-14-add-e2e-tests branch from 7fbc4bd to 6942517 Compare June 1, 2026 08:38
@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown

⚠️ Large PR detected

Your PR is large. Please consider breaking it into multiple PRs.

The do-not-merge/hold label has been added and can be removed by the reviewers based on their judgement.

@asaadbalum
asaadbalum requested a review from shmuelk June 2, 2026 10:57
@github-actions

Copy link
Copy Markdown

This PR is marked as stale after 21d of inactivity. After an additional 14d of inactivity (7d to become rotten, then 7d more), it will be closed. To prevent this PR from being closed, add a comment or remove the lifecycle/stale label.

@asaadbalum

Copy link
Copy Markdown
Contributor Author

@shmuelk Ready for review again, alll of the previous comments addressed and pr rebased.

@nirrozenbaum nirrozenbaum removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jul 8, 2026
Comment thread test/e2e/e2e_suite_test.go Outdated
Comment thread hack/test-e2e.sh Outdated
- role: control-plane
extraPortMappings:
- containerPort: 30080
hostPort: 30080

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This port here is hard coded. The environment variable E2E_PORT is useless.

Change this to use E2E_PORT when creating the cluster

Comment thread hack/test-e2e.sh Outdated
hostPort: 30080
protocol: TCP
- containerPort: 30090
hostPort: 30090

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This port is also hard coded. The environment variable E2E_METRICS_PORT is useless.

Change this to use E2E_METRICS_PORT when creating the cluster

Comment thread test/e2e/e2e_suite_test.go Outdated
Comment thread test/e2e/README.md Outdated
## Architecture

```text
Go test (OpenAI SDK) ──► Envoy NodePort:30080 (ext_proc) ──► Payload Processor

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The port numbers are the default values...

@shmuelk shmuelk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks much better. I left a few comments

@asaadbalum
asaadbalum force-pushed the feat/issue-14-add-e2e-tests branch from 573a25e to 0975629 Compare July 8, 2026 14:05
@asaadbalum

Copy link
Copy Markdown
Contributor Author

Looks much better. I left a few comments

Addressed

Comment thread hack/test-e2e.sh Outdated
nodes:
- role: control-plane
extraPortMappings:
- containerPort: ${E2E_PORT}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

As you didn't change Envoy's Service definition, this line shouldn't have been changed.

Suggested change
- containerPort: ${E2E_PORT}
- containerPort: 30080

Comment thread hack/test-e2e.sh Outdated
- containerPort: ${E2E_PORT}
hostPort: ${E2E_PORT}
protocol: TCP
- containerPort: ${E2E_METRICS_PORT}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

As you didn't change the IPPs Service definition this line shouldn't have been changed.

Suggested change
- containerPort: ${E2E_METRICS_PORT}
- containerPort: 30090

@shmuelk

shmuelk commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Getting close. I left two more comments. Please run the end to end test locally, with E2E_PORT=31080 and E2E_METRICS_PORT=31090 (i.e. non-default values)

Adds end-to-end tests that deploy a complete stack on a Kind cluster:
Envoy proxy (distroless-v1.33.2, FULL_DUPLEX_STREAMED ext_proc),
Payload Processor, Llama and DeepSeek model-server simulators, and
adapter ConfigMaps.
Kubernetes manifests live under deploy/ following the llm-d-router
pattern: shared components (deploy/components/) and environment-specific
infrastructure (deploy/environments/dev/e2e-infra/). Test code references
these manifests via relative paths with ${VAR} substitution.
Tests use the OpenAI Go SDK to send requests via Kind NodePort, with
net/http for adapter routing and streaming where raw headers are needed.
CI delegates all orchestration to hack/test-e2e.sh via make test-e2e.
Tests cover base-model routing, LoRA adapter resolution, streaming
requests, and ipp_* metrics exposure.
Signed-off-by: Asaad Balum <asaad.balum@gmail.com>
@asaadbalum
asaadbalum force-pushed the feat/issue-14-add-e2e-tests branch from 0975629 to d507609 Compare July 9, 2026 12:19
@asaadbalum

Copy link
Copy Markdown
Contributor Author

Getting close. I left two more comments. Please run the end to end test locally, with E2E_PORT=31080 and E2E_METRICS_PORT=31090 (i.e. non-default values)

Done

@shmuelk

shmuelk commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

/lgtm
/approve

@github-actions github-actions Bot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jul 9, 2026
@nirrozenbaum
nirrozenbaum merged commit 9378530 into llm-d:main Jul 9, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm "Looks good to me", indicates that a PR is ready to be merged. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants