Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

RedpandaContainer

A single-node Redpanda broker (Kafka API-compatible) with its schema registry enabled.

Default image: floats to redpandadata/redpanda:latest — this module previously pinned redpandadata/redpanda:v24.2.4. Guest ports: 9092 (external Kafka), 9093 (internal Kafka), 8081 (schema registry) Expected repository: redpandadata/redpanda

MethodOnEffect
RedpandaContainer::new()builderFloating default image.
RedpandaContainer::with_image(image)builderCaller-chosen image, kept verbatim.
.start()builder → Result<RedpandaGuard>Checks the image’s repository, then boots the container.
.bootstrap_servers()guardPLAINTEXT://host:port for the EXTERNAL listener.
.schema_registry_url()guardSchema registry base URI.
.stop()guardStops and removes the container, releases its ports.

Compatibility checking

with_image takes impl Into<ImageName> and keeps the image verbatim. start() then checks that image’s repository (registry host, tag, and digest stripped) against redpandadata/redpanda before any backend is resolved or any sandbox is created, which keeps the constructors infallible like every other module’s. A mismatch returns RightsizeError::IncompatibleImage; ImageName::parse(image) .as_compatible_substitute_for("redpandadata/redpanda") is the escape hatch for a verified drop-in replacement from another registry. new() goes through this same check against its own floating reference, so it can never fail in practice.

The advertised-listener rewrite

Redpanda needs to advertise the address a client can actually reach — but the mapped host port for the Kafka listener is only known after ports are allocated, which happens right before create(). This module uses Container::with_spec_customizer to rewrite the boot command the instant before create, once the mapped port is known:

  • EXTERNAL listener advertises 127.0.0.1:<mapped host port> — what a test process on the host actually dials.
  • INTERNAL listener advertises the fixed redpanda:9093 alias/port — what a sibling container on the same Network resolves to reach this broker without going through the host port mapping at all.

This is the same trick KafkaContainer uses for its single advertised listener; Redpanda’s version is the fuller example because it has two listeners to rewrite (EXTERNAL and INTERNAL) rather than one.

Complete example

use rightsize_modules::RedpandaContainer;

#[tokio::test]
async fn redpanda_boots_and_advertises_a_reachable_port() -> rightsize::Result<()> {
    let guard = RedpandaContainer::new().start().await?;

    // guard.bootstrap_servers() is a PLAINTEXT://127.0.0.1:<port> address usable by
    // any Kafka-protocol client crate (rdkafka, kafka-protocol, etc.) from the host.
    println!("bootstrap: {}", guard.bootstrap_servers());
    println!("schema registry: {}", guard.schema_registry_url());

    guard.stop().await?;
    Ok(())
}

This crate does not take a Kafka client-library dev-dependency for its own integration suite (crates/rightsize-modules/tests/broker_modules_it.rs checks the schema registry over plain HTTP instead) — bring whichever Kafka-protocol client your project already uses.

Backend notes

No memory-limit override. INTERNAL_ALIAS = "redpanda" is the alias siblings resolve through on a shared Network — this port has no sibling Kafka-consumer module of its own yet, so cross-container consumption over the microsandbox network-link emulation is best-effort, not covered by this crate’s own contract suite.