Skip to content

Commit

Permalink
757 - Integration test for Hot Reload of nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Chandler committed Nov 13, 2024
1 parent eca15d4 commit af59c5f
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 23 deletions.
26 changes: 16 additions & 10 deletions cassandra-test-image/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@
<name>EcChronos Cassandra Test Image</name>

<dependencies>
<!-- Internal -->
<dependency>
<groupId>com.ericsson.bss.cassandra.ecchronos</groupId>
<artifactId>application</artifactId>
<version>${project.version}</version>
</dependency>

<!-- Cassandra driver -->
<dependency>
<groupId>com.datastax.oss</groupId>
Expand Down Expand Up @@ -63,22 +70,21 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>


<dependency>
<groupId>com.ericsson.bss.cassandra.ecchronos</groupId>
<artifactId>application</artifactId>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.12.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.ericsson.bss.cassandra.ecchronos</groupId>
<artifactId>application</artifactId>
<version>1.0.0-SNAPSHOT</version>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>6.1.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.12.0</version>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.CqlSessionBuilder;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.file.Path;
Expand All @@ -27,12 +29,15 @@
import com.github.dockerjava.api.command.StopContainerCmd;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.platform.commons.util.StringUtils;
import org.testcontainers.DockerClientFactory;
import org.testcontainers.containers.DockerComposeContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.shaded.com.fasterxml.jackson.databind.node.BooleanNode;

import static org.junit.platform.commons.util.StringUtils.*;

public class AbstractCassandraCluster
{
protected static DockerComposeContainer<?> composeContainer;
Expand All @@ -50,7 +55,7 @@ public static void setup() throws InterruptedException
composeContainer = new DockerComposeContainer<>(dockerComposePath.toFile());
composeContainer.start();
LOG.info("Waiting for the Cassandra cluster to finish starting up.");
Thread.sleep(50000);
waitForNodesToBeUp("cassandra-seed-dc1-rack1-node1",4,50000);

containerIP = composeContainer.getContainerByServiceName("cassandra-seed-dc1-rack1-node1").get()
.getContainerInfo()
Expand All @@ -74,7 +79,12 @@ public static void tearDownCluster()

protected void decommissionNode ( String node) throws IOException, InterruptedException
{
String stdout = composeContainer.getContainerByServiceName(node).get()
composeContainer.getContainerByServiceName(node).get()
.execInContainer("nodetool", "-u", "cassandra", "-pw", "cassandra", "decommission").getStdout();
}
protected void setupEcchronosKeyspace ( String node) throws IOException, InterruptedException
{
composeContainer.getContainerByServiceName(node).get()
.execInContainer("nodetool", "-u", "cassandra", "-pw", "cassandra", "decommission").getStdout();
}

Expand All @@ -100,5 +110,63 @@ protected void stopContainer ( String node)
stopCmd.exec();
}
}
protected static int getNodeCountViaNodetool( String node) throws IOException, InterruptedException
{
String stdout = composeContainer.getContainerByServiceName(node).get()
.execInContainer("nodetool", "-u", "cassandra", "-pw", "cassandra", "status").getStdout();
return stdout.split("UN",-1).length-1;


}
protected static boolean waitForNodesToBeUp( String node, int expectedNodes, long maxWaitTimeInMillis)
{
long startTime = System.currentTimeMillis();
LOG.info("Waiting 10sec");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// ignore and retry
}
while ( startTime + maxWaitTimeInMillis > System.currentTimeMillis())
{
try
{
if (getNodeCountViaNodetool(node) == expectedNodes)
return true;
}
catch (IOException e)
{
// ignore and retry
}
catch (InterruptedException e)
{
// ignore and retry
}
}
LOG.info("Timed out waiting for the Cassandra cluster to finish starting up.");
return false;
}
protected void loadEcchronosKeyspace () throws InterruptedException {
Path cqlfile = Paths.get("")
.toAbsolutePath()
.getParent()
.resolve("cassandra-test-image/src/main/docker/create_keyspaces.cql");

try (BufferedReader reader = new BufferedReader(new FileReader(cqlfile.toFile()))) {
String line;
while ((line = reader.readLine()) != null) {

System.out.println(line);
mySession.execute(line);
Thread.sleep(500);
}
} catch (IOException e) {
System.err.println("Error reading the file: " + e.getMessage());
}


}


}

Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,28 @@
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.CqlSessionBuilder;
import com.ericsson.bss.cassandra.ecchronos.core.impl.repair.DefaultRepairConfigurationProvider;
import com.github.dockerjava.api.DockerClient;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.DockerClientFactory;
import org.testcontainers.containers.DockerComposeContainer;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.file.Path;
import java.nio.file.Paths;

