Skip to content

Commit 6584702

Browse files
committed
2246 Print containerAlias into logs to distinguish between same image containers
1 parent 43c6a97 commit 6584702

File tree

3 files changed

+131
-2
lines changed

3 files changed

+131
-2
lines changed

core/src/main/java/org/testcontainers/containers/Container.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,13 @@ SELF withClasspathResourceMapping(
375375
*/
376376
SELF withWorkingDirectory(String workDir);
377377

378+
/**
379+
* Set the container alias to distinguish between multiple containers.
380+
*
381+
* @param alias name
382+
*/
383+
SELF withContainerAlias(String alias);
384+
378385
/**
379386
* <b>Resolve</b> Docker image and set it.
380387
*

core/src/main/java/org/testcontainers/containers/GenericContainer.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ public class GenericContainer<SELF extends GenericContainer<SELF>>
138138
@Nullable
139139
private String workingDirectory = null;
140140

141+
@Nullable
142+
private String containerAlias = null;
143+
141144
/**
142145
* The shared memory size to use when starting the container.
143146
* This value is in bytes.
@@ -343,7 +346,14 @@ protected void doStart() {
343346
}
344347
);
345348
} catch (Exception e) {
346-
throw new ContainerLaunchException("Container startup failed for image " + getDockerImageName(), e);
349+
String containerAliasStr = "";
350+
if (StringUtils.isNotBlank(containerAlias)) {
351+
containerAliasStr = " (containerAlias='" + containerAlias.trim() + "')";
352+
}
353+
throw new ContainerLaunchException(
354+
"Container startup failed for image " + getDockerImageName() + containerAliasStr,
355+
e
356+
);
347357
}
348358
}
349359

@@ -663,7 +673,11 @@ public void stop() {
663673
* @return a logger that references the docker image name
664674
*/
665675
protected Logger logger() {
666-
return DockerLoggerFactory.getLogger(this.getDockerImageName());
676+
String loggerName = this.getDockerImageName();
677+
if (StringUtils.isNotBlank(containerAlias)) {
678+
loggerName = loggerName + "--" + containerAlias.trim();
679+
}
680+
return DockerLoggerFactory.getLogger(loggerName);
667681
}
668682

669683
/**
@@ -1256,6 +1270,12 @@ public SELF withWorkingDirectory(String workDir) {
12561270
return self();
12571271
}
12581272

1273+
@Override
1274+
public SELF withContainerAlias(String alias) {
1275+
this.setContainerAlias(alias);
1276+
return self();
1277+
}
1278+
12591279
/**
12601280
* {@inheritDoc}
12611281
*/
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package org.testcontainers.junit;
2+
3+
import ch.qos.logback.classic.Logger;
4+
import ch.qos.logback.classic.spi.ILoggingEvent;
5+
import ch.qos.logback.core.read.ListAppender;
6+
import org.junit.jupiter.api.AfterEach;
7+
import org.junit.jupiter.api.BeforeEach;
8+
import org.junit.jupiter.api.Test;
9+
import org.slf4j.LoggerFactory;
10+
import org.testcontainers.TestImages;
11+
import org.testcontainers.containers.ContainerLaunchException;
12+
import org.testcontainers.containers.GenericContainer;
13+
import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy;
14+
15+
import java.util.List;
16+
17+
import static org.assertj.core.api.Assertions.assertThat;
18+
import static org.assertj.core.api.Assertions.assertThatNoException;
19+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
20+
21+
class ContainerAliasTest {
22+
23+
private final TestLogger testLogger = new TestLogger();
24+
25+
public GenericContainer container1 = new GenericContainer(TestImages.ALPINE_IMAGE)
26+
.withContainerAlias("potato")
27+
.withStartupCheckStrategy(new OneShotStartupCheckStrategy())
28+
.withCommand("ls", "-al");
29+
30+
public GenericContainer container2 = new GenericContainer(TestImages.ALPINE_IMAGE)
31+
.withContainerAlias("monkey")
32+
.withStartupCheckStrategy(new OneShotStartupCheckStrategy())
33+
.withCommand("non-existing-command");
34+
35+
@BeforeEach
36+
void setUp() {
37+
testLogger.startCapturing();
38+
}
39+
40+
@AfterEach
41+
void tearDown() {
42+
testLogger.stopCapturing();
43+
}
44+
45+
@Test
46+
void checkOutput() {
47+
assertThatNoException()
48+
.isThrownBy(() -> {
49+
container1.start();
50+
});
51+
52+
assertThatThrownBy(() -> {
53+
container2.start();
54+
})
55+
.isInstanceOf(ContainerLaunchException.class)
56+
.hasMessage("Container startup failed for image alpine:3.17 (containerAlias='monkey')");
57+
58+
List<String> container1PotatoLogs = testLogger
59+
.getLogs()
60+
.stream()
61+
.filter(it -> "tc.alpine:3.17--potato".equals(it.getLoggerName()))
62+
.map(ILoggingEvent::getFormattedMessage)
63+
.toList();
64+
assertThat(container1PotatoLogs)
65+
.anyMatch(it -> it.equals("Creating container for image: alpine:3.17"))
66+
.anyMatch(it -> it.startsWith("Container alpine:3.17 is starting: "))
67+
.anyMatch(it -> it.startsWith("Container alpine:3.17 started in P"));
68+
69+
List<String> container2MonkeyLogs = testLogger
70+
.getLogs()
71+
.stream()
72+
.filter(it -> "tc.alpine:3.17--monkey".equals(it.getLoggerName()))
73+
.map(ILoggingEvent::getFormattedMessage)
74+
.toList();
75+
assertThat(container2MonkeyLogs)
76+
.anyMatch(it -> it.equals("Creating container for image: alpine:3.17"))
77+
.anyMatch(it -> it.startsWith("Container alpine:3.17 is starting: "))
78+
.anyMatch(it -> it.equals("Could not start container"))
79+
.anyMatch(it -> it.equals("There are no stdout/stderr logs available for the failed container"));
80+
}
81+
}
82+
83+
class TestLogger {
84+
85+
private final ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
86+
87+
public void startCapturing() {
88+
Logger rootLogger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
89+
listAppender.start();
90+
rootLogger.addAppender(listAppender);
91+
}
92+
93+
public void stopCapturing() {
94+
Logger rootLogger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
95+
rootLogger.detachAppender(listAppender);
96+
listAppender.stop();
97+
}
98+
99+
public List<ILoggingEvent> getLogs() {
100+
return listAppender.list;
101+
}
102+
}

0 commit comments

Comments
 (0)