testcontainers-scala icon indicating copy to clipboard operation
testcontainers-scala copied to clipboard

Couldn't get mapped port for localstackv2 container

Open sebarys opened this issue 3 years ago • 6 comments

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 :)

sebarys avatar Nov 24 '20 08:11 sebarys

@jbwheatley do you know what that could be?

dimafeng avatar Nov 24 '20 14:11 dimafeng

I'm not sure.. its a very thin wrapper around the java container, so I would think its an underlying problem there 🤔

jbwheatley avatar Nov 24 '20 15:11 jbwheatley

Are you able to verify if you see the same issue when running such test snippet?

sebarys avatar Nov 24 '20 15:11 sebarys

@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?

jbwheatley avatar Nov 24 '20 16:11 jbwheatley

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.

sebarys avatar Nov 25 '20 07:11 sebarys

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

sebarys avatar Nov 25 '20 17:11 sebarys