skip to Main Content

I am writing integration tests for AWS lambda function that is invoked with KinesisEvent and then writes some data to Redis and Kafka.
I am using LocalStack and Testcontainers to achieve the same.

I have tested the code with docker-compose.yml, and it works fine. But something goes wrong in Java tests.

Here are my container settings –

@ClassRule
  public static final LocalStackContainer localstack =
      new LocalStackContainer(localstackImage)
          .withEnv("AWS_DEFAULT_REGION", US_EAST_1.getName())
              .withNetwork(lambdaNetwork)
          .withServices(Service.KINESIS, Service.LAMBDA);

  @ClassRule
  public static final KafkaContainer kafkaContainer =
      new KafkaContainer(kafkaImage).withNetwork(lambdaNetwork).withExposedPorts(9093);

    redisContainer = new GenericContainer<>(redisImage).withNetwork(lambdaNetwork).withExposedPorts(6379);
    redisContainer.start();

    String redisHost = redisContainer.getHost();
    Integer redisPort = redisContainer.getFirstMappedPort();

When I put record on kinesis, lambda is invoked successfully, however I get following exception –

2023-08-24T18:41:03.309  WARN --- [   asgi_gw_1] l.s.a.i.executor_endpoint  : Execution environment startup failed: {"errorMessage":"Failed to connect to any host resolved for DNS name.","errorType":"redis.clients.jedis.exceptions.JedisConnectionException"}

I am also setting up network for containers. Can someone point out what could I be missing?

2

Answers


  1. Chosen as BEST ANSWER

    Thanks to Eddu! His piece along with port mappings helped.

        List<String> portBindings = new ArrayList<>(); portBindings.add("6379:6379"); // hostPort:containerPort 
    redisContainer =
            new GenericContainer<>(redisImage)
                .withNetwork(lambdaNetwork)
                .withNetworkMode(lambdaNetwork.getId())
                .withCreateContainerCmdModifier(
                    new Consumer<CreateContainerCmd>() {
                      @Override
                      public void accept(CreateContainerCmd createContainerCmd) {
                        createContainerCmd.withHostName("cache");
                        createContainerCmd.withName("cache");
                      }
                    })
                .withExtraHost("host.docker.internal", "host-gateway")
                .withCommand("redis-server", "--save", "20", "1", "--loglevel", "warning")
                .withNetworkAliases("cache")
                .withExposedPorts(6379); redisContainer.setPortBindings(portBindings); redisContainer.start();
    

  2. Having the following definition will allow to have the three containers use the same network

    • Postgres container
    • LocalStack container
    • Lambda container created by LocalStack
    static Network network = Network.newNetwork();
    
        @Container
        static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15-alpine")
                .withNetwork(network)
                .withNetworkAliases("postgres");
    
        @Container
        static LocalStackContainer localstack = new LocalStackContainer(DockerImageName.parse("localstack/localstack:2.2.0"))
                .withNetwork(network)
                .withEnv("LAMBDA_DOCKER_NETWORK", ((Network.NetworkImpl)network).getName())
                .withNetworkAliases("localstack");
    

    the key part is .withEnv("LAMBDA_DOCKER_NETWORK", ((Network.NetworkImpl)network).getName()) in LocalStackContainer

    Take into account to use the following information to connect from the lambda to postgres (in this example)

    url=jdbc:postgresql://postgres:5432/test
    username=test
    password=test
    

    Network alias postgres was declared in PostgresContainer, so it should be used by the lambda in order to connect through the docker network.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search