Skip to content

Conversation

@mabrarov
Copy link
Contributor

@mabrarov mabrarov commented Nov 8, 2025

Changes

  • feat(kafka): support of Apache Kafka images (apache/kafka and apache/kafka-native).

What does this PR do?

Adding support of Apache Kafka Docker Hub images - apache/kafka and apache/kafka-native - into kafka module.

Why is it important?

Images supported by kafka module are limited to confluentinc/confluent-local and these images have issues with graceful stop - refer to #2206 (comment). apache/kafka and apache/kafka-native images support graceful shutdown. apache/kafka-native image is also faster and can be used to speedup tests.

Related issues

Follow-ups

Need to decide if #3249 is a better choice to go.

@mabrarov mabrarov requested a review from a team as a code owner November 8, 2025 21:40
@netlify
Copy link

netlify bot commented Nov 8, 2025

Deploy Preview for testcontainers-go ready!

Name Link
🔨 Latest commit 731a095
🔍 Latest deploy log https://app.netlify.com/projects/testcontainers-go/deploys/69107c8d1cd3fe0008a197c5
😎 Deploy Preview https://deploy-preview-3488--testcontainers-go.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link

coderabbitai bot commented Nov 8, 2025

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for multiple Kafka distributions (Conflent Local, Apache Kafka, Apache Kafka Native).
    • Improved dynamic listener and port mapping configuration for Kafka containers.
    • Added graceful shutdown support and localhost listener validation.
  • Tests

    • Expanded test coverage for multiple Kafka image variants.
    • Added validation tests for graceful shutdown and localhost listener functionality.

Walkthrough

Reworks Kafka startup to compute listener ports at runtime, extract image entrypoint/cmd via the Docker provider, generate and copy a dynamic starter script into containers, and updates tests/examples to run per-image Kafka instances with graceful-shutdown and localhost-listener checks. (33 words)

Changes

Cohort / File(s) Summary
Examples — per-image examples
modules/kafka/examples_test.go
Replaced a single ExampleRun with three examples: ExampleRun_confluentLocal, ExampleRun_apacheKafka, and ExampleRun_apacheKafkaNative; each starts a container, defers termination, retrieves container state, prints clusterID and state.Running, and includes // Output: blocks.
Tests — multi-image and new test cases
modules/kafka/kafka_test.go
Converted tests to table-driven per-image subtests; added TestKafka, TestKafkaGracefulShutdown, and TestKafkaLocalhostListener; introduced image sets (gracefulShutdownSupportingKafkaImages, supportedKafkaImages), per-image lifecycle/cleanup, wait strategies, and assertions for clusterID, advertised listeners, and message round-trip.
Runtime & Docker integration — dynamic starter script and listeners
modules/kafka/kafka.go
Added dynamic listener port handling and multiple listener constants, compute KAFKA_LISTENERS and KAFKA_LISTENER_SECURITY_PROTOCOL_MAP at runtime, determine public port via nat.NewPort, inspect image entrypoint/cmd using a Docker provider, generate and copy a starter script into the container, update Run, copyStarterScript, Brokers, and controller quorum config to use dynamic ports, and added getDockerProvider.

Sequence Diagram

sequenceDiagram
    participant Test
    participant Run as kafka.Run
    participant Provider as DockerProvider
    participant Container
    participant Script as StarterScript

    Test->>Run: Run(ctx, image, opts...)
    Run->>Provider: getDockerProvider(opts...)
    Run->>Container: Start container (expose ports)
    Container-->>Run: Started (container ID, mapped host ports)
    Run->>Provider: Inspect image -> entrypoint & cmd
    Provider-->>Run: entrypoint & cmd
    Run->>Script: Build starter script (listeners, mapped ports, original entrypoint)
    Run->>Container: Copy starter script into container
    Run->>Container: Exec starter script to launch Kafka runtime
    Container-->>Run: Kafka process running / readiness met
    Run-->>Test: Return container info (clusterID, running state)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Files needing extra attention:
    • modules/kafka/kafka.go — dynamic script generation, image inspection, port mapping, and Docker provider extraction.
    • modules/kafka/kafka_test.go — table-driven tests, wait strategies, and graceful-shutdown timing.
    • modules/kafka/examples_test.go — per-example lifecycle and expected output assertions.

