Skip to content

Improve testcontainers-java-tarantool #99

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,11 @@
target/
.idea/
*.iml
.classpath
.project
.settings/
*.swp
workbench.xmi


src/test/resources/cartridge/tmp/*
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## [Unreleased]

- Bump testcontainers to 1.19.3

## [1.0.2] - 2023-11-10

- Make a separate step for building the cartridge ([#94](https://github.com/tarantool/testcontainers-java-tarantool/issues/94))
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
</scm>

<properties>
<testcontainers.version>1.18.0</testcontainers.version>
<testcontainers.version>1.19.3</testcontainers.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<logging.config>${project.basedir}/src/test/resources/logback-test.xml</logging.config>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ public class TarantoolCartridgeContainer extends GenericContainer<TarantoolCartr
private static final String ENV_TARANTOOL_DATADIR = "TARANTOOL_DATADIR";
private static final String ENV_TARANTOOL_INSTANCES_FILE = "TARANTOOL_INSTANCES_FILE";
private static final String ENV_TARANTOOL_CLUSTER_COOKIE = "TARANTOOL_CLUSTER_COOKIE";
private static final String healthyCmd = "return require('cartridge').is_healthy()";
private static final int TWO_MINUTES = 120;

private final CartridgeConfigParser instanceFileParser;
private final TarantoolContainerClientHelper clientHelper;
Expand All @@ -120,6 +122,7 @@ public class TarantoolCartridgeContainer extends GenericContainer<TarantoolCartr
private String directoryResourcePath = SCRIPT_RESOURCE_DIRECTORY;
private String instanceDir = INSTANCE_DIR;
private String topologyConfigurationFile;
private String instancesFile;
private SslContext sslContext;

/**
Expand Down Expand Up @@ -205,6 +208,7 @@ private TarantoolCartridgeContainer(ImageFromDockerfile image, String instancesF
if (topologyConfigurationFile == null || topologyConfigurationFile.isEmpty()) {
throw new IllegalArgumentException("Topology configuration file must not be null or empty");
}
this.instancesFile = instancesFile;
this.topologyConfigurationFile = topologyConfigurationFile;
this.instanceFileParser = new CartridgeConfigParser(instancesFile);
this.clientHelper = new TarantoolContainerClientHelper(this);
Expand Down Expand Up @@ -494,17 +498,23 @@ protected void containerIsStarting(InspectContainerResponse containerInfo) {
}

private boolean setupTopology() {
String fileType = topologyConfigurationFile.substring(topologyConfigurationFile.lastIndexOf('.') + 1);

String fileType = topologyConfigurationFile
.substring(topologyConfigurationFile.lastIndexOf('.') + 1);
if (fileType.equals("yml")) {
String replicasetsFileName = topologyConfigurationFile
.substring(topologyConfigurationFile.lastIndexOf('/') + 1);

.substring(topologyConfigurationFile.lastIndexOf('/') + 1);
String instancesFileName = instancesFile
.substring(instancesFile.lastIndexOf('/') + 1);
try {
ExecResult result = execInContainer("cartridge",
"replicasets",
"--run-dir=" + TARANTOOL_RUN_DIR,
"--file=" + replicasetsFileName, "setup", "--bootstrap-vshard");
ExecResult result = execInContainer(
"cartridge",
"replicasets",
"--run-dir=" + TARANTOOL_RUN_DIR,
"--file=" + replicasetsFileName,
"--cfg=" + instancesFileName,
"setup",
"--bootstrap-vshard"
);
if (result.getExitCode() != 0) {
throw new CartridgeTopologyException("Failed to change the app topology via cartridge CLI: "
+ result.getStdout());
Expand Down Expand Up @@ -540,7 +550,7 @@ private void retryingSetupTopology() {
if (!setupTopology()) {
try {
logger().info("Retrying setup topology in 10 seconds");
Thread.sleep(10000);
Thread.sleep(10_000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
Expand All @@ -563,10 +573,10 @@ private void bootstrapVshard() {
protected void containerIsStarted(InspectContainerResponse containerInfo, boolean reused) {
super.containerIsStarted(containerInfo, reused);

waitUntilRouterIsUp(60);
waitUntilRouterIsUp(TWO_MINUTES);
retryingSetupTopology();
// wait until Roles are configured
waitUntilCartridgeIsHealthy(10);
waitUntilCartridgeIsHealthy(TWO_MINUTES);
bootstrapVshard();

logger().info("Tarantool Cartridge cluster is started");
Expand All @@ -575,49 +585,74 @@ protected void containerIsStarted(InspectContainerResponse containerInfo, boolea
}

private void waitUntilRouterIsUp(int secondsToWait) {
waitUntilTrue(secondsToWait, this::routerIsUp);
if(!waitUntilTrue(secondsToWait, this::routerIsUp)) {
throw new RuntimeException("Timeout exceeded during router starting stage." +
" See the specific error in logs.");
}
}

private void waitUntilCartridgeIsHealthy(int secondsToWait) {
waitUntilTrue(secondsToWait, this::isCartridgeHealthy);
if(!waitUntilTrue(secondsToWait, this::isCartridgeHealthy)) {
throw new RuntimeException("Timeout exceeded during cartridge topology applying stage." +
" See the specific error in logs.");
}
}

private void waitUntilTrue(int secondsToWait, Supplier<Boolean> waitFunc) {
private boolean waitUntilTrue(int secondsToWait, Supplier<Boolean> waitFunc) {
int secondsPassed = 0;
boolean result = waitFunc.get();
while (!result && secondsPassed < secondsToWait) {
result = waitFunc.get();
try {
Thread.sleep(1000);
Thread.sleep(1_000);
secondsPassed++;
} catch (InterruptedException e) {
break;
}
}
if (!result) {
throw new RuntimeException("Failed to change the app topology after retry");
}
return result;
}

private boolean routerIsUp() {
String healthyCmd = " local cartridge = package.loaded['cartridge']" +
" return cartridge ~= nil";
ExecResult result;
try {
List<?> result = executeCommandDecoded(healthyCmd);
return result.get(0).getClass() == Boolean.class && (Boolean) result.get(0);
} catch (Exception e) {
logger().warn("Error while waiting for router instance to be up: " + e.getMessage());
result = executeCommand(healthyCmd);
if (result.getExitCode() != 0 && result.getStderr().contains("Connection refused") &&
result.getStdout().isEmpty()) {
return false;
} else if (result.getExitCode() != 0) {
logger().error("exit code: {}, stdout: {}, stderr: {}",result.getExitCode(), result.getStdout(),
result.getStderr());
return false;
} else {
return true;
}
}catch (Exception e) {
logger().error(e.getMessage());
return false;
}

}

private boolean isCartridgeHealthy() {
String healthyCmd = " local cartridge = package.loaded['cartridge']" +
" return cartridge ~= nil and cartridge.is_healthy()";
ExecResult result;
try {
List<?> result = executeCommandDecoded(healthyCmd);
return result.get(0).getClass() == Boolean.class && (Boolean) result.get(0);
result = executeCommand(healthyCmd);
if (result.getExitCode() != 0) {
logger().error("exitCode: {}, stdout: {}, stderr: {}", result.getExitCode(), result.getStdout(),
result.getStderr());
return false;
} else if (result.getStdout().startsWith("---\n- null\n")){
return false;
} else if (result.getStdout().contains("true")) {
return true;
} else {
logger().warn("exitCode: {}, stdout: {}, stderr: {}", result.getExitCode(), result.getStdout(),
result.getStderr());
return false;
}
} catch (Exception e) {
logger().warn("Error while waiting for cartridge healthy state: " + e.getMessage());
logger().error("Error while waiting for cartridge healthy state: " + e.getMessage());
return false;
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/main/resources/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ ARG TARANTOOL_DATADIR="/tmp/data"
ARG TARANTOOL_LOGDIR="/tmp/log"
ARG TARANTOOL_INSTANCES_FILE="./instances.yml"
ARG TARANTOOL_CLUSTER_COOKIE="testapp-cluster-cookie"
ARG START_DELAY="5s"
ENV START_DELAY=$START_DELAY
ENV TARANTOOL_WORKDIR=$TARANTOOL_WORKDIR
ENV TARANTOOL_RUNDIR=$TARANTOOL_RUNDIR
ENV TARANTOOL_DATADIR=$TARANTOOL_DATADIR
Expand All @@ -31,6 +33,7 @@ ENV TARANTOOL_INSTANCES_FILE=$TARANTOOL_INSTANCES_FILE
ENV TARANTOOL_CLUSTER_COOKIE=$TARANTOOL_CLUSTER_COOKIE
COPY $CARTRIDGE_SRC_DIR $TARANTOOL_WORKDIR
WORKDIR $TARANTOOL_WORKDIR
RUN cartridge build
CMD cartridge start --run-dir=$TARANTOOL_RUNDIR --data-dir=$TARANTOOL_DATADIR \

RUN rm -rf .rocks && cartridge build --verbose
CMD sleep $START_DELAY && cartridge start --run-dir=$TARANTOOL_RUNDIR --data-dir=$TARANTOOL_DATADIR \
--log-dir=$TARANTOOL_LOGDIR --cfg=$TARANTOOL_INSTANCES_FILE