From 86ed2cbf0ee39405ce2e428f52371fea67a4475b Mon Sep 17 00:00:00 2001 From: Maxim Korolyov Date: Tue, 2 Jan 2024 08:23:25 +0100 Subject: [PATCH 01/12] add scylladb module --- .github/ISSUE_TEMPLATE/bug_report.yaml | 1 + .github/ISSUE_TEMPLATE/enhancement.yaml | 1 + .github/ISSUE_TEMPLATE/feature.yaml | 1 + .github/dependabot.yml | 5 + .github/labeler.yml | 4 + docs/modules/databases/scylladb.md | 28 +++ modules/scylladb/build.gradle | 15 ++ .../containers/ScyllaDBContainer.java | 194 ++++++++++++++++++ .../delegate/ScyllaDBDatabaseDelegate.java | 69 +++++++ .../wait/ScyllaDBQueryWaitStrategy.java | 43 ++++ .../containers/ScyllaDBContainerTest.java | 117 +++++++++++ .../containers/ScyllaDBDriver4Test.java | 37 ++++ .../containers/ScyllaDBServer5Test.java | 35 ++++ .../scylladb/src/test/resources/initial.cql | 7 + .../src/test/resources/logback-test.xml | 16 ++ .../scylla.yaml | 62 ++++++ 16 files changed, 635 insertions(+) create mode 100644 docs/modules/databases/scylladb.md create mode 100644 modules/scylladb/build.gradle create mode 100644 modules/scylladb/src/main/java/org/testcontainers/containers/ScyllaDBContainer.java create mode 100644 modules/scylladb/src/main/java/org/testcontainers/containers/delegate/ScyllaDBDatabaseDelegate.java create mode 100644 modules/scylladb/src/main/java/org/testcontainers/containers/wait/ScyllaDBQueryWaitStrategy.java create mode 100644 modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBContainerTest.java create mode 100644 modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBDriver4Test.java create mode 100644 modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBServer5Test.java create mode 100644 modules/scylladb/src/test/resources/initial.cql create mode 100644 modules/scylladb/src/test/resources/logback-test.xml create mode 100644 modules/scylladb/src/test/resources/scylla-test-configuration-example/scylla.yaml diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 135c8323866..5992ccdc46c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -47,6 +47,7 @@ body: - QuestDB - RabbitMQ - Redpanda + - ScyllaDB - Selenium - Solace - Solr diff --git a/.github/ISSUE_TEMPLATE/enhancement.yaml b/.github/ISSUE_TEMPLATE/enhancement.yaml index d77b4ce07a2..48e5813cc89 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.yaml +++ b/.github/ISSUE_TEMPLATE/enhancement.yaml @@ -47,6 +47,7 @@ body: - QuestDB - RabbitMQ - Redpanda + - ScyllaDB - Selenium - Solace - Solr diff --git a/.github/ISSUE_TEMPLATE/feature.yaml b/.github/ISSUE_TEMPLATE/feature.yaml index 65a27e5f99a..5a2097bb62f 100644 --- a/.github/ISSUE_TEMPLATE/feature.yaml +++ b/.github/ISSUE_TEMPLATE/feature.yaml @@ -47,6 +47,7 @@ body: - Pulsar - RabbitMQ - Redpanda + - ScyllaDB - Selenium - Solace - Solr diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3cb3e0fd222..3569b8b5cc2 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -246,6 +246,11 @@ updates: schedule: interval: "weekly" open-pull-requests-limit: 10 + - package-ecosystem: "gradle" + directory: "/modules/scylladb" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 - package-ecosystem: "gradle" directory: "/modules/selenium" schedule: diff --git a/.github/labeler.yml b/.github/labeler.yml index eec54b67829..73df03d65f5 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -156,6 +156,10 @@ - changed-files: - any-glob-to-any-file: - modules/redpanda/**/* +"modules/scylladb": + - changed-files: + - any-glob-to-any-file: + - modules/scylladb/**/* "modules/selenium": - changed-files: - any-glob-to-any-file: diff --git a/docs/modules/databases/scylladb.md b/docs/modules/databases/scylladb.md new file mode 100644 index 00000000000..f2f6d2b6a52 --- /dev/null +++ b/docs/modules/databases/scylladb.md @@ -0,0 +1,28 @@ +# ScyllaDB Module + +## Usage example + +This example connects to the ScyllaDB Cluster, creates a keyspaces and asserts that is has been created. + + +[Building CqlSession](../../../modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBDriver4Test.java) inside_block:scylladb + + +## Adding this module to your project dependencies + +Add the following dependency to your `pom.xml`/`build.gradle` file: + +=== "Gradle" + ```groovy + testImplementation "org.testcontainers:scylladb:{{latest_version}}" + ``` + +=== "Maven" + ```xml + + org.testcontainers + scylladb + {{latest_version}} + test + + ``` diff --git a/modules/scylladb/build.gradle b/modules/scylladb/build.gradle new file mode 100644 index 00000000000..acb45635166 --- /dev/null +++ b/modules/scylladb/build.gradle @@ -0,0 +1,15 @@ +description = "Testcontainers :: ScyllaDB" + +configurations.all { + resolutionStrategy { + force 'io.dropwizard.metrics:metrics-core:3.2.6' + } +} + +dependencies { + api project(":database-commons") + api "com.scylladb:java-driver-core:4.15.0.0" + api "com.datastax.cassandra:cassandra-driver-core:3.10.0" + + testImplementation 'org.assertj:assertj-core:3.24.2' +} diff --git a/modules/scylladb/src/main/java/org/testcontainers/containers/ScyllaDBContainer.java b/modules/scylladb/src/main/java/org/testcontainers/containers/ScyllaDBContainer.java new file mode 100644 index 00000000000..e85eaacbdad --- /dev/null +++ b/modules/scylladb/src/main/java/org/testcontainers/containers/ScyllaDBContainer.java @@ -0,0 +1,194 @@ +package org.testcontainers.containers; + +import com.github.dockerjava.api.command.InspectContainerResponse; +import org.apache.commons.io.IOUtils; +import org.testcontainers.containers.delegate.ScyllaDBDatabaseDelegate; +import org.testcontainers.delegate.DatabaseDelegate; +import org.testcontainers.ext.ScriptUtils; +import org.testcontainers.ext.ScriptUtils.ScriptLoadException; +import org.testcontainers.utility.DockerImageName; +import org.testcontainers.utility.MountableFile; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Optional; + +import javax.script.ScriptException; + +/** + * Testcontainers implementation for ScyllaDB. + *

+ * Supported image: {@code scylladb} + *

