Skip to content

Add agentgateway to CI & rename dataplane flag - #1598

Merged
Lior Lieberman (LiorLieberman) merged 8 commits into
agent-substrate:mainfrom
keithmattix:add-agentgateway-e2es-to-ci
Sep 15, 2026
Merged

Lior Lieberman (LiorLieberman) merged 8 commits into
agent-substrate:mainfrom
keithmattix:add-agentgateway-e2es-to-ci

Conversation

@keithmattix

@keithmattix Keith Mattix II (keithmattix) commented Sep 10, 2026 •

Copy link
Copy Markdown
Collaborator

Run agentgateway data plane tests as a part of substrate CI (non-blocking to start so we can confirm it's not flaky). Also, change the --atenet-router flag to --atenet-dataplane to make it clearer that the flag controls ingress and egress.

I've run the e2es locally across gVisor and microVM plus the MITM variants for both. The only skip we do for agentgateway is TestIngressProtocolDowngrade because 1. the behavior its testing only exists on the non-CONNECT atunnel ingress path and agentgateway only sends CONNECT to atunnel and 2. I'm not sure that we want this to be a part of the contract that substrate is bound by (e.g. do we really want to commit to atunnel always parsing HTTP?).

My goal with getting both dataplanes into CI is to start taking steps to codify the proxy (router + egress PEP) contract for substrate. The telemetry they emit, atunnel expectations, etc. are all important contracts to explicitly call out so that they don't become too coupled to a single dataplane implementation.

It's a good idea to open an issue first for discussion.

  • Tests pass
  • Appropriate changes to documentation are included in the PR

@keithmattix

Copy link
Copy Markdown
Collaborator Author

Current failure is a postgres timeout. I think CI just needs to be re-kicked

@EItanya Eitan Yarmush (EItanya) 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.

🤖 Relocated with AI assistance; the original inline comment wording is preserved.

Moved from my review on #1628, which is stacked on this PR. The three inline comments and the ingress-contract portion of that review belong here:

I have some clarifying questions about what the actual ingress contract is since there are definitely dataplane specific checks in the tests

The benchmark-specific questions remain on #1628. The CI matrix suggestion is already addressed here.

t.Fatalf("creating statusz client: %v", err)
var statusz *e2e.StatuszClient
if os.Getenv("E2E_DATAPLANE") != "agentgateway" {
statusz, err = e2e.NewStatuszClient(ctx)

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.

Moved from my comment on #1628; this feedback belongs to #1598.

Can we use a more generic solution here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

My plan is to just get both data planes to a working state in CI then iterate on a contract that both data planes implement. New contracts need would need to be persisted there instead of one off. So agree with the comment but will do it in a follow up

t.Fatalf("timed out waiting for the parking gauge to satisfy the condition (last active=%d)", last)
}

func agentGatewayParkingCount(ctx context.Context) (int, bool) {

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.

Moved from my comment on #1628; this feedback belongs to #1598.

Same question about unifying the data gathering mechanism here

Keith’s reply on the original thread points to this PR’s description and its goal of defining a shared proxy contract.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yeah +1 to my comment above; we'll define it in a shared contract

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.

Thanks Keith, LGTM overall a few questions

Comment thread benchmarking/automation/tests.yaml Resolved
Comment on lines +270 to +276
case "envoy":
authority, ok := accessLogField(line.text, "authority")
if ok && strings.HasSuffix(authority, ":"+port) && strings.Contains(line.text, "/actor/"+actorName) {
t.Logf("egress gateway tunneled the request: %s", line.text)
return true
}
case "agentgateway":

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.

is there a way we can wrap it somehow to avoid many switch cases

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I can make an interface in the testbed to encode all the dataplane specific behavior. FWIW, my plan is to create a dataplane contract so some of these nuances/features get described in a central place, but we'll have the test wrapper to make this cleaner in the mentime

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

That being said it's a bigger change than the few conditionals we have today, so I'll push it in a new commit to get some feedback

Comment on lines -289 to -291
gatewayContainer = "envoy"
// The access log's line prefix, from the HttpConnectionManager
// text_format_source in manifests/ate-install/atenet-egress.yaml.

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.

where did these go to

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Abstracted into accessLogField and the caller assertEgressGatewayConnect

if err != nil {
t.Fatalf("creating statusz client: %v", err)
var statusz *e2e.StatuszClient
if os.Getenv("E2E_DATAPLANE") != "agentgateway" {

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.

We really need to avoid if envoy if agentgateway everywhere? is there a way we can initialize it in the suit once and avoid switch cases everywhere?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Implemented something in 25c30d6

Comment thread internal/e2e/collector_metrics.go Outdated
collectorNamespace = "otel-system"
collectorService = "opentelemetry-collector"
collectorPromPort = 8889
routerStatsPort = 15020

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.

what is this port for?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Will rename to prefix with agentgateway. The current metrics reader in our test code relies on OTLP exported metrics while agentgateway just has native prom metrics

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.

@LiorLieberman
Lior Lieberman (LiorLieberman) merged commit abd45ad into agent-substrate:main Sep 15, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants