testcontainers-scala
testcontainers-scala copied to clipboard
Couldn't get mapped port for localstackv2 container
Hi,
I was trying to use localstackV2 container in my tests. Unfortunately during attempt of setup it I'm not able to retrieve lambda mapper port properly.
Used dependencies
//aws lambda SDK
"software.amazon.awssdk" % "lambda" % awsSdkVersion,
"software.amazon.awssdk" % "netty-nio-client" % awsSdkVersion,
"org.scalatest" %% "scalatest" % "3.1.4" % Test,
"com.dimafeng" %% "testcontainers-scala-scalatest" % "0.38.7" % Test,
"com.dimafeng" %% "testcontainers-scala-localstack-v2" % "0.38.7" % Test,
// https://github.com/testcontainers/testcontainers-java/issues/1442
"com.amazonaws" % "aws-java-sdk-lambda" % "1.11.906" % Test
Example test (tried with 0.9.4
and 0.11.2
):
import com.dimafeng.testcontainers.{ForAllTestContainer, LocalStackV2Container}
import com.sap.cds.lambdacontroller.lambda.upsert.repositories.CreateRepository.FunctionCreated
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec
import org.testcontainers.containers.localstack.LocalStackContainer.Service
import software.amazon.awssdk.services.lambda.LambdaAsyncClient
class TestSpec extends AsyncWordSpec with Matchers with ForAllTestContainer {
override def container: LocalStackV2Container = LocalStackV2Container(services = Seq(Service.LAMBDA))
"A TestSpec" when {
"is called to create non existing AWS lambda function" should {
"create function and return version" in {
//given
val lambdaClient: LambdaAsyncClient = LambdaAsyncClient.builder()
.endpointOverride(container.endpointOverride(Service.LAMBDA))
.credentialsProvider(container.staticCredentialsProvider)
.region(container.region)
.build()
val createFunctionRequest = ???
val createRepository = new CreateRepository(lambdaClient)
//when
val createFunctionRes = createRepository.createFunction(createFunctionRequest)
//then
createFunctionRes.map { res =>
res shouldBe FunctionCreated("someVersionId")
}
}
}
}
}
result in exception during calling endpointOverride(container.endpointOverride(Service.LAMBDA))
:
Mapped port can only be obtained after the container is started
java.lang.IllegalStateException: Mapped port can only be obtained after the container is started
at org.testcontainers.shaded.com.google.common.base.Preconditions.checkState(Preconditions.java:174)
at org.testcontainers.containers.ContainerState.getMappedPort(ContainerState.java:141)
at org.testcontainers.containers.localstack.LocalStackContainer.getEndpointOverride(LocalStackContainer.java:215)
at com.dimafeng.testcontainers.LocalStackV2Container.endpointOverride(LocalStackV2Container.scala:21)
at com.sap.cds.lambdacontroller.lambda.upsert.repositories.TestSpec.$anonfun$new$3(TestSpec.scala:31)
at org.scalatest.wordspec.AsyncWordSpecLike.transformToOutcomeParam$1(AsyncWordSpecLike.scala:134)
...
Does anyone have an idea why it is happening? When I will put Thread.sleep(50000)
before LambdaAsyncClient
initialisation I am able to verify that localstack container is running and exposing lambda port:
~ $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
95fd869bce80 localstack/localstack:0.9.4 "docker-entrypoint.sh" 10 seconds ago Up 9 seconds 0.0.0.0:33877->4567/tcp, 0.0.0.0:33876->4568/tcp, 0.0.0.0:33875->4569/tcp, 0.0.0.0:33874->4570/tcp, 0.0.0.0:33873->4571/tcp, 0.0.0.0:33872->4572/tcp, 0.0.0.0:33871->4573/tcp, 0.0.0.0:33870->4574/tcp, 0.0.0.0:33869->4575/tcp, 0.0.0.0:33868->4576/tcp, 0.0.0.0:33867->4577/tcp, 0.0.0.0:33866->4578/tcp, 0.0.0.0:33865->4579/tcp, 0.0.0.0:33864->4580/tcp, 0.0.0.0:33863->4581/tcp, 0.0.0.0:33862->4582/tcp, 0.0.0.0:33861->4583/tcp, 0.0.0.0:33860->4584/tcp, 0.0.0.0:33859->4585/tcp, 0.0.0.0:33858->4586/tcp, 0.0.0.0:33857->4587/tcp, 0.0.0.0:33856->4588/tcp, 0.0.0.0:33855->4589/tcp, 0.0.0.0:33854->4590/tcp, 0.0.0.0:33853->4591/tcp, 0.0.0.0:33852->4592/tcp, 0.0.0.0:33851->4593/tcp, 0.0.0.0:33850->8080/tcp sharp_joliot
c00731ec1023 testcontainers/ryuk:0.3.0 "/app" 12 seconds ago Up 10 seconds 0.0.0.0:33849->8080/tcp testcontainers-ryuk-603688a4-bfef-4a47-85e4-46fff3705035
~ $ docker logs 95fd869bce80
Waiting for all LocalStack services to be ready
2020-11-24 08:58:00,799 CRIT Supervisor is running as root. Privileges were not dropped because no user is specified in the config file. If you intend to run as root, you can set user=root in the config file to avoid this message.
2020-11-24 08:58:00,801 INFO supervisord started with pid 10
2020-11-24 08:58:01,808 INFO spawned: 'dashboard' with pid 18
2020-11-24 08:58:01,812 INFO spawned: 'infra' with pid 19
(. .venv/bin/activate; bin/localstack web)
2020-11-24 08:58:01,818 INFO success: dashboard entered RUNNING state, process has stayed up for > than 0 seconds (startsecs)
(. .venv/bin/activate; exec bin/localstack start)
2020-11-24 08:58:02,820 INFO success: infra entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
Starting local dev environment. CTRL-C to quit.
Starting mock Lambda service (http port 4574)...
Starting mock CloudWatch Logs (http port 4586)...
Waiting for all LocalStack services to be ready
Ready.
~ $ aws --endpoint-url=http://localhost:33870 lambda list-functions
{
"Functions": []
}
Thanks in advance for any suggestions :)
@jbwheatley do you know what that could be?
I'm not sure.. its a very thin wrapper around the java container, so I would think its an underlying problem there 🤔
Are you able to verify if you see the same issue when running such test snippet?
@sebarys I did manage to recreate it. Changing this line override def container: LocalStackV2Container = LocalStackV2Container(services = Seq(Service.LAMBDA))
to be a val
rather than a def
fixed it for me.
Also good point about the class path issues with aws-v2 https://github.com/testcontainers/testcontainers-java/issues/1442#issuecomment-694342883
@dimafeng should a note in the readme be added to alert users to this issue with the java container?
Hi,
Thanks it helped! :)
Regarding documentation: did you know by chance why testcontainers reuse
feature is not documented at all? I know that it is not stable API, but using it if you don't use hardcoded the same identifiers in all tests could significantly reduce tests times.
Anyway @jbwheatley LocalstacvV2 module is not mentioned in docu https://github.com/testcontainers/testcontainers-scala#modules I think it would be worth here to mention it