Can't start localstack on Gitlab runner with LocalstackTestRunner

Viewed 841

I have an issue of running Java integration tests with LocalstackTestRunner on Gitlab agent. I've taken example from official localstack site:

import cloud.localstack.LocalstackTestRunner;
import cloud.localstack.TestUtils;
import cloud.localstack.docker.annotation.LocalstackDockerProperties;

@RunWith(LocalstackTestRunner.class)
@LocalstackDockerProperties(services = { "s3", "sqs", "kinesis:77077" })
public class MyCloudAppTest {

  @Test
  public void testLocalS3API() {
    AmazonS3 s3 = TestUtils.getClientS3();
    List<Bucket> buckets = s3.listBuckets();
  }
}

and run it with help of gradle as gradle clean test. If I run it locally on my Mac Book - all is ok but if it's run on Gitlab agent - there is an issue:

com.amazonaws.SdkClientException: Unable to execute HTTP request: Connect to localhost.localstack.cloud:4566 [localhost.localstack.cloud/127.0.0.1] failed: Connection refused (Connection refused)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleRetryableException(AmazonHttpClient.java:1207)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1153)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:802)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:770)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:744)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:704)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:686)

My gitlab ci job looks likes as follows:

Localstack_test:
  stage: test
  services:
    - docker:dind
  when: always
  script:
    - ./gradlew clean test --stacktrace

It happens that S3 client can't connect to localhost.localstack.cloud:4566 because docker container created by LocalstackTestRunner is started within parent docker:dind container and AmazonS3 client can't access it. I've tried with other AWS services - result is the same - AWS client can't access localstack endpoint.

I've found some workaround as follows:

  • add localstack as service in gitlab-ci
  • add alias to it
  • expose env variable HOSTNAME_EXTERNAL=alias
  • Make an implementation of IHostNameResolver to return my alias as HOSTNAME_EXTERNAL specified in gitlab-ci.

Something like that:

Gitlab-ci:

Localstack_test:
  stage: test
  services:
    - docker:dind
    - name: localstack/localstack
      alias: localstack-it
  variables:
    HOSTNAME_EXTERNAL: "localstack-it"
  when: always
  script:
    - ./gradlew clean test --stacktrace |& tee -a ./gradle.log

Java IT test:

@RunWith(LocalstackTestRunner.class)
@LocalstackDockerProperties(
        services = { "s3", "sqs", "kinesis:77077" },
        hostNameResolver = SystemEnvHostNameResolver.class
)
public class MyCloudAppTest {

    @Test
    public void testLocalS3API() {
        AmazonS3 s3 = TestUtils.getClientS3();
        List<Bucket> buckets = s3.listBuckets();
    }
}

public class SystemEnvHostNameResolver implements IHostNameResolver {
    private static final String HOSTNAME_EXTERNAL = "HOSTNAME_EXTERNAL";

    @Override
    public String getHostName() {
        String external = System.getenv(HOSTNAME_EXTERNAL);
        return !Strings.isNullOrEmpty(external) ?
                external :
                new LocalHostNameResolver().getHostName();
    }
}

It works but as a result 2 localstack Docker containers are run and internal docker container is still not available. Maybe does somebody know better solution?

STR:

  • gradle-6.7
  • cloud.localstack:localstack-utils:0.2.5
0 Answers
Related