Skip to content

Commit 7989b20

Browse files
authored
[localstack] Fix reuse mode (#8844)
2195610 allows to copy all `org.testcontainers.*` labels to `LAMBDA_DOCKER_FLAGS` and it generates a `session-id` breaking reuse mode. This commit waits until the container is starting with the right labels and then read the labels to set `LAMBDA_DOCKER_FLAGS`. Fixes #8814
1 parent 055839e commit 7989b20

File tree

3 files changed

+52
-34
lines changed

3 files changed

+52
-34
lines changed

modules/localstack/src/main/java/org/testcontainers/containers/localstack/LocalStackContainer.java

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.testcontainers.containers.localstack;
22

3+
import com.github.dockerjava.api.command.InspectContainerResponse;
34
import lombok.Getter;
45
import lombok.RequiredArgsConstructor;
56
import lombok.experimental.FieldDefaults;
@@ -8,9 +9,9 @@
89
import org.testcontainers.DockerClientFactory;
910
import org.testcontainers.containers.GenericContainer;
1011
import org.testcontainers.containers.wait.strategy.Wait;
12+
import org.testcontainers.images.builder.Transferable;
1113
import org.testcontainers.utility.ComparableVersion;
1214
import org.testcontainers.utility.DockerImageName;
13-
import org.testcontainers.utility.ResourceReaper;
1415

1516
import java.net.InetAddress;
1617
import java.net.URI;
@@ -20,7 +21,6 @@
2021
import java.util.Arrays;
2122
import java.util.List;
2223
import java.util.stream.Collectors;
23-
import java.util.stream.Stream;
2424

2525
/**
2626
* Testcontainers implementation for LocalStack.
@@ -53,6 +53,8 @@ public class LocalStackContainer extends GenericContainer<LocalStackContainer> {
5353

5454
private static final String DEFAULT_AWS_SECRET_ACCESS_KEY = "test";
5555

56+
private static final String STARTER_SCRIPT = "/testcontainers_start.sh";
57+
5658
@Deprecated
5759
public static final String VERSION = DEFAULT_TAG;
5860

@@ -121,6 +123,8 @@ public LocalStackContainer(final DockerImageName dockerImageName, boolean useLeg
121123

122124
withFileSystemBind(DockerClientFactory.instance().getRemoteDockerUnixSocketPath(), "/var/run/docker.sock");
123125
waitingFor(Wait.forLogMessage(".*Ready\\.\n", 1));
126+
withCreateContainerCmdModifier(cmd -> cmd.withEntrypoint("sh"));
127+
setCommand("-c", "while [ ! -f " + STARTER_SCRIPT + " ]; do sleep 0.1; done; " + STARTER_SCRIPT);
124128
}
125129

126130
private static boolean isVersion2(String version) {
@@ -167,34 +171,6 @@ static boolean shouldRunInLegacyMode(String version) {
167171
return true;
168172
}
169173

170-
/**
171-
* Provides a docker argument string including all default labels set on testcontainer containers
172-
* @return Argument string in the format `-l key1=value1 -l key2=value2`
173-
*/
174-
private static String internalMarkerLabels() {
175-
return Stream
176-
.concat(
177-
DockerClientFactory.DEFAULT_LABELS.entrySet().stream(),
178-
ResourceReaper.instance().getLabels().entrySet().stream()
179-
)
180-
.map(entry -> String.format("-l %s=%s", entry.getKey(), entry.getValue()))
181-
.collect(Collectors.joining(" "));
182-
}
183-
184-
/**
185-
* Configure the LocalStack container to include the default testcontainer labels on all spawned lambda containers
186-
* Necessary to properly clean up lambda containers even if the LocalStack container is killed before it gets the
187-
* chance.
188-
*/
189-
private void configureLambdaContainerLabels() {
190-
String lambdaDockerFlags = internalMarkerLabels();
191-
String existingLambdaDockerFlags = getEnvMap().get("LAMBDA_DOCKER_FLAGS");
192-
if (existingLambdaDockerFlags != null) {
193-
lambdaDockerFlags = existingLambdaDockerFlags + " " + lambdaDockerFlags;
194-
}
195-
withEnv("LAMBDA_DOCKER_FLAGS", lambdaDockerFlags);
196-
}
197-
198174
@Override
199175
protected void configure() {
200176
super.configure();
@@ -217,7 +193,50 @@ protected void configure() {
217193
}
218194

219195
exposePorts();
220-
configureLambdaContainerLabels();
196+
}
197+
198+
@Override
199+
protected void containerIsStarting(InspectContainerResponse containerInfo) {
200+
String command = "#!/bin/bash\n";
201+
command += "export LAMBDA_DOCKER_FLAGS=" + configureLambdaContainerLabels() + "\n";
202+
command += "/usr/local/bin/docker-entrypoint.sh\n";
203+
copyFileToContainer(Transferable.of(command, 0777), STARTER_SCRIPT);
204+
}
205+
206+
/**
207+
* Configure the LocalStack container to include the default testcontainers labels on all spawned lambda containers
208+
* Necessary to properly clean up lambda containers even if the LocalStack container is killed before it gets the
209+
* chance.
210+
* @return the lambda container labels as a string
211+
*/
212+
private String configureLambdaContainerLabels() {
213+
String lambdaDockerFlags = internalMarkerLabels();
214+
String existingLambdaDockerFlags = getEnvMap().get("LAMBDA_DOCKER_FLAGS");
215+
if (existingLambdaDockerFlags != null) {
216+
lambdaDockerFlags = existingLambdaDockerFlags + " " + lambdaDockerFlags;
217+
}
218+
return "\"" + lambdaDockerFlags + "\"";
219+
}
220+
221+
/**
222+
* Provides a docker argument string including all default labels set on testcontainers containers (excluding reuse labels)
223+
* @return Argument string in the format `-l key1=value1 -l key2=value2`
224+
*/
225+
private String internalMarkerLabels() {
226+
return getContainerInfo()
227+
.getConfig()
228+
.getLabels()
229+
.entrySet()
230+
.stream()
231+
.filter(entry -> entry.getKey().startsWith(DockerClientFactory.TESTCONTAINERS_LABEL))
232+
.filter(entry -> {
233+
return (
234+
!entry.getKey().equals("org.testcontainers.hash") &&
235+
!entry.getKey().equals("org.testcontainers.copied_files.hash")
236+
);
237+
})
238+
.map(entry -> String.format("-l %s=%s", entry.getKey(), entry.getValue()))
239+
.collect(Collectors.joining(" "));
221240
}
222241

223242
private void resolveHostname(String envVar) {

modules/localstack/src/test/java/org/testcontainers/containers/localstack/LegacyModeTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ public static Iterable<Object[]> constructors() {
3737
{ "0.12", new LocalStackContainer(LocalstackTestImages.LOCALSTACK_0_12_IMAGE) },
3838
{ "0.11", new LocalStackContainer(LocalstackTestImages.LOCALSTACK_0_11_IMAGE) },
3939
{
40-
"0.7 with legacy = off",
41-
new LocalStackContainer(LocalstackTestImages.LOCALSTACK_0_7_IMAGE, false),
40+
"0.11 with legacy = off",
41+
new LocalStackContainer(LocalstackTestImages.LOCALSTACK_0_11_IMAGE, false),
4242
},
4343
}
4444
);

modules/localstack/src/test/java/org/testcontainers/containers/localstack/LocalstackTestImages.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
public interface LocalstackTestImages {
66
DockerImageName LOCALSTACK_IMAGE = DockerImageName.parse("localstack/localstack:0.12.8");
7-
DockerImageName LOCALSTACK_0_7_IMAGE = LOCALSTACK_IMAGE.withTag("0.7.0");
87
DockerImageName LOCALSTACK_0_10_IMAGE = LOCALSTACK_IMAGE.withTag("0.10.7");
98
DockerImageName LOCALSTACK_0_11_IMAGE = LOCALSTACK_IMAGE.withTag("0.11.3");
109
DockerImageName LOCALSTACK_0_12_IMAGE = LOCALSTACK_IMAGE.withTag("0.12.8");

0 commit comments

Comments
 (0)