kiuby_88
kiuby_88

Reputation: 354

Ordered starting and waiting for containers

I have two containers in my tests using @Testcontainers with Junit5, a Kafka and a KafkaConnect.

@Container
private final KafkaContainer kafka = new KafkaContainer()
        .withNetwork(network)
        .withNetworkAliases("kafka");

@Container
private final GenericContainer KafkaConnect = 
        new GenericContainer("confluentinc/cp-kafka-connect:latest")
        .withEnv("CONNECT_BOOTSTRAP_SERVERS", "kafka:9092")
        .withEnv("CONNECT_REST_PORT", 8083)
        .withNetwork(network)
        ...

When I execute the tests, I find an error because Kafka Connect service in kafkaConnect is not is not started correctly (mapped port 8083 is not listening). It is because kafkaConnect is started before kafka and when the kafka:9092 url is reached during the kafkaConnect execution no response is obtained since kafka is not running yet. Then, I have tried to pospone the kafkaConnect start up in order to wait for kafka to ensure kafka:9092 availability.

I have tried different approach to do this but I did not fix the problem. I tried to add some configurations.

startupTimeout. As far as I know, this config does not pospone the start operation. It just increase the period to check if the container is started.

.withStartupTimeout(Duration.of(240, SECONDS)) 

I also tried some configurations for waitingFor, such as timeout-based, which,a s expected, produces the same result than withStartupTimeout

.waitingFor(Wait.defaultWaitStrategy().withStartupTimeout(...))

or port-based, which does not solve my issue because it does not point to kafka container but kafkaConnect.

.waitingFor(Wait.forHttp("http://kafka:9092"))

I have also tried to add a number of startup attempts but it does not solve the issue because the kafkaConnect is relaunch some times but always before kafka.

As a solution I removed @Container of kafkaConnect declaration in order to use manage manually its lifecycle, so I added the explicit starting to testcase, see below

@Test
test() {
    kafkaConnect.start();
    ...
}

This ensure kafkaConnect is started after kafka. However, I did not find a solution to define the order during the container definition, by means of strategies, policies or something similar, in order to add dependencies between containers and to avoid a imperative and manual lifecycle management.

is it possible?

Upvotes: 5

Views: 2208

Answers (1)

M. Leonhard
M. Leonhard

Reputation: 1582

import org.junit.rules.RuleChain;

// @Container <-- Remove annotation.
private final KafkaContainer kafka = new KafkaContainer()...;

// @Container <-- Remove annotation.
private final GenericContainer kafkaConnect = 
        new GenericContainer("confluentinc/cp-kafka-connect:latest")
        .withEnv("CONNECT_BOOTSTRAP_SERVERS", "kafka:9092")
        ...;

// Start the containers in the correct order.  Prevents
// "Mapped port can only be obtained after the container is started"
// error.
@Rule
public final RuleChain chain = 
    RuleChain
    // Started first.
    .outerRule(kafka)
    // Started later.
    .around(kafkaConnect);

Upvotes: 1

Related Questions