You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add Python Kafka sidecar delivery E2E test - #4111
🎁 Add an integration test proving the Kafka runtime sidecar delivers to Python end to end: a plain cloudevents Python function, built and deployed through func on the keda deployer, receives Kafka records via the injected sidecar as CloudEvents over HTTP — the function itself contains no Kafka code.
🎁 Assert real delivery, not just object creation: the test produces a record to the broker, waits for the Python function to log receipt, and confirms the consumer group drains to lag 0 (the sidecar commits the offset only on a 2xx).
The sidecar is language-agnostic by design, but so far only Go was validated end to end. Unlike the existing TestInt_KafkaScaling — which pins a prebuilt image and only checks the created KEDA objects — this exercises the real build + deploy pipeline for Python and asserts delivery. No template or runtime changes are needed; the stock python/cloudevents template is already a plain CloudEvents-over-HTTP receiver.
It runs against the same Strimzi broker the Kafka integration job already provisions and is picked up by the existing test-integration-kafka target, so no CI changes are needed.
The Kafka runtime sidecar is language-agnostic by design, but only Go
was validated end to end. Add an integration test that proves Python: a
plain cloudevents Python function, built and deployed through func on
the keda deployer, receives Kafka records via the injected sidecar as
CloudEvents over HTTP -- the function itself contains no Kafka code.
Unlike the existing TestInt_KafkaScaling, which pins a prebuilt image
and only checks the created KEDA objects, this exercises the real
build+deploy pipeline and asserts delivery: it produces a record to the
broker, waits for the function to log receipt, and confirms the consumer
group drains to lag 0 (the sidecar commits the offset only on a 2xx).
The test runs against the same Strimzi broker the Kafka integration job
already provisions and is picked up by the existing
test-integration-kafka target, so no CI changes are needed.
Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment
knative-prowBot
added
approved
🤖 PR has been approved by an approver from all required OWNERS files.
size/L
🤖 PR changes 100-499 lines, ignoring generated files.
labels
Oct 27, 2026
The delivery check only asserted the function logged "Request Received",
which proves a request reached the function but not that it was our
record with the payload intact. Produce a record carrying a unique
per-run token and instrument the scaffolded handler to echo the received
data, then assert that token appears in the function logs.
Delivery of the specific record (delivered and decoded intact) is now
verified, alongside the existing lag-0 check that independently confirms
the function acked it.
The Python Kafka delivery test instrumented the scaffolded handler in
place with a strings.Replace on func.py, anchored to a template line.
That coupled the test to the template's exact source and hid the only
part that matters -- the echo handler -- inside Go string surgery.
Replace it with a committed handler fixture under testdata that is
copied over the scaffold after func create. func create still provides
func.yaml and the dependencies; only the handler is swapped. The
fixture is a reviewable Python file and the test no longer breaks when
the template's wording changes.
func create derives the function name from the target directory's
basename. t.TempDir() returns a path whose leaf segment is numeric
(e.g. ".../002"), which fails function-name validation (a name must
start with an alphabetic character). Nest the function in a validly
named subdirectory so create succeeds.
The Kafka integration job runs a slim cluster with serving (and thus
the Contour ingress) disabled to save CPU. Pushing a built function
image to registry.localtest.me only works through that ingress, so the
Python delivery test's build+push failed with a connection reset -- the
first Kafka test to actually build and push, since the scaling test
pins a prebuilt image.
Expose the registry pod's hostPort (5000) to the host and push to
localhost:5000 instead. containerd treats localhost as insecure, and
the node already pulls it through the same hostPort the containerd
mirror uses, so no ingress is needed. This is the canonical
kind-local-registry pattern.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Failed Kafka tool pods are treated as successful, masking producer and consumer-group command failures instead of immediately reporting errors and pod logs.
runKafkaToolPod waited for the pod to reach either Succeeded or Failed
and then returned its logs regardless of which. A failed producer pod
was therefore treated as success and only surfaced minutes later as a
misleading "function did not log" delivery timeout; a failed
consumer-group command was parsed as a lag observation and reported as
a false "did not drain to lag 0".
Capture the terminal phase and fail the test immediately with the pod
logs when it is not Succeeded, so the real failure is reported at its
source.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
The cleanup command passes --namespace without the required function name and discards the resulting error, so func delete removes nothing and cleanup relies entirely on namespace deletion.
No open issues 🎉
1 previously missed issue
In code that hasn't changed since last review
Fix cleanup deletion to pass the required function name
pkg/keda/kafka_delivery_int_test.go:166
This cleanup command is always rejected: newDeleteConfig in cmd/delete.go requires a positional function name whenever --namespace is supplied. Because the error is discarded, func delete never removes anything, leaving cleanup entirely to namespace deletion. Omit --namespace so deletion uses the namespace and deployer recorded in the local func.yaml.
Looks good, thanks @aliok. A genuine end-to-end delivery check (per-run token in the function logs, plus consumer-group lag draining to 0).
One small question, non-blocking: the new host port 5000 mapping in hack/cluster.sh is unconditional, and macOS binds TCP 5000 for AirPlay Receiver by default, so local hack/cluster.sh runs on a Mac may now hit a port-in-use error from kind. Would it make sense to gate it (e.g. behind FUNC_CLUSTER_SERVING=false, or a flag the Kafka job sets), either here or as a follow-up?
The slim Kafka integration cluster skips serving, so it has no Contour
ingress and a host-side `func deploy` build+push cannot reach the
in-cluster registry through registry.localtest.me. #4111 exposed the
registry by mapping host port 5000 to the node unconditionally, for
every cluster hack/cluster.sh creates.
On macOS the AirPlay Receiver listens on *:5000, so that unconditional
mapping makes `kind create cluster` fail to bind -- breaking cluster
creation for every developer on a Mac, not just the Kafka job. CI runs
on Linux, so it never caught this.
Map the registry to the host only on serving-less clusters (full
clusters push through the ingress and need no host mapping), and use
host port 5001 to dodge AirPlay. The node still serves the registry on
container port 5000; a containerd mirror resolves localhost:5001 to it
so pushed images -- now tagged localhost:5001 -- can be pulled. Update
the Python delivery test to push to localhost:5001.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
approved🤖 PR has been approved by an approver from all required OWNERS files.kind/enhancementFeature additions or improvements to existinglgtm🤖 PR is ready to be merged.size/L🤖 PR changes 100-499 lines, ignoring generated files.
4 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes
cloudeventsPython function, built and deployed throughfuncon the keda deployer, receives Kafka records via the injected sidecar as CloudEvents over HTTP — the function itself contains no Kafka code.The sidecar is language-agnostic by design, but so far only Go was validated end to end. Unlike the existing
TestInt_KafkaScaling— which pins a prebuilt image and only checks the created KEDA objects — this exercises the real build + deploy pipeline for Python and asserts delivery. No template or runtime changes are needed; the stockpython/cloudeventstemplate is already a plain CloudEvents-over-HTTP receiver.It runs against the same Strimzi broker the Kafka integration job already provisions and is picked up by the existing
test-integration-kafkatarget, so no CI changes are needed./kind enhancement
Release Note
Docs