2121import java .util .stream .Collectors ;
2222
2323/**
24- * <p>Container for LocalStack, 'A fully functional local AWS cloud stack'.</p>
25- * <p>{@link LocalStackContainer#withServices(Service...)} should be used to select which services
26- * are to be launched. See {@link Service} for available choices.
24+ * Testcontainers implementation for LocalStack.
2725 */
2826@ Slf4j
2927public class LocalStackContainer extends GenericContainer <LocalStackContainer > {
3028
3129 static final int PORT = 4566 ;
3230
31+ @ Deprecated
3332 private static final String HOSTNAME_EXTERNAL_ENV_VAR = "HOSTNAME_EXTERNAL" ;
3433
34+ private static final String LOCALSTACK_HOST_ENV_VAR = "LOCALSTACK_HOST" ;
35+
3536 private final List <EnabledService > services = new ArrayList <>();
3637
3738 private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName .parse ("localstack/localstack" );
@@ -66,6 +67,8 @@ public class LocalStackContainer extends GenericContainer<LocalStackContainer> {
6667 */
6768 private final boolean servicesEnvVarRequired ;
6869
70+ private final boolean isVersion2 ;
71+
6972 /**
7073 * @deprecated use {@link LocalStackContainer(DockerImageName)} instead
7174 */
@@ -92,18 +95,31 @@ public LocalStackContainer(final DockerImageName dockerImageName) {
9295 /**
9396 * @param dockerImageName image name to use for Localstack
9497 * @param useLegacyMode if true, each AWS service is exposed on a different port
98+ * @deprecated use {@link LocalStackContainer(DockerImageName)} instead
9599 */
100+ @ Deprecated
96101 public LocalStackContainer (final DockerImageName dockerImageName , boolean useLegacyMode ) {
97102 super (dockerImageName );
98103 dockerImageName .assertCompatibleWith (DEFAULT_IMAGE_NAME );
99104
100105 this .legacyMode = useLegacyMode ;
101- this .servicesEnvVarRequired = isServicesEnvVarRequired (dockerImageName .getVersionPart ());
106+ String version = dockerImageName .getVersionPart ();
107+ this .servicesEnvVarRequired = isServicesEnvVarRequired (version );
108+ this .isVersion2 = isVersion2 (version );
102109
103110 withFileSystemBind (DockerClientFactory .instance ().getRemoteDockerUnixSocketPath (), "/var/run/docker.sock" );
104111 waitingFor (Wait .forLogMessage (".*Ready\\ .\n " , 1 ));
105112 }
106113
114+ private static boolean isVersion2 (String version ) {
115+ if (version .equals ("latest" )) {
116+ return true ;
117+ }
118+
119+ ComparableVersion comparableVersion = new ComparableVersion (version );
120+ return comparableVersion .isGreaterThanOrEqualTo ("2.0.0" );
121+ }
122+
107123 private static boolean isServicesEnvVarRequired (String version ) {
108124 if (version .equals ("latest" )) {
109125 return false ;
@@ -141,7 +157,7 @@ private static boolean shouldRunInLegacyMode(String version) {
141157 protected void configure () {
142158 super .configure ();
143159
144- if (servicesEnvVarRequired ) {
160+ if (this . servicesEnvVarRequired ) {
145161 Preconditions .check ("services list must not be empty" , !services .isEmpty ());
146162 }
147163
@@ -152,26 +168,30 @@ protected void configure() {
152168 }
153169 }
154170
171+ if (this .isVersion2 ) {
172+ resolveHostname (LOCALSTACK_HOST_ENV_VAR );
173+ } else {
174+ resolveHostname (HOSTNAME_EXTERNAL_ENV_VAR );
175+ }
176+
177+ exposePorts ();
178+ }
179+
180+ private void resolveHostname (String envVar ) {
155181 String hostnameExternalReason ;
156- if (getEnvMap ().containsKey (HOSTNAME_EXTERNAL_ENV_VAR )) {
182+ if (getEnvMap ().containsKey (envVar )) {
157183 // do nothing
158184 hostnameExternalReason = "explicitly as environment variable" ;
159185 } else if (getNetwork () != null && getNetworkAliases () != null && getNetworkAliases ().size () >= 1 ) {
160- withEnv (HOSTNAME_EXTERNAL_ENV_VAR , getNetworkAliases ().get (getNetworkAliases ().size () - 1 )); // use the last network alias set
186+ withEnv (envVar , getNetworkAliases ().get (getNetworkAliases ().size () - 1 )); // use the last network alias set
161187 hostnameExternalReason = "to match last network alias on container with non-default network" ;
162188 } else {
163- withEnv (HOSTNAME_EXTERNAL_ENV_VAR , getHost ());
189+ withEnv (envVar , getHost ());
164190 hostnameExternalReason = "to match host-routable address for container" ;
165191 }
166- logger ()
167- .info (
168- "{} environment variable set to {} ({})" ,
169- HOSTNAME_EXTERNAL_ENV_VAR ,
170- getEnvMap ().get (HOSTNAME_EXTERNAL_ENV_VAR ),
171- hostnameExternalReason
172- );
173192
174- exposePorts ();
193+ logger ()
194+ .info ("{} environment variable set to {} ({})" , envVar , getEnvMap ().get (envVar ), hostnameExternalReason );
175195 }
176196
177197 private void exposePorts () {
0 commit comments