All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cloud.localstack.docker.LocalstackDockerTestRunner Maven / Gradle / Ivy

package cloud.localstack.docker;

import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;

import cloud.localstack.LocalstackTestRunner;
import cloud.localstack.ServiceName;
import cloud.localstack.docker.annotation.IEnvironmentVariableProvider;
import cloud.localstack.docker.annotation.IHostNameResolver;
import cloud.localstack.docker.annotation.LocalstackDockerProperties;
import cloud.localstack.docker.command.RegexStream;

/**
 * JUnit test runner that automatically pulls and runs the latest localstack docker image
 * and then terminates when tests are complete.
 *
 * Having docker installed is a prerequisite for this test runner to execute.  If docker
 * is not installed in one of the default locations (C:\program files\docker\docker\resources\bin\, usr/local/bin or usr/bin)
 * then use the DOCKER_LOCATION environment variable to specify the location.
 *
 * Since ports are dynamically allocated, the external port needs to be resolved based on the default localstack port.
 *
 * The hostname defaults to localhost, but in some environments that is not sufficient, so the HostName can be specified
 * by using the LocalstackDockerProperties annotation with an IHostNameResolver.
 *
 * @author Alan Bevier
 */
public class LocalstackDockerTestRunner extends BlockJUnit4ClassRunner {

    private static final Logger LOG = Logger.getLogger(LocalstackDockerTestRunner.class.getName());

    private static String externalHostName = "localhost";
    private static boolean pullNewImage = true;
    private static boolean randomizePorts = false;
    private static Map environmentVariables = new HashMap<>();

    @Getter
    private static LocalstackDocker localstackDocker = LocalstackDocker.getLocalstackDocker();


    public LocalstackDockerTestRunner(Class klass) throws InitializationError {
        super(klass);
        processAnnotations(klass.getAnnotations());
    }

    @Override
    public void run(RunNotifier notifier) {
        localstackDocker.setExternalHostName(externalHostName);
        localstackDocker.setPullNewImage(pullNewImage);
        localstackDocker.setRandomizePorts(randomizePorts);
        localstackDocker.setEnvironmentVariables(environmentVariables);

        try {
            localstackDocker.startup();
            super.run(notifier);
        }
        finally {
            localstackDocker.stop();
        }
    }

    private void processAnnotations(Annotation[] annotations) {
        for(Annotation annotation : annotations) {
            if(annotation instanceof LocalstackDockerProperties) {
                processDockerPropertiesAnnotation((LocalstackDockerProperties)annotation);
            }
        }
    }


    private void processDockerPropertiesAnnotation(LocalstackDockerProperties properties) {
        pullNewImage = properties.pullNewImage();
        randomizePorts = properties.randomizePorts();

        try {
            IHostNameResolver hostNameResolver = properties.hostNameResolver().newInstance();
            String resolvedName = hostNameResolver.getHostName();
            if(StringUtils.isNotBlank(resolvedName)) {
                externalHostName = resolvedName;
            }
            LOG.info("External host name is set to: " + externalHostName);
        }
        catch(InstantiationException | IllegalAccessException ex) {
            throw new IllegalStateException("Unable to resolve hostname", ex);
        }

        try {
            IEnvironmentVariableProvider environmentProvider = properties.environmentVariableProvider().newInstance();
            environmentVariables = environmentProvider.getEnvironmentVariables();
        }
        catch(InstantiationException | IllegalAccessException ex) {
            throw new IllegalStateException("Unable to get environment variables", ex);
        }

        String services = String.join(",", properties.services());
        if(StringUtils.isNotEmpty(services)) {
            environmentVariables.put("SERVICES", services);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy