Skip to content

Commit

Permalink
[localstack] Fix reuse mode (#8844)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
eddumelendez authored Jul 4, 2024
1 parent 055839e commit 7989b20
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.testcontainers.containers.localstack;

import com.github.dockerjava.api.command.InspectContainerResponse;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
Expand All @@ -8,9 +9,9 @@
import org.testcontainers.DockerClientFactory;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.Transferable;
import org.testcontainers.utility.ComparableVersion;
import org.testcontainers.utility.DockerImageName;
import org.testcontainers.utility.ResourceReaper;

import java.net.InetAddress;
import java.net.URI;
Expand All @@ -20,7 +21,6 @@
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* Testcontainers implementation for LocalStack.
Expand Down Expand Up @@ -53,6 +53,8 @@ public class LocalStackContainer extends GenericContainer<LocalStackContainer> {

private static final String DEFAULT_AWS_SECRET_ACCESS_KEY = "test";

private static final String STARTER_SCRIPT = "/testcontainers_start.sh";

@Deprecated
public static final String VERSION = DEFAULT_TAG;

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

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

private static boolean isVersion2(String version) {
Expand Down Expand Up @@ -167,34 +171,6 @@ static boolean shouldRunInLegacyMode(String version) {
return true;
}

/**
* Provides a docker argument string including all default labels set on testcontainer containers
* @return Argument string in the format `-l key1=value1 -l key2=value2`
*/
private static String internalMarkerLabels() {
return Stream
.concat(
DockerClientFactory.DEFAULT_LABELS.entrySet().stream(),
ResourceReaper.instance().getLabels().entrySet().stream()
)
.map(entry -> String.format("-l %s=%s", entry.getKey(), entry.getValue()))
.collect(Collectors.joining(" "));
}

/**
* Configure the LocalStack container to include the default testcontainer labels on all spawned lambda containers
* Necessary to properly clean up lambda containers even if the LocalStack container is killed before it gets the
* chance.
*/
private void configureLambdaContainerLabels() {
String lambdaDockerFlags = internalMarkerLabels();
String existingLambdaDockerFlags = getEnvMap().get("LAMBDA_DOCKER_FLAGS");
if (existingLambdaDockerFlags != null) {
lambdaDockerFlags = existingLambdaDockerFlags + " " + lambdaDockerFlags;
}
withEnv("LAMBDA_DOCKER_FLAGS", lambdaDockerFlags);
}

@Override
protected void configure() {
super.configure();
Expand All @@ -217,7 +193,50 @@ protected void configure() {
}

exposePorts();
configureLambdaContainerLabels();
}

@Override
protected void containerIsStarting(InspectContainerResponse containerInfo) {
String command = "#!/bin/bash\n";
command += "export LAMBDA_DOCKER_FLAGS=" + configureLambdaContainerLabels() + "\n";
command += "/usr/local/bin/docker-entrypoint.sh\n";
copyFileToContainer(Transferable.of(command, 0777), STARTER_SCRIPT);
}

/**
* Configure the LocalStack container to include the default testcontainers labels on all spawned lambda containers
* Necessary to properly clean up lambda containers even if the LocalStack container is killed before it gets the
* chance.
* @return the lambda container labels as a string
*/
private String configureLambdaContainerLabels() {
String lambdaDockerFlags = internalMarkerLabels();
String existingLambdaDockerFlags = getEnvMap().get("LAMBDA_DOCKER_FLAGS");
if (existingLambdaDockerFlags != null) {
lambdaDockerFlags = existingLambdaDockerFlags + " " + lambdaDockerFlags;
}
return "\"" + lambdaDockerFlags + "\"";
}

/**
* Provides a docker argument string including all default labels set on testcontainers containers (excluding reuse labels)
* @return Argument string in the format `-l key1=value1 -l key2=value2`
*/
private String internalMarkerLabels() {
return getContainerInfo()
.getConfig()
.getLabels()
.entrySet()
.stream()
.filter(entry -> entry.getKey().startsWith(DockerClientFactory.TESTCONTAINERS_LABEL))
.filter(entry -> {
return (
!entry.getKey().equals("org.testcontainers.hash") &&
!entry.getKey().equals("org.testcontainers.copied_files.hash")
);
})
.map(entry -> String.format("-l %s=%s", entry.getKey(), entry.getValue()))
.collect(Collectors.joining(" "));
}

private void resolveHostname(String envVar) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ public static Iterable<Object[]> constructors() {
{ "0.12", new LocalStackContainer(LocalstackTestImages.LOCALSTACK_0_12_IMAGE) },
{ "0.11", new LocalStackContainer(LocalstackTestImages.LOCALSTACK_0_11_IMAGE) },
{
"0.7 with legacy = off",
new LocalStackContainer(LocalstackTestImages.LOCALSTACK_0_7_IMAGE, false),
"0.11 with legacy = off",
new LocalStackContainer(LocalstackTestImages.LOCALSTACK_0_11_IMAGE, false),
},
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

public interface LocalstackTestImages {
DockerImageName LOCALSTACK_IMAGE = DockerImageName.parse("localstack/localstack:0.12.8");
DockerImageName LOCALSTACK_0_7_IMAGE = LOCALSTACK_IMAGE.withTag("0.7.0");
DockerImageName LOCALSTACK_0_10_IMAGE = LOCALSTACK_IMAGE.withTag("0.10.7");
DockerImageName LOCALSTACK_0_11_IMAGE = LOCALSTACK_IMAGE.withTag("0.11.3");
DockerImageName LOCALSTACK_0_12_IMAGE = LOCALSTACK_IMAGE.withTag("0.12.8");
Expand Down

0 comments on commit 7989b20

Please sign in to comment.