All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ozangunalp.kafka.test.container.KafkaNativeContainer Maven / Gradle / Ivy

There is a newer version: 0.11.1
Show newest version
package com.ozangunalp.kafka.test.container;

import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;
import java.util.function.Function;

import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.output.OutputFrame;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.Transferable;
import org.testcontainers.utility.DockerImageName;

import com.github.dockerjava.api.command.InspectContainerResponse;

public class KafkaNativeContainer extends GenericContainer {

    public static final String DEFAULT_REPOSITORY = System.getProperty("kafka-native-container-image", "quay.io/ogunalp/kafka-native");
    public static final String DEFAULT_VERSION = System.getProperty("kafka-native-container-version", "latest");
    private static final String STARTER_SCRIPT = "/work/run.sh";
    private static final String SERVER_PROPERTIES = "/work/server.properties";
    private static final int KAFKA_PORT = 9092;

    // dynamic config
    private boolean hasServerProperties = false;
    private Function advertisedListenersProvider = KafkaNativeContainer::defaultAdvertisedAddresses;
    private String additionalArgs = null;
    private int exposedPort = -1;
    private Function, Consumer> outputFrameConsumer;
    private boolean autoConfigure = true;

    public static DockerImageName imageName(String version) {
        return DockerImageName.parse(DEFAULT_REPOSITORY + ":" + version);
    }

    public static DockerImageName imageName() {
        return DockerImageName.parse(DEFAULT_REPOSITORY + ":" + DEFAULT_VERSION);
    }

    public KafkaNativeContainer() {
        this(imageName());
    }

    public KafkaNativeContainer(DockerImageName dockerImageName) {
        super(dockerImageName);
        super.addExposedPort(9092);
        String cmd = String.format("while [ ! -f %s ]; do sleep 0.1; done; sleep 0.1; %s", STARTER_SCRIPT, STARTER_SCRIPT);
        super.withCommand("sh", "-c", cmd);
        super.waitingFor(Wait.forLogMessage(".*Kafka broker started.*", 1));
    }

    public KafkaNativeContainer withPort(int fixedPort) {
        assertNotRunning();
        if (fixedPort <= 0) {
            throw new IllegalArgumentException("The fixed Kafka port must be greater than 0");
        }
        addFixedExposedPort(fixedPort, KAFKA_PORT);
        return self();
    }

    public KafkaNativeContainer withServerProperties(Transferable transferable) {
        assertNotRunning();
        super.withCopyToContainer(transferable, SERVER_PROPERTIES);
        this.hasServerProperties = true;
        return self();
    }

    public KafkaNativeContainer withAutoConfigure(boolean autoConfigure) {
        assertNotRunning();
        this.autoConfigure = autoConfigure;
        return self();
    }

    public KafkaNativeContainer withAdvertisedListeners(final Function provider) {
        assertNotRunning();
        this.advertisedListenersProvider = provider;
        return self();
    }

    public KafkaNativeContainer withArgs(String args) {
        assertNotRunning();
        this.additionalArgs = args;
        return self();
    }

    public KafkaNativeContainer withFollowOutput(Function, Consumer> outputFrameConsumer) {
        this.outputFrameConsumer = outputFrameConsumer;
        return self();
    }

    @Override
    protected void containerIsStarting(InspectContainerResponse containerInfo, boolean reused) {
        super.containerIsStarting(containerInfo, reused);
        // Set exposed port
        this.exposedPort = getMappedPort(KAFKA_PORT);
        // follow output
        if (outputFrameConsumer != null) {
            followOutput(outputFrameConsumer.apply(this));
        }
        // Start and configure the advertised address
        String cmd = "#!/bin/bash\n/work/kafka";
        cmd += " -Dkafka.advertised.listeners=" + getBootstrapServers();
        if (hasServerProperties) {
            cmd += " -Dserver.properties-file=" + SERVER_PROPERTIES;
        }
        cmd += " -Dserver.auto-configure=" + autoConfigure;
        if (additionalArgs != null) {
            cmd += " " + additionalArgs;
        }

        //noinspection OctalInteger
        copyFileToContainer(
                Transferable.of(cmd.getBytes(StandardCharsets.UTF_8), 0777),
                STARTER_SCRIPT);
    }

    public static String defaultAdvertisedAddresses(KafkaNativeContainer container) {
        return String.format("PLAINTEXT://%s:%d", container.getHost(), container.getExposedKafkaPort());
    }

    public int getExposedKafkaPort() {
        return exposedPort;
    }

    public String getBootstrapServers() {
        return advertisedListenersProvider.apply(this);
    }

    private void assertNotRunning() {
        if (isRunning()) {
            throw new IllegalStateException("Configuration of the running broker is not permitted.");
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy