Skip to content

Commit 46fe670

Browse files
Add scylladb module (#8002)
Co-authored-by: Eddú Meléndez <[email protected]>
1 parent 847bb1a commit 46fe670

File tree

18 files changed

+1144
-0
lines changed

18 files changed

+1144
-0
lines changed

.github/ISSUE_TEMPLATE/bug_report.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ body:
5858
- QuestDB
5959
- RabbitMQ
6060
- Redpanda
61+
- ScyllaDB
6162
- Selenium
6263
- Solace
6364
- Solr

.github/ISSUE_TEMPLATE/enhancement.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ body:
5858
- QuestDB
5959
- RabbitMQ
6060
- Redpanda
61+
- ScyllaDB
6162
- Selenium
6263
- Solace
6364
- Solr

.github/ISSUE_TEMPLATE/feature.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ body:
5858
- Pulsar
5959
- RabbitMQ
6060
- Redpanda
61+
- ScyllaDB
6162
- Selenium
6263
- Solace
6364
- Solr

.github/dependabot.yml

+5
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,11 @@ updates:
315315
schedule:
316316
interval: "weekly"
317317
open-pull-requests-limit: 10
318+
- package-ecosystem: "gradle"
319+
directory: "/modules/scylladb"
320+
schedule:
321+
interval: "weekly"
322+
open-pull-requests-limit: 10
318323
- package-ecosystem: "gradle"
319324
directory: "/modules/selenium"
320325
schedule:

.github/labeler.yml

+4
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@
204204
- changed-files:
205205
- any-glob-to-any-file:
206206
- modules/redpanda/**/*
207+
"modules/scylladb":
208+
- changed-files:
209+
- any-glob-to-any-file:
210+
- modules/scylladb/**/*
207211
"modules/selenium":
208212
- changed-files:
209213
- any-glob-to-any-file:

docs/modules/databases/scylladb.md

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# ScyllaDB
2+
3+
Testcontainers module for [ScyllaDB](https://hub.docker.com/r/scylladb/scylla)
4+
5+
## ScyllaDB's usage examples
6+
7+
You can start a ScyllaDB container instance from any Java application by using:
8+
9+
<!--codeinclude-->
10+
[Create container](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:container
11+
<!--/codeinclude-->
12+
13+
<!--codeinclude-->
14+
[Custom config file](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:customConfiguration
15+
<!--/codeinclude-->
16+
17+
### Building CqlSession
18+
19+
<!--codeinclude-->
20+
[Using CQL port](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:session
21+
<!--/codeinclude-->
22+
23+
<!--codeinclude-->
24+
[Using SSL](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:sslContext
25+
<!--/codeinclude-->
26+
27+
<!--codeinclude-->
28+
[Using Shard Awareness port](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:shardAwarenessSession
29+
<!--/codeinclude-->
30+
31+
### Alternator
32+
33+
<!--codeinclude-->
34+
[Enabling Alternator](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:alternator
35+
<!--/codeinclude-->
36+
37+
<!--codeinclude-->
38+
[DynamoDbClient with Alternator](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:dynamodDbClient
39+
<!--/codeinclude-->
40+
41+
## Adding this module to your project dependencies
42+
43+
Add the following dependency to your `pom.xml`/`build.gradle` file:
44+
45+
=== "Gradle"
46+
```groovy
47+
testImplementation "org.testcontainers:scylladb:{{latest_version}}"
48+
```
49+
50+
=== "Maven"
51+
```xml
52+
<dependency>
53+
<groupId>org.testcontainers</groupId>
54+
<artifactId>scylladb</artifactId>
55+
<version>{{latest_version}}</version>
56+
<scope>test</scope>
57+
</dependency>
58+
```

mkdocs.yml

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ nav:
7272
- modules/databases/postgres.md
7373
- modules/databases/presto.md
7474
- modules/databases/questdb.md
75+
- modules/databases/scylladb.md
7576
- modules/databases/tidb.md
7677
- modules/databases/timeplus.md
7778
- modules/databases/trino.md

modules/scylladb/build.gradle

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
description = "Testcontainers :: ScyllaDB"
2+
3+
dependencies {
4+
api project(":testcontainers")
5+
6+
testImplementation 'com.scylladb:java-driver-core:4.15.0.0'
7+
testImplementation 'org.assertj:assertj-core:3.24.2'
8+
testImplementation 'software.amazon.awssdk:dynamodb:2.28.6'
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package org.testcontainers.scylladb;
2+
3+
import org.testcontainers.containers.GenericContainer;
4+
import org.testcontainers.containers.wait.strategy.Wait;
5+
import org.testcontainers.utility.DockerImageName;
6+
import org.testcontainers.utility.MountableFile;
7+
8+
import java.net.InetSocketAddress;
9+
import java.util.Optional;
10+
11+
/**
12+
* Testcontainers implementation for ScyllaDB.
13+
* <p>
14+
* Supported image: {@code scylladb/scylla}
15+
* <p>
16+
* Exposed ports:
17+
* <ul>
18+
* <li>CQL Port: 9042</li>
19+
* <li>Shard Aware Port: 19042</li>
20+
* <li>Alternator Port: 8000</li>
21+
* </ul>
22+
*/
23+
public class ScyllaDBContainer extends GenericContainer<ScyllaDBContainer> {
24+
25+
private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("scylladb/scylla");
26+
27+
private static final Integer CQL_PORT = 9042;
28+
29+
private static final Integer SHARD_AWARE_PORT = 19042;
30+
31+
private static final Integer ALTERNATOR_PORT = 8000;
32+
33+
private static final String COMMAND = "--developer-mode=1 --overprovisioned=1";
34+
35+
private static final String CONTAINER_CONFIG_LOCATION = "/etc/scylla";
36+
37+
private boolean alternatorEnabled = false;
38+
39+
private String configLocation;
40+
41+
public ScyllaDBContainer(String dockerImageName) {
42+
this(DockerImageName.parse(dockerImageName));
43+
}
44+
45+
public ScyllaDBContainer(DockerImageName dockerImageName) {
46+
super(dockerImageName);
47+
dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);
48+
49+
withExposedPorts(CQL_PORT, SHARD_AWARE_PORT);
50+
51+
withCommand(COMMAND);
52+
waitingFor(Wait.forLogMessage(".*initialization completed..*", 1));
53+
}
54+
55+
@Override
56+
protected void configure() {
57+
if (this.alternatorEnabled) {
58+
addExposedPort(8000);
59+
String newCommand =
60+
COMMAND + " --alternator-port=" + ALTERNATOR_PORT + " --alternator-write-isolation=always";
61+
withCommand(newCommand);
62+
}
63+
64+
// Map (effectively replace) directory in Docker with the content of resourceLocation if resource location is
65+
// not null.
66+
Optional
67+
.ofNullable(configLocation)
68+
.map(MountableFile::forClasspathResource)
69+
.ifPresent(mountableFile -> withCopyFileToContainer(mountableFile, CONTAINER_CONFIG_LOCATION));
70+
}
71+
72+
public ScyllaDBContainer withConfigurationOverride(String configLocation) {
73+
this.configLocation = configLocation;
74+
return this;
75+
}
76+
77+
public ScyllaDBContainer withSsl(MountableFile certificate, MountableFile keyfile, MountableFile truststore) {
78+
withCopyFileToContainer(certificate, "/etc/scylla/scylla.cer.pem");
79+
withCopyFileToContainer(keyfile, "/etc/scylla/scylla.key.pem");
80+
withCopyFileToContainer(truststore, "/etc/scylla/scylla.truststore");
81+
withEnv("SSL_CERTFILE", "/etc/scylla/scylla.cer.pem");
82+
return this;
83+
}
84+
85+
public ScyllaDBContainer withAlternator() {
86+
this.alternatorEnabled = true;
87+
return this;
88+
}
89+
90+
/**
91+
* Retrieve an {@link InetSocketAddress} for connecting to the ScyllaDB container via the driver.
92+
*
93+
* @return A InetSocketAddress representation of this ScyllaDB container's host and port.
94+
*/
95+
public InetSocketAddress getContactPoint() {
96+
return new InetSocketAddress(getHost(), getMappedPort(CQL_PORT));
97+
}
98+
99+
public InetSocketAddress getShardAwareContactPoint() {
100+
return new InetSocketAddress(getHost(), getMappedPort(SHARD_AWARE_PORT));
101+
}
102+
103+
public String getAlternatorEndpoint() {
104+
if (!this.alternatorEnabled) {
105+
throw new IllegalStateException("Alternator is not enabled");
106+
}
107+
return "http://" + getHost() + ":" + getMappedPort(ALTERNATOR_PORT);
108+
}
109+
}

0 commit comments

Comments
 (0)