+ * Exposed ports: 9042 + */ +public class ScyllaDBContainer> extends GenericContainer { + + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("scylladb/scylla:5.2.9"); + + public static final Integer CQL_PORT = 9042; + + private static final String DEFAULT_LOCAL_DATACENTER = "datacenter1"; + + private static final String CONTAINER_CONFIG_LOCATION = "/etc/scylla"; + + private static final String USERNAME = "scylladb"; + + private static final String PASSWORD = "scylladb"; + + private String configLocation; + + private String initScriptPath; + + private boolean enableJmxReporting; + + public ScyllaDBContainer(String dockerImageName) { + this(DockerImageName.parse(dockerImageName)); + } + + public ScyllaDBContainer(DockerImageName dockerImageName) { + super(dockerImageName); + dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); + + addExposedPort(CQL_PORT); + this.enableJmxReporting = false; + + withEnv("CASSANDRA_SNITCH", "GossipingPropertyFileSnitch"); + withEnv("JVM_OPTS", "-Dcassandra.skip_wait_for_gossip_to_settle=0 -Dcassandra.initial_token=0"); + withEnv("HEAP_NEWSIZE", "128M"); + withEnv("MAX_HEAP_SIZE", "1024M"); + withEnv("SCYLLADB_ENDPOINT_SNITCH", "GossipingPropertyFileSnitch"); + withEnv("SCYLLADB_DC", DEFAULT_LOCAL_DATACENTER); + } + + @Override + protected void configure() { + optionallyMapResourceParameterAsVolume(CONTAINER_CONFIG_LOCATION, configLocation); + } + + @Override + protected void containerIsStarted(InspectContainerResponse containerInfo) { + runInitScriptIfRequired(); + } + + /** + * Load init script content and apply it to the database if initScriptPath is set + */ + private void runInitScriptIfRequired() { + if (initScriptPath != null) { + try { + URL resource = Thread.currentThread().getContextClassLoader().getResource(initScriptPath); + if (resource == null) { + logger().warn("Could not load classpath init script: {}", initScriptPath); + throw new ScriptLoadException( + "Could not load classpath init script: " + initScriptPath + ". Resource not found." + ); + } + String cql = IOUtils.toString(resource, StandardCharsets.UTF_8); + DatabaseDelegate databaseDelegate = new ScyllaDBDatabaseDelegate(this); + ScriptUtils.executeDatabaseScript(databaseDelegate, initScriptPath, cql); + } catch (IOException e) { + logger().warn("Could not load classpath init script: {}", initScriptPath); + throw new ScriptLoadException("Could not load classpath init script: " + initScriptPath, e); + } catch (ScriptException e) { + logger().error("Error while executing init script: {}", initScriptPath, e); + throw new ScriptUtils.UncategorizedScriptException( + "Error while executing init script: " + initScriptPath, + e + ); + } + } + } + + /** + * Map (effectively replace) directory in Docker with the content of resourceLocation if resource location is not null + * + * Protected to allow for changing implementation by extending the class + * + * @param pathNameInContainer path in docker + * @param resourceLocation relative classpath to resource + */ + protected void optionallyMapResourceParameterAsVolume(String pathNameInContainer, String resourceLocation) { + Optional + .ofNullable(resourceLocation) + .map(MountableFile::forClasspathResource) + .ifPresent(mountableFile -> withCopyFileToContainer(mountableFile, pathNameInContainer)); + } + + /** + * Initialize ScyllaDB with the custom overridden ScyllaDB configuration + *

+ * Be aware, that Docker effectively replaces all /etc/sylladb content with the content of config location, so if + * scylladb.yaml in configLocation is absent or corrupted, then ScyllaDB just won't launch + * + * @param configLocation relative classpath with the directory that contains cassandra.yaml and other configuration files + */ + public SELF withConfigurationOverride(String configLocation) { + this.configLocation = configLocation; + return self(); + } + + /** + * Initialize ScyllaDB with init CQL script + *

+ * CQL script will be applied after container is started (see using WaitStrategy) + * + * @param initScriptPath relative classpath resource + */ + public SELF withInitScript(String initScriptPath) { + this.initScriptPath = initScriptPath; + return self(); + } + + /** + * Initialize ScyllaDB client with JMX reporting enabled or disabled + */ + public SELF withJmxReporting(boolean enableJmxReporting) { + this.enableJmxReporting = enableJmxReporting; + return self(); + } + + /** + * Get username + * + * By default ScyllaDB has authenticator: AllowAllAuthenticator in scylladb.yaml + * If username and password need to be used, then authenticator should be set as PasswordAuthenticator + * (through custom ScyllaDB configuration) and through CQL with default scylladb-scylladb credentials + * user management should be modified + */ + public String getUsername() { + return USERNAME; + } + + /** + * Get password + * + * By default ScyllaDB has authenticator: AllowAllAuthenticator in scylladb.yaml + * If username and password need to be used, then authenticator should be set as PasswordAuthenticator + * (through custom Cassandra configuration) and through CQL with default scylladb-scylladb credentials + * user management should be modified + */ + public String getPassword() { + return PASSWORD; + } + + /** + * Retrieve an {@link InetSocketAddress} for connecting to the ScyllaDB container via the driver. + * + * @return A InetSocketAddrss representation of this ScyllaDB container's host and port. + */ + public InetSocketAddress getContactPoint() { + return new InetSocketAddress(getHost(), getMappedPort(CQL_PORT)); + } + + /** + * Retrieve the Local Datacenter for connecting to the ScyllaDB container via the driver. + * + * @return The configured local Datacenter name. + */ + public String getLocalDatacenter() { + return getEnvMap().getOrDefault("SCYLLADB_DC", DEFAULT_LOCAL_DATACENTER); + } +} diff --git a/modules/scylladb/src/main/java/org/testcontainers/containers/delegate/ScyllaDBDatabaseDelegate.java b/modules/scylladb/src/main/java/org/testcontainers/containers/delegate/ScyllaDBDatabaseDelegate.java new file mode 100644 index 00000000000..255ec5d90c8 --- /dev/null +++ b/modules/scylladb/src/main/java/org/testcontainers/containers/delegate/ScyllaDBDatabaseDelegate.java @@ -0,0 +1,69 @@ +package org.testcontainers.containers.delegate; + +import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.core.DriverException; +import com.datastax.oss.driver.api.core.cql.ResultSet; +import org.slf4j.Logger; +import org.testcontainers.containers.ContainerState; +import org.testcontainers.containers.ScyllaDBContainer; +import org.testcontainers.delegate.AbstractDatabaseDelegate; +import org.testcontainers.exception.ConnectionCreationException; +import org.testcontainers.ext.ScriptUtils.ScriptStatementFailedException; +import org.testcontainers.utility.DockerLoggerFactory; + +import java.net.InetSocketAddress; + +public class ScyllaDBDatabaseDelegate extends AbstractDatabaseDelegate { + + public ScyllaDBDatabaseDelegate(ContainerState container) { + this.container = container; + } + + protected Logger logger() { + return DockerLoggerFactory.getLogger(container.getCurrentContainerInfo().getName()); + } + + private final ContainerState container; + + @Override + protected CqlSession createNewConnection() { + try { + return CqlSession + .builder() + .addContactPoint( + new InetSocketAddress(container.getHost(), container.getMappedPort(ScyllaDBContainer.CQL_PORT)) + ) + .withLocalDatacenter("datacenter1") + .build(); + } catch (DriverException e) { + throw new ConnectionCreationException("Could not obtain cassandra connection", e); + } + } + + @Override + public void execute( + String statement, + String scriptPath, + int lineNumber, + boolean continueOnError, + boolean ignoreFailedDrops + ) { + try { + ResultSet result = getConnection().execute(statement); + if (!result.wasApplied()) { + throw new ScriptStatementFailedException(statement, lineNumber, scriptPath); + } + } catch (DriverException e) { + throw new ScriptStatementFailedException(statement, lineNumber, scriptPath, e); + } + } + + @Override + protected void closeConnectionQuietly(CqlSession session) { + try { + session.close(); + } catch (Exception e) { + logger().error("Could not close cassandra connection", e); + } + } +} diff --git a/modules/scylladb/src/main/java/org/testcontainers/containers/wait/ScyllaDBQueryWaitStrategy.java b/modules/scylladb/src/main/java/org/testcontainers/containers/wait/ScyllaDBQueryWaitStrategy.java new file mode 100644 index 00000000000..c72822932ff --- /dev/null +++ b/modules/scylladb/src/main/java/org/testcontainers/containers/wait/ScyllaDBQueryWaitStrategy.java @@ -0,0 +1,43 @@ +package org.testcontainers.containers.wait; + +import org.rnorth.ducttape.TimeoutException; +import org.testcontainers.containers.ContainerLaunchException; +import org.testcontainers.containers.delegate.ScyllaDBDatabaseDelegate; +import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy; +import org.testcontainers.delegate.DatabaseDelegate; + +import java.util.concurrent.TimeUnit; + +import static org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess; + +/** + * Waits until ScyllaDB returns its version + */ +public class ScyllaDBQueryWaitStrategy extends AbstractWaitStrategy { + + private static final String SELECT_VERSION_QUERY = "SELECT release_version FROM system.local"; + + private static final String TIMEOUT_ERROR = "Timed out waiting for ScyllaDB to be accessible for query execution"; + + @Override + protected void waitUntilReady() { + // execute select version query until success or timeout + try { + retryUntilSuccess( + (int) startupTimeout.getSeconds(), + TimeUnit.SECONDS, + () -> { + getRateLimiter() + .doWhenReady(() -> { + try (DatabaseDelegate databaseDelegate = new ScyllaDBDatabaseDelegate(waitStrategyTarget)) { + databaseDelegate.execute(SELECT_VERSION_QUERY, "", 1, false, false); + } + }); + return true; + } + ); + } catch (TimeoutException e) { + throw new ContainerLaunchException(TIMEOUT_ERROR); + } + } +} diff --git a/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBContainerTest.java b/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBContainerTest.java new file mode 100644 index 00000000000..61aceaa3ea6 --- /dev/null +++ b/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBContainerTest.java @@ -0,0 +1,117 @@ +package org.testcontainers.containers; + +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.testcontainers.containers.wait.ScyllaDBQueryWaitStrategy; +import org.testcontainers.utility.DockerImageName; + +import static org.assertj.core.api.Assertions.assertThat; + +@Slf4j +public class ScyllaDBContainerTest { + + private static final DockerImageName SCYLLADB_IMAGE = DockerImageName.parse("scylladb/scylla:5.2.9"); + + private static final String TEST_CLUSTER_NAME_IN_CONF = "Test Cluster Integration Test"; + + private static final String BASIC_QUERY = "SELECT release_version FROM system.local"; + + @Test + public void testSimple() { + try (ScyllaDBContainer scylladbContainer = new ScyllaDBContainer<>(SCYLLADB_IMAGE)) { + scylladbContainer.start(); + ResultSet resultSet = performQuery(scylladbContainer, BASIC_QUERY); + assertThat(resultSet.wasApplied()).as("Query was applied").isTrue(); + assertThat(resultSet.one().getString(0)).as("Result set has release_version").isNotNull(); + } + } + + @Test + public void testSpecificVersion() { + String scyllaDBReportedVersion = "3.0.8"; + try ( + ScyllaDBContainer ScyllaDBContainer = new ScyllaDBContainer<>(SCYLLADB_IMAGE) + ) { + ScyllaDBContainer.start(); + ResultSet resultSet = performQuery(ScyllaDBContainer, BASIC_QUERY); + assertThat(resultSet.wasApplied()).as("Query was applied").isTrue(); + assertThat(resultSet.one().getString(0)).as("ScyllaDB has right version").isEqualTo(scyllaDBReportedVersion); + } + } + + @Test + public void testConfigurationOverride() { + try ( + ScyllaDBContainer ScyllaDBContainer = new ScyllaDBContainer<>(SCYLLADB_IMAGE) + .withConfigurationOverride("scylla-test-configuration-example") + ) { + ScyllaDBContainer.start(); + ResultSet resultSet = performQuery(ScyllaDBContainer, "SELECT cluster_name FROM system.local"); + assertThat(resultSet.wasApplied()).as("Query was applied").isTrue(); + assertThat(resultSet.one().getString(0)) + .as("ScyllaDB configuration is overridden") + .isEqualTo(TEST_CLUSTER_NAME_IN_CONF); + } + } + + @Test(expected = ContainerLaunchException.class) + public void testEmptyConfigurationOverride() { + try ( + ScyllaDBContainer ScyllaDBContainer = new ScyllaDBContainer<>(SCYLLADB_IMAGE) + .withConfigurationOverride("scylladb-empty-configuration") + ) { + ScyllaDBContainer.start(); + } + } + + @Test + public void testInitScript() { + try ( + ScyllaDBContainer ScyllaDBContainer = new ScyllaDBContainer<>(SCYLLADB_IMAGE) + .withInitScript("initial.cql") + ) { + ScyllaDBContainer.start(); + testInitScript(ScyllaDBContainer); + } + } + + @Test + public void testScyllaDBQueryWaitStrategy() { + try ( + ScyllaDBContainer scyllaDBContainer = new ScyllaDBContainer<>(SCYLLADB_IMAGE) + .waitingFor(new ScyllaDBQueryWaitStrategy()) + ) { + scyllaDBContainer.start(); + ResultSet resultSet = performQuery(scyllaDBContainer, BASIC_QUERY); + assertThat(resultSet.wasApplied()).as("Query was applied").isTrue(); + } + } + + private void testInitScript(ScyllaDBContainer ScyllaDBContainer) { + ResultSet resultSet = performQuery(ScyllaDBContainer, "SELECT * FROM keySpaceTest.catalog_category"); + assertThat(resultSet.wasApplied()).as("Query was applied").isTrue(); + Row row = resultSet.one(); + assertThat(row.getLong(0)).as("Inserted row is in expected state").isEqualTo(1); + assertThat(row.getString(1)).as("Inserted row is in expected state").isEqualTo("test_category"); + } + + private ResultSet performQuery(ScyllaDBContainer ScyllaDBContainer, String cql) { + Cluster explicitCluster = Cluster + .builder() + .addContactPoint(ScyllaDBContainer.getHost()) + .withPort(ScyllaDBContainer.getMappedPort(ScyllaDBContainer.CQL_PORT)) + .build(); + return performQuery(explicitCluster, cql); + } + + private ResultSet performQuery(Cluster cluster, String cql) { + try (Cluster closeableCluster = cluster) { + Session session = closeableCluster.newSession(); + return session.execute(cql); + } + } +} diff --git a/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBDriver4Test.java b/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBDriver4Test.java new file mode 100644 index 00000000000..3953a1e1118 --- /dev/null +++ b/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBDriver4Test.java @@ -0,0 +1,37 @@ +package org.testcontainers.containers; + +import com.datastax.oss.driver.api.core.CqlIdentifier; +import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.core.metadata.schema.KeyspaceMetadata; +import org.junit.Rule; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ScyllaDBDriver4Test { + + @Rule + public ScyllaDBContainer scyllaDB = new ScyllaDBContainer<>("scylladb/scylla:5.2.9"); + + @Test + public void testCassandraGetContactPoint() { + try ( + // cassandra { + CqlSession session = CqlSession + .builder() + .addContactPoint(this.scyllaDB.getContactPoint()) + .withLocalDatacenter(this.scyllaDB.getLocalDatacenter()) + .build() + // } + ) { + session.execute( + "CREATE KEYSPACE IF NOT EXISTS test WITH replication = \n" + + "{'class':'SimpleStrategy','replication_factor':'1'};" + ); + + KeyspaceMetadata keyspace = session.getMetadata().getKeyspaces().get(CqlIdentifier.fromCql("test")); + + assertThat(keyspace).as("keyspace created").isNotNull(); + } + } +} diff --git a/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBServer5Test.java b/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBServer5Test.java new file mode 100644 index 00000000000..f6959744db7 --- /dev/null +++ b/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBServer5Test.java @@ -0,0 +1,35 @@ +package org.testcontainers.containers; + +import com.datastax.oss.driver.api.core.CqlIdentifier; +import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.core.metadata.schema.KeyspaceMetadata; +import org.junit.Rule; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ScyllaDBServer5Test { + + @Rule + public ScyllaDBContainer scylladb = new ScyllaDBContainer<>("scylladb/scylla:5.2.9"); + + @Test + public void testScyllaDBGetContactPoint() { + try ( + CqlSession session = CqlSession + .builder() + .addContactPoint(this.scylladb.getContactPoint()) + .withLocalDatacenter(this.scylladb.getLocalDatacenter()) + .build() + ) { + session.execute( + "CREATE KEYSPACE IF NOT EXISTS test WITH replication = \n" + + "{'class':'SimpleStrategy','replication_factor':'1'};" + ); + + KeyspaceMetadata keyspace = session.getMetadata().getKeyspaces().get(CqlIdentifier.fromCql("test")); + + assertThat(keyspace).as("test keyspace created").isNotNull(); + } + } +} diff --git a/modules/scylladb/src/test/resources/initial.cql b/modules/scylladb/src/test/resources/initial.cql new file mode 100644 index 00000000000..2caad3746f8 --- /dev/null +++ b/modules/scylladb/src/test/resources/initial.cql @@ -0,0 +1,7 @@ +CREATE KEYSPACE keySpaceTest WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1}; + +USE keySpaceTest; + +CREATE TABLE catalog_category (id bigint primary key, name text); + +INSERT INTO catalog_category (id, name) VALUES (1, 'test_category'); \ No newline at end of file diff --git a/modules/scylladb/src/test/resources/logback-test.xml b/modules/scylladb/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..83ef7a1a3ef --- /dev/null +++ b/modules/scylladb/src/test/resources/logback-test.xml @@ -0,0 +1,16 @@ + + + + + + %d{HH:mm:ss.SSS} %-5level %logger - %msg%n + + + + + + + + + diff --git a/modules/scylladb/src/test/resources/scylla-test-configuration-example/scylla.yaml b/modules/scylladb/src/test/resources/scylla-test-configuration-example/scylla.yaml new file mode 100644 index 00000000000..086ae07239f --- /dev/null +++ b/modules/scylladb/src/test/resources/scylla-test-configuration-example/scylla.yaml @@ -0,0 +1,62 @@ +# ScyllaDB storage config YAML + +# NOTE: +# See https://opensource.docs.scylladb.com/stable/operating-scylla/admin.html for +# full explanations of configuration directives +# /NOTE + +# The name of the cluster. This is mainly used to prevent machines in +# one logical cluster from joining another. +cluster_name: 'Test Cluster Integration Test' + +# This defines the number of tokens randomly assigned to this node on the ring +# The more tokens, relative to other nodes, the larger the proportion of data +# that this node will store. You probably want all nodes to have the same number +# of tokens assuming they have equal hardware capability. +num_tokens: 256 + +# Directory where Scylla should store data on disk. +data_file_directories: + - /var/lib/scylla/data + +# commit log. when running on magnetic HDD, this should be a +# separate spindle than the data directories. +commitlog_directory: /var/lib/scylla/commitlog + +# schema commit log. A special commitlog instance +# used for schema and system tables. +# When running on magnetic HDD, this should be a +# separate spindle than the data directories. +# schema_commitlog_directory: /var/lib/scylla/commitlog/schema + +# seed_provider class_name is saved for future use. +# A seed address is mandatory. +seed_provider: + # The addresses of hosts that will serve as contact points for the joining node. + # It allows the node to discover the cluster ring topology on startup (when + # joining the cluster). + # Once the node has joined the cluster, the seed list has no function. + - class_name: org.apache.cassandra.locator.SimpleSeedProvider + parameters: + # In a new cluster, provide the address of the first node. + # In an existing cluster, specify the address of at least one existing node. + # If you specify addresses of more than one node, use a comma to separate them. + # For example: ",," + - seeds: "127.0.0.1" + +# Address or interface to bind to and tell other Scylla nodes to connect to. +# You _must_ change this if you want multiple nodes to be able to communicate! +# +# Setting listen_address to 0.0.0.0 is always wrong. +listen_address: localhost + +# Address to broadcast to other Scylla nodes +# Leaving this blank will set it to the same value as listen_address +# broadcast_address: 1.2.3.4 + +# port for the CQL native transport to listen for clients on +# For security reasons, you should not expose this port to the internet. Firewall it if needed. +native_transport_port: 9042 + +# Uncomment to enable experimental features +# experimental: true From bc7eb8be3952d7b9526e902994255528a469ecdc Mon Sep 17 00:00:00 2001 From: Maxim Korolyov Date: Tue, 16 Jan 2024 09:25:03 +0100 Subject: [PATCH 02/12] Update docs/modules/databases/scylladb.md fix typos in docs Co-authored-by: Yaniv Kaul --- docs/modules/databases/scylladb.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/databases/scylladb.md b/docs/modules/databases/scylladb.md index f2f6d2b6a52..e3024eb451c 100644 --- a/docs/modules/databases/scylladb.md +++ b/docs/modules/databases/scylladb.md @@ -2,7 +2,7 @@ ## Usage example -This example connects to the ScyllaDB Cluster, creates a keyspaces and asserts that is has been created. +This example connects to a ScyllaDB Cluster, creates a keyspace and asserts that is has been created. [Building CqlSession](../../../modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBDriver4Test.java) inside_block:scylladb From 35ea1c2a91596bb924a20cef29537ad61af2734c Mon Sep 17 00:00:00 2001 From: Maxim Korolyov Date: Tue, 16 Jan 2024 10:29:20 +0100 Subject: [PATCH 03/12] remove com.datastax.cassandra:cassandra-driver-core from deps --- modules/scylladb/build.gradle | 1 - .../containers/ScyllaDBContainerTest.java | 32 +++++++++---------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/modules/scylladb/build.gradle b/modules/scylladb/build.gradle index acb45635166..b3708ddf458 100644 --- a/modules/scylladb/build.gradle +++ b/modules/scylladb/build.gradle @@ -9,7 +9,6 @@ configurations.all { dependencies { api project(":database-commons") api "com.scylladb:java-driver-core:4.15.0.0" - api "com.datastax.cassandra:cassandra-driver-core:3.10.0" testImplementation 'org.assertj:assertj-core:3.24.2' } diff --git a/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBContainerTest.java b/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBContainerTest.java index 61aceaa3ea6..fc3babd9427 100644 --- a/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBContainerTest.java +++ b/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBContainerTest.java @@ -1,15 +1,17 @@ package org.testcontainers.containers; -import com.datastax.driver.core.Cluster; -import com.datastax.driver.core.ResultSet; -import com.datastax.driver.core.Row; -import com.datastax.driver.core.Session; +import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.core.cql.ResultSet; +import com.datastax.oss.driver.api.core.cql.Row; import lombok.extern.slf4j.Slf4j; import org.junit.Test; import org.testcontainers.containers.wait.ScyllaDBQueryWaitStrategy; import org.testcontainers.utility.DockerImageName; +import java.net.InetSocketAddress; + import static org.assertj.core.api.Assertions.assertThat; +import static org.testcontainers.containers.ScyllaDBContainer.CQL_PORT; @Slf4j public class ScyllaDBContainerTest { @@ -100,18 +102,16 @@ private void testInitScript(ScyllaDBContainer ScyllaDBContainer) { } private ResultSet performQuery(ScyllaDBContainer ScyllaDBContainer, String cql) { - Cluster explicitCluster = Cluster - .builder() - .addContactPoint(ScyllaDBContainer.getHost()) - .withPort(ScyllaDBContainer.getMappedPort(ScyllaDBContainer.CQL_PORT)) - .build(); - return performQuery(explicitCluster, cql); - } + CqlSession session = CqlSession. + builder(). + addContactPoint( + new InetSocketAddress( + ScyllaDBContainer.getHost(), + ScyllaDBContainer.getMappedPort(CQL_PORT) + )). + withLocalDatacenter("datacenter1"). + build(); - private ResultSet performQuery(Cluster cluster, String cql) { - try (Cluster closeableCluster = cluster) { - Session session = closeableCluster.newSession(); - return session.execute(cql); - } + return session.execute(cql); } } From 1805c16854890eedace5038af1a31b9c79285fc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Tue, 17 Dec 2024 17:26:20 -0600 Subject: [PATCH 04/12] Polish --- docs/modules/databases/scylladb.md | 30 ++- modules/scylladb/build.gradle | 7 +- .../containers/ScyllaDBContainer.java | 194 ------------------ .../delegate/ScyllaDBDatabaseDelegate.java | 69 ------- .../wait/ScyllaDBQueryWaitStrategy.java | 43 ---- .../scylladb/ScyllaDBContainer.java | 83 ++++++++ .../containers/ScyllaDBContainerTest.java | 117 ----------- .../containers/ScyllaDBDriver4Test.java | 37 ---- .../containers/ScyllaDBServer5Test.java | 35 ---- .../scylladb/ScyllaDBContainerTest.java | 107 ++++++++++ 10 files changed, 217 insertions(+), 505 deletions(-) delete mode 100644 modules/scylladb/src/main/java/org/testcontainers/containers/ScyllaDBContainer.java delete mode 100644 modules/scylladb/src/main/java/org/testcontainers/containers/delegate/ScyllaDBDatabaseDelegate.java delete mode 100644 modules/scylladb/src/main/java/org/testcontainers/containers/wait/ScyllaDBQueryWaitStrategy.java create mode 100644 modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java delete mode 100644 modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBContainerTest.java delete mode 100644 modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBDriver4Test.java delete mode 100644 modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBServer5Test.java create mode 100644 modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java diff --git a/docs/modules/databases/scylladb.md b/docs/modules/databases/scylladb.md index e3024eb451c..825f0d515db 100644 --- a/docs/modules/databases/scylladb.md +++ b/docs/modules/databases/scylladb.md @@ -1,11 +1,33 @@ -# ScyllaDB Module +# ScyllaDB -## Usage example +Testcontainers module for [ScyllaDB](https://hub.docker.com/r/scylladb/scylla) -This example connects to a ScyllaDB Cluster, creates a keyspace and asserts that is has been created. +## ScyllaDB's usage examples + +You can start a ScyllaDB container instance from any Java application by using: + + +[Create container](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:container + + +### Building CqlSession + + +[Using CQL port](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:session + + + +[Using Shard Awareness port](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:shardAwarenessSession + + +### Alternator + + +[Enabling Alternator](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:alternator + -[Building CqlSession](../../../modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBDriver4Test.java) inside_block:scylladb +[DynamoDbClient with Alternator](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:dynamodDbClient ## Adding this module to your project dependencies diff --git a/modules/scylladb/build.gradle b/modules/scylladb/build.gradle index b3708ddf458..069a79cf36a 100644 --- a/modules/scylladb/build.gradle +++ b/modules/scylladb/build.gradle @@ -1,14 +1,9 @@ description = "Testcontainers :: ScyllaDB" -configurations.all { - resolutionStrategy { - force 'io.dropwizard.metrics:metrics-core:3.2.6' - } -} - dependencies { api project(":database-commons") api "com.scylladb:java-driver-core:4.15.0.0" testImplementation 'org.assertj:assertj-core:3.24.2' + testImplementation 'software.amazon.awssdk:dynamodb:2.28.6' } diff --git a/modules/scylladb/src/main/java/org/testcontainers/containers/ScyllaDBContainer.java b/modules/scylladb/src/main/java/org/testcontainers/containers/ScyllaDBContainer.java deleted file mode 100644 index e85eaacbdad..00000000000 --- a/modules/scylladb/src/main/java/org/testcontainers/containers/ScyllaDBContainer.java +++ /dev/null @@ -1,194 +0,0 @@ -package org.testcontainers.containers; - -import com.github.dockerjava.api.command.InspectContainerResponse; -import org.apache.commons.io.IOUtils; -import org.testcontainers.containers.delegate.ScyllaDBDatabaseDelegate; -import org.testcontainers.delegate.DatabaseDelegate; -import org.testcontainers.ext.ScriptUtils; -import org.testcontainers.ext.ScriptUtils.ScriptLoadException; -import org.testcontainers.utility.DockerImageName; -import org.testcontainers.utility.MountableFile; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.Optional; - -import javax.script.ScriptException; - -/** - * Testcontainers implementation for ScyllaDB. - *

- * Supported image: {@code scylladb} - *

- * Exposed ports: 9042 - */ -public class ScyllaDBContainer> extends GenericContainer { - - private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("scylladb/scylla:5.2.9"); - - public static final Integer CQL_PORT = 9042; - - private static final String DEFAULT_LOCAL_DATACENTER = "datacenter1"; - - private static final String CONTAINER_CONFIG_LOCATION = "/etc/scylla"; - - private static final String USERNAME = "scylladb"; - - private static final String PASSWORD = "scylladb"; - - private String configLocation; - - private String initScriptPath; - - private boolean enableJmxReporting; - - public ScyllaDBContainer(String dockerImageName) { - this(DockerImageName.parse(dockerImageName)); - } - - public ScyllaDBContainer(DockerImageName dockerImageName) { - super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); - - addExposedPort(CQL_PORT); - this.enableJmxReporting = false; - - withEnv("CASSANDRA_SNITCH", "GossipingPropertyFileSnitch"); - withEnv("JVM_OPTS", "-Dcassandra.skip_wait_for_gossip_to_settle=0 -Dcassandra.initial_token=0"); - withEnv("HEAP_NEWSIZE", "128M"); - withEnv("MAX_HEAP_SIZE", "1024M"); - withEnv("SCYLLADB_ENDPOINT_SNITCH", "GossipingPropertyFileSnitch"); - withEnv("SCYLLADB_DC", DEFAULT_LOCAL_DATACENTER); - } - - @Override - protected void configure() { - optionallyMapResourceParameterAsVolume(CONTAINER_CONFIG_LOCATION, configLocation); - } - - @Override - protected void containerIsStarted(InspectContainerResponse containerInfo) { - runInitScriptIfRequired(); - } - - /** - * Load init script content and apply it to the database if initScriptPath is set - */ - private void runInitScriptIfRequired() { - if (initScriptPath != null) { - try { - URL resource = Thread.currentThread().getContextClassLoader().getResource(initScriptPath); - if (resource == null) { - logger().warn("Could not load classpath init script: {}", initScriptPath); - throw new ScriptLoadException( - "Could not load classpath init script: " + initScriptPath + ". Resource not found." - ); - } - String cql = IOUtils.toString(resource, StandardCharsets.UTF_8); - DatabaseDelegate databaseDelegate = new ScyllaDBDatabaseDelegate(this); - ScriptUtils.executeDatabaseScript(databaseDelegate, initScriptPath, cql); - } catch (IOException e) { - logger().warn("Could not load classpath init script: {}", initScriptPath); - throw new ScriptLoadException("Could not load classpath init script: " + initScriptPath, e); - } catch (ScriptException e) { - logger().error("Error while executing init script: {}", initScriptPath, e); - throw new ScriptUtils.UncategorizedScriptException( - "Error while executing init script: " + initScriptPath, - e - ); - } - } - } - - /** - * Map (effectively replace) directory in Docker with the content of resourceLocation if resource location is not null - * - * Protected to allow for changing implementation by extending the class - * - * @param pathNameInContainer path in docker - * @param resourceLocation relative classpath to resource - */ - protected void optionallyMapResourceParameterAsVolume(String pathNameInContainer, String resourceLocation) { - Optional - .ofNullable(resourceLocation) - .map(MountableFile::forClasspathResource) - .ifPresent(mountableFile -> withCopyFileToContainer(mountableFile, pathNameInContainer)); - } - - /** - * Initialize ScyllaDB with the custom overridden ScyllaDB configuration - *

- * Be aware, that Docker effectively replaces all /etc/sylladb content with the content of config location, so if - * scylladb.yaml in configLocation is absent or corrupted, then ScyllaDB just won't launch - * - * @param configLocation relative classpath with the directory that contains cassandra.yaml and other configuration files - */ - public SELF withConfigurationOverride(String configLocation) { - this.configLocation = configLocation; - return self(); - } - - /** - * Initialize ScyllaDB with init CQL script - *

- * CQL script will be applied after container is started (see using WaitStrategy) - * - * @param initScriptPath relative classpath resource - */ - public SELF withInitScript(String initScriptPath) { - this.initScriptPath = initScriptPath; - return self(); - } - - /** - * Initialize ScyllaDB client with JMX reporting enabled or disabled - */ - public SELF withJmxReporting(boolean enableJmxReporting) { - this.enableJmxReporting = enableJmxReporting; - return self(); - } - - /** - * Get username - * - * By default ScyllaDB has authenticator: AllowAllAuthenticator in scylladb.yaml - * If username and password need to be used, then authenticator should be set as PasswordAuthenticator - * (through custom ScyllaDB configuration) and through CQL with default scylladb-scylladb credentials - * user management should be modified - */ - public String getUsername() { - return USERNAME; - } - - /** - * Get password - * - * By default ScyllaDB has authenticator: AllowAllAuthenticator in scylladb.yaml - * If username and password need to be used, then authenticator should be set as PasswordAuthenticator - * (through custom Cassandra configuration) and through CQL with default scylladb-scylladb credentials - * user management should be modified - */ - public String getPassword() { - return PASSWORD; - } - - /** - * Retrieve an {@link InetSocketAddress} for connecting to the ScyllaDB container via the driver. - * - * @return A InetSocketAddrss representation of this ScyllaDB container's host and port. - */ - public InetSocketAddress getContactPoint() { - return new InetSocketAddress(getHost(), getMappedPort(CQL_PORT)); - } - - /** - * Retrieve the Local Datacenter for connecting to the ScyllaDB container via the driver. - * - * @return The configured local Datacenter name. - */ - public String getLocalDatacenter() { - return getEnvMap().getOrDefault("SCYLLADB_DC", DEFAULT_LOCAL_DATACENTER); - } -} diff --git a/modules/scylladb/src/main/java/org/testcontainers/containers/delegate/ScyllaDBDatabaseDelegate.java b/modules/scylladb/src/main/java/org/testcontainers/containers/delegate/ScyllaDBDatabaseDelegate.java deleted file mode 100644 index 255ec5d90c8..00000000000 --- a/modules/scylladb/src/main/java/org/testcontainers/containers/delegate/ScyllaDBDatabaseDelegate.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.testcontainers.containers.delegate; - -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.DriverException; -import com.datastax.oss.driver.api.core.cql.ResultSet; -import org.slf4j.Logger; -import org.testcontainers.containers.ContainerState; -import org.testcontainers.containers.ScyllaDBContainer; -import org.testcontainers.delegate.AbstractDatabaseDelegate; -import org.testcontainers.exception.ConnectionCreationException; -import org.testcontainers.ext.ScriptUtils.ScriptStatementFailedException; -import org.testcontainers.utility.DockerLoggerFactory; - -import java.net.InetSocketAddress; - -public class ScyllaDBDatabaseDelegate extends AbstractDatabaseDelegate { - - public ScyllaDBDatabaseDelegate(ContainerState container) { - this.container = container; - } - - protected Logger logger() { - return DockerLoggerFactory.getLogger(container.getCurrentContainerInfo().getName()); - } - - private final ContainerState container; - - @Override - protected CqlSession createNewConnection() { - try { - return CqlSession - .builder() - .addContactPoint( - new InetSocketAddress(container.getHost(), container.getMappedPort(ScyllaDBContainer.CQL_PORT)) - ) - .withLocalDatacenter("datacenter1") - .build(); - } catch (DriverException e) { - throw new ConnectionCreationException("Could not obtain cassandra connection", e); - } - } - - @Override - public void execute( - String statement, - String scriptPath, - int lineNumber, - boolean continueOnError, - boolean ignoreFailedDrops - ) { - try { - ResultSet result = getConnection().execute(statement); - if (!result.wasApplied()) { - throw new ScriptStatementFailedException(statement, lineNumber, scriptPath); - } - } catch (DriverException e) { - throw new ScriptStatementFailedException(statement, lineNumber, scriptPath, e); - } - } - - @Override - protected void closeConnectionQuietly(CqlSession session) { - try { - session.close(); - } catch (Exception e) { - logger().error("Could not close cassandra connection", e); - } - } -} diff --git a/modules/scylladb/src/main/java/org/testcontainers/containers/wait/ScyllaDBQueryWaitStrategy.java b/modules/scylladb/src/main/java/org/testcontainers/containers/wait/ScyllaDBQueryWaitStrategy.java deleted file mode 100644 index c72822932ff..00000000000 --- a/modules/scylladb/src/main/java/org/testcontainers/containers/wait/ScyllaDBQueryWaitStrategy.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.testcontainers.containers.wait; - -import org.rnorth.ducttape.TimeoutException; -import org.testcontainers.containers.ContainerLaunchException; -import org.testcontainers.containers.delegate.ScyllaDBDatabaseDelegate; -import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy; -import org.testcontainers.delegate.DatabaseDelegate; - -import java.util.concurrent.TimeUnit; - -import static org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess; - -/** - * Waits until ScyllaDB returns its version - */ -public class ScyllaDBQueryWaitStrategy extends AbstractWaitStrategy { - - private static final String SELECT_VERSION_QUERY = "SELECT release_version FROM system.local"; - - private static final String TIMEOUT_ERROR = "Timed out waiting for ScyllaDB to be accessible for query execution"; - - @Override - protected void waitUntilReady() { - // execute select version query until success or timeout - try { - retryUntilSuccess( - (int) startupTimeout.getSeconds(), - TimeUnit.SECONDS, - () -> { - getRateLimiter() - .doWhenReady(() -> { - try (DatabaseDelegate databaseDelegate = new ScyllaDBDatabaseDelegate(waitStrategyTarget)) { - databaseDelegate.execute(SELECT_VERSION_QUERY, "", 1, false, false); - } - }); - return true; - } - ); - } catch (TimeoutException e) { - throw new ContainerLaunchException(TIMEOUT_ERROR); - } - } -} diff --git a/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java b/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java new file mode 100644 index 00000000000..03e5a29237c --- /dev/null +++ b/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java @@ -0,0 +1,83 @@ +package org.testcontainers.scylladb; + +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; + +import java.net.InetSocketAddress; + +/** + * Testcontainers implementation for ScyllaDB. + *

+ * Supported image: {@code scylladb/scylla} + *

+ * Exposed ports: + *

+ */ +public class ScyllaDBContainer extends GenericContainer { + + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("scylladb/scylla"); + + private static final Integer CQL_PORT = 9042; + + private static final Integer SHARD_AWARE_PORT = 19042; + + private static final Integer ALTERNATOR_PORT = 8000; + + private static final String COMMAND = "--developer-mode=1 --overprovisioned=1"; + + private boolean alternatorEnabled = false; + + public ScyllaDBContainer(String dockerImageName) { + this(DockerImageName.parse(dockerImageName)); + } + + public ScyllaDBContainer(DockerImageName dockerImageName) { + super(dockerImageName); + dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); + + withExposedPorts(CQL_PORT, SHARD_AWARE_PORT); + + withCommand(COMMAND); + waitingFor(Wait.forLogMessage(".*initialization completed..*", 1)); + } + + @Override + protected void configure() { + if (this.alternatorEnabled) { + addExposedPort(8000); + String newCommand = + COMMAND + " --alternator-port=" + ALTERNATOR_PORT + " --alternator-write-isolation=always"; + withCommand(newCommand); + } + } + + public ScyllaDBContainer withAlternator() { + this.alternatorEnabled = true; + return this; + } + + /** + * Retrieve an {@link InetSocketAddress} for connecting to the ScyllaDB container via the driver. + * + * @return A InetSocketAddress representation of this ScyllaDB container's host and port. + */ + public InetSocketAddress getContactPoint() { + return new InetSocketAddress(getHost(), getMappedPort(CQL_PORT)); + } + + public InetSocketAddress getShardAwareContactPoint() { + return new InetSocketAddress(getHost(), getMappedPort(SHARD_AWARE_PORT)); + } + + public String getAlternatorEndpoint() { + if (!this.alternatorEnabled) { + throw new IllegalStateException("Alternator is not enabled"); + } + return "http://" + getHost() + ":" + getMappedPort(ALTERNATOR_PORT); + } +} diff --git a/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBContainerTest.java b/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBContainerTest.java deleted file mode 100644 index fc3babd9427..00000000000 --- a/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBContainerTest.java +++ /dev/null @@ -1,117 +0,0 @@ -package org.testcontainers.containers; - -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.cql.ResultSet; -import com.datastax.oss.driver.api.core.cql.Row; -import lombok.extern.slf4j.Slf4j; -import org.junit.Test; -import org.testcontainers.containers.wait.ScyllaDBQueryWaitStrategy; -import org.testcontainers.utility.DockerImageName; - -import java.net.InetSocketAddress; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.testcontainers.containers.ScyllaDBContainer.CQL_PORT; - -@Slf4j -public class ScyllaDBContainerTest { - - private static final DockerImageName SCYLLADB_IMAGE = DockerImageName.parse("scylladb/scylla:5.2.9"); - - private static final String TEST_CLUSTER_NAME_IN_CONF = "Test Cluster Integration Test"; - - private static final String BASIC_QUERY = "SELECT release_version FROM system.local"; - - @Test - public void testSimple() { - try (ScyllaDBContainer scylladbContainer = new ScyllaDBContainer<>(SCYLLADB_IMAGE)) { - scylladbContainer.start(); - ResultSet resultSet = performQuery(scylladbContainer, BASIC_QUERY); - assertThat(resultSet.wasApplied()).as("Query was applied").isTrue(); - assertThat(resultSet.one().getString(0)).as("Result set has release_version").isNotNull(); - } - } - - @Test - public void testSpecificVersion() { - String scyllaDBReportedVersion = "3.0.8"; - try ( - ScyllaDBContainer ScyllaDBContainer = new ScyllaDBContainer<>(SCYLLADB_IMAGE) - ) { - ScyllaDBContainer.start(); - ResultSet resultSet = performQuery(ScyllaDBContainer, BASIC_QUERY); - assertThat(resultSet.wasApplied()).as("Query was applied").isTrue(); - assertThat(resultSet.one().getString(0)).as("ScyllaDB has right version").isEqualTo(scyllaDBReportedVersion); - } - } - - @Test - public void testConfigurationOverride() { - try ( - ScyllaDBContainer ScyllaDBContainer = new ScyllaDBContainer<>(SCYLLADB_IMAGE) - .withConfigurationOverride("scylla-test-configuration-example") - ) { - ScyllaDBContainer.start(); - ResultSet resultSet = performQuery(ScyllaDBContainer, "SELECT cluster_name FROM system.local"); - assertThat(resultSet.wasApplied()).as("Query was applied").isTrue(); - assertThat(resultSet.one().getString(0)) - .as("ScyllaDB configuration is overridden") - .isEqualTo(TEST_CLUSTER_NAME_IN_CONF); - } - } - - @Test(expected = ContainerLaunchException.class) - public void testEmptyConfigurationOverride() { - try ( - ScyllaDBContainer ScyllaDBContainer = new ScyllaDBContainer<>(SCYLLADB_IMAGE) - .withConfigurationOverride("scylladb-empty-configuration") - ) { - ScyllaDBContainer.start(); - } - } - - @Test - public void testInitScript() { - try ( - ScyllaDBContainer ScyllaDBContainer = new ScyllaDBContainer<>(SCYLLADB_IMAGE) - .withInitScript("initial.cql") - ) { - ScyllaDBContainer.start(); - testInitScript(ScyllaDBContainer); - } - } - - @Test - public void testScyllaDBQueryWaitStrategy() { - try ( - ScyllaDBContainer scyllaDBContainer = new ScyllaDBContainer<>(SCYLLADB_IMAGE) - .waitingFor(new ScyllaDBQueryWaitStrategy()) - ) { - scyllaDBContainer.start(); - ResultSet resultSet = performQuery(scyllaDBContainer, BASIC_QUERY); - assertThat(resultSet.wasApplied()).as("Query was applied").isTrue(); - } - } - - private void testInitScript(ScyllaDBContainer ScyllaDBContainer) { - ResultSet resultSet = performQuery(ScyllaDBContainer, "SELECT * FROM keySpaceTest.catalog_category"); - assertThat(resultSet.wasApplied()).as("Query was applied").isTrue(); - Row row = resultSet.one(); - assertThat(row.getLong(0)).as("Inserted row is in expected state").isEqualTo(1); - assertThat(row.getString(1)).as("Inserted row is in expected state").isEqualTo("test_category"); - } - - private ResultSet performQuery(ScyllaDBContainer ScyllaDBContainer, String cql) { - CqlSession session = CqlSession. - builder(). - addContactPoint( - new InetSocketAddress( - ScyllaDBContainer.getHost(), - ScyllaDBContainer.getMappedPort(CQL_PORT) - )). - withLocalDatacenter("datacenter1"). - build(); - - return session.execute(cql); - } -} diff --git a/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBDriver4Test.java b/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBDriver4Test.java deleted file mode 100644 index 3953a1e1118..00000000000 --- a/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBDriver4Test.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.testcontainers.containers; - -import com.datastax.oss.driver.api.core.CqlIdentifier; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.metadata.schema.KeyspaceMetadata; -import org.junit.Rule; -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class ScyllaDBDriver4Test { - - @Rule - public ScyllaDBContainer scyllaDB = new ScyllaDBContainer<>("scylladb/scylla:5.2.9"); - - @Test - public void testCassandraGetContactPoint() { - try ( - // cassandra { - CqlSession session = CqlSession - .builder() - .addContactPoint(this.scyllaDB.getContactPoint()) - .withLocalDatacenter(this.scyllaDB.getLocalDatacenter()) - .build() - // } - ) { - session.execute( - "CREATE KEYSPACE IF NOT EXISTS test WITH replication = \n" + - "{'class':'SimpleStrategy','replication_factor':'1'};" - ); - - KeyspaceMetadata keyspace = session.getMetadata().getKeyspaces().get(CqlIdentifier.fromCql("test")); - - assertThat(keyspace).as("keyspace created").isNotNull(); - } - } -} diff --git a/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBServer5Test.java b/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBServer5Test.java deleted file mode 100644 index f6959744db7..00000000000 --- a/modules/scylladb/src/test/java/org/testcontainers/containers/ScyllaDBServer5Test.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.testcontainers.containers; - -import com.datastax.oss.driver.api.core.CqlIdentifier; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.metadata.schema.KeyspaceMetadata; -import org.junit.Rule; -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class ScyllaDBServer5Test { - - @Rule - public ScyllaDBContainer scylladb = new ScyllaDBContainer<>("scylladb/scylla:5.2.9"); - - @Test - public void testScyllaDBGetContactPoint() { - try ( - CqlSession session = CqlSession - .builder() - .addContactPoint(this.scylladb.getContactPoint()) - .withLocalDatacenter(this.scylladb.getLocalDatacenter()) - .build() - ) { - session.execute( - "CREATE KEYSPACE IF NOT EXISTS test WITH replication = \n" + - "{'class':'SimpleStrategy','replication_factor':'1'};" - ); - - KeyspaceMetadata keyspace = session.getMetadata().getKeyspaces().get(CqlIdentifier.fromCql("test")); - - assertThat(keyspace).as("test keyspace created").isNotNull(); - } - } -} diff --git a/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java b/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java new file mode 100644 index 00000000000..32c64480e86 --- /dev/null +++ b/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java @@ -0,0 +1,107 @@ +package org.testcontainers.scylladb; + +import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.core.cql.ResultSet; +import org.junit.Test; +import org.testcontainers.utility.DockerImageName; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition; +import software.amazon.awssdk.services.dynamodb.model.BillingMode; +import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest; +import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement; +import software.amazon.awssdk.services.dynamodb.model.KeyType; +import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; + +import java.net.URI; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class ScyllaDBContainerTest { + + private static final DockerImageName SCYLLADB_IMAGE = DockerImageName.parse("scylladb/scylla:5.2.9"); + + private static final String BASIC_QUERY = "SELECT release_version FROM system.local"; + + @Test + public void testSimple() { + try ( // container { + ScyllaDBContainer scylladb = new ScyllaDBContainer("scylladb/scylla:5.2.9") + // } + ) { + scylladb.start(); + // session { + CqlSession session = CqlSession + .builder() + .addContactPoint(scylladb.getContactPoint()) + .withLocalDatacenter("datacenter1") + .build(); + // } + ResultSet resultSet = session.execute(BASIC_QUERY); + assertThat(resultSet.wasApplied()).isTrue(); + assertThat(resultSet.one().getString(0)).isNotNull(); + assertThat(session.getMetadata().getNodes().values()).hasSize(1); + } + } + + @Test + public void testShardAwareness() { + try (ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE)) { + scylladb.start(); + // shardAwarenessSession { + CqlSession session = CqlSession + .builder() + .addContactPoint(scylladb.getShardAwareContactPoint()) + .withLocalDatacenter("datacenter1") + .build(); + // } + ResultSet resultSet = session.execute("SELECT driver_name FROM system.clients"); + assertThat(resultSet.one().getString(0)).isNotNull(); + assertThat(session.getMetadata().getNodes().values()).hasSize(1); + } + } + + @Test + public void testAlternator() { + try ( // alternator { + ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE).withAlternator() + // } + ) { + scylladb.start(); + + // dynamodDbClient { + DynamoDbClient client = DynamoDbClient + .builder() + .endpointOverride(URI.create(scylladb.getAlternatorEndpoint())) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("test", "test"))) + .region(Region.US_EAST_1) + .build(); + // } + client.createTable( + CreateTableRequest + .builder() + .tableName("demo_table") + .keySchema(KeySchemaElement.builder().attributeName("id").keyType(KeyType.HASH).build()) + .attributeDefinitions( + AttributeDefinition.builder().attributeName("id").attributeType(ScalarAttributeType.S).build() + ) + .billingMode(BillingMode.PAY_PER_REQUEST) + .build() + ); + assertThat(client.listTables().tableNames()).containsExactly(("demo_table")); + } + } + + @Test + public void throwExceptionWhenAlternatorDisabled() { + try (ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE)) { + scylladb.start(); + assertThatThrownBy(scylladb::getAlternatorEndpoint) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Alternator is not enabled"); + } + } +} From b5fa599cfbcf989b30e16c8130b1dbdb401f8a91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Tue, 17 Dec 2024 17:29:11 -0600 Subject: [PATCH 05/12] Add docs --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index c308128969b..946b0053f58 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -72,6 +72,7 @@ nav: - modules/databases/postgres.md - modules/databases/presto.md - modules/databases/questdb.md + - modules/databases/scylladb.md - modules/databases/tidb.md - modules/databases/timeplus.md - modules/databases/trino.md From af00b412eb20f71bd21bdc33fb71b89e934221dc Mon Sep 17 00:00:00 2001 From: Maxim Korolyov Date: Sun, 5 Jan 2025 21:56:03 +0100 Subject: [PATCH 06/12] add custom config file. add ssl test and document it --- docs/modules/databases/scylladb.md | 8 + .../scylladb/ScyllaDBContainer.java | 18 + .../scylladb/ScyllaDBContainerTest.java | 76 +- .../scylla.yaml | 62 -- .../resources/scylla-test-ssl/keystore.node0 | Bin 0 -> 3510 bytes .../test/resources/scylla-test-ssl/node0.cer | Bin 0 -> 1087 bytes .../resources/scylla-test-ssl/node0.cer.pem | 30 + .../resources/scylla-test-ssl/node0.key.pem | 44 ++ .../test/resources/scylla-test-ssl/node0.p12 | Bin 0 -> 3510 bytes .../resources/scylla-test-ssl/scylla.yaml | 662 ++++++++++++++++++ .../scylla-test-ssl/truststore.node0 | Bin 0 -> 1462 bytes 11 files changed, 833 insertions(+), 67 deletions(-) delete mode 100644 modules/scylladb/src/test/resources/scylla-test-configuration-example/scylla.yaml create mode 100644 modules/scylladb/src/test/resources/scylla-test-ssl/keystore.node0 create mode 100644 modules/scylladb/src/test/resources/scylla-test-ssl/node0.cer create mode 100644 modules/scylladb/src/test/resources/scylla-test-ssl/node0.cer.pem create mode 100644 modules/scylladb/src/test/resources/scylla-test-ssl/node0.key.pem create mode 100644 modules/scylladb/src/test/resources/scylla-test-ssl/node0.p12 create mode 100644 modules/scylladb/src/test/resources/scylla-test-ssl/scylla.yaml create mode 100644 modules/scylladb/src/test/resources/scylla-test-ssl/truststore.node0 diff --git a/docs/modules/databases/scylladb.md b/docs/modules/databases/scylladb.md index 825f0d515db..37e6d897434 100644 --- a/docs/modules/databases/scylladb.md +++ b/docs/modules/databases/scylladb.md @@ -10,12 +10,20 @@ You can start a ScyllaDB container instance from any Java application by using: [Create container](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:container + +[Custom config file](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:custom_configuration + + ### Building CqlSession [Using CQL port](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:session + +[Using SSL](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:sslContext + + [Using Shard Awareness port](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:shardAwarenessSession diff --git a/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java b/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java index 03e5a29237c..f255eda2717 100644 --- a/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java +++ b/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java @@ -3,8 +3,10 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.utility.DockerImageName; +import org.testcontainers.utility.MountableFile; import java.net.InetSocketAddress; +import java.util.Optional; /** * Testcontainers implementation for ScyllaDB. @@ -30,8 +32,12 @@ public class ScyllaDBContainer extends GenericContainer { private static final String COMMAND = "--developer-mode=1 --overprovisioned=1"; + private static final String CONTAINER_CONFIG_LOCATION = "/etc/scylla"; + private boolean alternatorEnabled = false; + private String configLocation; + public ScyllaDBContainer(String dockerImageName) { this(DockerImageName.parse(dockerImageName)); } @@ -54,6 +60,18 @@ protected void configure() { COMMAND + " --alternator-port=" + ALTERNATOR_PORT + " --alternator-write-isolation=always"; withCommand(newCommand); } + + // Map (effectively replace) directory in Docker with the content of resourceLocation if resource location is + // not null. + Optional + .ofNullable(configLocation) + .map(MountableFile::forClasspathResource) + .ifPresent(mountableFile -> withCopyFileToContainer(mountableFile, CONTAINER_CONFIG_LOCATION)); + } + + public ScyllaDBContainer withConfigurationOverride(String configLocation) { + this.configLocation = configLocation; + return this; } public ScyllaDBContainer withAlternator() { diff --git a/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java b/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java index 32c64480e86..2ef4cd7ed9f 100644 --- a/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java +++ b/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java @@ -15,22 +15,34 @@ import software.amazon.awssdk.services.dynamodb.model.KeyType; import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import java.io.IOException; import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class ScyllaDBContainerTest { - private static final DockerImageName SCYLLADB_IMAGE = DockerImageName.parse("scylladb/scylla:5.2.9"); + private static final DockerImageName SCYLLADB_IMAGE = DockerImageName.parse("scylladb/scylla:6.2"); private static final String BASIC_QUERY = "SELECT release_version FROM system.local"; @Test public void testSimple() { try ( // container { - ScyllaDBContainer scylladb = new ScyllaDBContainer("scylladb/scylla:5.2.9") - // } + ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE) + // } ) { scylladb.start(); // session { @@ -47,6 +59,49 @@ public void testSimple() { } } + @Test + public void testSimpleSsl() throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException, KeyManagementException { + try ( + // custom_configuration { + ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE) + .withConfigurationOverride("scylla-test-ssl") + // } + ) { + + // sslContext { + String testResourcesDir = getClass().getClassLoader().getResource("scylla-test-ssl/").getPath(); + + KeyStore keyStore = KeyStore.getInstance("PKCS12"); + keyStore.load(Files.newInputStream(Paths.get(testResourcesDir + "keystore.node0")), "scylla".toCharArray()); + + KeyStore trustStore = KeyStore.getInstance("PKCS12"); + trustStore.load(Files.newInputStream(Paths.get(testResourcesDir + "truststore.node0")), "scylla".toCharArray()); + + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(keyStore, "scylla".toCharArray()); + + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(trustStore); + + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); + // } + + scylladb.start(); + + CqlSession session = CqlSession + .builder() + .addContactPoint(scylladb.getContactPoint()) + .withLocalDatacenter("datacenter1") + .withSslContext(sslContext) + .build(); + ResultSet resultSet = session.execute(BASIC_QUERY); + assertThat(resultSet.wasApplied()).isTrue(); + assertThat(resultSet.one().getString(0)).isNotNull(); + assertThat(session.getMetadata().getNodes().values()).hasSize(1); + } + } + @Test public void testShardAwareness() { try (ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE)) { @@ -67,8 +122,8 @@ public void testShardAwareness() { @Test public void testAlternator() { try ( // alternator { - ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE).withAlternator() - // } + ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE).withAlternator() + // } ) { scylladb.start(); @@ -104,4 +159,15 @@ public void throwExceptionWhenAlternatorDisabled() { .hasMessageContaining("Alternator is not enabled"); } } + + @Test + public void testSslConfiguration() { + try (ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE)) { + scylladb.start(); + assertThat(scylladb.getEnvMap().get("SCYLLA_SSL")).isEqualTo("1"); + assertThat(scylladb.getEnvMap().get("SCYLLA_SSL_CERT_FILE")).isEqualTo("/etc/scylla/certs/scylla.crt"); + assertThat(scylladb.getEnvMap().get("SCYLLA_SSL_KEY_FILE")).isEqualTo("/etc/scylla/certs/scylla.key"); + assertThat(scylladb.getEnvMap().get("SCYLLA_SSL_CA_FILE")).isEqualTo("/etc/scylla/certs/ca.crt"); + } + } } diff --git a/modules/scylladb/src/test/resources/scylla-test-configuration-example/scylla.yaml b/modules/scylladb/src/test/resources/scylla-test-configuration-example/scylla.yaml deleted file mode 100644 index 086ae07239f..00000000000 --- a/modules/scylladb/src/test/resources/scylla-test-configuration-example/scylla.yaml +++ /dev/null @@ -1,62 +0,0 @@ -# ScyllaDB storage config YAML - -# NOTE: -# See https://opensource.docs.scylladb.com/stable/operating-scylla/admin.html for -# full explanations of configuration directives -# /NOTE - -# The name of the cluster. This is mainly used to prevent machines in -# one logical cluster from joining another. -cluster_name: 'Test Cluster Integration Test' - -# This defines the number of tokens randomly assigned to this node on the ring -# The more tokens, relative to other nodes, the larger the proportion of data -# that this node will store. You probably want all nodes to have the same number -# of tokens assuming they have equal hardware capability. -num_tokens: 256 - -# Directory where Scylla should store data on disk. -data_file_directories: - - /var/lib/scylla/data - -# commit log. when running on magnetic HDD, this should be a -# separate spindle than the data directories. -commitlog_directory: /var/lib/scylla/commitlog - -# schema commit log. A special commitlog instance -# used for schema and system tables. -# When running on magnetic HDD, this should be a -# separate spindle than the data directories. -# schema_commitlog_directory: /var/lib/scylla/commitlog/schema - -# seed_provider class_name is saved for future use. -# A seed address is mandatory. -seed_provider: - # The addresses of hosts that will serve as contact points for the joining node. - # It allows the node to discover the cluster ring topology on startup (when - # joining the cluster). - # Once the node has joined the cluster, the seed list has no function. - - class_name: org.apache.cassandra.locator.SimpleSeedProvider - parameters: - # In a new cluster, provide the address of the first node. - # In an existing cluster, specify the address of at least one existing node. - # If you specify addresses of more than one node, use a comma to separate them. - # For example: ",," - - seeds: "127.0.0.1" - -# Address or interface to bind to and tell other Scylla nodes to connect to. -# You _must_ change this if you want multiple nodes to be able to communicate! -# -# Setting listen_address to 0.0.0.0 is always wrong. -listen_address: localhost - -# Address to broadcast to other Scylla nodes -# Leaving this blank will set it to the same value as listen_address -# broadcast_address: 1.2.3.4 - -# port for the CQL native transport to listen for clients on -# For security reasons, you should not expose this port to the internet. Firewall it if needed. -native_transport_port: 9042 - -# Uncomment to enable experimental features -# experimental: true diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/keystore.node0 b/modules/scylladb/src/test/resources/scylla-test-ssl/keystore.node0 new file mode 100644 index 0000000000000000000000000000000000000000..7f027beaf649e0f2292788888336994807b5cd75 GIT binary patch literal 3510 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 +-----BEGIN PRIVATE KEY----- +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 +fMq1U6czbhYvEjp3Y42Exw== +-----END PRIVATE KEY----- diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/node0.p12 b/modules/scylladb/src/test/resources/scylla-test-ssl/node0.p12 new file mode 100644 index 0000000000000000000000000000000000000000..e6a2f5634ece7d4328cffa429e4c5fc77c66c50c GIT binary patch literal 3510 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 Jfd4z8{{jWwZw~+f literal 0 HcmV?d00001 diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/scylla.yaml b/modules/scylladb/src/test/resources/scylla-test-ssl/scylla.yaml new file mode 100644 index 00000000000..e71e807463b --- /dev/null +++ b/modules/scylladb/src/test/resources/scylla-test-ssl/scylla.yaml @@ -0,0 +1,662 @@ +# Scylla storage config YAML + +####################################### +# This file is split to two sections: +# 1. Supported parameters +# 2. Unsupported parameters: reserved for future use or backwards +# compatibility. +# Scylla will only read and use the first segment +####################################### + +### Supported Parameters + +# The name of the cluster. This is mainly used to prevent machines in +# one logical cluster from joining another. +# It is recommended to change the default value when creating a new cluster. +# You can NOT modify this value for an existing cluster +#cluster_name: 'Test Cluster' + +# This defines the number of tokens randomly assigned to this node on the ring +# The more tokens, relative to other nodes, the larger the proportion of data +# that this node will store. You probably want all nodes to have the same number +# of tokens assuming they have equal hardware capability. +num_tokens: 256 + +# Directory where Scylla should store all its files, which are commitlog, +# data, hints, view_hints and saved_caches subdirectories. All of these +# subs can be overridden by the respective options below. +# If unset, the value defaults to /var/lib/scylla +# workdir: /var/lib/scylla + +# Directory where Scylla should store data on disk. +# data_file_directories: +# - /var/lib/scylla/data + +# commit log. when running on magnetic HDD, this should be a +# separate spindle than the data directories. +# commitlog_directory: /var/lib/scylla/commitlog + +# schema commit log. A special commitlog instance +# used for schema and system tables. +# When running on magnetic HDD, this should be a +# separate spindle than the data directories. +# schema_commitlog_directory: /var/lib/scylla/commitlog/schema + +# commitlog_sync may be either "periodic" or "batch." +# +# When in batch mode, Scylla won't ack writes until the commit log +# has been fsynced to disk. It will wait +# commitlog_sync_batch_window_in_ms milliseconds between fsyncs. +# This window should be kept short because the writer threads will +# be unable to do extra work while waiting. (You may need to increase +# concurrent_writes for the same reason.) +# +# commitlog_sync: batch +# commitlog_sync_batch_window_in_ms: 2 +# +# the other option is "periodic" where writes may be acked immediately +# and the CommitLog is simply synced every commitlog_sync_period_in_ms +# milliseconds. +commitlog_sync: periodic +commitlog_sync_period_in_ms: 10000 + +# The size of the individual commitlog file segments. A commitlog +# segment may be archived, deleted, or recycled once all the data +# in it (potentially from each columnfamily in the system) has been +# flushed to sstables. +# +# The default size is 32, which is almost always fine, but if you are +# archiving commitlog segments (see commitlog_archiving.properties), +# then you probably want a finer granularity of archiving; 8 or 16 MB +# is reasonable. +commitlog_segment_size_in_mb: 32 + +# The size of the individual schema commitlog file segments. +# +# The default size is 128, which is 4 times larger than the default +# size of the data commitlog. It's because the segment size puts +# a limit on the mutation size that can be written at once, and some +# schema mutation writes are much larger than average. +schema_commitlog_segment_size_in_mb: 128 + +# any class that implements the SeedProvider interface and has a +# constructor that takes a Map of parameters will do. +seed_provider: + # Addresses of hosts that are deemed contact points. + # Cassandra nodes use this list of hosts to find each other and learn + # the topology of the ring. You must change this if you are running + # multiple nodes! + - class_name: org.apache.cassandra.locator.SimpleSeedProvider + parameters: + # seeds is actually a comma-delimited list of addresses. + # Ex: ",," + - seeds: "172.17.0.3,127.0.0.1,172.17.0.2,172.17.0.4,172.17.0.5" + + +# Address to bind to and tell other Scylla nodes to connect to. +# You _must_ change this if you want multiple nodes to be able to communicate! +# +# If you leave broadcast_address (below) empty, then setting listen_address +# to 0.0.0.0 is wrong as other nodes will not know how to reach this node. +# If you set broadcast_address, then you can set listen_address to 0.0.0.0. +listen_address: localhost + +# Address to broadcast to other Scylla nodes +# Leaving this blank will set it to the same value as listen_address +# broadcast_address: 1.2.3.4 + + +# When using multiple physical network interfaces, set this to true to listen on broadcast_address +# in addition to the listen_address, allowing nodes to communicate in both interfaces. +# Ignore this property if the network configuration automatically routes between the public and private networks such as EC2. +# +# listen_on_broadcast_address: false + +# port for the CQL native transport to listen for clients on +# For security reasons, you should not expose this port to the internet. Firewall it if needed. +# To disable the CQL native transport, remove this option and configure native_transport_port_ssl. +native_transport_port: 9042 + +# Like native_transport_port, but clients are forwarded to specific shards, based on the +# client-side port numbers. +native_shard_aware_transport_port: 19042 + +# Enabling native transport encryption in client_encryption_options allows you to either use +# encryption for the standard port or to use a dedicated, additional port along with the unencrypted +# standard native_transport_port. +# Enabling client encryption and keeping native_transport_port_ssl disabled will use encryption +# for native_transport_port. Setting native_transport_port_ssl to a different value +# from native_transport_port will use encryption for native_transport_port_ssl while +# keeping native_transport_port unencrypted. +#native_transport_port_ssl: 9142 + +# Like native_transport_port_ssl, but clients are forwarded to specific shards, based on the +# client-side port numbers. +#native_shard_aware_transport_port_ssl: 19142 + +# How long the coordinator should wait for read operations to complete +read_request_timeout_in_ms: 5000 + +# How long the coordinator should wait for writes to complete +write_request_timeout_in_ms: 2000 +# how long a coordinator should continue to retry a CAS operation +# that contends with other proposals for the same row +cas_contention_timeout_in_ms: 1000 + +# phi value that must be reached for a host to be marked down. +# most users should never need to adjust this. +# phi_convict_threshold: 8 + +# IEndpointSnitch. The snitch has two functions: +# - it teaches Scylla enough about your network topology to route +# requests efficiently +# - it allows Scylla to spread replicas around your cluster to avoid +# correlated failures. It does this by grouping machines into +# "datacenters" and "racks." Scylla will do its best not to have +# more than one replica on the same "rack" (which may not actually +# be a physical location) +# +# IF YOU CHANGE THE SNITCH AFTER DATA IS INSERTED INTO THE CLUSTER, +# YOU MUST RUN A FULL REPAIR, SINCE THE SNITCH AFFECTS WHERE REPLICAS +# ARE PLACED. +# +# Out of the box, Scylla provides +# - SimpleSnitch: +# Treats Strategy order as proximity. This can improve cache +# locality when disabling read repair. Only appropriate for +# single-datacenter deployments. +# - GossipingPropertyFileSnitch +# This should be your go-to snitch for production use. The rack +# and datacenter for the local node are defined in +# cassandra-rackdc.properties and propagated to other nodes via +# gossip. If cassandra-topology.properties exists, it is used as a +# fallback, allowing migration from the PropertyFileSnitch. +# - PropertyFileSnitch: +# Proximity is determined by rack and data center, which are +# explicitly configured in cassandra-topology.properties. +# - Ec2Snitch: +# Appropriate for EC2 deployments in a single Region. Loads Region +# and Availability Zone information from the EC2 API. The Region is +# treated as the datacenter, and the Availability Zone as the rack. +# Only private IPs are used, so this will not work across multiple +# Regions. +# - Ec2MultiRegionSnitch: +# Uses public IPs as broadcast_address to allow cross-region +# connectivity. (Thus, you should set seed addresses to the public +# IP as well.) You will need to open the storage_port or +# ssl_storage_port on the public IP firewall. (For intra-Region +# traffic, Scylla will switch to the private IP after +# establishing a connection.) +# - RackInferringSnitch: +# Proximity is determined by rack and data center, which are +# assumed to correspond to the 3rd and 2nd octet of each node's IP +# address, respectively. Unless this happens to match your +# deployment conventions, this is best used as an example of +# writing a custom Snitch class and is provided in that spirit. +# +# You can use a custom Snitch by setting this to the full class name +# of the snitch, which will be assumed to be on your classpath. +endpoint_snitch: SimpleSnitch + +# The address or interface to bind the native transport server to. +# +# Set rpc_address OR rpc_interface, not both. Interfaces must correspond +# to a single address, IP aliasing is not supported. +# +# Leaving rpc_address blank has the same effect as on listen_address +# (i.e. it will be based on the configured hostname of the node). +# +# Note that unlike listen_address, you can specify 0.0.0.0, but you must also +# set broadcast_rpc_address to a value other than 0.0.0.0. +# +# For security reasons, you should not expose this port to the internet. Firewall it if needed. +# +# If you choose to specify the interface by name and the interface has an ipv4 and an ipv6 address +# you can specify which should be chosen using rpc_interface_prefer_ipv6. If false the first ipv4 +# address will be used. If true the first ipv6 address will be used. Defaults to false preferring +# ipv4. If there is only one address it will be selected regardless of ipv4/ipv6. +rpc_address: localhost +# rpc_interface: eth1 +# rpc_interface_prefer_ipv6: false + +# port for REST API server +api_port: 10000 + +# IP for the REST API server +api_address: 127.0.0.1 + +# Log WARN on any batch size exceeding this value. 128 kiB per batch by default. +# Caution should be taken on increasing the size of this threshold as it can lead to node instability. +batch_size_warn_threshold_in_kb: 128 + +# Fail any multiple-partition batch exceeding this value. 1 MiB (8x warn threshold) by default. +batch_size_fail_threshold_in_kb: 1024 + + # Authentication backend, identifying users + # Out of the box, Scylla provides org.apache.cassandra.auth.{AllowAllAuthenticator, + # PasswordAuthenticator}. + # + # - AllowAllAuthenticator performs no checks - set it to disable authentication. + # - PasswordAuthenticator relies on username/password pairs to authenticate + # users. It keeps usernames and hashed passwords in system_auth.credentials table. + # Please increase system_auth keyspace replication factor if you use this authenticator. + # - com.scylladb.auth.TransitionalAuthenticator requires username/password pair + # to authenticate in the same manner as PasswordAuthenticator, but improper credentials + # result in being logged in as an anonymous user. Use for upgrading clusters' auth. + # authenticator: AllowAllAuthenticator + + # Authorization backend, implementing IAuthorizer; used to limit access/provide permissions + # Out of the box, Scylla provides org.apache.cassandra.auth.{AllowAllAuthorizer, + # CassandraAuthorizer}. + # + # - AllowAllAuthorizer allows any action to any user - set it to disable authorization. + # - CassandraAuthorizer stores permissions in system_auth.permissions table. Please + # increase system_auth keyspace replication factor if you use this authorizer. + # - com.scylladb.auth.TransitionalAuthorizer wraps around the CassandraAuthorizer, using it for + # authorizing permission management. Otherwise, it allows all. Use for upgrading + # clusters' auth. + # authorizer: AllowAllAuthorizer + + # initial_token allows you to specify tokens manually. While you can use # it with + # vnodes (num_tokens > 1, above) -- in which case you should provide a + # comma-separated list -- it's primarily used when adding nodes # to legacy clusters + # that do not have vnodes enabled. + # initial_token: + + # RPC address to broadcast to drivers and other Scylla nodes. This cannot + # be set to 0.0.0.0. If left blank, this will be set to the value of + # rpc_address. If rpc_address is set to 0.0.0.0, broadcast_rpc_address must + # be set. + # broadcast_rpc_address: 1.2.3.4 + + # Uncomment to enable experimental features + # experimental_features: + # - udf + # - alternator-streams + # - broadcast-tables + # - keyspace-storage-options + + # The directory where hints files are stored if hinted handoff is enabled. + # hints_directory: /var/lib/scylla/hints + +# The directory where hints files are stored for materialized-view updates +# view_hints_directory: /var/lib/scylla/view_hints + +# See https://docs.scylladb.com/architecture/anti-entropy/hinted-handoff +# May either be "true" or "false" to enable globally, or contain a list +# of data centers to enable per-datacenter. +# hinted_handoff_enabled: DC1,DC2 +# hinted_handoff_enabled: true + +# this defines the maximum amount of time a dead host will have hints +# generated. After it has been dead this long, new hints for it will not be +# created until it has been seen alive and gone down again. +# max_hint_window_in_ms: 10800000 # 3 hours + + +# Validity period for permissions cache (fetching permissions can be an +# expensive operation depending on the authorizer, CassandraAuthorizer is +# one example). Defaults to 10000, set to 0 to disable. +# Will be disabled automatically for AllowAllAuthorizer. +# permissions_validity_in_ms: 10000 + +# Refresh interval for permissions cache (if enabled). +# After this interval, cache entries become eligible for refresh. Upon next +# access, an async reload is scheduled and the old value returned until it +# completes. If permissions_validity_in_ms is non-zero, then this also must have +# a non-zero value. Defaults to 2000. It's recommended to set this value to +# be at least 3 times smaller than the permissions_validity_in_ms. +# permissions_update_interval_in_ms: 2000 + +# The partitioner is responsible for distributing groups of rows (by +# partition key) across nodes in the cluster. You should leave this +# alone for new clusters. The partitioner can NOT be changed without +# reloading all data, so when upgrading you should set this to the +# same partitioner you were already using. +# +# Murmur3Partitioner is currently the only supported partitioner, +# +partitioner: org.apache.cassandra.dht.Murmur3Partitioner + +# Total space to use for commitlogs. +# +# If space gets above this value (it will round up to the next nearest +# segment multiple), Scylla will flush every dirty CF in the oldest +# segment and remove it. So a small total commitlog space will tend +# to cause more flush activity on less-active columnfamilies. +# +# A value of -1 (default) will automatically equate it to the total amount of memory +# available for Scylla. +commitlog_total_space_in_mb: -1 + +# TCP port, for commands and data +# For security reasons, you should not expose this port to the internet. Firewall it if needed. +# storage_port: 7000 + +# SSL port, for encrypted communication. Unused unless enabled in +# encryption_options +# For security reasons, you should not expose this port to the internet. Firewall it if needed. +# ssl_storage_port: 7001 + +# listen_interface: eth0 +# listen_interface_prefer_ipv6: false + +# Whether to start the native transport server. +# Please note that the address on which the native transport is bound is the +# same as the rpc_address. The port however is different and specified below. +# start_native_transport: true + +# The maximum size of allowed frame. Frame (requests) larger than this will +# be rejected as invalid. The default is 256MB. +# native_transport_max_frame_size_in_mb: 256 + +# enable or disable keepalive on rpc/native connections +# rpc_keepalive: true + +# Set to true to have Scylla create a hard link to each sstable +# flushed or streamed locally in a backups/ subdirectory of the +# keyspace data. Removing these links is the operator's +# responsibility. +# incremental_backups: false + +# Whether or not to take a snapshot before each compaction. Be +# careful using this option, since Scylla won't clean up the +# snapshots for you. Mostly useful if you're paranoid when there +# is a data format change. +# snapshot_before_compaction: false + +# Whether or not a snapshot is taken of the data before keyspace truncation +# or dropping of column families. The STRONGLY advised default of true +# should be used to provide data safety. If you set this flag to false, you will +# lose data on truncation or drop. +# auto_snapshot: true + +# When executing a scan, within or across a partition, we need to keep the +# tombstones seen in memory so we can return them to the coordinator, which +# will use them to make sure other replicas also know about the deleted rows. +# With workloads that generate a lot of tombstones, this can cause performance +# problems and even exhaust the server heap. +# (http://www.datastax.com/dev/blog/cassandra-anti-patterns-queues-and-queue-like-datasets) +# Adjust the thresholds here if you understand the dangers and want to +# scan more tombstones anyway. These thresholds may also be adjusted at runtime +# using the StorageService mbean. +# tombstone_warn_threshold: 1000 +# tombstone_failure_threshold: 100000 + +# Granularity of the collation index of rows within a partition. +# Increase if your rows are large, or if you have a very large +# number of rows per partition. The competing goals are these: +# 1) a smaller granularity means more index entries are generated +# and looking up rows within the partition by collation column +# is faster +# 2) but, Scylla will keep the collation index in memory for hot +# rows (as part of the key cache), so a larger granularity means +# you can cache more hot rows +# column_index_size_in_kb: 64 + +# Auto-scaling of the promoted index prevents running out of memory +# when the promoted index grows too large (due to partitions with many rows +# vs. too small column_index_size_in_kb). When the serialized representation +# of the promoted index grows by this threshold, the desired block size +# for this partition (initialized to column_index_size_in_kb) +# is doubled, to decrease the sampling resolution by half. +# +# To disable promoted index auto-scaling, set the threshold to 0. +# column_index_auto_scale_threshold_in_kb: 10240 + +# Log a warning when writing partitions larger than this value +# compaction_large_partition_warning_threshold_mb: 1000 + +# Log a warning when writing rows larger than this value +# compaction_large_row_warning_threshold_mb: 10 + +# Log a warning when writing cells larger than this value +# compaction_large_cell_warning_threshold_mb: 1 + +# Log a warning when row number is larger than this value +# compaction_rows_count_warning_threshold: 100000 + +# Log a warning when writing a collection containing more elements than this value +# compaction_collection_elements_count_warning_threshold: 10000 + +# How long the coordinator should wait for seq or index scans to complete +# range_request_timeout_in_ms: 10000 +# How long the coordinator should wait for writes to complete +# counter_write_request_timeout_in_ms: 5000 +# How long a coordinator should continue to retry a CAS operation +# that contends with other proposals for the same row +# cas_contention_timeout_in_ms: 1000 +# How long the coordinator should wait for truncates to complete +# (This can be much longer, because unless auto_snapshot is disabled +# we need to flush first so we can snapshot before removing the data.) +# truncate_request_timeout_in_ms: 60000 +# The default timeout for other, miscellaneous operations +# request_timeout_in_ms: 10000 + +# Enable or disable inter-node encryption. +# You must also generate keys and provide the appropriate key and trust store locations and passwords. +# +# The available internode options are : all, none, dc, rack +# If set to dc scylla will encrypt the traffic between the DCs +# If set to rack scylla will encrypt the traffic between the racks +# +# SSL/TLS algorithm and ciphers used can be controlled by +# the priority_string parameter. Info on priority string +# syntax and values is available at: +# https://gnutls.org/manual/html_node/Priority-Strings.html +# +# The require_client_auth parameter allows you to +# restrict access to service based on certificate +# validation. Client must provide a certificate +# accepted by the used trust store to connect. +# +# server_encryption_options: +# internode_encryption: none +# certificate: conf/scylla.crt +# keyfile: conf/scylla.key +# truststore: +# certficate_revocation_list: +# require_client_auth: False +# priority_string: + +# enable or disable client/server encryption. +client_encryption_options: + enabled: true + certificate: /etc/scylla/node0.cer.pem + keyfile: /etc/scylla/node0.key.pem + truststore: /etc/scylla/truststore.node0 + truststore_password: scylla +# certficate_revocation_list: +# require_client_auth: False +# priority_string: + +# internode_compression controls whether traffic between nodes is +# compressed. +# can be: all - all traffic is compressed +# dc - traffic between different datacenters is compressed +# none - nothing is compressed. +# internode_compression: none + +# Enables inter-node traffic compression metrics (`scylla_rpc_compression_...`) +# and enables a new implementation of inter-node traffic compressors, +# capable of using zstd (in addition to the default lz4) +# and shared dictionaries. +# (Those features must still be enabled by other settings). +# Has minor CPU cost. +# +# internode_compression_enable_advanced: false + +# Enables training of shared compression dictionaries on inter-node traffic. +# New dictionaries are distributed throughout the cluster via Raft, +# and used to improve the effectiveness of inter-node traffic compression +# when `internode_compression_enable_advanced` is enabled. +# +# WARNING: this may leak unencrypted data to disk. The trained dictionaries +# contain randomly-selected pieces of data written to the cluster. +# When the Raft log is unencrypted, those pieces of data will be +# written to disk unencrypted. At the moment of writing, there is no +# way to encrypt the Raft log. +# This problem is tracked by https://github.com/scylladb/scylla-enterprise/issues/4717. +# +# Can be: never - Dictionaries aren't trained by this node. +# when_leader - New dictionaries are trained by this node only if +# it's the current Raft leader. +# always - Dictionaries are trained by this node unconditionally. +# +# For efficiency reasons, training shouldn't be enabled on more than one node. +# To enable it on a single node, one can let the cluster pick the trainer +# by setting `when_leader` on all nodes, or specify one manually by setting `always` +# on one node and `never` on others. +# +# rpc_dict_training_when: never + +# A number in range [0.0, 1.0] specifying the share of CPU which can be spent +# by this node on compressing inter-node traffic with zstd. +# +# Depending on the workload, enabling zstd might have a drastic negative +# effect on performance, so it shouldn't be done lightly. +# +# internode_compression_zstd_max_cpu_fraction: 0.0 + +# Enable or disable tcp_nodelay for inter-dc communication. +# Disabling it will result in larger (but fewer) network packets being sent, +# reducing overhead from the TCP protocol itself, at the cost of increasing +# latency if you block for cross-datacenter responses. +# inter_dc_tcp_nodelay: false + +# Relaxation of environment checks. +# +# Scylla places certain requirements on its environment. If these requirements are +# not met, performance and reliability can be degraded. +# +# These requirements include: +# - A filesystem with good support for asynchronous I/O (AIO). Currently, +# this means XFS. +# +# false: strict environment checks are in place; do not start if they are not met. +# true: relaxed environment checks; performance and reliability may degraade. +# +# developer_mode: false + + +# Idle-time background processing +# +# Scylla can perform certain jobs in the background while the system is otherwise idle, +# freeing processor resources when there is other work to be done. +# +# defragment_memory_on_idle: true +# +# prometheus port +# By default, Scylla opens prometheus API port on port 9180 +# setting the port to 0 will disable the prometheus API. +# prometheus_port: 9180 +# +# prometheus address +# Leaving this blank will set it to the same value as listen_address. +# This means that by default, Scylla listens to the prometheus API on the same +# listening address (and therefore network interface) used to listen for +# internal communication. If the monitoring node is not in this internal +# network, you can override prometheus_address explicitly - e.g., setting +# it to 0.0.0.0 to listen on all interfaces. +# prometheus_address: 1.2.3.4 + +# Distribution of data among cores (shards) within a node +# +# Scylla distributes data within a node among shards, using a round-robin +# strategy: +# [shard0] [shard1] ... [shardN-1] [shard0] [shard1] ... [shardN-1] ... +# +# Scylla versions 1.6 and below used just one repetition of the pattern; +# this interfered with data placement among nodes (vnodes). +# +# Scylla versions 1.7 and above use 4096 repetitions of the pattern; this +# provides for better data distribution. +# +# the value below is log (base 2) of the number of repetitions. +# +# Set to 0 to avoid rewriting all data when upgrading from Scylla 1.6 and +# below. +# +# Keep at 12 for new clusters. +murmur3_partitioner_ignore_msb_bits: 12 + +# Use on a new, parallel algorithm for performing aggregate queries. +# Set to `false` to fall-back to the old algorithm. +# enable_parallelized_aggregation: true + +# Time for which task manager task started internally is kept in memory after it completes. +# task_ttl_in_seconds: 0 + +# Time for which task manager task started by user is kept in memory after it completes. +# user_task_ttl_in_seconds: 3600 + +# In materialized views, restrictions are allowed only on the view's primary key columns. +# In old versions Scylla mistakenly allowed IS NOT NULL restrictions on columns which were not part +# of the view's primary key. These invalid restrictions were ignored. +# This option controls the behavior when someone tries to create a view with such invalid IS NOT NULL restrictions. +# +# Can be true, false, or warn. +# * `true`: IS NOT NULL is allowed only on the view's primary key columns, +# trying to use it on other columns will cause an error, as it should. +# * `false`: Scylla accepts IS NOT NULL restrictions on regular columns, but they're silently ignored. +# It's useful for backwards compatibility. +# * `warn`: The same as false, but there's a warning about invalid view restrictions. +# +# To preserve backwards compatibility on old clusters, Scylla's default setting is `warn`. +# New clusters have this option set to `true` by scylla.yaml (which overrides the default `warn`) +# to make sure that trying to create an invalid view causes an error. +strict_is_not_null_in_views: true + +# The Unix Domain Socket the node uses for maintenance socket. +# The possible options are: +# * ignore: the node will not open the maintenance socket, +# * workdir: the node will open the maintenance socket on the path /cql.m, +# where is a path defined by the workdir configuration option, +# * : the node will open the maintenance socket on the path . +maintenance_socket: ignore + +# If set to true, configuration parameters defined with LiveUpdate option can be updated in runtime with CQL +# by updating system.config virtual table. If we don't want any configuration parameter to be changed in runtime +# via CQL, this option should be set to false. This parameter doesn't impose any limits on other mechanisms updating +# configuration parameters in runtime, e.g. sending SIGHUP or using API. This option should be set to false +# e.g. for cloud users, for whom scylla's configuration should be changed only by support engineers. +# live_updatable_config_params_changeable_via_cql: true + +# **************** +# * GUARDRAILS * +# **************** + +# Guardrails to warn or fail when Replication Factor is smaller/greater than the threshold. +# Please note that the value of 0 is always allowed, +# which means that having no replication at all, i.e. RF = 0, is always valid. +# A guardrail value smaller than 0, e.g. -1, means that the guardrail is disabled. +# Commenting out a guardrail also means it is disabled. +# minimum_replication_factor_fail_threshold: -1 +# minimum_replication_factor_warn_threshold: 3 +# maximum_replication_factor_warn_threshold: -1 +# maximum_replication_factor_fail_threshold: -1 + +# Guardrails to warn about or disallow creating a keyspace with specific replication strategy. +# Each of these 2 settings is a list storing replication strategies considered harmful. +# The replication strategies to choose from are: +# 1) SimpleStrategy, +# 2) NetworkTopologyStrategy, +# 3) LocalStrategy, +# 4) EverywhereStrategy +# +# replication_strategy_warn_list: +# - SimpleStrategy +# replication_strategy_fail_list: + +# Enable tablets for new keyspaces. +# When enabled, newly created keyspaces will have tablets enabled by default. +# That can be explicitly disabled in the CREATE KEYSPACE query +# by using the `tablets = {'enabled': false}` replication option. +# +# Correspondingly, when disabled, newly created keyspaces will use vnodes +# unless tablets are explicitly enabled in the CREATE KEYSPACE query +# by using the `tablets = {'enabled': true}` replication option. +# +# Note that creating keyspaces with tablets enabled or disabled is irreversible. +# The `tablets` option cannot be changed using `ALTER KEYSPACE`. +enable_tablets: true diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/truststore.node0 b/modules/scylladb/src/test/resources/scylla-test-ssl/truststore.node0 new file mode 100644 index 0000000000000000000000000000000000000000..a798f8dcce44d3c329d6195ba3af64ed4a53a50a GIT binary patch literal 1462 zcmV;n1xflaf(5by0Ru3C1zZLRDuzgg_YDCD0ic2fO$34kNic#1MKFQ|K?VsbhDe6@ z4FLxRpn?T5FoFdx0s#Opf(0iA2`Yw2hW8Bt2LUi<1_>&LNQU5-gZ~153!C`mHv|RJqkRGbClCSwATSID2r7n1hW8Bu2?YQ! z9R>+thDZTr0|Wso1Q2DPC;#aGeKa6bP33KLOmBdK1hAHP;qn_}1BXg}MP%07z!J29 zFu@r!$kn9y6|W%ZHC5^Vm^lbFlTfC7XiZz++R@**rg>V5_V*g!C?R`e=(VMP+9(ps zn%UD;=da#Ufs|o1Sxn<-`>1Xmz5t8upK_822W2hJFHEu_UVBLWSQP947cRx$nEUSX&38@wjN9~-Whhd zgYjxS5H39viu2k=YBGS$Wq~3dX9Z$LSZj;O4uoK=2{f<$rEo8KAT79D9{D0KOh|D4 zt$x7SGzs%WDrX)X^fDHbAioXb=O^gc&OFj7;E{K^iP8pEMN{D5+>=Td4o^D4W7G1UEN!M-GGx2;4`4?-_Zx>Rsw! zuG^iH57<=S-JADMCWZ=dF$z zaU9F1_t7oZOq>k&7)b=X?GZ+zy#_vc&ArughWgk4W)O>nlJ2IR%qkXs$F>f+u&78u zAWfp2)|lS={~L1u(`-RdM(6K5gHFM_vZ3*Y~*ll61wagf(EJK}fKeX_vHtaEW`$xmNi}0x@cO>s9#QdG#9a%B2 zs}VLWw^F2K{kR)OutJ;;WWlCx4!b72t%8|4vVFRwbHs3)!POOL5D4_wT0A7*X5M#I zC*1kPy+I*e&;#7aG>I7Jpy?xT#;Sb4D8L0yfGvh#_AeY66GMQssfMXL*`;1AJI;s@ zKomECt#Cx|Ve!ibEqz^g91TydEg9oi1_{PJA&BHbM3|xa$d~Q`r|-*OEbbjFpJO5s z$A|ZP2_DWs{DeQ1iW_nKYBxgGTs&j;7~9m$l4rf){J}0yY`0I;GGrMB%s1fo>X?gy z_!1Eob)3WJ)KI?f-`x)#-f*hi5rkbQ&+V2a0UIK4M=2##eo# zBQ$=_IHmJHu(taY;|=Bt@Xsf`-Iv@KX{waxst>^0(N%St|J#-)|MeTwbu0_Ot<%cc3Z@blgj343RkISjLS`z~0!!qRb%Qvy=B;ZgdgK zD`>4$Jq&Ho^wP*jve&n$sgFkB?T}LuA3nh|2bEcHxNC9O7 z1OfpC00baJ_x}tCC{h-ATwLUNtcqciVtnQq0najyZYDmrr=G|J6n11P0&KFjY9D>$ Qm&0GUI!}BEy#fL!5K#57VgLXD literal 0 HcmV?d00001 From 7badf3d106b024334dcaa1fd49e4ebbbbac3bfd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Mon, 6 Jan 2025 10:07:38 -0500 Subject: [PATCH 07/12] Fix format --- .../scylladb/ScyllaDBContainerTest.java | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java b/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java index 2ef4cd7ed9f..82eb2bdb585 100644 --- a/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java +++ b/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java @@ -15,9 +15,6 @@ import software.amazon.awssdk.services.dynamodb.model.KeyType; import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; import java.io.IOException; import java.net.URI; import java.nio.file.Files; @@ -29,6 +26,10 @@ import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -41,8 +42,8 @@ public class ScyllaDBContainerTest { @Test public void testSimple() { try ( // container { - ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE) - // } + ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE) + // } ) { scylladb.start(); // session { @@ -60,14 +61,14 @@ public void testSimple() { } @Test - public void testSimpleSsl() throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException, KeyManagementException { + public void testSimpleSsl() + throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException, KeyManagementException { try ( // custom_configuration { ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE) .withConfigurationOverride("scylla-test-ssl") // } ) { - // sslContext { String testResourcesDir = getClass().getClassLoader().getResource("scylla-test-ssl/").getPath(); @@ -75,12 +76,19 @@ public void testSimpleSsl() throws NoSuchAlgorithmException, KeyStoreException, keyStore.load(Files.newInputStream(Paths.get(testResourcesDir + "keystore.node0")), "scylla".toCharArray()); KeyStore trustStore = KeyStore.getInstance("PKCS12"); - trustStore.load(Files.newInputStream(Paths.get(testResourcesDir + "truststore.node0")), "scylla".toCharArray()); + trustStore.load( + Files.newInputStream(Paths.get(testResourcesDir + "truststore.node0")), + "scylla".toCharArray() + ); - KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance( + KeyManagerFactory.getDefaultAlgorithm() + ); keyManagerFactory.init(keyStore, "scylla".toCharArray()); - TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( + TrustManagerFactory.getDefaultAlgorithm() + ); trustManagerFactory.init(trustStore); SSLContext sslContext = SSLContext.getInstance("TLS"); @@ -122,8 +130,8 @@ public void testShardAwareness() { @Test public void testAlternator() { try ( // alternator { - ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE).withAlternator() - // } + ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE).withAlternator() + // } ) { scylladb.start(); From 60f7dd41051d85f8f3dfe4d1574d7ea797607649 Mon Sep 17 00:00:00 2001 From: Maxim Korolyov Date: Tue, 7 Jan 2025 16:37:08 +0100 Subject: [PATCH 08/12] remove temporary ssl test --- .../scylladb/ScyllaDBContainerTest.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java b/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java index 82eb2bdb585..4b889fd78d7 100644 --- a/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java +++ b/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java @@ -167,15 +167,4 @@ public void throwExceptionWhenAlternatorDisabled() { .hasMessageContaining("Alternator is not enabled"); } } - - @Test - public void testSslConfiguration() { - try (ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE)) { - scylladb.start(); - assertThat(scylladb.getEnvMap().get("SCYLLA_SSL")).isEqualTo("1"); - assertThat(scylladb.getEnvMap().get("SCYLLA_SSL_CERT_FILE")).isEqualTo("/etc/scylla/certs/scylla.crt"); - assertThat(scylladb.getEnvMap().get("SCYLLA_SSL_KEY_FILE")).isEqualTo("/etc/scylla/certs/scylla.key"); - assertThat(scylladb.getEnvMap().get("SCYLLA_SSL_CA_FILE")).isEqualTo("/etc/scylla/certs/ca.crt"); - } - } } From ccd7e411300e5e8b3b92f87769e165be3c4b314d Mon Sep 17 00:00:00 2001 From: Maxim Korolyov Date: Thu, 9 Jan 2025 23:43:51 +0100 Subject: [PATCH 09/12] add ssl cqlsh test and docs --- docs/modules/databases/scylladb.md | 4 ++++ .../scylladb/ScyllaDBContainerTest.java | 20 ++++++++++++++++++- .../scylladb/src/test/resources/initial.cql | 7 ------- .../test/resources/scylla-test-ssl/cqlshrc | 7 +++++++ 4 files changed, 30 insertions(+), 8 deletions(-) delete mode 100644 modules/scylladb/src/test/resources/initial.cql create mode 100644 modules/scylladb/src/test/resources/scylla-test-ssl/cqlshrc diff --git a/docs/modules/databases/scylladb.md b/docs/modules/databases/scylladb.md index 37e6d897434..b58e62264f9 100644 --- a/docs/modules/databases/scylladb.md +++ b/docs/modules/databases/scylladb.md @@ -24,6 +24,10 @@ You can start a ScyllaDB container instance from any Java application by using: [Using SSL](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:sslContext + +[Using SSL with cqlsh](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:sslCqlsh + + [Using Shard Awareness port](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:shardAwarenessSession diff --git a/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java b/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java index 4b889fd78d7..d7e4f921976 100644 --- a/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java +++ b/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java @@ -3,7 +3,9 @@ import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.cql.ResultSet; import org.junit.Test; +import org.testcontainers.containers.Container; import org.testcontainers.utility.DockerImageName; +import org.testcontainers.utility.MountableFile; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.regions.Region; @@ -62,7 +64,7 @@ public void testSimple() { @Test public void testSimpleSsl() - throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException, KeyManagementException { + throws InterruptedException, NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException, KeyManagementException { try ( // custom_configuration { ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE) @@ -110,6 +112,22 @@ public void testSimpleSsl() } } + @Test + public void testSimpleSslCqlsh() throws InterruptedException, IOException { + try ( + ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE) + .withConfigurationOverride("scylla-test-ssl") + ) { + scylladb.start(); + + // sslCqlsh { + scylladb.execInContainer("mv", "-f", "/etc/scylla/cqlshrc", "/root/.cassandra/cqlshrc"); + Container.ExecResult execResult = scylladb.execInContainer("cqlsh", "--ssl", "-e", "select * from system_schema.keyspaces;"); + assertThat(execResult.getStdout()).contains("keyspace_name"); + // } + } + } + @Test public void testShardAwareness() { try (ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE)) { diff --git a/modules/scylladb/src/test/resources/initial.cql b/modules/scylladb/src/test/resources/initial.cql deleted file mode 100644 index 2caad3746f8..00000000000 --- a/modules/scylladb/src/test/resources/initial.cql +++ /dev/null @@ -1,7 +0,0 @@ -CREATE KEYSPACE keySpaceTest WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1}; - -USE keySpaceTest; - -CREATE TABLE catalog_category (id bigint primary key, name text); - -INSERT INTO catalog_category (id, name) VALUES (1, 'test_category'); \ No newline at end of file diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/cqlshrc b/modules/scylladb/src/test/resources/scylla-test-ssl/cqlshrc new file mode 100644 index 00000000000..5025c1a6d10 --- /dev/null +++ b/modules/scylladb/src/test/resources/scylla-test-ssl/cqlshrc @@ -0,0 +1,7 @@ +[connection] +port = 9042 +hostname = 172.17.0.3 +factory = cqlshlib.ssl.ssl_transport_factory +[ssl] +certfile = /etc/scylla/node0.cer.pem +validate = false From 181472eda6ed5f23f1d5e1abbb1cd1f30846e2a0 Mon Sep 17 00:00:00 2001 From: Maxim Korolyov Date: Sun, 26 Jan 2025 22:49:53 +0100 Subject: [PATCH 10/12] add withSsl method to ScyllaDBContainer --- docs/modules/databases/scylladb.md | 2 +- .../scylladb/ScyllaDBContainer.java | 7 +++ .../scylladb/ScyllaDBContainerTest.java | 47 +++++++++++------- .../test/resources/scylla-test-ssl/cqlshrc | 7 --- .../resources/scylla-test-ssl/keys/node0.cer | 0 .../resources/scylla-test-ssl/keys/node0.p12 | 0 .../{node0.cer.pem => keys/scylla.cer.pem} | 0 .../{node0.key.pem => keys/scylla.key.pem} | 0 .../{keystore.node0 => keys/scylla.keystore} | Bin .../scylla.truststore} | Bin .../test/resources/scylla-test-ssl/node0.cer | Bin 1087 -> 0 bytes .../test/resources/scylla-test-ssl/node0.p12 | Bin 3510 -> 0 bytes .../resources/scylla-test-ssl/scylla.yaml | 6 +-- 13 files changed, 40 insertions(+), 29 deletions(-) delete mode 100644 modules/scylladb/src/test/resources/scylla-test-ssl/cqlshrc create mode 100644 modules/scylladb/src/test/resources/scylla-test-ssl/keys/node0.cer create mode 100644 modules/scylladb/src/test/resources/scylla-test-ssl/keys/node0.p12 rename modules/scylladb/src/test/resources/scylla-test-ssl/{node0.cer.pem => keys/scylla.cer.pem} (100%) rename modules/scylladb/src/test/resources/scylla-test-ssl/{node0.key.pem => keys/scylla.key.pem} (100%) rename modules/scylladb/src/test/resources/scylla-test-ssl/{keystore.node0 => keys/scylla.keystore} (100%) rename modules/scylladb/src/test/resources/scylla-test-ssl/{truststore.node0 => keys/scylla.truststore} (100%) delete mode 100644 modules/scylladb/src/test/resources/scylla-test-ssl/node0.cer delete mode 100644 modules/scylladb/src/test/resources/scylla-test-ssl/node0.p12 diff --git a/docs/modules/databases/scylladb.md b/docs/modules/databases/scylladb.md index b58e62264f9..9fab786c470 100644 --- a/docs/modules/databases/scylladb.md +++ b/docs/modules/databases/scylladb.md @@ -11,7 +11,7 @@ You can start a ScyllaDB container instance from any Java application by using: -[Custom config file](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:custom_configuration +[Custom config file](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:customConfiguration ### Building CqlSession diff --git a/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java b/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java index f255eda2717..93cc42905bf 100644 --- a/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java +++ b/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java @@ -74,6 +74,13 @@ public ScyllaDBContainer withConfigurationOverride(String configLocation) { return this; } + public ScyllaDBContainer withSsl(MountableFile certificate, MountableFile keyfile, MountableFile truststore) { + return withCopyFileToContainer(certificate, "/etc/scylla/scylla.cer.pem") + .withCopyFileToContainer(keyfile, "/etc/scylla/scylla.key.pem") + .withCopyFileToContainer(truststore, "/etc/scylla/scylla.truststore") + .withEnv("SSL_CERTFILE", "/etc/scylla/scylla.cer.pem"); + } + public ScyllaDBContainer withAlternator() { this.alternatorEnabled = true; return this; diff --git a/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java b/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java index d7e4f921976..9a205c66e8b 100644 --- a/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java +++ b/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java @@ -17,6 +17,9 @@ import software.amazon.awssdk.services.dynamodb.model.KeyType; import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; import java.io.IOException; import java.net.URI; import java.nio.file.Files; @@ -28,10 +31,6 @@ import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; - import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -44,8 +43,8 @@ public class ScyllaDBContainerTest { @Test public void testSimple() { try ( // container { - ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE) - // } + ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE) + // } ) { scylladb.start(); // session { @@ -64,22 +63,28 @@ public void testSimple() { @Test public void testSimpleSsl() - throws InterruptedException, NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException, KeyManagementException { + throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException, KeyManagementException { try ( - // custom_configuration { + // customConfiguration { ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE) .withConfigurationOverride("scylla-test-ssl") // } ) { // sslContext { - String testResourcesDir = getClass().getClassLoader().getResource("scylla-test-ssl/").getPath(); + ScyllaDBContainer sslScylladb = scylladb.withSsl( + MountableFile.forClasspathResource("scylla-test-ssl/keys/scylla.cer.pem"), + MountableFile.forClasspathResource("scylla-test-ssl/keys/scylla.key.pem"), + MountableFile.forClasspathResource("scylla-test-ssl/keys/scylla.truststore") + ); + + String testResourcesDir = getClass().getClassLoader().getResource("scylla-test-ssl/keys/").getPath(); KeyStore keyStore = KeyStore.getInstance("PKCS12"); - keyStore.load(Files.newInputStream(Paths.get(testResourcesDir + "keystore.node0")), "scylla".toCharArray()); + keyStore.load(Files.newInputStream(Paths.get(testResourcesDir + "scylla.keystore")), "scylla".toCharArray()); KeyStore trustStore = KeyStore.getInstance("PKCS12"); trustStore.load( - Files.newInputStream(Paths.get(testResourcesDir + "truststore.node0")), + Files.newInputStream(Paths.get(testResourcesDir + "scylla.truststore")), "scylla".toCharArray() ); @@ -97,11 +102,11 @@ public void testSimpleSsl() sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); // } - scylladb.start(); + sslScylladb.start(); CqlSession session = CqlSession .builder() - .addContactPoint(scylladb.getContactPoint()) + .addContactPoint(sslScylladb.getContactPoint()) .withLocalDatacenter("datacenter1") .withSslContext(sslContext) .build(); @@ -113,15 +118,20 @@ public void testSimpleSsl() } @Test - public void testSimpleSslCqlsh() throws InterruptedException, IOException { + public void testSimpleSslCqlsh() throws IllegalStateException, InterruptedException, IOException { + // sslConfiguration { + // } try ( ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE) .withConfigurationOverride("scylla-test-ssl") - ) { + .withSsl( + MountableFile.forClasspathResource("scylla-test-ssl/keys/scylla.cer.pem"), + MountableFile.forClasspathResource("scylla-test-ssl/keys/scylla.key.pem"), + MountableFile.forClasspathResource("scylla-test-ssl/keys/scylla.truststore") + )) { scylladb.start(); // sslCqlsh { - scylladb.execInContainer("mv", "-f", "/etc/scylla/cqlshrc", "/root/.cassandra/cqlshrc"); Container.ExecResult execResult = scylladb.execInContainer("cqlsh", "--ssl", "-e", "select * from system_schema.keyspaces;"); assertThat(execResult.getStdout()).contains("keyspace_name"); // } @@ -148,8 +158,8 @@ public void testShardAwareness() { @Test public void testAlternator() { try ( // alternator { - ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE).withAlternator() - // } + ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE).withAlternator() + // } ) { scylladb.start(); @@ -185,4 +195,5 @@ public void throwExceptionWhenAlternatorDisabled() { .hasMessageContaining("Alternator is not enabled"); } } + } diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/cqlshrc b/modules/scylladb/src/test/resources/scylla-test-ssl/cqlshrc deleted file mode 100644 index 5025c1a6d10..00000000000 --- a/modules/scylladb/src/test/resources/scylla-test-ssl/cqlshrc +++ /dev/null @@ -1,7 +0,0 @@ -[connection] -port = 9042 -hostname = 172.17.0.3 -factory = cqlshlib.ssl.ssl_transport_factory -[ssl] -certfile = /etc/scylla/node0.cer.pem -validate = false diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/keys/node0.cer b/modules/scylladb/src/test/resources/scylla-test-ssl/keys/node0.cer new file mode 100644 index 00000000000..e69de29bb2d diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/keys/node0.p12 b/modules/scylladb/src/test/resources/scylla-test-ssl/keys/node0.p12 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/node0.cer.pem b/modules/scylladb/src/test/resources/scylla-test-ssl/keys/scylla.cer.pem similarity index 100% rename from modules/scylladb/src/test/resources/scylla-test-ssl/node0.cer.pem rename to modules/scylladb/src/test/resources/scylla-test-ssl/keys/scylla.cer.pem diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/node0.key.pem b/modules/scylladb/src/test/resources/scylla-test-ssl/keys/scylla.key.pem similarity index 100% rename from modules/scylladb/src/test/resources/scylla-test-ssl/node0.key.pem rename to modules/scylladb/src/test/resources/scylla-test-ssl/keys/scylla.key.pem diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/keystore.node0 b/modules/scylladb/src/test/resources/scylla-test-ssl/keys/scylla.keystore similarity index 100% rename from modules/scylladb/src/test/resources/scylla-test-ssl/keystore.node0 rename to modules/scylladb/src/test/resources/scylla-test-ssl/keys/scylla.keystore diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/truststore.node0 b/modules/scylladb/src/test/resources/scylla-test-ssl/keys/scylla.truststore similarity index 100% rename from modules/scylladb/src/test/resources/scylla-test-ssl/truststore.node0 rename to modules/scylladb/src/test/resources/scylla-test-ssl/keys/scylla.truststore diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/node0.cer b/modules/scylladb/src/test/resources/scylla-test-ssl/node0.cer deleted file mode 100644 index 619eccb02282d3e439df1c67c8294110ff3aee14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1087 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 Jfd4z8{{jWwZw~+f diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/scylla.yaml b/modules/scylladb/src/test/resources/scylla-test-ssl/scylla.yaml index e71e807463b..7d79fabb70e 100644 --- a/modules/scylladb/src/test/resources/scylla-test-ssl/scylla.yaml +++ b/modules/scylladb/src/test/resources/scylla-test-ssl/scylla.yaml @@ -462,9 +462,9 @@ commitlog_total_space_in_mb: -1 # enable or disable client/server encryption. client_encryption_options: enabled: true - certificate: /etc/scylla/node0.cer.pem - keyfile: /etc/scylla/node0.key.pem - truststore: /etc/scylla/truststore.node0 + certificate: /etc/scylla/scylla.cer.pem + keyfile: /etc/scylla/scylla.key.pem + truststore: /etc/scylla/scylla.truststore truststore_password: scylla # certficate_revocation_list: # require_client_auth: False From 19ae30add45161b704ae95028783442ac02098f8 Mon Sep 17 00:00:00 2001 From: Maxim Korolyov Date: Fri, 31 Jan 2025 00:03:20 +0100 Subject: [PATCH 11/12] add additional withSsl(certificate, keyfile) --- .../scylladb/ScyllaDBContainer.java | 6 +++++- .../scylladb/ScyllaDBContainerTest.java | 14 +++++++------- .../{scylla-test-ssl => }/keys/node0.cer | 0 .../{scylla-test-ssl => }/keys/node0.p12 | 0 .../{scylla-test-ssl => }/keys/scylla.cer.pem | 0 .../{scylla-test-ssl => }/keys/scylla.key.pem | 0 .../{scylla-test-ssl => }/keys/scylla.keystore | Bin .../{scylla-test-ssl => }/keys/scylla.truststore | Bin 8 files changed, 12 insertions(+), 8 deletions(-) rename modules/scylladb/src/test/resources/{scylla-test-ssl => }/keys/node0.cer (100%) rename modules/scylladb/src/test/resources/{scylla-test-ssl => }/keys/node0.p12 (100%) rename modules/scylladb/src/test/resources/{scylla-test-ssl => }/keys/scylla.cer.pem (100%) rename modules/scylladb/src/test/resources/{scylla-test-ssl => }/keys/scylla.key.pem (100%) rename modules/scylladb/src/test/resources/{scylla-test-ssl => }/keys/scylla.keystore (100%) rename modules/scylladb/src/test/resources/{scylla-test-ssl => }/keys/scylla.truststore (100%) diff --git a/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java b/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java index 93cc42905bf..0a6939bd34b 100644 --- a/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java +++ b/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java @@ -75,9 +75,13 @@ public ScyllaDBContainer withConfigurationOverride(String configLocation) { } public ScyllaDBContainer withSsl(MountableFile certificate, MountableFile keyfile, MountableFile truststore) { + return withSsl(certificate, keyfile) + .withCopyFileToContainer(truststore, "/etc/scylla/scylla.truststore"); + } + + public ScyllaDBContainer withSsl(MountableFile certificate, MountableFile keyfile) { return withCopyFileToContainer(certificate, "/etc/scylla/scylla.cer.pem") .withCopyFileToContainer(keyfile, "/etc/scylla/scylla.key.pem") - .withCopyFileToContainer(truststore, "/etc/scylla/scylla.truststore") .withEnv("SSL_CERTFILE", "/etc/scylla/scylla.cer.pem"); } diff --git a/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java b/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java index 9a205c66e8b..5d99e8b6911 100644 --- a/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java +++ b/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java @@ -72,12 +72,12 @@ public void testSimpleSsl() ) { // sslContext { ScyllaDBContainer sslScylladb = scylladb.withSsl( - MountableFile.forClasspathResource("scylla-test-ssl/keys/scylla.cer.pem"), - MountableFile.forClasspathResource("scylla-test-ssl/keys/scylla.key.pem"), - MountableFile.forClasspathResource("scylla-test-ssl/keys/scylla.truststore") + MountableFile.forClasspathResource("keys/scylla.cer.pem"), + MountableFile.forClasspathResource("keys/scylla.key.pem"), + MountableFile.forClasspathResource("keys/scylla.truststore") ); - String testResourcesDir = getClass().getClassLoader().getResource("scylla-test-ssl/keys/").getPath(); + String testResourcesDir = getClass().getClassLoader().getResource("keys/").getPath(); KeyStore keyStore = KeyStore.getInstance("PKCS12"); keyStore.load(Files.newInputStream(Paths.get(testResourcesDir + "scylla.keystore")), "scylla".toCharArray()); @@ -125,9 +125,9 @@ public void testSimpleSslCqlsh() throws IllegalStateException, InterruptedExcept ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE) .withConfigurationOverride("scylla-test-ssl") .withSsl( - MountableFile.forClasspathResource("scylla-test-ssl/keys/scylla.cer.pem"), - MountableFile.forClasspathResource("scylla-test-ssl/keys/scylla.key.pem"), - MountableFile.forClasspathResource("scylla-test-ssl/keys/scylla.truststore") + MountableFile.forClasspathResource("keys/scylla.cer.pem"), + MountableFile.forClasspathResource("keys/scylla.key.pem"), + MountableFile.forClasspathResource("keys/scylla.truststore") )) { scylladb.start(); diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/keys/node0.cer b/modules/scylladb/src/test/resources/keys/node0.cer similarity index 100% rename from modules/scylladb/src/test/resources/scylla-test-ssl/keys/node0.cer rename to modules/scylladb/src/test/resources/keys/node0.cer diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/keys/node0.p12 b/modules/scylladb/src/test/resources/keys/node0.p12 similarity index 100% rename from modules/scylladb/src/test/resources/scylla-test-ssl/keys/node0.p12 rename to modules/scylladb/src/test/resources/keys/node0.p12 diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/keys/scylla.cer.pem b/modules/scylladb/src/test/resources/keys/scylla.cer.pem similarity index 100% rename from modules/scylladb/src/test/resources/scylla-test-ssl/keys/scylla.cer.pem rename to modules/scylladb/src/test/resources/keys/scylla.cer.pem diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/keys/scylla.key.pem b/modules/scylladb/src/test/resources/keys/scylla.key.pem similarity index 100% rename from modules/scylladb/src/test/resources/scylla-test-ssl/keys/scylla.key.pem rename to modules/scylladb/src/test/resources/keys/scylla.key.pem diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/keys/scylla.keystore b/modules/scylladb/src/test/resources/keys/scylla.keystore similarity index 100% rename from modules/scylladb/src/test/resources/scylla-test-ssl/keys/scylla.keystore rename to modules/scylladb/src/test/resources/keys/scylla.keystore diff --git a/modules/scylladb/src/test/resources/scylla-test-ssl/keys/scylla.truststore b/modules/scylladb/src/test/resources/keys/scylla.truststore similarity index 100% rename from modules/scylladb/src/test/resources/scylla-test-ssl/keys/scylla.truststore rename to modules/scylladb/src/test/resources/keys/scylla.truststore From 6ab9c7e9116b0f78e550bb67aff468c0e2cdcb15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Fri, 31 Jan 2025 13:55:17 -0600 Subject: [PATCH 12/12] Polish --- docs/modules/databases/scylladb.md | 4 -- modules/scylladb/build.gradle | 4 +- .../scylladb/ScyllaDBContainer.java | 13 ++--- .../scylladb/ScyllaDBContainerTest.java | 52 ++++++++++--------- 4 files changed, 35 insertions(+), 38 deletions(-) diff --git a/docs/modules/databases/scylladb.md b/docs/modules/databases/scylladb.md index 9fab786c470..186f5097d39 100644 --- a/docs/modules/databases/scylladb.md +++ b/docs/modules/databases/scylladb.md @@ -24,10 +24,6 @@ You can start a ScyllaDB container instance from any Java application by using: [Using SSL](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:sslContext - -[Using SSL with cqlsh](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:sslCqlsh - - [Using Shard Awareness port](../../../modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java) inside_block:shardAwarenessSession diff --git a/modules/scylladb/build.gradle b/modules/scylladb/build.gradle index 069a79cf36a..6d92489ef30 100644 --- a/modules/scylladb/build.gradle +++ b/modules/scylladb/build.gradle @@ -1,9 +1,9 @@ description = "Testcontainers :: ScyllaDB" dependencies { - api project(":database-commons") - api "com.scylladb:java-driver-core:4.15.0.0" + api project(":testcontainers") + testImplementation 'com.scylladb:java-driver-core:4.15.0.0' testImplementation 'org.assertj:assertj-core:3.24.2' testImplementation 'software.amazon.awssdk:dynamodb:2.28.6' } diff --git a/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java b/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java index 0a6939bd34b..f181b8b9f00 100644 --- a/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java +++ b/modules/scylladb/src/main/java/org/testcontainers/scylladb/ScyllaDBContainer.java @@ -75,14 +75,11 @@ public ScyllaDBContainer withConfigurationOverride(String configLocation) { } public ScyllaDBContainer withSsl(MountableFile certificate, MountableFile keyfile, MountableFile truststore) { - return withSsl(certificate, keyfile) - .withCopyFileToContainer(truststore, "/etc/scylla/scylla.truststore"); - } - - public ScyllaDBContainer withSsl(MountableFile certificate, MountableFile keyfile) { - return withCopyFileToContainer(certificate, "/etc/scylla/scylla.cer.pem") - .withCopyFileToContainer(keyfile, "/etc/scylla/scylla.key.pem") - .withEnv("SSL_CERTFILE", "/etc/scylla/scylla.cer.pem"); + withCopyFileToContainer(certificate, "/etc/scylla/scylla.cer.pem"); + withCopyFileToContainer(keyfile, "/etc/scylla/scylla.key.pem"); + withCopyFileToContainer(truststore, "/etc/scylla/scylla.truststore"); + withEnv("SSL_CERTFILE", "/etc/scylla/scylla.cer.pem"); + return this; } public ScyllaDBContainer withAlternator() { diff --git a/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java b/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java index 5d99e8b6911..d151424fd20 100644 --- a/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java +++ b/modules/scylladb/src/test/java/org/testcontainers/scylladb/ScyllaDBContainerTest.java @@ -17,9 +17,6 @@ import software.amazon.awssdk.services.dynamodb.model.KeyType; import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; import java.io.IOException; import java.net.URI; import java.nio.file.Files; @@ -31,6 +28,10 @@ import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -43,8 +44,8 @@ public class ScyllaDBContainerTest { @Test public void testSimple() { try ( // container { - ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE) - // } + ScyllaDBContainer scylladb = new ScyllaDBContainer("scylladb/scylla:6.2") + // } ) { scylladb.start(); // session { @@ -66,21 +67,23 @@ public void testSimpleSsl() throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException, KeyManagementException { try ( // customConfiguration { - ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE) + ScyllaDBContainer scylladb = new ScyllaDBContainer("scylladb/scylla:6.2") .withConfigurationOverride("scylla-test-ssl") + .withSsl( + MountableFile.forClasspathResource("keys/scylla.cer.pem"), + MountableFile.forClasspathResource("keys/scylla.key.pem"), + MountableFile.forClasspathResource("keys/scylla.truststore") + ) // } ) { // sslContext { - ScyllaDBContainer sslScylladb = scylladb.withSsl( - MountableFile.forClasspathResource("keys/scylla.cer.pem"), - MountableFile.forClasspathResource("keys/scylla.key.pem"), - MountableFile.forClasspathResource("keys/scylla.truststore") - ); - String testResourcesDir = getClass().getClassLoader().getResource("keys/").getPath(); KeyStore keyStore = KeyStore.getInstance("PKCS12"); - keyStore.load(Files.newInputStream(Paths.get(testResourcesDir + "scylla.keystore")), "scylla".toCharArray()); + keyStore.load( + Files.newInputStream(Paths.get(testResourcesDir + "scylla.keystore")), + "scylla".toCharArray() + ); KeyStore trustStore = KeyStore.getInstance("PKCS12"); trustStore.load( @@ -102,11 +105,11 @@ public void testSimpleSsl() sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); // } - sslScylladb.start(); + scylladb.start(); CqlSession session = CqlSession .builder() - .addContactPoint(sslScylladb.getContactPoint()) + .addContactPoint(scylladb.getContactPoint()) .withLocalDatacenter("datacenter1") .withSslContext(sslContext) .build(); @@ -119,8 +122,6 @@ public void testSimpleSsl() @Test public void testSimpleSslCqlsh() throws IllegalStateException, InterruptedException, IOException { - // sslConfiguration { - // } try ( ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE) .withConfigurationOverride("scylla-test-ssl") @@ -128,13 +129,17 @@ public void testSimpleSslCqlsh() throws IllegalStateException, InterruptedExcept MountableFile.forClasspathResource("keys/scylla.cer.pem"), MountableFile.forClasspathResource("keys/scylla.key.pem"), MountableFile.forClasspathResource("keys/scylla.truststore") - )) { + ) + ) { scylladb.start(); - // sslCqlsh { - Container.ExecResult execResult = scylladb.execInContainer("cqlsh", "--ssl", "-e", "select * from system_schema.keyspaces;"); + Container.ExecResult execResult = scylladb.execInContainer( + "cqlsh", + "--ssl", + "-e", + "select * from system_schema.keyspaces;" + ); assertThat(execResult.getStdout()).contains("keyspace_name"); - // } } } @@ -158,8 +163,8 @@ public void testShardAwareness() { @Test public void testAlternator() { try ( // alternator { - ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE).withAlternator() - // } + ScyllaDBContainer scylladb = new ScyllaDBContainer(SCYLLADB_IMAGE).withAlternator() + // } ) { scylladb.start(); @@ -195,5 +200,4 @@ public void throwExceptionWhenAlternatorDisabled() { .hasMessageContaining("Alternator is not enabled"); } } - }