1 package de.juplo.kafka.chat.backend;
3 import lombok.extern.slf4j.Slf4j;
4 import org.awaitility.Awaitility;
5 import org.springframework.http.HttpStatus;
6 import org.springframework.web.reactive.function.client.WebClient;
7 import org.testcontainers.containers.BindMode;
8 import org.testcontainers.containers.GenericContainer;
9 import org.testcontainers.containers.Network;
10 import org.testcontainers.containers.output.Slf4jLogConsumer;
11 import org.testcontainers.containers.wait.strategy.Wait;
12 import org.testcontainers.images.ImagePullPolicy;
13 import org.testcontainers.utility.DockerImageName;
14 import reactor.core.publisher.Mono;
16 import java.time.Duration;
17 import java.util.Arrays;
21 public abstract class AbstractContainerTemplates
23 static final ImagePullPolicy NEVER_PULL = imageName -> false;
26 final Network network = Network.newNetwork();
27 final GenericContainer haproxy, backend1, backend2, backend3;
30 AbstractContainerTemplates()
32 haproxy = createHaproxyContainer();
33 backend1 = createBackendContainer("1");
34 backend2 = createBackendContainer("2");
35 backend3 = createBackendContainer("3");
39 void setUpExtra() throws Exception
41 log.info("This setup does not need any extra containers");
44 void setUp() throws Exception
54 .atMost(Duration.ofMinutes(10))
55 .until(() -> WebClient
56 .create("http://localhost:" + backend1.getMappedPort(8080))
58 .uri("/actuator/health")
59 .exchangeToMono(response ->
61 if (response.statusCode().equals(HttpStatus.OK))
64 .bodyToMono(StatusTO.class)
65 .map(StatusTO::getStatus)
66 .map(status -> status.equalsIgnoreCase("UP"));
70 return Mono.just(false);
77 .killContainerCmd(haproxy.getContainerId())
84 .atMost(Duration.ofMinutes(10))
85 .until(() -> WebClient
86 .create("http://localhost:" + haproxy.getMappedPort(8400))
88 .uri("/actuator/health")
89 .exchangeToMono(response ->
91 if (response.statusCode().equals(HttpStatus.OK))
94 .bodyToMono(StatusTO.class)
95 .map(StatusTO::getStatus)
96 .map(status -> status.equalsIgnoreCase("UP"));
100 return Mono.just(false);
106 abstract String[] getBackendCommand();
108 final GenericContainer createHaproxyContainer()
110 return new GenericContainer(DockerImageName.parse("haproxytech/haproxy-debian:2.8"))
111 .withNetwork(network)
112 .withNetworkAliases("haproxy")
113 .withClasspathResourceMapping(
115 "/usr/local/etc/haproxy/haproxy.cfg",
117 .withClasspathResourceMapping(
119 "/usr/local/etc/haproxy/sharding.map",
121 .withExposedPorts(8400, 8401, 8404)
122 .withLogConsumer(new Slf4jLogConsumer(log, true).withPrefix("HAPROXY"));
125 final GenericContainer createBackendContainer(String id)
127 return new GenericContainer(DockerImageName.parse("juplo/chat-backend:0.0.1-SNAPSHOT"))
128 .withImagePullPolicy(NEVER_PULL)
129 .withNetwork(network)
130 .withNetworkAliases("backend-ID".replaceAll("ID", id))
131 .withCommand(Arrays.stream(getBackendCommand())
132 .map(commandPart -> commandPart.replaceAll("ID", id))
133 .toArray(size -> new String[size]))
134 .withExposedPorts(8080)
135 .waitingFor(Wait.forLogMessage(".*Started\\ ChatBackendApplication.*\\n", 1))
136 .withLogConsumer(new Slf4jLogConsumer(
140 .withPrefix("BACKEND-ID".replaceAll("ID", id)));