import static org.mockito.Mockito.*;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.any;

public class TestNodeAddition extends AbstractCassandraCluster
{
private static final Logger LOG = LoggerFactory.getLogger(TestNodeAddition.class);
@BeforeClass
public static void setup() throws InterruptedException {

Path dockerComposePath = Paths.get("")
.toAbsolutePath()
.getParent()
Expand All @@ -47,12 +49,13 @@ public static void setup() throws InterruptedException {
composeContainer.withScaledService("cassandra-seed-dc1-rack1-node1", 1 );
composeContainer.withScaledService("cassandra-seed-dc2-rack1-node1", 0 );
composeContainer.start();

LOG.info("Waiting for the Cassandra cluster to finish starting up.");
Thread.sleep(50000);
waitForNodesToBeUp("cassandra-seed-dc1-rack1-node1",1,50000);

}
@Test
public void testAdditionalNodesAddedToCluster() throws InterruptedException
{
public void testAdditionalNodesAddedToCluster() throws InterruptedException, IOException {
DefaultRepairConfigurationProvider listener = mock(DefaultRepairConfigurationProvider.class);
containerIP = composeContainer.getContainerByServiceName("cassandra-seed-dc1-rack1-node1").get()
.getContainerInfo()
Expand All @@ -70,7 +73,10 @@ public void testAdditionalNodesAddedToCluster() throws InterruptedException
composeContainer.withScaledService("cassandra-seed-dc2-rack1-node1", 1 );
composeContainer.start();
LOG.info("Waiting for the new nodes to finish starting up.");
Thread.sleep(50000);
waitForNodesToBeUp("cassandra-seed-dc1-rack1-node1",4,50000);


assertEquals( 4, getNodeCountViaNodetool("cassandra-node-dc1-rack1-node2"));

verify(listener, times(3)).onAdd(any());
verify(listener, times(0)).onRemove(any());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.CqlSessionBuilder;
import com.ericsson.bss.cassandra.ecchronos.core.impl.repair.DefaultRepairConfigurationProvider;

import com.ericsson.bss.cassandra.ecchronos.utils.exceptions.ConfigurationException;
import com.ericsson.bss.cassandra.ecchronos.utils.exceptions.EcChronosException;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -26,14 +29,14 @@

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;

public class TestNodeRemoval extends AbstractCassandraCluster
{
private static final Logger LOG = LoggerFactory.getLogger(TestNodeRemoval.class);
@Test
public void testNodeDecommissionedFromCluster() throws InterruptedException
public void testNodeDecommissionedFromCluster() throws InterruptedException, IOException, ConfigurationException, EcChronosException
{
DefaultRepairConfigurationProvider listener = mock(DefaultRepairConfigurationProvider.class);

containerIP = composeContainer.getContainerByServiceName("cassandra-seed-dc1-rack1-node1").get()
.getContainerInfo()
.getNetworkSettings().getNetworks().values().stream().findFirst().get().getIpAddress();
Expand All @@ -53,7 +56,7 @@ public void testNodeDecommissionedFromCluster() throws InterruptedException
throw new RuntimeException(e);
}
LOG.info("Waiting for node to be decommissioned.");
Thread.sleep(50000);
waitForNodesToBeUp("cassandra-seed-dc2-rack1-node1",4,50000);

verify(listener, times(1)).onRemove(any());
}
Expand Down

0 comments on commit af59c5f

Please sign in to comment.