diff --git a/pom.xml b/pom.xml index 065dac5..9d82f36 100644 --- a/pom.xml +++ b/pom.xml @@ -91,11 +91,6 @@ 1.2.3 test - - com.github.docker-java - docker-java - 3.2.13 - diff --git a/src/main/java/org/testcontainers/containers/TarantoolCartridgeContainer.java b/src/main/java/org/testcontainers/containers/TarantoolCartridgeContainer.java index 86e39ef..85122ce 100644 --- a/src/main/java/org/testcontainers/containers/TarantoolCartridgeContainer.java +++ b/src/main/java/org/testcontainers/containers/TarantoolCartridgeContainer.java @@ -2,16 +2,15 @@ import com.github.dockerjava.api.command.InspectContainerResponse; import io.tarantool.driver.exceptions.TarantoolConnectionException; -import org.testcontainers.images.builder.ImageFromDockerfile; import java.net.URL; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; import java.util.concurrent.TimeoutException; import static org.testcontainers.containers.PathUtils.normalizePath; @@ -88,16 +87,13 @@ public class TarantoolCartridgeContainer extends GenericContainer buildArgs) { - this(DOCKERFILE, "", instancesFile, topologyConfigurationFile, buildArgs); + this(DOCKERFILE, BUILD_IMAGE_NAME, instancesFile, topologyConfigurationFile, buildArgs); } /** @@ -148,7 +144,7 @@ public TarantoolCartridgeContainer(String instancesFile, String topologyConfigur * @param topologyConfigurationFile path to a topology bootstrap script, relative to the classpath resources */ public TarantoolCartridgeContainer(String dockerFile, String instancesFile, String topologyConfigurationFile) { - this(dockerFile, "", instancesFile, topologyConfigurationFile); + this(dockerFile, BUILD_IMAGE_NAME, instancesFile, topologyConfigurationFile); } /** @@ -181,13 +177,13 @@ public TarantoolCartridgeContainer(String dockerFile, String buildImageName, */ public TarantoolCartridgeContainer(String dockerFile, String buildImageName, String instancesFile, String topologyConfigurationFile, final Map buildArgs) { - this(withArguments(buildImage(dockerFile, buildImageName), instancesFile, buildArgs), - instancesFile, topologyConfigurationFile); + this(buildImage(dockerFile, buildImageName, buildArgs), instancesFile, topologyConfigurationFile); } - private TarantoolCartridgeContainer(Future image, String instancesFile, String topologyConfigurationFile) { - super(image); + private TarantoolCartridgeContainer(TarantoolImageParams tarantoolImageParams, String instancesFile, String topologyConfigurationFile) { + super(TarantoolContainerImageHelper.getImage(tarantoolImageParams)); + if (instancesFile == null || instancesFile.isEmpty()) { throw new IllegalArgumentException("Instance file name must not be null or empty"); } @@ -197,46 +193,44 @@ private TarantoolCartridgeContainer(Future image, String instancesFile, String fileType = topologyConfigurationFile.substring(topologyConfigurationFile.lastIndexOf('.') + 1); if (fileType.equals("lua")) { this.topologyConfigurationFile = topologyConfigurationFile; - }else{ - this.replicasetsFileName = topologyConfigurationFile.substring(topologyConfigurationFile.lastIndexOf('/')+1); + } else { + this.replicasetsFileName = topologyConfigurationFile.substring(topologyConfigurationFile.lastIndexOf('/') + 1); } this.instanceFileParser = new CartridgeConfigParser(instancesFile); this.clientHelper = new TarantoolContainerClientHelper(this); } - private static Future withArguments(ImageFromDockerfile image, String instancesFile, - final Map buildArgs) { - if (!buildArgs.isEmpty()) { - image.withBuildArgs(buildArgs); - } - + private static Map mergeBuildArgsWithEnv(final Map buildArgs) { + Map args = new HashMap<>(buildArgs); for (String envVariable : Arrays.asList( ENV_TARANTOOL_VERSION, - ENV_TARANTOOL_SERVER_USER, - ENV_TARANTOOL_SERVER_UID, - ENV_TARANTOOL_SERVER_GROUP, - ENV_TARANTOOL_SERVER_GID, ENV_TARANTOOL_WORKDIR, ENV_TARANTOOL_RUNDIR, ENV_TARANTOOL_DATADIR, ENV_TARANTOOL_INSTANCES_FILE )) { String variableValue = System.getenv(envVariable); - if (variableValue != null) { - image.withBuildArg(envVariable, variableValue); + // env values do not override build args from code + if (variableValue != null && !args.containsKey(envVariable)) { + args.put(envVariable, variableValue); } } - return image; + return args; } - private static ImageFromDockerfile buildImage(String dockerFile, String buildImageName) { - if (buildImageName != null && !buildImageName.isEmpty()) { - return new ImageFromDockerfile(buildImageName, false) - .withFileFromClasspath("Dockerfile", dockerFile); + private static String getImageTag(String buildImageName) { + if (!buildImageName.contains(":")) { + return buildImageName + ":latest"; } - return new ImageFromDockerfile().withFileFromClasspath("Dockerfile", dockerFile); + return buildImageName; } + private static TarantoolImageParams buildImage(String dockerFile, String buildImageName, Map buildArgs) { + Map args = mergeBuildArgsWithEnv(buildArgs); + return new TarantoolImageParams(getImageTag(buildImageName), dockerFile, args); + } + + /** * Get the router host * @@ -481,7 +475,7 @@ private boolean setupTopology() { try { Container.ExecResult lsResult = this.execInContainer("cartridge", "replicasets", "--run-dir=" + runDirPath, - "--file=" + this.replicasetsFileName, "setup", "--bootstrap-vshard"); + "--file=" + this.replicasetsFileName, "setup", "--bootstrap-vshard"); String stdout = lsResult.getStdout(); int exitCode = lsResult.getExitCode(); if (exitCode != 0) { @@ -512,20 +506,6 @@ private boolean setupTopology() { return true; } - private void retryingSetupTopology() { - if (!setupTopology()) { - try { - logger().info("Retrying setup topology in 10 seconds"); - Thread.sleep(10000); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - if (!setupTopology()) { - throw new RuntimeException("Failed to change the app topology after retry"); - } - } - } - private void bootstrapVshard() { try { executeCommand(VSHARD_BOOTSTRAP_COMMAND).get(); @@ -539,14 +519,43 @@ private void bootstrapVshard() { protected void containerIsStarted(InspectContainerResponse containerInfo, boolean reused) { super.containerIsStarted(containerInfo, reused); - retryingSetupTopology(); + setupTopology(); bootstrapVshard(); + waitUntilCartridgeIsHealthy(60); logger().info("Tarantool Cartridge cluster is started"); logger().info("Tarantool Cartridge router is listening at {}:{}", getRouterHost(), getRouterPort()); logger().info("Tarantool Cartridge HTTP API is available at {}:{}", getAPIHost(), getAPIPort()); } + private void waitUntilCartridgeIsHealthy(int secondsToWait) { + int secondsPassed = 0; + boolean healthy = isCartridgeHealthy(); + while (!healthy && secondsPassed < secondsToWait) { + healthy = isCartridgeHealthy(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + break; + } + } + if (!healthy) { + throw new RuntimeException("Failed to change the app topology after retry"); + } + } + + private boolean isCartridgeHealthy() { + String healthyCmd = " local cartridge = package.loaded['cartridge']" + + " return assert(cartridge) and assert(cartridge.is_healthy())"; + try { + List result = executeCommand(healthyCmd).get(); + return (Boolean) result.get(0); + } catch (Exception e) { + logger().warn("Error while waiting for cartridge healthy state: " + e.getMessage()); + return false; + } + } + @Override public CompletableFuture> executeScript(String scriptResourcePath) throws Exception { return clientHelper.executeScript(scriptResourcePath); diff --git a/src/main/java/org/testcontainers/containers/TarantoolContainerImageHelper.java b/src/main/java/org/testcontainers/containers/TarantoolContainerImageHelper.java index bfab354..65ebfc9 100644 --- a/src/main/java/org/testcontainers/containers/TarantoolContainerImageHelper.java +++ b/src/main/java/org/testcontainers/containers/TarantoolContainerImageHelper.java @@ -4,15 +4,17 @@ import com.github.dockerjava.api.command.BuildImageCmd; import com.github.dockerjava.api.command.BuildImageResultCallback; import com.github.dockerjava.api.model.Image; -import com.github.dockerjava.core.DockerClientBuilder; -import org.apache.commons.lang3.StringUtils; +import org.testcontainers.DockerClientFactory; +import java.io.File; +import java.net.URISyntaxException; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; /** * Class for working with docker directly @@ -21,13 +23,11 @@ */ class TarantoolContainerImageHelper { - private static final DockerClient dockerClient = DockerClientBuilder.getInstance().build(); - private TarantoolContainerImageHelper() { } /** - * Checks image for existing by name and build if it not exist + * Checks image for existing by name and build if it not exists * * @param imageParams parameters for building tarantool image * @return image name @@ -35,7 +35,7 @@ private TarantoolContainerImageHelper() { static String getImage(TarantoolImageParams imageParams) { final String tag = imageParams.getTag(); - if (StringUtils.isEmpty(tag)) { + if (tag.isEmpty()) { throw new IllegalArgumentException("Image tag is null or empty!"); } @@ -52,7 +52,18 @@ static String getImage(TarantoolImageParams imageParams) { * @param imageParams parameters for building tarantool image */ private static void buildImage(TarantoolImageParams imageParams) { - final BuildImageCmd buildImageCmd = dockerClient.buildImageCmd(imageParams.getDockerfile()); + final File dockerfile; + try { + dockerfile = new File( + Objects.requireNonNull(TarantoolContainerImageHelper.class.getClassLoader().getResource( + imageParams.getDockerfile())).toURI() + ); + } catch (URISyntaxException e) { + throw new RuntimeException("Failed to build docker image from resource '" + + imageParams.getDockerfile() + "'", e); + } + + final BuildImageCmd buildImageCmd = getDockerClient().buildImageCmd(dockerfile); final Map buildArgs = imageParams.getBuildArgs(); for (Map.Entry entry : buildArgs.entrySet()) { @@ -71,11 +82,15 @@ private static void buildImage(TarantoolImageParams imageParams) { * @return true if image exist and false if not */ private static boolean hasImage(String tag) { - final List images = dockerClient.listImagesCmd().exec(); + final List images = getDockerClient().listImagesCmd().exec(); return images.stream() .map(Image::getRepoTags) .map(Arrays::asList) .flatMap(Collection::stream) .anyMatch(repoTag -> repoTag.equals(tag)); } + + private static DockerClient getDockerClient() { + return DockerClientFactory.instance().client(); + } } diff --git a/src/main/java/org/testcontainers/containers/TarantoolImageParams.java b/src/main/java/org/testcontainers/containers/TarantoolImageParams.java index 6c0f8a7..96427c7 100644 --- a/src/main/java/org/testcontainers/containers/TarantoolImageParams.java +++ b/src/main/java/org/testcontainers/containers/TarantoolImageParams.java @@ -12,36 +12,36 @@ public class TarantoolImageParams { private final String tag; - private final File dockerfile; + private final String dockerfile; private final Map buildArgs; /** * Custom constructor for tarantool image parameters * - * @param tag docker image tag + * @param tag docker image tag. For example: "tarantool-enterprise-bundle:latest" * @param dockerfile dockerfile for building custom tarantool image */ - public TarantoolImageParams(String tag, File dockerfile) { + public TarantoolImageParams(String tag, String dockerfile) { this(tag, dockerfile, Collections.emptyMap()); } /** * Custom constructor for tarantool image parameters * - * @param tag docker image tag + * @param tag docker image tag. For example: "tarantool-enterprise-bundle:latest" * @param dockerfile dockerfile for building custom tarantool image * @param buildArgs args for building docker image */ - public TarantoolImageParams(String tag, File dockerfile, Map buildArgs) { + public TarantoolImageParams(String tag, String dockerfile, Map buildArgs) { this.tag = tag; this.dockerfile = dockerfile; this.buildArgs = buildArgs; } /** - * Getter for sdk version + * Getter for docker image tag * - * @return sdk version + * @return docker image tag */ public String getTag() { return tag; @@ -52,7 +52,7 @@ public String getTag() { * * @return dockerfile */ - public File getDockerfile() { + public String getDockerfile() { return dockerfile; } diff --git a/src/main/resources/Dockerfile b/src/main/resources/Dockerfile index 7e33c16..84ae852 100644 --- a/src/main/resources/Dockerfile +++ b/src/main/resources/Dockerfile @@ -1,9 +1,5 @@ -FROM centos:7 AS tarantool-base +FROM centos:7 ARG TARANTOOL_VERSION=2.8 -ARG TARANTOOL_SERVER_USER="tarantool" -ARG TARANTOOL_SERVER_UID=1000 -ARG TARANTOOL_SERVER_GROUP="tarantool" -ARG TARANTOOL_SERVER_GID=1000 ARG TARANTOOL_WORKDIR="/app" ARG TARANTOOL_RUNDIR="/tmp/run" ARG TARANTOOL_DATADIR="/tmp/data" @@ -15,12 +11,7 @@ ENV TARANTOOL_INSTANCES_FILE=$TARANTOOL_INSTANCES_FILE RUN curl -L https://tarantool.io/installer.sh | VER=$TARANTOOL_VERSION /bin/bash -s -- --repo-only && \ yum -y install cmake make gcc gcc-c++ git unzip tarantool tarantool-devel cartridge-cli && \ yum clean all -RUN groupadd -g $TARANTOOL_SERVER_GID $TARANTOOL_SERVER_GROUP && \ - useradd -u $TARANTOOL_SERVER_UID -g $TARANTOOL_SERVER_GID -m -s /bin/bash $TARANTOOL_SERVER_USER \ - || true -USER $TARANTOOL_SERVER_USER:$TARANTOOL_SERVER_GROUP -RUN cartridge version -FROM tarantool-base AS cartridge-base WORKDIR $TARANTOOL_WORKDIR -CMD cartridge build && cartridge start --run-dir=$TARANTOOL_RUNDIR --data-dir=$TARANTOOL_DATADIR --cfg=$TARANTOOL_INSTANCES_FILE +CMD cartridge build && \ + cartridge start --run-dir=$TARANTOOL_RUNDIR --data-dir=$TARANTOOL_DATADIR --cfg=$TARANTOOL_INSTANCES_FILE diff --git a/src/test/java/org/testcontainers/containers/TarantoolCartridgeContainerReplicasetsTest.java b/src/test/java/org/testcontainers/containers/TarantoolCartridgeContainerReplicasetsTest.java deleted file mode 100644 index 2efbb2c..0000000 --- a/src/test/java/org/testcontainers/containers/TarantoolCartridgeContainerReplicasetsTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.testcontainers.containers; - -import org.junit.jupiter.api.Test; -import org.slf4j.LoggerFactory; -import org.testcontainers.containers.output.Slf4jLogConsumer; -import org.testcontainers.utility.MountableFile; - -import java.time.Duration; -import java.util.HashMap; -import java.util.Map; - -public class TarantoolCartridgeContainerReplicasetsTest { - - @Test - public void test_ClusterContainer_StartsSuccessfully_ifFilesAreCopiedUnderRoot() throws Exception { - Map buildArgs = new HashMap() { - { - put("TARANTOOL_SERVER_USER", "root"); - put("TARANTOOL_SERVER_UID", "0"); - put("TARANTOOL_SERVER_GROUP", "root"); - put("TARANTOOL_SERVER_GID", "0"); - } - }; - TarantoolCartridgeContainer container = - new TarantoolCartridgeContainer( - "Dockerfile", - "testcontainers-java-tarantool:test", - "cartridge/instances.yml", - "cartridge/replicasets.yml", - buildArgs) - .withCopyFileToContainer(MountableFile.forClasspathResource("cartridge"), "/app") - .withStartupTimeout(Duration.ofSeconds(300)) - .withLogConsumer(new Slf4jLogConsumer( - LoggerFactory.getLogger(TarantoolCartridgeContainerReplicasetsTest.class))); - - container.start(); - CartridgeContainerTestUtils.executeProfileReplaceSmokeTest(container); - if (container.isRunning()) - container.stop(); - } -} diff --git a/src/test/java/org/testcontainers/containers/TarantoolCartridgeContainerTest.java b/src/test/java/org/testcontainers/containers/TarantoolCartridgeContainerTest.java index 14a79a1..b4875ea 100644 --- a/src/test/java/org/testcontainers/containers/TarantoolCartridgeContainerTest.java +++ b/src/test/java/org/testcontainers/containers/TarantoolCartridgeContainerTest.java @@ -1,37 +1,38 @@ package org.testcontainers.containers; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.LoggerFactory; import org.testcontainers.containers.output.Slf4jLogConsumer; -import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.utility.MountableFile; import java.time.Duration; -import java.util.HashMap; -import java.util.Map; /** * @author Vladimir Rogach */ public class TarantoolCartridgeContainerTest { + @Container + TarantoolCartridgeContainer container; + + @AfterEach + public void setUp() { + if (container != null && container.isRunning()) { + container.stop(); + } + } + @Test - public void test_ClusterContainer_StartsSuccessfully_ifFilesAreCopiedUnderRoot() throws Exception { - Map buildArgs = new HashMap() { - { - put("TARANTOOL_SERVER_USER", "root"); - put("TARANTOOL_SERVER_UID", "0"); - put("TARANTOOL_SERVER_GROUP", "root"); - put("TARANTOOL_SERVER_GID", "0"); - } - }; - TarantoolCartridgeContainer container = - new TarantoolCartridgeContainer( + public void test_ClusterContainer_StartsSuccessfully_ifFilesAreCopied() throws Exception { + container = new TarantoolCartridgeContainer( "Dockerfile", - "testcontainers-java-tarantool:test", + "tarantool-community:latest", "cartridge/instances.yml", - "cartridge/topology.lua", - buildArgs) + "cartridge/topology.lua") .withCopyFileToContainer(MountableFile.forClasspathResource("cartridge"), "/app") .withStartupTimeout(Duration.ofSeconds(300)) .withLogConsumer(new Slf4jLogConsumer( @@ -39,43 +40,42 @@ public void test_ClusterContainer_StartsSuccessfully_ifFilesAreCopiedUnderRoot() container.start(); CartridgeContainerTestUtils.executeProfileReplaceSmokeTest(container); - if(container.isRunning()) - container.stop(); } @Test public void test_ClusterContainer_StartsSuccessfully_ifFixedPortsAreConfigured() throws Exception { - Map buildArgs = new HashMap() { - { - put("TARANTOOL_SERVER_USER", "root"); - put("TARANTOOL_SERVER_UID", "0"); - put("TARANTOOL_SERVER_GROUP", "root"); - put("TARANTOOL_SERVER_GID", "0"); - } - }; - - TarantoolCartridgeContainer container = - new TarantoolCartridgeContainer( + container = new TarantoolCartridgeContainer( "Dockerfile", - "testcontainers-java-tarantool-fixport:test", + "tarantool-community:latest", "cartridge/instances_fixedport.yml", - "cartridge/topology_fixedport.lua", - buildArgs) + "cartridge/topology_fixedport.lua") .withCopyFileToContainer(MountableFile.forClasspathResource("cartridge"), "/app") - .withCopyFileToContainer(MountableFile.forClasspathResource("cartridge/instances_fixedport.yml"),"/app/instances.yml") + .withCopyFileToContainer(MountableFile.forClasspathResource("cartridge/instances_fixedport.yml"), "/app/instances.yml") .withStartupTimeout(Duration.ofSeconds(300)) .withUseFixedPorts(true) .withAPIPort(18081) .withRouterPort(13301) - .waitingFor( - Wait.forLogMessage(".*Listening HTTP on.*", 2) - ) .withLogConsumer(new Slf4jLogConsumer( LoggerFactory.getLogger(TarantoolCartridgeContainerTest.class))); container.start(); CartridgeContainerTestUtils.executeProfileReplaceSmokeTest(container); - if(container.isRunning()) - container.stop(); + } + + + @Test + public void test_CartridgeContainer_shouldBootStrapFromYaml() throws Exception { + container = new TarantoolCartridgeContainer( + "Dockerfile", + "tarantool-community:latest", + "cartridge/instances.yml", + "cartridge/replicasets.yml") + .withCopyFileToContainer(MountableFile.forClasspathResource("cartridge"), "/app") + .withStartupTimeout(Duration.ofSeconds(300)) + .withLogConsumer(new Slf4jLogConsumer( + LoggerFactory.getLogger(TarantoolCartridgeContainerTest.class))); + + container.start(); + CartridgeContainerTestUtils.executeProfileReplaceSmokeTest(container); } } diff --git a/src/test/java/org/testcontainers/containers/TarantoolCartridgeMigrationsTest.java b/src/test/java/org/testcontainers/containers/TarantoolCartridgeMigrationsTest.java deleted file mode 100644 index da54cc3..0000000 --- a/src/test/java/org/testcontainers/containers/TarantoolCartridgeMigrationsTest.java +++ /dev/null @@ -1,124 +0,0 @@ -package org.testcontainers.containers; - -import org.junit.Assert; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.slf4j.LoggerFactory; -import org.testcontainers.containers.output.Slf4jLogConsumer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.time.Duration; -import java.util.HashMap; -import java.util.Map; - -@Testcontainers -public class TarantoolCartridgeMigrationsTest { - - @Container - private static final TarantoolCartridgeContainer container = - new TarantoolCartridgeContainer( - "Dockerfile", - "cartridge/instances.yml", - "cartridge/topology.lua") - .withDirectoryBinding("cartridge") - .withStartupTimeout(Duration.ofSeconds(300)) - .withLogConsumer(new Slf4jLogConsumer( - LoggerFactory.getLogger(TarantoolCartridgeStaticContainerTest.class))); - - @BeforeAll - public static void test_start_container() { - if (!container.isRunning()) { - try { - container.start(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - @AfterAll - public static void clear_stop_container() { - if (container.isRunning()) { - container.stop(); - } - } - - @Test - public void test_migrations_migrator() throws Exception { - container.executeCommand("require('migrator').up()").get(); - } - - @Test - public void test_migrations_curl() throws IOException, InterruptedException { - - String urlStr = "http://" + container.getRouterHost() + ":" + "8081" + "/migrations/up"; - int code = -1; - org.testcontainers.containers.Container.ExecResult answer = container.execInContainer("curl", "-X", "POST", urlStr); - code = answer.getExitCode(); - Assert.assertEquals(0, code); - } - - @Test - public void test_migrations_http() throws Exception { - - HttpURLConnection connection; - OutputStream os = null; - InputStreamReader inputStreamReader = null; - BufferedReader bfR = null; - StringBuilder strBuilder = new StringBuilder(); - - Map bodyHttpPostRequest = new HashMap<>(); - byte[] outSteamByte = bodyHttpPostRequest.toString().getBytes(StandardCharsets.UTF_8); - - try { - String urlStr = "http://" + container.getRouterHost() + ":" + container.getAPIPort() + "/migrations/up"; - connection = createConnection(urlStr); - os = connection.getOutputStream(); - os.write(outSteamByte); - - if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { - inputStreamReader = new InputStreamReader(connection.getInputStream()); - bfR = new BufferedReader(inputStreamReader); - String line; - while ((line = bfR.readLine()) != null) { - strBuilder.append(line); - } - } - - } catch (MalformedURLException ex) { - } catch (IOException e) { - } finally { - inputStreamReader.close(); - os.close(); - bfR.close(); - } - Assert.assertTrue(strBuilder.toString().contains("applied")); - } - - public HttpURLConnection createConnection(String urlStr) throws IOException { - HttpURLConnection connection = null; - URL url = new URL(urlStr); - - connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("POST"); - connection.setDoOutput(true); - connection.setDoInput(true); - connection.setRequestProperty("Content-Type", "application/json"); - connection.setConnectTimeout(200); - connection.setReadTimeout(200); - connection.connect(); - - return connection; - } - -} diff --git a/src/test/java/org/testcontainers/containers/TarantoolCartridgeStaticContainerTest.java b/src/test/java/org/testcontainers/containers/TarantoolCartridgeStaticContainerTest.java index 090667a..37d7fee 100644 --- a/src/test/java/org/testcontainers/containers/TarantoolCartridgeStaticContainerTest.java +++ b/src/test/java/org/testcontainers/containers/TarantoolCartridgeStaticContainerTest.java @@ -1,12 +1,23 @@ package org.testcontainers.containers; +import org.junit.Assert; import org.junit.jupiter.api.Test; import org.slf4j.LoggerFactory; import org.testcontainers.containers.output.Slf4jLogConsumer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.StandardCharsets; import java.time.Duration; +import java.util.HashMap; +import java.util.Map; /** * @author Alexey Kuzin @@ -18,6 +29,7 @@ public class TarantoolCartridgeStaticContainerTest { private static final TarantoolCartridgeContainer container = new TarantoolCartridgeContainer( "Dockerfile", + "tarantool-community:latest", "cartridge/instances.yml", "cartridge/topology.lua") .withDirectoryBinding("cartridge") @@ -29,4 +41,70 @@ public class TarantoolCartridgeStaticContainerTest { public void test_StaticClusterContainer_StartsSuccessfully_ifDirectoryBindingIsUsed() throws Exception { CartridgeContainerTestUtils.executeProfileReplaceSmokeTest(container); } + + + @Test + public void test_migrations_migrator() throws Exception { + container.executeCommand("require('migrator').up()").get(); + } + + @Test + public void test_migrations_curl() throws IOException, InterruptedException { + + String urlStr = "http://" + container.getRouterHost() + ":" + "8081" + "/migrations/up"; + int code = -1; + org.testcontainers.containers.Container.ExecResult answer = container.execInContainer("curl", "-X", "POST", urlStr); + code = answer.getExitCode(); + Assert.assertEquals(0, code); + } + + @Test + public void test_migrations_http() throws Exception { + + HttpURLConnection connection; + OutputStream os = null; + InputStreamReader inputStreamReader = null; + BufferedReader bfR = null; + StringBuilder strBuilder = new StringBuilder(); + + Map bodyHttpPostRequest = new HashMap<>(); + byte[] outSteamByte = bodyHttpPostRequest.toString().getBytes(StandardCharsets.UTF_8); + + try { + String urlStr = "http://" + container.getRouterHost() + ":" + container.getAPIPort() + "/migrations/up"; + connection = createConnection(urlStr); + os = connection.getOutputStream(); + os.write(outSteamByte); + + if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { + inputStreamReader = new InputStreamReader(connection.getInputStream()); + bfR = new BufferedReader(inputStreamReader); + String line; + while ((line = bfR.readLine()) != null) { + strBuilder.append(line); + } + } + + } catch (MalformedURLException ex) { + } catch (IOException e) { + } finally { + inputStreamReader.close(); + os.close(); + bfR.close(); + } + Assert.assertTrue(strBuilder.toString().contains("applied")); + } + + private HttpURLConnection createConnection(String urlStr) throws IOException { + HttpURLConnection connection = (HttpURLConnection) new URL(urlStr).openConnection(); + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + connection.setDoInput(true); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setConnectTimeout(200); + connection.setReadTimeout(200); + connection.connect(); + + return connection; + } } diff --git a/src/test/java/org/testcontainers/containers/TarantoolSdkContainerTestEnterprise.java b/src/test/java/org/testcontainers/containers/TarantoolSdkContainerTestEnterprise.java index 274e023..1f0e240 100644 --- a/src/test/java/org/testcontainers/containers/TarantoolSdkContainerTestEnterprise.java +++ b/src/test/java/org/testcontainers/containers/TarantoolSdkContainerTestEnterprise.java @@ -9,7 +9,6 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import java.io.File; import java.net.URISyntaxException; import java.util.HashMap; import java.util.List; @@ -22,15 +21,13 @@ public class TarantoolSdkContainerTestEnterprise { @Test void test_should_createTarantoolContainerFromSdk() throws URISyntaxException { - final File dockerfile = new File( - TarantoolSdkContainerTestEnterprise.class.getClassLoader().getResource("testsdk/Dockerfile").toURI() - ); final Map buildArgs = new HashMap<>(); + //Official SDK URIs look like: https://user:password@download.tarantool.io/enterprise buildArgs.put("DOWNLOAD_SDK_URI", System.getenv("DOWNLOAD_SDK_URI")); buildArgs.put("SDK_VERSION", "tarantool-enterprise-bundle-2.7.3-0-gdddf926c3-r443"); try (final TarantoolContainer tarantoolContainer = new TarantoolContainer( - new TarantoolImageParams("tarantool-enterprise-bundle:latest", dockerfile, buildArgs)) + new TarantoolImageParams("tarantool-enterprise-bundle:latest", "testsdk/Dockerfile", buildArgs)) .withDirectoryBinding("testsdk")) { tarantoolContainer.start(); diff --git a/src/test/resources/cartridge/migrations/001_create_test_space.lua b/src/test/resources/cartridge/migrations/001_create_test_space.lua new file mode 100644 index 0000000..12a4912 --- /dev/null +++ b/src/test/resources/cartridge/migrations/001_create_test_space.lua @@ -0,0 +1,23 @@ +return{ + up = function() + local space = box.schema.space.create('test_space', { if_not_exists = true }) + space:format({ + { name = 'bucket_id', type = 'unsigned', is_nullable = false }, + { name = 'test_id', type = 'integer' }, + { name = 'test_data', type = 'string' }, + }) + + space:create_index('primary', { parts = { { field = 'test_id' } }, + unique = true, + if_not_exists = true }) + + space:create_index('bucket_id', { + parts = { 'bucket_id' }, + unique = false, + if_not_exists = true + }) + + require('migrator.utils').register_sharding_key('test_space', { 'sessionId' }) + return true + end +} diff --git "a/src/test/resources/cartridge/migrations/001_spa\321\201e_test.lua" "b/src/test/resources/cartridge/migrations/001_spa\321\201e_test.lua" deleted file mode 100644 index 89dc336..0000000 --- "a/src/test/resources/cartridge/migrations/001_spa\321\201e_test.lua" +++ /dev/null @@ -1,31 +0,0 @@ -return{ - - up = function() - local utils = require('migrator.utils') - - local spaceTest = box.schema.space.create('spaceTest', { if_not_exists = true }) - spaceTest:format({ - { name = 'sessionId', type = 'string' }, - { name = 'data', type = 'map', is_nullable = true }, - { name = 'ts', type = 'number' }, - - -- vshard bucket id - { name = 'bucket_id', type = 'unsigned', is_nullable = false }, - }) - - spaceTest:create_index('primary', { parts = { { field = 'sessionId' } }, - unique = true, - if_not_exists = true }) - - spaceTest:create_index('bucket_id', { - parts = { 'bucket_id' }, - unique = false, - if_not_exists = true - }) - - utils.register_sharding_key('spaceTest', { 'sessionId' }) - - return true - - end -} diff --git a/src/test/resources/cartridge/testapp-scm-1.rockspec b/src/test/resources/cartridge/testapp-scm-1.rockspec index 62fe199..d5c0c4e 100644 --- a/src/test/resources/cartridge/testapp-scm-1.rockspec +++ b/src/test/resources/cartridge/testapp-scm-1.rockspec @@ -3,13 +3,12 @@ version = 'scm-1' source = { url = '/dev/null', } --- Put any modules your app depends on here dependencies = { 'tarantool', 'lua >= 5.1', - 'cartridge == 2.7.3-1', - 'crud == 0.10.0-1', - 'migrations == 0.4.1-1', + 'cartridge == 2.7.4-1', + 'crud == 0.11.1-1', + 'migrations == 0.4.2-1', } build = { type = 'none';