Possibly related PRs

Poem

🐰
I hop through images, one by one,
I stitch a script until it's spun.
Ports align and listeners sing,
Brokers wake — the cluster springs.
I nudge the logs and then I run.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main objective: adding support for Apache Kafka images to the kafka module.
Description check ✅ Passed The description directly relates to the changeset by explaining what Apache Kafka images are being added, why they matter (graceful shutdown support), and references related issues.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 73ec41e and 731a095.

📒 Files selected for processing (3)
  • modules/kafka/examples_test.go (2 hunks)
  • modules/kafka/kafka.go (6 hunks)
  • modules/kafka/kafka_test.go (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-29T15:08:18.694Z
Learnt from: mdelapenya
Repo: testcontainers/testcontainers-go PR: 3320
File: modules/artemis/artemis.go:98-103
Timestamp: 2025-09-29T15:08:18.694Z
Learning: In testcontainers-go, nat.Port is a type alias for string, so untyped string constants can be passed directly to functions expecting nat.Port (like wait.ForListeningPort) without explicit type conversion - the Go compiler handles the implicit conversion automatically.

Applied to files:

  • modules/kafka/kafka.go
📚 Learning: 2025-09-29T13:57:14.636Z
Learnt from: mdelapenya
Repo: testcontainers/testcontainers-go PR: 3319
File: modules/arangodb/arangodb.go:46-57
Timestamp: 2025-09-29T13:57:14.636Z
Learning: In testcontainers-go ArangoDB module, the wait strategy combines port listening check with HTTP readiness check using wait.ForAll - both strategies are required and complementary, not redundant.

Applied to files:

  • modules/kafka/kafka.go
🧬 Code graph analysis (3)
modules/kafka/kafka.go (4)
container.go (1)
  • Container (41-73)
docker.go (1)
  • DockerProvider (977-984)
generic.go (1)
  • GenericContainerRequest (21-27)
log/logger.go (2)
  • Logger (18-20)
  • Default (38-40)
modules/kafka/examples_test.go (2)
modules/kafka/kafka.go (2)
  • Run (53-140)
  • WithClusterID (186-190)
cleanup.go (1)
  • TerminateContainer (97-108)
modules/kafka/kafka_test.go (6)
modules/kafka/kafka.go (2)
  • Run (53-140)
  • WithClusterID (186-190)
testing.go (1)
  • CleanupContainer (91-97)
cleanup.go (1)
  • StopTimeout (76-80)
modules/kafka/consumer_test.go (1)
  • NewTestKafkaConsumer (18-29)
options.go (1)
  • WithWaitStrategy (366-368)
wait/exec.go (1)
  • NewExecStrategy (30-37)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: test (1.25.x, modules/kafka) / test: modules/kafka/1.25.x
  • GitHub Check: test (1.24.x, modules/kafka) / test: modules/kafka/1.24.x
  • GitHub Check: Analyze (go)
🔇 Additional comments (13)
modules/kafka/examples_test.go (3)

12-41: LGTM! Example demonstrates confluentLocal image usage.

The example function correctly demonstrates the Kafka module usage with the Confluent Local image, including state retrieval and output verification. The defer placement before error checking is intentional and correct, ensuring cleanup occurs even if Run returns an error (since Run returns a container even on failure).


43-72: LGTM! Example demonstrates Apache Kafka image support.

This new example correctly demonstrates usage with the apache/kafka image, one of the main additions in this PR. The implementation follows the same correct pattern as the confluentLocal example.


74-103: LGTM! Example demonstrates Apache Kafka Native image support.

This new example correctly demonstrates usage with the apache/kafka-native image, which per the PR description may provide faster test execution. The implementation is consistent with the other examples.

modules/kafka/kafka.go (6)

20-38: LGTM! Well-structured listener configuration.

The multiple port constants and starter script template provide a clean foundation for the dynamic multi-listener setup. The script template appropriately handles Confluent-specific configuration while supporting the apache images.


54-62: LGTM! Proper initialization of port and provider.

The dynamic port creation and early provider extraction are well-structured. Error handling with wrapped errors provides good context for debugging.


68-77: LGTM! Comprehensive listener configuration.

The dynamic listener configuration correctly includes all four listeners with appropriate security protocol mappings. This supports both the Confluent and Apache Kafka images.


194-206: LGTM! Consistent dynamic port handling in Brokers method.

The method correctly recreates the publicPort and retrieves the endpoint dynamically. While this duplicates the port creation logic from Run, the approach is reasonable given that nat.NewPort is inexpensive and avoiding the need to store the port in the struct keeps the API simpler.


234-257: LGTM! Well-designed provider extraction helper.

The getDockerProvider function uses a clean pattern to extract the DockerProvider from container options. The dummy request approach, proper logger handling, and clear error messages make this a solid utility function. The type assertion check appropriately ensures the module works with the expected provider type.


143-184: I need to gather information using alternative methods since Docker isn't available in the sandbox.

Based on web search for Kafka image configurations, confluentinc/confluent-local is a Kafka package optimized for local development that enables quick Kafka startup in KRaft mode with no configuration setup. Confluent Kafka Connect images have entrypoints defined (e.g., [/etc/confluent/docker/run]), and the apache/kafka image includes many helpful scripts in the /opt/kafka/bin directory. All standard production Kafka images are built with explicit entrypoints or commands.

The edge case of both Entrypoint and Cmd being empty is not realistic for supported Kafka images. The defensive check suggested in the review is unnecessary.

No critical issues found.

modules/kafka/kafka_test.go (4)

17-29: LGTM! Well-organized image lists for parameterized testing.

The separation of gracefulShutdownSupportingKafkaImages and supportedKafkaImages clearly reflects the PR objective: Apache Kafka images support graceful shutdown while Confluent images have limitations. The version coverage is appropriate for testing across multiple image variants.


31-95: LGTM! Comprehensive multi-image test coverage.

The TestKafka function provides thorough coverage across all supported images, validating the complete producer-consumer workflow for each. The use of StopTimeout(0) during cleanup is appropriate since not all tested images support graceful shutdown. Per-image subtests enable clear identification of failures for specific images.


97-121: LGTM! Test validates key PR objective.

This test directly validates the graceful shutdown capability that is the primary motivation for this PR. The timeout values (120s for Stop, 60s for test) provide reasonable margins, and limiting the test to gracefulShutdownSupportingKafkaImages appropriately focuses on images that support this feature.


123-138: LGTM! Test validates localhost listener configuration.

This test effectively validates that the LOCALHOST listener on port 9095 is properly configured and accessible. Using the kafka-topics.sh command with a custom exec wait strategy is an appropriate approach to verify listener availability.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
modules/kafka/kafka_test.go (1)

51-79: Close Sarama clients per iteration

We now spin up a consumer group and sync producer for every image in the loop, but never close them. Releasing them with t.Cleanup keeps goroutines and network resources from bleeding into later iterations.

 			client, err := sarama.NewConsumerGroup(brokers, "groupName", config)
 			require.NoError(t, err)
+			t.Cleanup(func() {
+				if err := client.Close(); err != nil {
+					t.Errorf("close consumer group: %v", err)
+				}
+			})
@@
 			producer, err := sarama.NewSyncProducer(brokers, config)
 			require.NoError(t, err)
+			t.Cleanup(func() {
+				if err := producer.Close(); err != nil {
+					t.Errorf("close producer: %v", err)
+				}
+			})
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec51c67 and c74f62a.

📒 Files selected for processing (3)
  • modules/kafka/examples_test.go (1 hunks)
  • modules/kafka/kafka.go (7 hunks)
  • modules/kafka/kafka_test.go (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-29T15:08:18.694Z
Learnt from: mdelapenya
Repo: testcontainers/testcontainers-go PR: 3320
File: modules/artemis/artemis.go:98-103
Timestamp: 2025-09-29T15:08:18.694Z
Learning: In testcontainers-go, nat.Port is a type alias for string, so untyped string constants can be passed directly to functions expecting nat.Port (like wait.ForListeningPort) without explicit type conversion - the Go compiler handles the implicit conversion automatically.

Applied to files:

  • modules/kafka/kafka.go
📚 Learning: 2025-09-29T13:57:14.636Z
Learnt from: mdelapenya
Repo: testcontainers/testcontainers-go PR: 3319
File: modules/arangodb/arangodb.go:46-57
Timestamp: 2025-09-29T13:57:14.636Z
Learning: In testcontainers-go ArangoDB module, the wait strategy combines port listening check with HTTP readiness check using wait.ForAll - both strategies are required and complementary, not redundant.

Applied to files:

  • modules/kafka/kafka.go
🧬 Code graph analysis (3)
modules/kafka/examples_test.go (3)
modules/kafka/kafka.go (2)
  • Run (52-139)
  • WithClusterID (191-195)
cleanup.go (1)
  • TerminateContainer (97-108)
log/logger.go (1)
  • Printf (47-49)
modules/kafka/kafka_test.go (6)
modules/kafka/kafka.go (2)
  • Run (52-139)
  • WithClusterID (191-195)
testing.go (1)
  • CleanupContainer (91-97)
cleanup.go (1)
  • StopTimeout (76-80)
modules/kafka/consumer_test.go (1)
  • NewTestKafkaConsumer (18-29)
options.go (1)
  • WithWaitStrategy (366-368)
wait/exec.go (1)
  • NewExecStrategy (30-37)
modules/kafka/kafka.go (6)
options.go (1)
  • ContainerCustomizer (22-24)
container.go (1)
  • Container (41-73)
docker.go (1)
  • DockerProvider (977-984)
generic.go (1)
  • GenericContainerRequest (21-27)
log/logger.go (2)
  • Logger (18-20)
  • Default (38-40)
provider.go (1)
  • ProviderType (24-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: test (1.25.x, modules/kafka) / test: modules/kafka/1.25.x
  • GitHub Check: test (1.24.x, modules/kafka) / test: modules/kafka/1.24.x
  • GitHub Check: Analyze (go)

@mabrarov mabrarov force-pushed the feat/kafka_alt_images branch from c74f62a to ee5c1aa Compare November 9, 2025 01:51
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c74f62a and ee5c1aa.

📒 Files selected for processing (3)
  • modules/kafka/examples_test.go (2 hunks)
  • modules/kafka/kafka.go (7 hunks)
  • modules/kafka/kafka_test.go (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-29T15:08:18.694Z
Learnt from: mdelapenya
Repo: testcontainers/testcontainers-go PR: 3320
File: modules/artemis/artemis.go:98-103
Timestamp: 2025-09-29T15:08:18.694Z
Learning: In testcontainers-go, nat.Port is a type alias for string, so untyped string constants can be passed directly to functions expecting nat.Port (like wait.ForListeningPort) without explicit type conversion - the Go compiler handles the implicit conversion automatically.

Applied to files:

  • modules/kafka/kafka.go
📚 Learning: 2025-09-29T13:57:14.636Z
Learnt from: mdelapenya
Repo: testcontainers/testcontainers-go PR: 3319
File: modules/arangodb/arangodb.go:46-57
Timestamp: 2025-09-29T13:57:14.636Z
Learning: In testcontainers-go ArangoDB module, the wait strategy combines port listening check with HTTP readiness check using wait.ForAll - both strategies are required and complementary, not redundant.

Applied to files:

  • modules/kafka/kafka.go
🧬 Code graph analysis (3)
modules/kafka/examples_test.go (2)
modules/kafka/kafka.go (2)
  • Run (52-139)
  • WithClusterID (191-195)
cleanup.go (1)
  • TerminateContainer (97-108)
modules/kafka/kafka_test.go (6)
modules/kafka/kafka.go (2)
  • Run (52-139)
  • WithClusterID (191-195)
testing.go (1)
  • CleanupContainer (91-97)
cleanup.go (1)
  • StopTimeout (76-80)
modules/kafka/consumer_test.go (1)
  • NewTestKafkaConsumer (18-29)
options.go (1)
  • WithWaitStrategy (366-368)
wait/exec.go (1)
  • NewExecStrategy (30-37)
modules/kafka/kafka.go (6)
container.go (1)
  • Container (41-73)
docker.go (1)
  • DockerProvider (977-984)
wait/host_port.go (1)
  • ForMappedPort (79-81)
generic.go (1)
  • GenericContainerRequest (21-27)
log/logger.go (2)
  • Logger (18-20)
  • Default (38-40)
provider.go (1)
  • ProviderType (24-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: test (1.25.x, modules/kafka) / test: modules/kafka/1.25.x
  • GitHub Check: test (1.24.x, modules/kafka) / test: modules/kafka/1.24.x
  • GitHub Check: Analyze (go)

@mabrarov mabrarov force-pushed the feat/kafka_alt_images branch from ee5c1aa to 73ec41e Compare November 9, 2025 02:29
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
modules/kafka/kafka_test.go (1)

17-29: Consider reordering variable declarations for clarity.

While Go correctly resolves the dependency and initializes gracefulShutdownSupportingKafkaImages before supportedKafkaImages, explicitly defining gracefulShutdownSupportingKafkaImages first would improve readability.

 var (
-	supportedKafkaImages = append(gracefulShutdownSupportingKafkaImages,
-		"confluentinc/confluent-local:7.4.0",
-		"confluentinc/confluent-local:7.5.0",
-	)
-
 	gracefulShutdownSupportingKafkaImages = []string{
 		"apache/kafka:3.9.1",
 		"apache/kafka:4.0.1",
 		"apache/kafka-native:3.9.1",
 		"apache/kafka-native:4.0.1",
 	}
+
+	supportedKafkaImages = append(gracefulShutdownSupportingKafkaImages,
+		"confluentinc/confluent-local:7.4.0",
+		"confluentinc/confluent-local:7.5.0",
+	)
 )
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ee5c1aa and 73ec41e.

📒 Files selected for processing (3)
  • modules/kafka/examples_test.go (2 hunks)
  • modules/kafka/kafka.go (6 hunks)
  • modules/kafka/kafka_test.go (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-29T15:08:18.694Z
Learnt from: mdelapenya
Repo: testcontainers/testcontainers-go PR: 3320
File: modules/artemis/artemis.go:98-103
Timestamp: 2025-09-29T15:08:18.694Z
Learning: In testcontainers-go, nat.Port is a type alias for string, so untyped string constants can be passed directly to functions expecting nat.Port (like wait.ForListeningPort) without explicit type conversion - the Go compiler handles the implicit conversion automatically.

Applied to files:

  • modules/kafka/kafka.go
📚 Learning: 2025-09-29T13:57:14.636Z
Learnt from: mdelapenya
Repo: testcontainers/testcontainers-go PR: 3319
File: modules/arangodb/arangodb.go:46-57
Timestamp: 2025-09-29T13:57:14.636Z
Learning: In testcontainers-go ArangoDB module, the wait strategy combines port listening check with HTTP readiness check using wait.ForAll - both strategies are required and complementary, not redundant.

Applied to files:

  • modules/kafka/kafka.go
🧬 Code graph analysis (3)
modules/kafka/examples_test.go (3)
log/logger.go (1)
  • Printf (47-49)
modules/kafka/kafka.go (2)
  • Run (53-140)
  • WithClusterID (186-190)
cleanup.go (1)
  • TerminateContainer (97-108)
modules/kafka/kafka_test.go (6)
modules/kafka/kafka.go (2)
  • Run (53-140)
  • WithClusterID (186-190)
testing.go (1)
  • CleanupContainer (91-97)
cleanup.go (1)
  • StopTimeout (76-80)
modules/kafka/consumer_test.go (1)
  • NewTestKafkaConsumer (18-29)
options.go (1)
  • WithWaitStrategy (366-368)
wait/exec.go (1)
  • NewExecStrategy (30-37)
modules/kafka/kafka.go (5)
options.go (1)
  • ContainerCustomizer (22-24)
container.go (1)
  • Container (41-73)
docker.go (1)
  • DockerProvider (977-984)
generic.go (1)
  • GenericContainerRequest (21-27)
log/logger.go (2)
  • Logger (18-20)
  • Default (38-40)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: test (1.24.x, modules/kafka) / test: modules/kafka/1.24.x
  • GitHub Check: test (1.25.x, modules/kafka) / test: modules/kafka/1.25.x
  • GitHub Check: Analyze (go)
🔇 Additional comments (12)
modules/kafka/examples_test.go (1)

12-103: LGTM! Excellent refactoring that resolves the closure issue.

Splitting the original loop into three separate example functions (ExampleRun_confluentLocal, ExampleRun_apacheKafka, ExampleRun_apacheKafkaNative) cleanly eliminates the defer closure problem from the previous version. Each example is now independently runnable with clear, testable output expectations.

modules/kafka/kafka_test.go (3)

31-95: LGTM! Comprehensive per-image testing.

The test properly exercises each supported image with a full producer/consumer flow. The use of StopTimeout(0) for cleanup is appropriate for test scenarios where immediate termination is acceptable.


97-121: LGTM! Graceful shutdown test validates the key PR objective.

The test correctly verifies that Apache Kafka images support graceful shutdown within a reasonable timeout (60s), which addresses one of the main motivations for this PR.


123-138: LGTM! Localhost listener verification is appropriate.

The test validates that the LOCALHOST listener on port 9095 is accessible within the container, which is essential for certain Kafka client scenarios.

modules/kafka/kafka.go (8)

21-37: LGTM! Clear listener port organization.

The port constants and starter script template are well-structured. The script properly exports advertised listeners and preserves the original container entrypoint execution.


54-62: LGTM! Clean initialization of dynamic port and provider.

The explicit port creation and provider extraction enable the dynamic listener configuration needed to support multiple Kafka image variants.


68-77: LGTM! Dynamic listener configuration supports multiple images.

The parameterized listener setup with the LOCALHOST mapping properly accommodates different Kafka image requirements.


91-93: LGTM! Elegant wait-and-exec pattern.

The entrypoint override combined with the polling loop ensures the starter script is copied before execution, preventing race conditions.


194-206: LGTM! Consistent dynamic port handling.

The Brokers function now uses the same port constant as Run, maintaining consistency across the module.


211-232: LGTM! Controller quorum voters use consistent port constant.

The function now references controllerListenerLocalPort instead of a hardcoded value, maintaining alignment with the dynamic listener configuration.


234-257: LGTM! Practical approach to extract provider from options.

The function applies customizers to a temporary request to extract the provider configuration, which is a reasonable pattern for accessing the Docker client needed for image inspection. Options are effectively applied twice (here and during actual Run), but standard customizers like WithEnv and WithExposedPorts are idempotent.


164-177: IPv6 handling is already correct—no action needed.

Both PortEndpoint (docker.go:158 and modules/ollama/local.go:662) and the brokerHostPort construction (kafka.go:170) use net.JoinHostPort, which automatically wraps IPv6 addresses in brackets per Go's standard library. For an IPv6 host like fd00::1, this produces [fd00::1]:port, resulting in correctly formatted endpoints like PLAINTEXT://[fd00::1]:9093.

…kafka-native).

Signed-off-by: Marat Abrarov <abrarov@gmail.com>
@mabrarov mabrarov force-pushed the feat/kafka_alt_images branch from 73ec41e to 731a095 Compare November 9, 2025 11:35
@mabrarov mabrarov changed the title feat(kafka): support of Apache Kafka Docker Hub images feat(kafka): support of Apache Kafka images Nov 9, 2025
@mabrarov
Copy link
Contributor Author

mabrarov commented Nov 9, 2025

Closing this PR in favor of #3249 which now (e.g. with support of custom startup script) seems much better than this one. Many thanks to @strowk for making such a deep change.

@mabrarov mabrarov closed this Nov 9, 2025
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.

1 participant