From 20889fd856b96fe7b1bd75159986a5490369afab Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Sun, 15 Aug 2021 15:13:46 +0530 Subject: [PATCH 01/18] yugabytedb - initial commit Signed-off-by: Srinivasa Vasu --- docs/modules/databases/yugabytedb.md | 46 +++++ modules/yugabytedb/build.gradle | 10 ++ .../YugabyteContainerConstants.java | 42 +++++ .../containers/YugabyteYCQLContainer.java | 160 ++++++++++++++++++ .../containers/YugabyteYSQLContainer.java | 137 +++++++++++++++ .../YugabyteYSQLContainerProvider.java | 38 +++++ .../delegate/YugabyteYCQLDelegate.java | 41 +++++ .../strategy/YugabyteYCQLWaitStrategy.java | 50 ++++++ .../strategy/YugabyteYSQLWaitStrategy.java | 56 ++++++ ...s.containers.JdbcDatabaseContainerProvider | 1 + .../YugabyteTestContainerConstants.java | 18 ++ .../YugabyteYSQLJDBCDriverTest.java | 25 +++ .../yugabytedb/YugabyteYCQLUnitTest.java | 88 ++++++++++ .../yugabytedb/YugabyteYSQLUnitTest.java | 72 ++++++++ .../src/test/resources/init/init_yql.sql | 5 + 15 files changed, 789 insertions(+) create mode 100644 docs/modules/databases/yugabytedb.md create mode 100644 modules/yugabytedb/build.gradle create mode 100644 modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteContainerConstants.java create mode 100644 modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteYCQLContainer.java create mode 100644 modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteYSQLContainer.java create mode 100644 modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteYSQLContainerProvider.java create mode 100644 modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/YugabyteYCQLDelegate.java create mode 100644 modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteYCQLWaitStrategy.java create mode 100644 modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteYSQLWaitStrategy.java create mode 100644 modules/yugabytedb/src/main/resources/META-INF/services/org.testcontainers.containers.JdbcDatabaseContainerProvider create mode 100644 modules/yugabytedb/src/test/java/org/testcontainers/YugabyteTestContainerConstants.java create mode 100644 modules/yugabytedb/src/test/java/org/testcontainers/jdbc/yugabytedb/YugabyteYSQLJDBCDriverTest.java create mode 100644 modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteYCQLUnitTest.java create mode 100644 modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteYSQLUnitTest.java create mode 100644 modules/yugabytedb/src/test/resources/init/init_yql.sql diff --git a/docs/modules/databases/yugabytedb.md b/docs/modules/databases/yugabytedb.md new file mode 100644 index 00000000000..47204a8cdb9 --- /dev/null +++ b/docs/modules/databases/yugabytedb.md @@ -0,0 +1,46 @@ +# YugabyteDB Module + +See [Database containers](./index.md) for documentation and usage that is common to all database container types. + +YugabyteDB supports two APIs. +- Yugabyte Structured Query Language [YSQL](https://docs.yugabyte.com/latest/api/ysql/) is a fully-relational API that is built by the PostgreSQL code +- Yugabyte Cloud Query Language [YCQL](https://docs.yugabyte.com/latest/api/ycql/) is a semi-relational SQL API that has its roots in the Cassandra Query Language + +## Usage example + +### YSQL API + +```java +public class YugabyteDBTest { + + @Rule + public YugabyteYSQLContainer container = new YugabyteYSQLContainer("yugabytedb/yugabyte:2.7.2.0-b216"); + + @Test + public void method() { + String url = container.getJdbcUrl(); + + ... create a connection and run the tests as usual. It also depends on the frameworks being used. +``` + +#### JDBC URL + +`jdbc:tc:yugabyte:2.7.2.0-b216:///yugabyte` + +### YCQL API + +```java +public class YugabyteDBTest { + + @Rule + public YugabyteYCQLContainer container = new YugabyteYCQLContainer("yugabytedb/yugabyte:2.7.2.0-b216"); + + @Test + public void method() { + Session session = container.getSession(); + + ... create a connection and run the tests as usual. It also depends on the frameworks being used. +``` + +## Adding this module to your project dependencies +[[TODO]] diff --git a/modules/yugabytedb/build.gradle b/modules/yugabytedb/build.gradle new file mode 100644 index 00000000000..7992e09b95a --- /dev/null +++ b/modules/yugabytedb/build.gradle @@ -0,0 +1,10 @@ +description = "Testcontainers :: JDBC :: YugabyteDB" + +dependencies { + api project(':jdbc') + testImplementation project(':jdbc-test') + // YCQL driver + implementation 'com.yugabyte:java-driver-core:4.6.0-yb-6' + // YSQL driver + testImplementation 'com.yugabyte:jdbc-yugabytedb:42.2.7-yb-5-beta.2' +} diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteContainerConstants.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteContainerConstants.java new file mode 100644 index 00000000000..53a716fa963 --- /dev/null +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteContainerConstants.java @@ -0,0 +1,42 @@ +package org.testcontainers.containers; + +import org.testcontainers.utility.DockerImageName; + +/** + * Constants used in both YCQL and YSQL APIs + * + * @author srinivasa-vasu + */ +public interface YugabyteContainerConstants { + + DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("yugabytedb/yugabyte"); + + String DEFAULT_TAG = "2.7.2.0-b216"; + + String NAME = "yugabyte"; + + Integer YSQL_PORT = 5433; + + Integer YCQL_PORT = 9042; + + Integer MASTER_DASHBOARD_PORT = 7000; + + Integer TSERVER_DASHBOARD_PORT = 9000; + + String JDBC_DRIVER_CLASS = "org.postgresql.Driver"; + + String JDBC_CONNECT_PREFIX = "jdbc:postgresql"; + + String ENTRYPOINT = "bin/yugabyted start --daemon=false"; + + String LOCAL_DC = "datacenter1"; + + String USER_PARAM = "user"; + + String PASSWORD_PARAM = "password"; + + String YSQL_TEST_QUERY = "SELECT 1"; + + String YCQL_TEST_QUERY = "SELECT release_version FROM system.local"; + +} diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteYCQLContainer.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteYCQLContainer.java new file mode 100644 index 00000000000..a46f8fec4b8 --- /dev/null +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteYCQLContainer.java @@ -0,0 +1,160 @@ +package org.testcontainers.containers; + +import java.net.InetSocketAddress; +import java.time.Duration; + +import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.core.CqlSessionBuilder; +import com.github.dockerjava.api.command.InspectContainerResponse; +import org.testcontainers.containers.delegate.YugabyteYCQLDelegate; +import org.testcontainers.containers.strategy.YugabyteYCQLWaitStrategy; +import org.testcontainers.ext.ScriptUtils; +import org.testcontainers.utility.DockerImageName; + +import static org.testcontainers.containers.YugabyteContainerConstants.DEFAULT_IMAGE_NAME; +import static org.testcontainers.containers.YugabyteContainerConstants.ENTRYPOINT; +import static org.testcontainers.containers.YugabyteContainerConstants.LOCAL_DC; +import static org.testcontainers.containers.YugabyteContainerConstants.MASTER_DASHBOARD_PORT; +import static org.testcontainers.containers.YugabyteContainerConstants.TSERVER_DASHBOARD_PORT; +import static org.testcontainers.containers.YugabyteContainerConstants.YCQL_PORT; + +/** + * YugabyteDB YCQL (Cloud Query Language) API container + * + * @author srinivasa-vasu + * @see YCQL API + */ +public class YugabyteYCQLContainer extends GenericContainer { + + private String keyspace; + + private String username; + + private String password; + + private String initScript; + + /** + * @param imageName image name + */ + public YugabyteYCQLContainer(final String imageName) { + this(DockerImageName.parse(imageName)); + } + + /** + * @param imageName image name + */ + public YugabyteYCQLContainer(final DockerImageName imageName) { + super(imageName); + imageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); + withExposedPorts(YCQL_PORT, MASTER_DASHBOARD_PORT, TSERVER_DASHBOARD_PORT); + waitingFor(new YugabyteYCQLWaitStrategy(this).withStartupTimeout(Duration.ofSeconds(60))); + withCommand(ENTRYPOINT); + } + + /** + * Configures the environment variables. Setting up these variables would create the + * custom objects. Setting {@link #withKeyspaceName(String)}, + * {@link #withUsername(String)}, {@link #withPassword(String)} these parameters will + * initilaize the database with those custom values + */ + @Override + protected void configure() { + addEnv("YCQL_KEYSPACE", keyspace); + addEnv("YCQL_USER", username); + addEnv("YCQL_PASSWORD", password); + } + + /** + * @param initScript path of the initialization script file + * @return {@link YugabyteYCQLContainer} instance + */ + public YugabyteYCQLContainer withInitScript(String initScript) { + this.initScript = initScript; + return this; + } + + /** + * Setting this would create the keyspace + * @param keyspace keyspace + * @return {@link YugabyteYCQLContainer} instance + */ + public YugabyteYCQLContainer withKeyspaceName(final String keyspace) { + this.keyspace = keyspace; + return this; + } + + /** + * Setting this would create the custom user role + * @param username user name + * @return {@link YugabyteYCQLContainer} instance + */ + public YugabyteYCQLContainer withUsername(final String username) { + this.username = username; + return this; + } + + /** + * Setting this along with {@link #withUsername(String)} would enable authentication + * @param password password + * @return {@link YugabyteYCQLContainer} instance + */ + public YugabyteYCQLContainer withPassword(final String password) { + this.password = password; + return this; + } + + /** + * Executes the initilization script + * @param containerInfo containerInfo + */ + @Override + protected void containerIsStarted(InspectContainerResponse containerInfo) { + if (initScript != null) { + ScriptUtils.runInitScript(new YugabyteYCQLDelegate(getSessionBuilder()), initScript); + } + } + + /** + * Builds a {@link CqlSession} instance + * @return {@link CqlSession} instance + */ + public CqlSession getSession() { + return getSessionBuilder().build(); + } + + /** + * Builder method for {#com.datastax.oss.driver.api.core.CqlSession} + * @return {@link CqlSessionBuilder} + */ + public CqlSessionBuilder getSessionBuilder() { + return CqlSession.builder().withLocalDatacenter(LOCAL_DC).withKeyspace(this.getKeyspace()) + .withAuthCredentials(this.getUsername(), this.getPassword()) + .addContactPoint(new InetSocketAddress(this.getHost(), this.getMappedPort(YCQL_PORT))); + } + + /** + * Username getter method + * @return username + */ + public String getUsername() { + return username; + } + + /** + * Password getter method + * @return password + */ + public String getPassword() { + return password; + } + + /** + * Keyspace getter method + * @return keyspace + */ + public String getKeyspace() { + return keyspace; + } + +} diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteYSQLContainer.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteYSQLContainer.java new file mode 100644 index 00000000000..5e7083856ee --- /dev/null +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteYSQLContainer.java @@ -0,0 +1,137 @@ +package org.testcontainers.containers; + +import java.time.Duration; +import java.util.Set; + +import org.testcontainers.containers.strategy.YugabyteYSQLWaitStrategy; +import org.testcontainers.utility.DockerImageName; + +import static java.util.Collections.singleton; +import static org.testcontainers.containers.YugabyteContainerConstants.DEFAULT_IMAGE_NAME; +import static org.testcontainers.containers.YugabyteContainerConstants.ENTRYPOINT; +import static org.testcontainers.containers.YugabyteContainerConstants.JDBC_CONNECT_PREFIX; +import static org.testcontainers.containers.YugabyteContainerConstants.JDBC_DRIVER_CLASS; +import static org.testcontainers.containers.YugabyteContainerConstants.MASTER_DASHBOARD_PORT; +import static org.testcontainers.containers.YugabyteContainerConstants.TSERVER_DASHBOARD_PORT; +import static org.testcontainers.containers.YugabyteContainerConstants.YSQL_PORT; + +/** + * YugabyteDB YSQL (Structured Query Language) API container + * + * @author srinivasa-vasu + * @see YSQL API + */ + +public class YugabyteYSQLContainer extends JdbcDatabaseContainer { + + private String database = "yugabyte"; + + private String username = "yugabyte"; + + private String password = "yugabyte"; + + /** + * @param imageName image name + */ + public YugabyteYSQLContainer(final String imageName) { + this(DockerImageName.parse(imageName)); + } + + /** + * @param imageName image name + */ + public YugabyteYSQLContainer(final DockerImageName imageName) { + super(imageName); + imageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); + withExposedPorts(YSQL_PORT, MASTER_DASHBOARD_PORT, TSERVER_DASHBOARD_PORT); + waitingFor(new YugabyteYSQLWaitStrategy(this).withStartupTimeout(Duration.ofSeconds(60))); + withCommand(ENTRYPOINT); + } + + @Override + public Set getLivenessCheckPortNumbers() { + return singleton(getMappedPort(YSQL_PORT)); + } + + /** + * Configures the environment variables. Setting up these variables would create the + * custom objects. Setting {@link #withDatabaseName(String)}, + * {@link #withUsername(String)}, {@link #withPassword(String)} these parameters will + * initilaize the database with those custom values + */ + + @Override + protected void configure() { + addEnv("YSQL_DB", database); + addEnv("YSQL_USER", username); + addEnv("YSQL_PASSWORD", password); + } + + @Override + public String getDriverClassName() { + return JDBC_DRIVER_CLASS; + } + + @Override + public String getJdbcUrl() { + return JDBC_CONNECT_PREFIX + "://" + getHost() + ":" + getMappedPort(YSQL_PORT) + "/" + database + + constructUrlParameters("?", "&"); + } + + @Override + public String getDatabaseName() { + return database; + } + + @Override + public String getUsername() { + return username; + } + + @Override + public String getPassword() { + return password; + } + + @Override + public String getTestQueryString() { + return "SELECT 1"; + } + + /** + * Setting this would create the keyspace + * @param database database name + * @return {@link YugabyteYSQLContainer} instance + */ + + @Override + public YugabyteYSQLContainer withDatabaseName(final String database) { + this.database = database; + return this; + } + + /** + * Setting this would create the custom user role + * @param username user name + * @return {@link YugabyteYSQLContainer} instance + */ + + @Override + public YugabyteYSQLContainer withUsername(final String username) { + this.username = username; + return this; + } + + /** + * Setting this along with {@link #withUsername(String)} would enable authentication + * @param password password + * @return {@link YugabyteYSQLContainer} instance + */ + + @Override + public YugabyteYSQLContainer withPassword(final String password) { + this.password = password; + return this; + } + +} diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteYSQLContainerProvider.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteYSQLContainerProvider.java new file mode 100644 index 00000000000..3b729a5dc46 --- /dev/null +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteYSQLContainerProvider.java @@ -0,0 +1,38 @@ +package org.testcontainers.containers; + +import org.testcontainers.jdbc.ConnectionUrl; + +import static org.testcontainers.containers.YugabyteContainerConstants.DEFAULT_IMAGE_NAME; +import static org.testcontainers.containers.YugabyteContainerConstants.DEFAULT_TAG; +import static org.testcontainers.containers.YugabyteContainerConstants.NAME; +import static org.testcontainers.containers.YugabyteContainerConstants.PASSWORD_PARAM; +import static org.testcontainers.containers.YugabyteContainerConstants.USER_PARAM; + +/** + * YugabyteDB YSQL (Structured Query Language) JDBC container provider + * + * @author srinivasa-vasu + */ +public class YugabyteYSQLContainerProvider extends JdbcDatabaseContainerProvider { + + @Override + public boolean supports(String databaseType) { + return databaseType.equals(NAME); + } + + @Override + public JdbcDatabaseContainer newInstance() { + return newInstance(DEFAULT_TAG); + } + + @Override + public JdbcDatabaseContainer newInstance(String tag) { + return new YugabyteYSQLContainer(DEFAULT_IMAGE_NAME.withTag(tag)); + } + + @Override + public JdbcDatabaseContainer newInstance(ConnectionUrl connectionUrl) { + return newInstanceFromConnectionUrl(connectionUrl, USER_PARAM, PASSWORD_PARAM); + } + +} diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/YugabyteYCQLDelegate.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/YugabyteYCQLDelegate.java new file mode 100644 index 00000000000..5a2eac05800 --- /dev/null +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/YugabyteYCQLDelegate.java @@ -0,0 +1,41 @@ +package org.testcontainers.containers.delegate; + +import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.core.CqlSessionBuilder; +import com.datastax.oss.driver.api.core.session.Session; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.testcontainers.containers.YugabyteYCQLContainer; +import org.testcontainers.delegate.AbstractDatabaseDelegate; + +/** + * Query execution delegate class for YCQL API to delegate init-scripts statements. + * + * @author srinivasa-vasu + * @see YugabyteYCQLContainer + */ +@Slf4j +@RequiredArgsConstructor +public final class YugabyteYCQLDelegate extends AbstractDatabaseDelegate { + + private final CqlSessionBuilder builder; + + @Override + protected Session createNewConnection() { + return builder.build(); + } + + @Override + public void execute(String statement, String scriptPath, int lineNumber, boolean continueOnError, + boolean ignoreFailedDrops) { + ((CqlSession) getConnection()).execute(statement); + } + + @Override + protected void closeConnectionQuietly(Session session) { + if (session != null) { + session.close(); + } + } + +} diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteYCQLWaitStrategy.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteYCQLWaitStrategy.java new file mode 100644 index 00000000000..de2b3c851b2 --- /dev/null +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteYCQLWaitStrategy.java @@ -0,0 +1,50 @@ +package org.testcontainers.containers.strategy; + +import java.util.concurrent.TimeUnit; + +import com.datastax.oss.driver.api.core.CqlSession; +import lombok.RequiredArgsConstructor; +import org.testcontainers.containers.YugabyteYCQLContainer; +import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy; +import org.testcontainers.containers.wait.strategy.WaitStrategyTarget; + +import static org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess; +import static org.testcontainers.containers.YugabyteContainerConstants.YCQL_TEST_QUERY; + +/** + * Custom wait strategy for YCQL API. + * + *

+ * Though we can either use HTTP or PORT based wait strategy, when we create a custom + * keyspace/role, it gets executed asynchronously. As the wait on container.start() on a + * specific port wouldn't fully guarantee the custom object execution. It's better to + * check the DB status with this way with a smoke test query that uses the underlying + * custom objects and wait for the operation to complete. + *

+ * + * @author srinivasa-vasu + */ +@RequiredArgsConstructor +public final class YugabyteYCQLWaitStrategy extends AbstractWaitStrategy { + + private final WaitStrategyTarget target; + + @Override + public void waitUntilReady(WaitStrategyTarget target) { + YugabyteYCQLContainer container = (YugabyteYCQLContainer) target; + retryUntilSuccess((int) startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> { + getRateLimiter().doWhenReady(() -> { + try (CqlSession session = container.getSession()) { + session.execute(YCQL_TEST_QUERY); + } + }); + return true; + }); + } + + @Override + public void waitUntilReady() { + waitUntilReady(target); + } + +} diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteYSQLWaitStrategy.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteYSQLWaitStrategy.java new file mode 100644 index 00000000000..1f114489f39 --- /dev/null +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteYSQLWaitStrategy.java @@ -0,0 +1,56 @@ +package org.testcontainers.containers.strategy; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.concurrent.TimeUnit; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.testcontainers.containers.YugabyteYSQLContainer; +import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy; +import org.testcontainers.containers.wait.strategy.WaitStrategyTarget; + +import static org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess; +import static org.testcontainers.containers.YugabyteContainerConstants.YSQL_TEST_QUERY; + +/** + * Custom wait strategy for YSQL API. + * + *

+ * Though we can either use HTTP or PORT based wait strategy, when we create a custom + * database/role, it gets executed asynchronously. As the wait on container.start() on a + * specific port wouldn't fully guarantee the custom object execution. It's better to + * check the DB status with this way with a smoke test query that uses the underlying + * custom objects and wait for the operation to complete. + *

+ * + * @author srinivasa-vasu + */ +@RequiredArgsConstructor +@Slf4j +public final class YugabyteYSQLWaitStrategy extends AbstractWaitStrategy { + + private final WaitStrategyTarget target; + + @Override + public void waitUntilReady(WaitStrategyTarget target) { + YugabyteYSQLContainer container = (YugabyteYSQLContainer) target; + retryUntilSuccess((int) startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> { + getRateLimiter().doWhenReady(() -> { + try (Connection con = container.createConnection(container.getJdbcUrl())) { + con.createStatement().execute(YSQL_TEST_QUERY); + } + catch (SQLException ex) { + log.error("Error connecting to the database", ex); + } + }); + return true; + }); + } + + @Override + public void waitUntilReady() { + waitUntilReady(target); + } + +} diff --git a/modules/yugabytedb/src/main/resources/META-INF/services/org.testcontainers.containers.JdbcDatabaseContainerProvider b/modules/yugabytedb/src/main/resources/META-INF/services/org.testcontainers.containers.JdbcDatabaseContainerProvider new file mode 100644 index 00000000000..d4b25fba9f4 --- /dev/null +++ b/modules/yugabytedb/src/main/resources/META-INF/services/org.testcontainers.containers.JdbcDatabaseContainerProvider @@ -0,0 +1 @@ +org.testcontainers.containers.YugabyteYSQLContainerProvider diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/YugabyteTestContainerConstants.java b/modules/yugabytedb/src/test/java/org/testcontainers/YugabyteTestContainerConstants.java new file mode 100644 index 00000000000..d94b01a422b --- /dev/null +++ b/modules/yugabytedb/src/test/java/org/testcontainers/YugabyteTestContainerConstants.java @@ -0,0 +1,18 @@ +package org.testcontainers; + +import org.testcontainers.utility.DockerImageName; + +/** + * @author srinivasa-vasu + */ +public interface YugabyteTestContainerConstants { + + String IMAGE_NAME = "yugabytedb/yugabyte:2.7.2.0-b216"; + + DockerImageName YBDB_TEST_IMAGE = DockerImageName.parse(IMAGE_NAME); + + String LOCAL_DC = "datacenter1"; + + int YCQL_PORT = 9042; + +} diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/jdbc/yugabytedb/YugabyteYSQLJDBCDriverTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/jdbc/yugabytedb/YugabyteYSQLJDBCDriverTest.java new file mode 100644 index 00000000000..510a71f26d3 --- /dev/null +++ b/modules/yugabytedb/src/test/java/org/testcontainers/jdbc/yugabytedb/YugabyteYSQLJDBCDriverTest.java @@ -0,0 +1,25 @@ +package org.testcontainers.jdbc.yugabytedb; + +import java.util.EnumSet; + +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.testcontainers.jdbc.AbstractJDBCDriverTest; + +import static java.util.Arrays.asList; + +/** + * YugabyteDB YSQL API JDBC connectivity driver test class + * + * @author srinivasa-vasu + */ +@RunWith(Parameterized.class) +public class YugabyteYSQLJDBCDriverTest extends AbstractJDBCDriverTest { + + @Parameterized.Parameters(name = "{index} - {0}") + public static Iterable data() { + return asList(new Object[][] { { "jdbc:tc:yugabyte://hostname/yugabyte?user=yugabyte&password=yugabyte", + EnumSet.noneOf(Options.class) }, }); + } + +} diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteYCQLUnitTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteYCQLUnitTest.java new file mode 100644 index 00000000000..ad3fc44f1aa --- /dev/null +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteYCQLUnitTest.java @@ -0,0 +1,88 @@ +package org.testcontainers.junit.yugabytedb; + +import java.net.InetSocketAddress; + +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.YugabyteYCQLContainer; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.testcontainers.YugabyteTestContainerConstants.IMAGE_NAME; +import static org.testcontainers.YugabyteTestContainerConstants.LOCAL_DC; +import static org.testcontainers.YugabyteTestContainerConstants.YBDB_TEST_IMAGE; +import static org.testcontainers.YugabyteTestContainerConstants.YCQL_PORT; + +/** + * YugabyteDB YCQL API unit test class + * + * @author srinivasa-vasu + */ +public class YugabyteYCQLUnitTest { + + @Test + public void testSmoke() { + try (YugabyteYCQLContainer container = new YugabyteYCQLContainer(IMAGE_NAME)) { + container.start(); + assertNotNull("Smoke test simple query execution fails!", + performQuery(container, "SELECT release_version FROM system.local").one().getString(0)); + } + } + + @Test + public void testCustomKeyspace() throws InterruptedException { + String key = "random"; + try (YugabyteYCQLContainer container = new YugabyteYCQLContainer(YBDB_TEST_IMAGE).withKeyspaceName(key)) { + container.start(); + assertEquals("Custom keyspace creation fails!", key, + performQuery(container, + "SELECT keyspace_name FROM system_schema.keyspaces where keyspace_name='" + key + "'").one() + .getString(0)); + } + } + + @Test + public void testAuthenticationEnabled() throws InterruptedException { + String role = "random"; + try (YugabyteYCQLContainer container = new YugabyteYCQLContainer(YBDB_TEST_IMAGE).withUsername(role) + .withPassword(role)) { + container.start(); + assertEquals("Keyspace login fails with authentication enabled!", role, + performQuery(container, "SELECT role FROM system_auth.roles where role='" + role + "'").one() + .getString(0)); + } + } + + @Test + public void testAuthenticationDisabled() { + try (YugabyteYCQLContainer container = new YugabyteYCQLContainer(YBDB_TEST_IMAGE).withPassword("") + .withUsername("")) { + container.start(); + assertTrue("Query execution fails!", + performQuery(container, "SELECT release_version FROM system.local").wasApplied()); + } + } + + @Test + public void testInitScript() throws InterruptedException { + String key = "random"; + try (YugabyteYCQLContainer container = new YugabyteYCQLContainer(YBDB_TEST_IMAGE).withKeyspaceName(key) + .withUsername(key).withPassword(key).withInitScript("init/init_yql.sql")) { + container.start(); + assertTrue("Query execution fails to execute statements from a custom script!", + performQuery(container, "SELECT * FROM random.bar").wasApplied()); + } + } + + private ResultSet performQuery(YugabyteYCQLContainer container, String cql) { + try (CqlSession session = CqlSession.builder().withKeyspace(container.getKeyspace()) + .withAuthCredentials(container.getUsername(), container.getPassword()).withLocalDatacenter(LOCAL_DC) + .addContactPoint(new InetSocketAddress(container.getHost(), container.getMappedPort(YCQL_PORT))) + .build()) { + return session.execute(cql); + } + } + +} diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteYSQLUnitTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteYSQLUnitTest.java new file mode 100644 index 00000000000..707a3604991 --- /dev/null +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteYSQLUnitTest.java @@ -0,0 +1,72 @@ +package org.testcontainers.junit.yugabytedb; + +import java.sql.SQLException; + +import org.junit.Test; +import org.testcontainers.containers.YugabyteYSQLContainer; +import org.testcontainers.db.AbstractContainerDatabaseTest; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.testcontainers.YugabyteTestContainerConstants.IMAGE_NAME; +import static org.testcontainers.YugabyteTestContainerConstants.YBDB_TEST_IMAGE; + +/** + * YugabyteDB YSQL API unit test class + * + * @author srinivasa-vasu + */ +public class YugabyteYSQLUnitTest extends AbstractContainerDatabaseTest { + + @Test + public void testSmoke() throws SQLException { + try (YugabyteYSQLContainer container = new YugabyteYSQLContainer(IMAGE_NAME)) { + container.start(); + assertEquals("Query execution fails!", 1, performQuery(container, "SELECT 1").getInt(1)); + } + } + + @Test + public void testCustomDatabase() throws SQLException { + String key = "random"; + try (YugabyteYSQLContainer container = new YugabyteYSQLContainer(YBDB_TEST_IMAGE).withDatabaseName(key)) { + container.start(); + assertEquals("Query execution on a custom database fails!", 1, + performQuery(container, "SELECT 1").getInt(1)); + } + } + + @Test + public void testExplicitInitScript() throws SQLException { + try (YugabyteYSQLContainer container = new YugabyteYSQLContainer(YBDB_TEST_IMAGE) + .withInitScript("init/init_yql.sql")) { + container.start(); + assertEquals("Value from the init script does not match the real value", "hello world", + performQuery(container, "SELECT foo FROM bar").getString(1)); + } + } + + @Test + public void testWithAdditionalUrlParamInJdbcUrl() { + try (YugabyteYSQLContainer container = new YugabyteYSQLContainer(YBDB_TEST_IMAGE) + .withUrlParam("sslmode", "disable").withUrlParam("application_name", "yugabyte")) { + container.start(); + String jdbcUrl = container.getJdbcUrl(); + assertThat(jdbcUrl, containsString("?")); + assertThat(jdbcUrl, containsString("&")); + assertThat(jdbcUrl, containsString("sslmode=disable")); + assertThat(jdbcUrl, containsString("application_name=yugabyte")); + } + } + + @Test + public void testWithCustomRole() throws SQLException { + try (YugabyteYSQLContainer container = new YugabyteYSQLContainer(YBDB_TEST_IMAGE).withDatabaseName("yugabyte") + .withPassword("yugabyte").withUsername("yugabyte")) { + container.start(); + assertEquals("Query execution with a custom role fails!", 1, performQuery(container, "SELECT 1").getInt(1)); + } + } + +} diff --git a/modules/yugabytedb/src/test/resources/init/init_yql.sql b/modules/yugabytedb/src/test/resources/init/init_yql.sql new file mode 100644 index 00000000000..f09647da277 --- /dev/null +++ b/modules/yugabytedb/src/test/resources/init/init_yql.sql @@ -0,0 +1,5 @@ +CREATE TABLE bar( + foo text primary key +); + +INSERT INTO bar (foo) VALUES ('hello world'); From b247c5661a398ee53b22f02e43a3d92fa3a66a9f Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Sun, 14 Nov 2021 08:35:20 +0530 Subject: [PATCH 02/18] update: ysql latest driver and the default image tag Signed-off-by: Srinivasa Vasu --- modules/yugabytedb/build.gradle | 5 +++-- .../containers/YugabyteContainerConstants.java | 6 +++--- .../org/testcontainers/YugabyteTestContainerConstants.java | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/modules/yugabytedb/build.gradle b/modules/yugabytedb/build.gradle index 7992e09b95a..c68b9337424 100644 --- a/modules/yugabytedb/build.gradle +++ b/modules/yugabytedb/build.gradle @@ -1,10 +1,11 @@ description = "Testcontainers :: JDBC :: YugabyteDB" dependencies { - api project(':jdbc') + // api project(':jdbc') + api 'org.testcontainers:jdbc:1.16.0' testImplementation project(':jdbc-test') // YCQL driver implementation 'com.yugabyte:java-driver-core:4.6.0-yb-6' // YSQL driver - testImplementation 'com.yugabyte:jdbc-yugabytedb:42.2.7-yb-5-beta.2' + testImplementation 'com.yugabyte:jdbc-yugabytedb:42.3.0' } diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteContainerConstants.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteContainerConstants.java index 53a716fa963..398dc309f3b 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteContainerConstants.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteContainerConstants.java @@ -11,7 +11,7 @@ public interface YugabyteContainerConstants { DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("yugabytedb/yugabyte"); - String DEFAULT_TAG = "2.7.2.0-b216"; + String DEFAULT_TAG = "2.9.1.0-b140"; String NAME = "yugabyte"; @@ -23,9 +23,9 @@ public interface YugabyteContainerConstants { Integer TSERVER_DASHBOARD_PORT = 9000; - String JDBC_DRIVER_CLASS = "org.postgresql.Driver"; + String JDBC_DRIVER_CLASS = "com.yugabyte.Driver"; - String JDBC_CONNECT_PREFIX = "jdbc:postgresql"; + String JDBC_CONNECT_PREFIX = "jdbc:yugabytedb"; String ENTRYPOINT = "bin/yugabyted start --daemon=false"; diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/YugabyteTestContainerConstants.java b/modules/yugabytedb/src/test/java/org/testcontainers/YugabyteTestContainerConstants.java index d94b01a422b..f71dd83ea14 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/YugabyteTestContainerConstants.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/YugabyteTestContainerConstants.java @@ -7,7 +7,7 @@ */ public interface YugabyteTestContainerConstants { - String IMAGE_NAME = "yugabytedb/yugabyte:2.7.2.0-b216"; + String IMAGE_NAME = "yugabytedb/yugabyte:2.9.1.0-b140"; DockerImageName YBDB_TEST_IMAGE = DockerImageName.parse(IMAGE_NAME); From ab9773ea781dabb481a21ffe199a93225b98a39a Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Sun, 14 Nov 2021 09:25:07 +0530 Subject: [PATCH 03/18] update: build info Signed-off-by: Srinivasa Vasu --- docs/modules/databases/yugabytedb.md | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/docs/modules/databases/yugabytedb.md b/docs/modules/databases/yugabytedb.md index 47204a8cdb9..35d37bec135 100644 --- a/docs/modules/databases/yugabytedb.md +++ b/docs/modules/databases/yugabytedb.md @@ -14,7 +14,7 @@ YugabyteDB supports two APIs. public class YugabyteDBTest { @Rule - public YugabyteYSQLContainer container = new YugabyteYSQLContainer("yugabytedb/yugabyte:2.7.2.0-b216"); + public YugabyteYSQLContainer container = new YugabyteYSQLContainer("yugabytedb/yugabyte:2.9.1.0-b140"); @Test public void method() { @@ -33,7 +33,7 @@ public class YugabyteDBTest { public class YugabyteDBTest { @Rule - public YugabyteYCQLContainer container = new YugabyteYCQLContainer("yugabytedb/yugabyte:2.7.2.0-b216"); + public YugabyteYCQLContainer container = new YugabyteYCQLContainer("yugabytedb/yugabyte:2.9.1.0-b140"); @Test public void method() { @@ -43,4 +43,23 @@ public class YugabyteDBTest { ``` ## Adding this module to your project dependencies -[[TODO]] + +Add the following dependency to your `pom.xml`/`build.gradle` file: + +```groovy tab='Gradle' +testImplementation "org.testcontainers:yugabytedb:{{latest_version}}" +``` + +```xml tab='Maven' + + org.testcontainers + yugabytedb + {{latest_version}} + test + +``` + +!!! hint + Adding this Testcontainers library JAR will not automatically add the Yugabytedb driver JAR to your project. + You should ensure that your project has the Yugabytedb driver as a dependency, if you plan on using it. + Refer to the driver page [YSQL](https://docs.yugabyte.com/latest/integrations/jdbc-driver/) and [YCQL](https://docs.yugabyte.com/latest/reference/drivers/ycql-client-drivers/) for instructions. From cb4f3b0f18f848f6ea653d0aa772f855d30eaad3 Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Wed, 9 Mar 2022 22:39:07 +0530 Subject: [PATCH 04/18] version update to 2.12 Signed-off-by: Srinivasa Vasu --- docs/modules/databases/yugabytedb.md | 6 +++--- modules/yugabytedb/build.gradle | 7 +++---- .../containers/YugabyteContainerConstants.java | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/docs/modules/databases/yugabytedb.md b/docs/modules/databases/yugabytedb.md index 35d37bec135..e723b2f1e25 100644 --- a/docs/modules/databases/yugabytedb.md +++ b/docs/modules/databases/yugabytedb.md @@ -14,7 +14,7 @@ YugabyteDB supports two APIs. public class YugabyteDBTest { @Rule - public YugabyteYSQLContainer container = new YugabyteYSQLContainer("yugabytedb/yugabyte:2.9.1.0-b140"); + public YugabyteYSQLContainer container = new YugabyteYSQLContainer("yugabytedb/yugabyte:2.12.1.0-b41"); @Test public void method() { @@ -25,7 +25,7 @@ public class YugabyteDBTest { #### JDBC URL -`jdbc:tc:yugabyte:2.7.2.0-b216:///yugabyte` +`jdbc:tc:yugabyte:2.12.1.0-b41:///yugabyte` ### YCQL API @@ -33,7 +33,7 @@ public class YugabyteDBTest { public class YugabyteDBTest { @Rule - public YugabyteYCQLContainer container = new YugabyteYCQLContainer("yugabytedb/yugabyte:2.9.1.0-b140"); + public YugabyteYCQLContainer container = new YugabyteYCQLContainer("yugabytedb/yugabyte:2.12.1.0-b41"); @Test public void method() { diff --git a/modules/yugabytedb/build.gradle b/modules/yugabytedb/build.gradle index c68b9337424..1b52a2d3394 100644 --- a/modules/yugabytedb/build.gradle +++ b/modules/yugabytedb/build.gradle @@ -1,11 +1,10 @@ description = "Testcontainers :: JDBC :: YugabyteDB" dependencies { - // api project(':jdbc') - api 'org.testcontainers:jdbc:1.16.0' + api project(':jdbc') testImplementation project(':jdbc-test') // YCQL driver - implementation 'com.yugabyte:java-driver-core:4.6.0-yb-6' + implementation 'com.yugabyte:java-driver-core:4.6.0-yb-10' // YSQL driver - testImplementation 'com.yugabyte:jdbc-yugabytedb:42.3.0' + testImplementation 'com.yugabyte:jdbc-yugabytedb:42.3.4' } diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteContainerConstants.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteContainerConstants.java index 398dc309f3b..fde5ebd4fc3 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteContainerConstants.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteContainerConstants.java @@ -11,7 +11,7 @@ public interface YugabyteContainerConstants { DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("yugabytedb/yugabyte"); - String DEFAULT_TAG = "2.9.1.0-b140"; + String DEFAULT_TAG = "2.12.1.0-b41"; String NAME = "yugabyte"; From ad5f960d0629f868c677de9b51e95de230a6a45d Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Wed, 9 Mar 2022 22:45:13 +0530 Subject: [PATCH 05/18] version update to 2.12 for the test Signed-off-by: Srinivasa Vasu --- .../java/org/testcontainers/YugabyteTestContainerConstants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/YugabyteTestContainerConstants.java b/modules/yugabytedb/src/test/java/org/testcontainers/YugabyteTestContainerConstants.java index f71dd83ea14..063337b3a0d 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/YugabyteTestContainerConstants.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/YugabyteTestContainerConstants.java @@ -7,7 +7,7 @@ */ public interface YugabyteTestContainerConstants { - String IMAGE_NAME = "yugabytedb/yugabyte:2.9.1.0-b140"; + String IMAGE_NAME = "yugabytedb/yugabyte:2.12.1.0-b41"; DockerImageName YBDB_TEST_IMAGE = DockerImageName.parse(IMAGE_NAME); From e645fb3fca4333680b3dbb192e9b5a417855eef7 Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Tue, 26 Jul 2022 22:09:09 +0530 Subject: [PATCH 06/18] refactor from yugabyte to yugabytedb Signed-off-by: Srinivasa Vasu --- docs/modules/databases/yugabytedb.md | 36 +++---- .../YugabyteContainerConstants.java | 42 -------- ...iner.java => YugabyteDBYCQLContainer.java} | 49 +++++---- ...iner.java => YugabyteDBYSQLContainer.java} | 43 ++++---- ...a => YugabyteDBYSQLContainerProvider.java} | 21 ++-- ...egate.java => YugabyteDBYCQLDelegate.java} | 6 +- ...y.java => YugabyteDBYCQLWaitStrategy.java} | 9 +- ...y.java => YugabyteDBYSQLWaitStrategy.java} | 9 +- ...s.containers.JdbcDatabaseContainerProvider | 2 +- .../YugabyteTestContainerConstants.java | 18 ---- ...java => YugabyteDBYSQLJDBCDriverTest.java} | 2 +- .../yugabytedb/YugabyteDBYCQLUnitTest.java | 101 ++++++++++++++++++ .../yugabytedb/YugabyteDBYSQLUnitTest.java | 83 ++++++++++++++ .../yugabytedb/YugabyteYCQLUnitTest.java | 88 --------------- .../yugabytedb/YugabyteYSQLUnitTest.java | 72 ------------- 15 files changed, 277 insertions(+), 304 deletions(-) delete mode 100644 modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteContainerConstants.java rename modules/yugabytedb/src/main/java/org/testcontainers/containers/{YugabyteYCQLContainer.java => YugabyteDBYCQLContainer.java} (67%) rename modules/yugabytedb/src/main/java/org/testcontainers/containers/{YugabyteYSQLContainer.java => YugabyteDBYSQLContainer.java} (63%) rename modules/yugabytedb/src/main/java/org/testcontainers/containers/{YugabyteYSQLContainerProvider.java => YugabyteDBYSQLContainerProvider.java} (52%) rename modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/{YugabyteYCQLDelegate.java => YugabyteDBYCQLDelegate.java} (84%) rename modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/{YugabyteYCQLWaitStrategy.java => YugabyteDBYCQLWaitStrategy.java} (81%) rename modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/{YugabyteYSQLWaitStrategy.java => YugabyteDBYSQLWaitStrategy.java} (84%) delete mode 100644 modules/yugabytedb/src/test/java/org/testcontainers/YugabyteTestContainerConstants.java rename modules/yugabytedb/src/test/java/org/testcontainers/jdbc/yugabytedb/{YugabyteYSQLJDBCDriverTest.java => YugabyteDBYSQLJDBCDriverTest.java} (89%) create mode 100644 modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java create mode 100644 modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java delete mode 100644 modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteYCQLUnitTest.java delete mode 100644 modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteYSQLUnitTest.java diff --git a/docs/modules/databases/yugabytedb.md b/docs/modules/databases/yugabytedb.md index e723b2f1e25..0cc7c66cc84 100644 --- a/docs/modules/databases/yugabytedb.md +++ b/docs/modules/databases/yugabytedb.md @@ -10,37 +10,27 @@ YugabyteDB supports two APIs. ### YSQL API -```java -public class YugabyteDBTest { + +[Creating a YSQL container](../../../modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java) inside_block:creatingYSQLContainer + - @Rule - public YugabyteYSQLContainer container = new YugabyteYSQLContainer("yugabytedb/yugabyte:2.12.1.0-b41"); - - @Test - public void method() { - String url = container.getJdbcUrl(); - ... create a connection and run the tests as usual. It also depends on the frameworks being used. -``` - -#### JDBC URL + +[Starting a YSQL container](../../../modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java) inside_block:startingYSQLContainer + -`jdbc:tc:yugabyte:2.12.1.0-b41:///yugabyte` ### YCQL API -```java -public class YugabyteDBTest { + +[Creating a YCQL container](../../../modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java) inside_block:creatingYCQLContainer + - @Rule - public YugabyteYCQLContainer container = new YugabyteYCQLContainer("yugabytedb/yugabyte:2.12.1.0-b41"); - - @Test - public void method() { - Session session = container.getSession(); - ... create a connection and run the tests as usual. It also depends on the frameworks being used. -``` + +[Starting a YCQL container](../../../modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java) inside_block:startingYCQLContainer + + ## Adding this module to your project dependencies diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteContainerConstants.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteContainerConstants.java deleted file mode 100644 index fde5ebd4fc3..00000000000 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteContainerConstants.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.testcontainers.containers; - -import org.testcontainers.utility.DockerImageName; - -/** - * Constants used in both YCQL and YSQL APIs - * - * @author srinivasa-vasu - */ -public interface YugabyteContainerConstants { - - DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("yugabytedb/yugabyte"); - - String DEFAULT_TAG = "2.12.1.0-b41"; - - String NAME = "yugabyte"; - - Integer YSQL_PORT = 5433; - - Integer YCQL_PORT = 9042; - - Integer MASTER_DASHBOARD_PORT = 7000; - - Integer TSERVER_DASHBOARD_PORT = 9000; - - String JDBC_DRIVER_CLASS = "com.yugabyte.Driver"; - - String JDBC_CONNECT_PREFIX = "jdbc:yugabytedb"; - - String ENTRYPOINT = "bin/yugabyted start --daemon=false"; - - String LOCAL_DC = "datacenter1"; - - String USER_PARAM = "user"; - - String PASSWORD_PARAM = "password"; - - String YSQL_TEST_QUERY = "SELECT 1"; - - String YCQL_TEST_QUERY = "SELECT release_version FROM system.local"; - -} diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteYCQLContainer.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java similarity index 67% rename from modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteYCQLContainer.java rename to modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java index a46f8fec4b8..0e2783297c2 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteYCQLContainer.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java @@ -6,25 +6,30 @@ import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.CqlSessionBuilder; import com.github.dockerjava.api.command.InspectContainerResponse; -import org.testcontainers.containers.delegate.YugabyteYCQLDelegate; -import org.testcontainers.containers.strategy.YugabyteYCQLWaitStrategy; +import org.testcontainers.containers.delegate.YugabyteDBYCQLDelegate; +import org.testcontainers.containers.strategy.YugabyteDBYCQLWaitStrategy; import org.testcontainers.ext.ScriptUtils; import org.testcontainers.utility.DockerImageName; -import static org.testcontainers.containers.YugabyteContainerConstants.DEFAULT_IMAGE_NAME; -import static org.testcontainers.containers.YugabyteContainerConstants.ENTRYPOINT; -import static org.testcontainers.containers.YugabyteContainerConstants.LOCAL_DC; -import static org.testcontainers.containers.YugabyteContainerConstants.MASTER_DASHBOARD_PORT; -import static org.testcontainers.containers.YugabyteContainerConstants.TSERVER_DASHBOARD_PORT; -import static org.testcontainers.containers.YugabyteContainerConstants.YCQL_PORT; - /** * YugabyteDB YCQL (Cloud Query Language) API container * * @author srinivasa-vasu * @see YCQL API */ -public class YugabyteYCQLContainer extends GenericContainer { +public class YugabyteDBYCQLContainer extends GenericContainer { + + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("yugabytedb/yugabyte"); + + private static final Integer YCQL_PORT = 9042; + + private static final Integer MASTER_DASHBOARD_PORT = 7000; + + private static final Integer TSERVER_DASHBOARD_PORT = 9000; + + private static final String ENTRYPOINT = "bin/yugabyted start --daemon=false"; + + private static final String LOCAL_DC = "datacenter1"; private String keyspace; @@ -37,18 +42,18 @@ public class YugabyteYCQLContainer extends GenericContainerYSQL API */ -public class YugabyteYSQLContainer extends JdbcDatabaseContainer { +public class YugabyteDBYSQLContainer extends JdbcDatabaseContainer { + + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("yugabytedb/yugabyte"); + + private static final Integer YSQL_PORT = 5433; + + private static final Integer MASTER_DASHBOARD_PORT = 7000; + + private static final Integer TSERVER_DASHBOARD_PORT = 9000; + + private static final String JDBC_DRIVER_CLASS = "com.yugabyte.Driver"; + + private static final String JDBC_CONNECT_PREFIX = "jdbc:yugabytedb"; + + private static final String ENTRYPOINT = "bin/yugabyted start --daemon=false"; private String database = "yugabyte"; @@ -33,18 +40,18 @@ public class YugabyteYSQLContainer extends JdbcDatabaseContainer { +public final class YugabyteDBYCQLDelegate extends AbstractDatabaseDelegate { private final CqlSessionBuilder builder; diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteYCQLWaitStrategy.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYCQLWaitStrategy.java similarity index 81% rename from modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteYCQLWaitStrategy.java rename to modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYCQLWaitStrategy.java index de2b3c851b2..3dbcec51226 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteYCQLWaitStrategy.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYCQLWaitStrategy.java @@ -4,12 +4,11 @@ import com.datastax.oss.driver.api.core.CqlSession; import lombok.RequiredArgsConstructor; -import org.testcontainers.containers.YugabyteYCQLContainer; +import org.testcontainers.containers.YugabyteDBYCQLContainer; import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitStrategyTarget; import static org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess; -import static org.testcontainers.containers.YugabyteContainerConstants.YCQL_TEST_QUERY; /** * Custom wait strategy for YCQL API. @@ -25,13 +24,15 @@ * @author srinivasa-vasu */ @RequiredArgsConstructor -public final class YugabyteYCQLWaitStrategy extends AbstractWaitStrategy { +public final class YugabyteDBYCQLWaitStrategy extends AbstractWaitStrategy { + + private static final String YCQL_TEST_QUERY = "SELECT release_version FROM system.local"; private final WaitStrategyTarget target; @Override public void waitUntilReady(WaitStrategyTarget target) { - YugabyteYCQLContainer container = (YugabyteYCQLContainer) target; + YugabyteDBYCQLContainer container = (YugabyteDBYCQLContainer) target; retryUntilSuccess((int) startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> { getRateLimiter().doWhenReady(() -> { try (CqlSession session = container.getSession()) { diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteYSQLWaitStrategy.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYSQLWaitStrategy.java similarity index 84% rename from modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteYSQLWaitStrategy.java rename to modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYSQLWaitStrategy.java index 1f114489f39..03d6134123f 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteYSQLWaitStrategy.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYSQLWaitStrategy.java @@ -6,12 +6,11 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.testcontainers.containers.YugabyteYSQLContainer; +import org.testcontainers.containers.YugabyteDBYSQLContainer; import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitStrategyTarget; import static org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess; -import static org.testcontainers.containers.YugabyteContainerConstants.YSQL_TEST_QUERY; /** * Custom wait strategy for YSQL API. @@ -28,13 +27,15 @@ */ @RequiredArgsConstructor @Slf4j -public final class YugabyteYSQLWaitStrategy extends AbstractWaitStrategy { +public final class YugabyteDBYSQLWaitStrategy extends AbstractWaitStrategy { + + private static final String YSQL_TEST_QUERY = "SELECT 1"; private final WaitStrategyTarget target; @Override public void waitUntilReady(WaitStrategyTarget target) { - YugabyteYSQLContainer container = (YugabyteYSQLContainer) target; + YugabyteDBYSQLContainer container = (YugabyteDBYSQLContainer) target; retryUntilSuccess((int) startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> { getRateLimiter().doWhenReady(() -> { try (Connection con = container.createConnection(container.getJdbcUrl())) { diff --git a/modules/yugabytedb/src/main/resources/META-INF/services/org.testcontainers.containers.JdbcDatabaseContainerProvider b/modules/yugabytedb/src/main/resources/META-INF/services/org.testcontainers.containers.JdbcDatabaseContainerProvider index d4b25fba9f4..26e372d51ab 100644 --- a/modules/yugabytedb/src/main/resources/META-INF/services/org.testcontainers.containers.JdbcDatabaseContainerProvider +++ b/modules/yugabytedb/src/main/resources/META-INF/services/org.testcontainers.containers.JdbcDatabaseContainerProvider @@ -1 +1 @@ -org.testcontainers.containers.YugabyteYSQLContainerProvider +org.testcontainers.containers.YugabyteDBYSQLContainerProvider diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/YugabyteTestContainerConstants.java b/modules/yugabytedb/src/test/java/org/testcontainers/YugabyteTestContainerConstants.java deleted file mode 100644 index 063337b3a0d..00000000000 --- a/modules/yugabytedb/src/test/java/org/testcontainers/YugabyteTestContainerConstants.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.testcontainers; - -import org.testcontainers.utility.DockerImageName; - -/** - * @author srinivasa-vasu - */ -public interface YugabyteTestContainerConstants { - - String IMAGE_NAME = "yugabytedb/yugabyte:2.12.1.0-b41"; - - DockerImageName YBDB_TEST_IMAGE = DockerImageName.parse(IMAGE_NAME); - - String LOCAL_DC = "datacenter1"; - - int YCQL_PORT = 9042; - -} diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/jdbc/yugabytedb/YugabyteYSQLJDBCDriverTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/jdbc/yugabytedb/YugabyteDBYSQLJDBCDriverTest.java similarity index 89% rename from modules/yugabytedb/src/test/java/org/testcontainers/jdbc/yugabytedb/YugabyteYSQLJDBCDriverTest.java rename to modules/yugabytedb/src/test/java/org/testcontainers/jdbc/yugabytedb/YugabyteDBYSQLJDBCDriverTest.java index 510a71f26d3..6e3790c92c1 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/jdbc/yugabytedb/YugabyteYSQLJDBCDriverTest.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/jdbc/yugabytedb/YugabyteDBYSQLJDBCDriverTest.java @@ -14,7 +14,7 @@ * @author srinivasa-vasu */ @RunWith(Parameterized.class) -public class YugabyteYSQLJDBCDriverTest extends AbstractJDBCDriverTest { +public class YugabyteDBYSQLJDBCDriverTest extends AbstractJDBCDriverTest { @Parameterized.Parameters(name = "{index} - {0}") public static Iterable data() { diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java new file mode 100644 index 00000000000..f8ff33c01b4 --- /dev/null +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java @@ -0,0 +1,101 @@ +package org.testcontainers.junit.yugabytedb; + +import java.net.InetSocketAddress; + +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.YugabyteDBYCQLContainer; +import org.testcontainers.utility.DockerImageName; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * YugabyteDB YCQL API unit test class + * + * @author srinivasa-vasu + */ +public class YugabyteDBYCQLUnitTest { + + private static final String IMAGE_NAME = "yugabytedb/yugabyte:2.14.0.0-b94"; + + private static final DockerImageName YBDB_TEST_IMAGE = DockerImageName.parse(IMAGE_NAME); + + private static final String LOCAL_DC = "datacenter1"; + + private static final int YCQL_PORT = 9042; + + @Test + public void testSmoke() { + try ( + // creatingYCQLContainer { + final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(IMAGE_NAME) + // } + ) { + // startingYCQLContainer { + ycqlContainer.start(); + // } + assertNotNull("Smoke test simple query execution fails!", + performQuery(ycqlContainer, "SELECT release_version FROM system.local").one().getString(0)); + } + } + + @Test + public void testCustomKeyspace() throws InterruptedException { + String key = "random"; + try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) + .withKeyspaceName(key)) { + ycqlContainer.start(); + assertEquals("Custom keyspace creation fails!", key, + performQuery(ycqlContainer, + "SELECT keyspace_name FROM system_schema.keyspaces where keyspace_name='" + key + "'").one() + .getString(0)); + } + } + + @Test + public void testAuthenticationEnabled() throws InterruptedException { + String role = "random"; + try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE).withUsername(role) + .withPassword(role)) { + ycqlContainer.start(); + assertEquals("Keyspace login fails with authentication enabled!", role, + performQuery(ycqlContainer, "SELECT role FROM system_auth.roles where role='" + role + "'").one() + .getString(0)); + } + } + + @Test + public void testAuthenticationDisabled() { + try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE).withPassword("") + .withUsername("")) { + ycqlContainer.start(); + assertTrue("Query execution fails!", + performQuery(ycqlContainer, "SELECT release_version FROM system.local").wasApplied()); + } + } + + @Test + public void testInitScript() throws InterruptedException { + String key = "random"; + try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) + .withKeyspaceName(key).withUsername(key).withPassword(key).withInitScript("init/init_yql.sql")) { + ycqlContainer.start(); + assertTrue("Query execution fails to execute statements from a custom script!", + performQuery(ycqlContainer, "SELECT * FROM random.bar").wasApplied()); + } + } + + private ResultSet performQuery(YugabyteDBYCQLContainer ycqlContainer, String cql) { + try (CqlSession session = CqlSession.builder().withKeyspace(ycqlContainer.getKeyspace()) + .withAuthCredentials(ycqlContainer.getUsername(), ycqlContainer.getPassword()) + .withLocalDatacenter(LOCAL_DC) + .addContactPoint(new InetSocketAddress(ycqlContainer.getHost(), ycqlContainer.getMappedPort(YCQL_PORT))) + .build()) { + return session.execute(cql); + } + } + +} diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java new file mode 100644 index 00000000000..29675e242f1 --- /dev/null +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java @@ -0,0 +1,83 @@ +package org.testcontainers.junit.yugabytedb; + +import java.sql.SQLException; + +import org.junit.Test; +import org.testcontainers.containers.YugabyteDBYSQLContainer; +import org.testcontainers.db.AbstractContainerDatabaseTest; +import org.testcontainers.utility.DockerImageName; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; + +/** + * YugabyteDB YSQL API unit test class + * + * @author srinivasa-vasu + */ +public class YugabyteDBYSQLUnitTest extends AbstractContainerDatabaseTest { + + private static final String IMAGE_NAME = "yugabytedb/yugabyte:2.14.0.0-b94"; + + private static final DockerImageName YBDB_TEST_IMAGE = DockerImageName.parse(IMAGE_NAME); + + @Test + public void testSmoke() throws SQLException { + try ( + // creatingYSQLContainer { + final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(IMAGE_NAME) + // } + ) { + // startingYSQLContainer { + ysqlContainer.start(); + // } + assertEquals("Query execution fails!", 1, performQuery(ysqlContainer, "SELECT 1").getInt(1)); + } + } + + @Test + public void testCustomDatabase() throws SQLException { + String key = "random"; + try (final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) + .withDatabaseName(key)) { + ysqlContainer.start(); + assertEquals("Query execution on a custom database fails!", 1, + performQuery(ysqlContainer, "SELECT 1").getInt(1)); + } + } + + @Test + public void testExplicitInitScript() throws SQLException { + try (final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) + .withInitScript("init/init_yql.sql")) { + ysqlContainer.start(); + assertEquals("Value from the init script does not match the real value", "hello world", + performQuery(ysqlContainer, "SELECT foo FROM bar").getString(1)); + } + } + + @Test + public void testWithAdditionalUrlParamInJdbcUrl() { + try (final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) + .withUrlParam("sslmode", "disable").withUrlParam("application_name", "yugabyte")) { + ysqlContainer.start(); + String jdbcUrl = ysqlContainer.getJdbcUrl(); + assertThat(jdbcUrl, containsString("?")); + assertThat(jdbcUrl, containsString("&")); + assertThat(jdbcUrl, containsString("sslmode=disable")); + assertThat(jdbcUrl, containsString("application_name=yugabyte")); + } + } + + @Test + public void testWithCustomRole() throws SQLException { + try (final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) + .withDatabaseName("yugabyte").withPassword("yugabyte").withUsername("yugabyte")) { + ysqlContainer.start(); + assertEquals("Query execution with a custom role fails!", 1, + performQuery(ysqlContainer, "SELECT 1").getInt(1)); + } + } + +} diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteYCQLUnitTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteYCQLUnitTest.java deleted file mode 100644 index ad3fc44f1aa..00000000000 --- a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteYCQLUnitTest.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.testcontainers.junit.yugabytedb; - -import java.net.InetSocketAddress; - -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.YugabyteYCQLContainer; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.testcontainers.YugabyteTestContainerConstants.IMAGE_NAME; -import static org.testcontainers.YugabyteTestContainerConstants.LOCAL_DC; -import static org.testcontainers.YugabyteTestContainerConstants.YBDB_TEST_IMAGE; -import static org.testcontainers.YugabyteTestContainerConstants.YCQL_PORT; - -/** - * YugabyteDB YCQL API unit test class - * - * @author srinivasa-vasu - */ -public class YugabyteYCQLUnitTest { - - @Test - public void testSmoke() { - try (YugabyteYCQLContainer container = new YugabyteYCQLContainer(IMAGE_NAME)) { - container.start(); - assertNotNull("Smoke test simple query execution fails!", - performQuery(container, "SELECT release_version FROM system.local").one().getString(0)); - } - } - - @Test - public void testCustomKeyspace() throws InterruptedException { - String key = "random"; - try (YugabyteYCQLContainer container = new YugabyteYCQLContainer(YBDB_TEST_IMAGE).withKeyspaceName(key)) { - container.start(); - assertEquals("Custom keyspace creation fails!", key, - performQuery(container, - "SELECT keyspace_name FROM system_schema.keyspaces where keyspace_name='" + key + "'").one() - .getString(0)); - } - } - - @Test - public void testAuthenticationEnabled() throws InterruptedException { - String role = "random"; - try (YugabyteYCQLContainer container = new YugabyteYCQLContainer(YBDB_TEST_IMAGE).withUsername(role) - .withPassword(role)) { - container.start(); - assertEquals("Keyspace login fails with authentication enabled!", role, - performQuery(container, "SELECT role FROM system_auth.roles where role='" + role + "'").one() - .getString(0)); - } - } - - @Test - public void testAuthenticationDisabled() { - try (YugabyteYCQLContainer container = new YugabyteYCQLContainer(YBDB_TEST_IMAGE).withPassword("") - .withUsername("")) { - container.start(); - assertTrue("Query execution fails!", - performQuery(container, "SELECT release_version FROM system.local").wasApplied()); - } - } - - @Test - public void testInitScript() throws InterruptedException { - String key = "random"; - try (YugabyteYCQLContainer container = new YugabyteYCQLContainer(YBDB_TEST_IMAGE).withKeyspaceName(key) - .withUsername(key).withPassword(key).withInitScript("init/init_yql.sql")) { - container.start(); - assertTrue("Query execution fails to execute statements from a custom script!", - performQuery(container, "SELECT * FROM random.bar").wasApplied()); - } - } - - private ResultSet performQuery(YugabyteYCQLContainer container, String cql) { - try (CqlSession session = CqlSession.builder().withKeyspace(container.getKeyspace()) - .withAuthCredentials(container.getUsername(), container.getPassword()).withLocalDatacenter(LOCAL_DC) - .addContactPoint(new InetSocketAddress(container.getHost(), container.getMappedPort(YCQL_PORT))) - .build()) { - return session.execute(cql); - } - } - -} diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteYSQLUnitTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteYSQLUnitTest.java deleted file mode 100644 index 707a3604991..00000000000 --- a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteYSQLUnitTest.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.testcontainers.junit.yugabytedb; - -import java.sql.SQLException; - -import org.junit.Test; -import org.testcontainers.containers.YugabyteYSQLContainer; -import org.testcontainers.db.AbstractContainerDatabaseTest; - -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertEquals; -import static org.testcontainers.YugabyteTestContainerConstants.IMAGE_NAME; -import static org.testcontainers.YugabyteTestContainerConstants.YBDB_TEST_IMAGE; - -/** - * YugabyteDB YSQL API unit test class - * - * @author srinivasa-vasu - */ -public class YugabyteYSQLUnitTest extends AbstractContainerDatabaseTest { - - @Test - public void testSmoke() throws SQLException { - try (YugabyteYSQLContainer container = new YugabyteYSQLContainer(IMAGE_NAME)) { - container.start(); - assertEquals("Query execution fails!", 1, performQuery(container, "SELECT 1").getInt(1)); - } - } - - @Test - public void testCustomDatabase() throws SQLException { - String key = "random"; - try (YugabyteYSQLContainer container = new YugabyteYSQLContainer(YBDB_TEST_IMAGE).withDatabaseName(key)) { - container.start(); - assertEquals("Query execution on a custom database fails!", 1, - performQuery(container, "SELECT 1").getInt(1)); - } - } - - @Test - public void testExplicitInitScript() throws SQLException { - try (YugabyteYSQLContainer container = new YugabyteYSQLContainer(YBDB_TEST_IMAGE) - .withInitScript("init/init_yql.sql")) { - container.start(); - assertEquals("Value from the init script does not match the real value", "hello world", - performQuery(container, "SELECT foo FROM bar").getString(1)); - } - } - - @Test - public void testWithAdditionalUrlParamInJdbcUrl() { - try (YugabyteYSQLContainer container = new YugabyteYSQLContainer(YBDB_TEST_IMAGE) - .withUrlParam("sslmode", "disable").withUrlParam("application_name", "yugabyte")) { - container.start(); - String jdbcUrl = container.getJdbcUrl(); - assertThat(jdbcUrl, containsString("?")); - assertThat(jdbcUrl, containsString("&")); - assertThat(jdbcUrl, containsString("sslmode=disable")); - assertThat(jdbcUrl, containsString("application_name=yugabyte")); - } - } - - @Test - public void testWithCustomRole() throws SQLException { - try (YugabyteYSQLContainer container = new YugabyteYSQLContainer(YBDB_TEST_IMAGE).withDatabaseName("yugabyte") - .withPassword("yugabyte").withUsername("yugabyte")) { - container.start(); - assertEquals("Query execution with a custom role fails!", 1, performQuery(container, "SELECT 1").getInt(1)); - } - } - -} From 415eef3981aa8ed9f5c80c842cef4b93e6e8b9de Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Tue, 26 Jul 2022 22:32:52 +0530 Subject: [PATCH 07/18] add incubating module note to the module readme file Signed-off-by: Srinivasa Vasu --- docs/modules/databases/yugabytedb.md | 3 ++ .../containers/YugabyteDBYSQLContainer.java | 4 +-- .../yugabytedb/YugabyteDBYCQLUnitTest.java | 27 ++++++++--------- .../yugabytedb/YugabyteDBYSQLUnitTest.java | 29 +++++++++---------- 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/docs/modules/databases/yugabytedb.md b/docs/modules/databases/yugabytedb.md index 0cc7c66cc84..3678dc1bd69 100644 --- a/docs/modules/databases/yugabytedb.md +++ b/docs/modules/databases/yugabytedb.md @@ -1,5 +1,8 @@ # YugabyteDB Module +!!! note +This module is INCUBATING. While it is ready for use and operational in the current version of Testcontainers, it is possible that it may receive breaking changes in the future. See [our contributing guidelines](/contributing/#incubating-modules) for more information on our incubating modules policy. + See [Database containers](./index.md) for documentation and usage that is common to all database container types. YugabyteDB supports two APIs. diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainer.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainer.java index 3e64c24d25e..4c6ec44b784 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainer.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainer.java @@ -6,7 +6,7 @@ import org.testcontainers.containers.strategy.YugabyteDBYSQLWaitStrategy; import org.testcontainers.utility.DockerImageName; -import static java.util.Collections.singleton; +import java.util.Collections; /** * YugabyteDB YSQL (Structured Query Language) API container @@ -57,7 +57,7 @@ public YugabyteDBYSQLContainer(final DockerImageName imageName) { @Override public Set getLivenessCheckPortNumbers() { - return singleton(getMappedPort(YSQL_PORT)); + return Collections.singleton(getMappedPort(YSQL_PORT)); } /** diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java index f8ff33c01b4..b1723b2d7c4 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java @@ -4,14 +4,11 @@ import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.cql.ResultSet; +import org.junit.Assert; import org.junit.Test; import org.testcontainers.containers.YugabyteDBYCQLContainer; import org.testcontainers.utility.DockerImageName; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - /** * YugabyteDB YCQL API unit test class * @@ -25,19 +22,19 @@ public class YugabyteDBYCQLUnitTest { private static final String LOCAL_DC = "datacenter1"; - private static final int YCQL_PORT = 9042; + private static final int YCQL_PORT = 9042; @Test public void testSmoke() { try ( - // creatingYCQLContainer { - final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(IMAGE_NAME) - // } + // creatingYCQLContainer { + final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(IMAGE_NAME) + // } ) { // startingYCQLContainer { ycqlContainer.start(); // } - assertNotNull("Smoke test simple query execution fails!", + Assert.assertNotNull("Smoke test simple query execution fails!", performQuery(ycqlContainer, "SELECT release_version FROM system.local").one().getString(0)); } } @@ -48,7 +45,7 @@ public void testCustomKeyspace() throws InterruptedException { try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) .withKeyspaceName(key)) { ycqlContainer.start(); - assertEquals("Custom keyspace creation fails!", key, + Assert.assertEquals("Custom keyspace creation fails!", key, performQuery(ycqlContainer, "SELECT keyspace_name FROM system_schema.keyspaces where keyspace_name='" + key + "'").one() .getString(0)); @@ -58,10 +55,10 @@ public void testCustomKeyspace() throws InterruptedException { @Test public void testAuthenticationEnabled() throws InterruptedException { String role = "random"; - try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE).withUsername(role) - .withPassword(role)) { + try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) + .withUsername(role).withPassword(role)) { ycqlContainer.start(); - assertEquals("Keyspace login fails with authentication enabled!", role, + Assert.assertEquals("Keyspace login fails with authentication enabled!", role, performQuery(ycqlContainer, "SELECT role FROM system_auth.roles where role='" + role + "'").one() .getString(0)); } @@ -72,7 +69,7 @@ public void testAuthenticationDisabled() { try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE).withPassword("") .withUsername("")) { ycqlContainer.start(); - assertTrue("Query execution fails!", + Assert.assertTrue("Query execution fails!", performQuery(ycqlContainer, "SELECT release_version FROM system.local").wasApplied()); } } @@ -83,7 +80,7 @@ public void testInitScript() throws InterruptedException { try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) .withKeyspaceName(key).withUsername(key).withPassword(key).withInitScript("init/init_yql.sql")) { ycqlContainer.start(); - assertTrue("Query execution fails to execute statements from a custom script!", + Assert.assertTrue("Query execution fails to execute statements from a custom script!", performQuery(ycqlContainer, "SELECT * FROM random.bar").wasApplied()); } } diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java index 29675e242f1..f0fc2f71922 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java @@ -2,15 +2,14 @@ import java.sql.SQLException; +import org.hamcrest.CoreMatchers; +import org.hamcrest.MatcherAssert; +import org.junit.Assert; import org.junit.Test; import org.testcontainers.containers.YugabyteDBYSQLContainer; import org.testcontainers.db.AbstractContainerDatabaseTest; import org.testcontainers.utility.DockerImageName; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertEquals; - /** * YugabyteDB YSQL API unit test class * @@ -25,14 +24,14 @@ public class YugabyteDBYSQLUnitTest extends AbstractContainerDatabaseTest { @Test public void testSmoke() throws SQLException { try ( - // creatingYSQLContainer { - final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(IMAGE_NAME) - // } + // creatingYSQLContainer { + final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(IMAGE_NAME) + // } ) { // startingYSQLContainer { ysqlContainer.start(); // } - assertEquals("Query execution fails!", 1, performQuery(ysqlContainer, "SELECT 1").getInt(1)); + Assert.assertEquals("Query execution fails!", 1, performQuery(ysqlContainer, "SELECT 1").getInt(1)); } } @@ -42,7 +41,7 @@ public void testCustomDatabase() throws SQLException { try (final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) .withDatabaseName(key)) { ysqlContainer.start(); - assertEquals("Query execution on a custom database fails!", 1, + Assert.assertEquals("Query execution on a custom database fails!", 1, performQuery(ysqlContainer, "SELECT 1").getInt(1)); } } @@ -52,7 +51,7 @@ public void testExplicitInitScript() throws SQLException { try (final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) .withInitScript("init/init_yql.sql")) { ysqlContainer.start(); - assertEquals("Value from the init script does not match the real value", "hello world", + Assert.assertEquals("Value from the init script does not match the real value", "hello world", performQuery(ysqlContainer, "SELECT foo FROM bar").getString(1)); } } @@ -63,10 +62,10 @@ public void testWithAdditionalUrlParamInJdbcUrl() { .withUrlParam("sslmode", "disable").withUrlParam("application_name", "yugabyte")) { ysqlContainer.start(); String jdbcUrl = ysqlContainer.getJdbcUrl(); - assertThat(jdbcUrl, containsString("?")); - assertThat(jdbcUrl, containsString("&")); - assertThat(jdbcUrl, containsString("sslmode=disable")); - assertThat(jdbcUrl, containsString("application_name=yugabyte")); + MatcherAssert.assertThat(jdbcUrl, CoreMatchers.containsString("?")); + MatcherAssert.assertThat(jdbcUrl, CoreMatchers.containsString("&")); + MatcherAssert.assertThat(jdbcUrl, CoreMatchers.containsString("sslmode=disable")); + MatcherAssert.assertThat(jdbcUrl, CoreMatchers.containsString("application_name=yugabyte")); } } @@ -75,7 +74,7 @@ public void testWithCustomRole() throws SQLException { try (final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) .withDatabaseName("yugabyte").withPassword("yugabyte").withUsername("yugabyte")) { ysqlContainer.start(); - assertEquals("Query execution with a custom role fails!", 1, + Assert.assertEquals("Query execution with a custom role fails!", 1, performQuery(ysqlContainer, "SELECT 1").getInt(1)); } } From 38c74eea69f074d9f7de891d9f9a9826e7eb40c0 Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Tue, 26 Jul 2022 22:46:23 +0530 Subject: [PATCH 08/18] update dependency info in doc Signed-off-by: Srinivasa Vasu --- docs/modules/databases/yugabytedb.md | 25 ++++++++++--------- modules/yugabytedb/build.gradle | 2 +- .../yugabytedb/YugabyteDBYCQLUnitTest.java | 6 ++--- .../yugabytedb/YugabyteDBYSQLUnitTest.java | 6 ++--- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/docs/modules/databases/yugabytedb.md b/docs/modules/databases/yugabytedb.md index 3678dc1bd69..307d63530a8 100644 --- a/docs/modules/databases/yugabytedb.md +++ b/docs/modules/databases/yugabytedb.md @@ -39,18 +39,19 @@ YugabyteDB supports two APIs. Add the following dependency to your `pom.xml`/`build.gradle` file: -```groovy tab='Gradle' -testImplementation "org.testcontainers:yugabytedb:{{latest_version}}" -``` - -```xml tab='Maven' - - org.testcontainers - yugabytedb - {{latest_version}} - test - -``` +=== "Gradle" + ```groovy + testImplementation "org.testcontainers:yugabytedb:{{latest_version}}" + ``` +=== "Maven" + ```xml + + org.testcontainers + yugabytedb + {{latest_version}} + test + + ``` !!! hint Adding this Testcontainers library JAR will not automatically add the Yugabytedb driver JAR to your project. diff --git a/modules/yugabytedb/build.gradle b/modules/yugabytedb/build.gradle index 1b52a2d3394..1fcecad0c9e 100644 --- a/modules/yugabytedb/build.gradle +++ b/modules/yugabytedb/build.gradle @@ -4,7 +4,7 @@ dependencies { api project(':jdbc') testImplementation project(':jdbc-test') // YCQL driver - implementation 'com.yugabyte:java-driver-core:4.6.0-yb-10' + implementation 'com.yugabyte:java-driver-core:4.6.0-yb-11' // YSQL driver testImplementation 'com.yugabyte:jdbc-yugabytedb:42.3.4' } diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java index b1723b2d7c4..6e959a30362 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java @@ -27,9 +27,9 @@ public class YugabyteDBYCQLUnitTest { @Test public void testSmoke() { try ( - // creatingYCQLContainer { - final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(IMAGE_NAME) - // } + // creatingYCQLContainer { + final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(IMAGE_NAME) + // } ) { // startingYCQLContainer { ycqlContainer.start(); diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java index f0fc2f71922..98f01b34858 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java @@ -24,9 +24,9 @@ public class YugabyteDBYSQLUnitTest extends AbstractContainerDatabaseTest { @Test public void testSmoke() throws SQLException { try ( - // creatingYSQLContainer { - final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(IMAGE_NAME) - // } + // creatingYSQLContainer { + final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(IMAGE_NAME) + // } ) { // startingYSQLContainer { ysqlContainer.start(); From 2272f85700a84c74b978703c31287c982000ba97 Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Tue, 26 Jul 2022 22:49:14 +0530 Subject: [PATCH 09/18] update doc alignment issue Signed-off-by: Srinivasa Vasu --- docs/modules/databases/yugabytedb.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/databases/yugabytedb.md b/docs/modules/databases/yugabytedb.md index 307d63530a8..da9c5759e64 100644 --- a/docs/modules/databases/yugabytedb.md +++ b/docs/modules/databases/yugabytedb.md @@ -1,7 +1,7 @@ # YugabyteDB Module !!! note -This module is INCUBATING. While it is ready for use and operational in the current version of Testcontainers, it is possible that it may receive breaking changes in the future. See [our contributing guidelines](/contributing/#incubating-modules) for more information on our incubating modules policy. + This module is INCUBATING. While it is ready for use and operational in the current version of Testcontainers, it is possible that it may receive breaking changes in the future. See [our contributing guidelines](/contributing/#incubating-modules) for more information on our incubating modules policy. See [Database containers](./index.md) for documentation and usage that is common to all database container types. From 41b4a17296f53939b9bfd92550a3806491080aed Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Thu, 28 Jul 2022 23:32:13 +0530 Subject: [PATCH 10/18] update gradle build file Signed-off-by: Srinivasa Vasu --- modules/yugabytedb/build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/yugabytedb/build.gradle b/modules/yugabytedb/build.gradle index 1fcecad0c9e..68a6f03abc7 100644 --- a/modules/yugabytedb/build.gradle +++ b/modules/yugabytedb/build.gradle @@ -4,7 +4,8 @@ dependencies { api project(':jdbc') testImplementation project(':jdbc-test') // YCQL driver - implementation 'com.yugabyte:java-driver-core:4.6.0-yb-11' + compileOnly 'com.yugabyte:java-driver-core:4.6.0-yb-11' + testImplementation 'com.yugabyte:java-driver-core:4.6.0-yb-11' // YSQL driver testImplementation 'com.yugabyte:jdbc-yugabytedb:42.3.4' } From 058527ad6a7ce3e443b106ef954a772f42892940 Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Wed, 3 Aug 2022 20:05:26 +0530 Subject: [PATCH 11/18] rename test classes Signed-off-by: Srinivasa Vasu --- .../containers/YCQLSessionDelegate.java | 25 +++++++++++++++++++ .../containers/YugabyteDBYCQLContainer.java | 24 ++++++++---------- .../containers/YugabyteDBYSQLContainer.java | 2 +- .../delegate/YugabyteDBYCQLDelegate.java | 17 ++++++------- .../strategy/YugabyteDBYCQLWaitStrategy.java | 5 ++-- ...LUnitTest.java => YugabyteDBYCQLTest.java} | 2 +- ...LUnitTest.java => YugabyteDBYSQLTest.java} | 2 +- 7 files changed, 48 insertions(+), 29 deletions(-) create mode 100644 modules/yugabytedb/src/main/java/org/testcontainers/containers/YCQLSessionDelegate.java rename modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/{YugabyteDBYCQLUnitTest.java => YugabyteDBYCQLTest.java} (98%) rename modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/{YugabyteDBYSQLUnitTest.java => YugabyteDBYSQLTest.java} (97%) diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YCQLSessionDelegate.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YCQLSessionDelegate.java new file mode 100644 index 00000000000..844260e80fe --- /dev/null +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YCQLSessionDelegate.java @@ -0,0 +1,25 @@ +package org.testcontainers.containers; + +import com.datastax.oss.driver.api.core.CqlSession; + +/** + * A builder abstraction to construct {@link CqlSession} instance from + * {@link YugabyteDBYCQLContainer} instance. + * + * @author srinivasa-vasu + */ +public interface YCQLSessionDelegate { + + /** + * Constructs a {@link CqlSession} instance from {@link YugabyteDBYCQLContainer} + * instance. + * @param container YCQL container instance + * @return {@link CqlSession} instance + */ + default CqlSession builder(YugabyteDBYCQLContainer container) { + return CqlSession.builder().withLocalDatacenter(container.getLocalDc()).withKeyspace(container.getKeyspace()) + .withAuthCredentials(container.getUsername(), container.getPassword()) + .addContactPoint(container.getContactPoint()).build(); + } + +} diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java index 0e2783297c2..1d3a5f18f8e 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java @@ -3,8 +3,6 @@ import java.net.InetSocketAddress; import java.time.Duration; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.CqlSessionBuilder; import com.github.dockerjava.api.command.InspectContainerResponse; import org.testcontainers.containers.delegate.YugabyteDBYCQLDelegate; import org.testcontainers.containers.strategy.YugabyteDBYCQLWaitStrategy; @@ -15,7 +13,7 @@ * YugabyteDB YCQL (Cloud Query Language) API container * * @author srinivasa-vasu - * @see YCQL API + * @see YCQL API */ public class YugabyteDBYCQLContainer extends GenericContainer { @@ -116,26 +114,24 @@ public YugabyteDBYCQLContainer withPassword(final String password) { @Override protected void containerIsStarted(InspectContainerResponse containerInfo) { if (initScript != null) { - ScriptUtils.runInitScript(new YugabyteDBYCQLDelegate(getSessionBuilder()), initScript); + ScriptUtils.runInitScript(new YugabyteDBYCQLDelegate(this), initScript); } } /** - * Builds a {@link CqlSession} instance - * @return {@link CqlSession} instance + * Returns a {@link InetSocketAddress} representation of YCQL's contact point info + * @return contactpoint */ - public CqlSession getSession() { - return getSessionBuilder().build(); + public InetSocketAddress getContactPoint() { + return new InetSocketAddress(getHost(), getMappedPort(YCQL_PORT)); } /** - * Builder method for {#com.datastax.oss.driver.api.core.CqlSession} - * @return {@link CqlSessionBuilder} + * Returns the local datacenter name + * @return localdc name */ - public CqlSessionBuilder getSessionBuilder() { - return CqlSession.builder().withLocalDatacenter(LOCAL_DC).withKeyspace(this.getKeyspace()) - .withAuthCredentials(this.getUsername(), this.getPassword()) - .addContactPoint(new InetSocketAddress(this.getHost(), this.getMappedPort(YCQL_PORT))); + public String getLocalDc() { + return LOCAL_DC; } /** diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainer.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainer.java index 4c6ec44b784..6f3d83f49b0 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainer.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainer.java @@ -12,7 +12,7 @@ * YugabyteDB YSQL (Structured Query Language) API container * * @author srinivasa-vasu - * @see YSQL API + * @see YSQL API */ public class YugabyteDBYSQLContainer extends JdbcDatabaseContainer { diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/YugabyteDBYCQLDelegate.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/YugabyteDBYCQLDelegate.java index 11b8d27a6df..1502d0b3250 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/YugabyteDBYCQLDelegate.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/YugabyteDBYCQLDelegate.java @@ -1,10 +1,8 @@ package org.testcontainers.containers.delegate; import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.CqlSessionBuilder; -import com.datastax.oss.driver.api.core.session.Session; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; +import org.testcontainers.containers.YCQLSessionDelegate; import org.testcontainers.containers.YugabyteDBYCQLContainer; import org.testcontainers.delegate.AbstractDatabaseDelegate; @@ -14,25 +12,24 @@ * @author srinivasa-vasu * @see YugabyteDBYCQLContainer */ -@Slf4j @RequiredArgsConstructor -public final class YugabyteDBYCQLDelegate extends AbstractDatabaseDelegate { +public final class YugabyteDBYCQLDelegate extends AbstractDatabaseDelegate implements YCQLSessionDelegate { - private final CqlSessionBuilder builder; + private final YugabyteDBYCQLContainer container; @Override - protected Session createNewConnection() { - return builder.build(); + protected CqlSession createNewConnection() { + return builder(container); } @Override public void execute(String statement, String scriptPath, int lineNumber, boolean continueOnError, boolean ignoreFailedDrops) { - ((CqlSession) getConnection()).execute(statement); + getConnection().execute(statement); } @Override - protected void closeConnectionQuietly(Session session) { + protected void closeConnectionQuietly(CqlSession session) { if (session != null) { session.close(); } diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYCQLWaitStrategy.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYCQLWaitStrategy.java index 3dbcec51226..73274dfc562 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYCQLWaitStrategy.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYCQLWaitStrategy.java @@ -4,6 +4,7 @@ import com.datastax.oss.driver.api.core.CqlSession; import lombok.RequiredArgsConstructor; +import org.testcontainers.containers.YCQLSessionDelegate; import org.testcontainers.containers.YugabyteDBYCQLContainer; import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitStrategyTarget; @@ -24,7 +25,7 @@ * @author srinivasa-vasu */ @RequiredArgsConstructor -public final class YugabyteDBYCQLWaitStrategy extends AbstractWaitStrategy { +public final class YugabyteDBYCQLWaitStrategy extends AbstractWaitStrategy implements YCQLSessionDelegate { private static final String YCQL_TEST_QUERY = "SELECT release_version FROM system.local"; @@ -35,7 +36,7 @@ public void waitUntilReady(WaitStrategyTarget target) { YugabyteDBYCQLContainer container = (YugabyteDBYCQLContainer) target; retryUntilSuccess((int) startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> { getRateLimiter().doWhenReady(() -> { - try (CqlSession session = container.getSession()) { + try (CqlSession session = builder(container)) { session.execute(YCQL_TEST_QUERY); } }); diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java similarity index 98% rename from modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java rename to modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java index 6e959a30362..2f097797fe7 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java @@ -14,7 +14,7 @@ * * @author srinivasa-vasu */ -public class YugabyteDBYCQLUnitTest { +public class YugabyteDBYCQLTest { private static final String IMAGE_NAME = "yugabytedb/yugabyte:2.14.0.0-b94"; diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java similarity index 97% rename from modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java rename to modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java index 98f01b34858..0480343546c 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java @@ -15,7 +15,7 @@ * * @author srinivasa-vasu */ -public class YugabyteDBYSQLUnitTest extends AbstractContainerDatabaseTest { +public class YugabyteDBYSQLTest extends AbstractContainerDatabaseTest { private static final String IMAGE_NAME = "yugabytedb/yugabyte:2.14.0.0-b94"; From f17bc5eb74db41ce93dee58959fdc069bc642809 Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Wed, 3 Aug 2022 23:16:43 +0530 Subject: [PATCH 12/18] update readme Signed-off-by: Srinivasa Vasu --- docs/modules/databases/yugabytedb.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/modules/databases/yugabytedb.md b/docs/modules/databases/yugabytedb.md index da9c5759e64..4ab3436b57c 100644 --- a/docs/modules/databases/yugabytedb.md +++ b/docs/modules/databases/yugabytedb.md @@ -14,24 +14,24 @@ YugabyteDB supports two APIs. ### YSQL API -[Creating a YSQL container](../../../modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java) inside_block:creatingYSQLContainer +[Creating a YSQL container](../../../modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java) inside_block:creatingYSQLContainer -[Starting a YSQL container](../../../modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLUnitTest.java) inside_block:startingYSQLContainer +[Starting a YSQL container](../../../modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java) inside_block:startingYSQLContainer ### YCQL API -[Creating a YCQL container](../../../modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java) inside_block:creatingYCQLContainer +[Creating a YCQL container](../../../modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java) inside_block:creatingYCQLContainer -[Starting a YCQL container](../../../modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLUnitTest.java) inside_block:startingYCQLContainer +[Starting a YCQL container](../../../modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java) inside_block:startingYCQLContainer From 112f4ebb2637c61b13906e291dc0b6dcae278172 Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Fri, 5 Aug 2022 06:57:10 +0530 Subject: [PATCH 13/18] add yugabytedb to the .github template files for issue/enhancement tracking Signed-off-by: Srinivasa Vasu --- .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 | 2 ++ .../containers/YugabyteDBYCQLContainer.java | 9 ++++++++- .../containers/YugabyteDBYSQLContainer.java | 2 +- 7 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 37609ce1424..406483c2d45 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -50,6 +50,7 @@ body: - ToxiProxy - Trino - Vault + - YugabyteDB validations: required: true - type: input diff --git a/.github/ISSUE_TEMPLATE/enhancement.yaml b/.github/ISSUE_TEMPLATE/enhancement.yaml index 2bbca5db3ae..2f543615dee 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.yaml +++ b/.github/ISSUE_TEMPLATE/enhancement.yaml @@ -50,6 +50,7 @@ body: - ToxiProxy - Trino - Vault + - YugabyteDB validations: required: true - type: textarea diff --git a/.github/ISSUE_TEMPLATE/feature.yaml b/.github/ISSUE_TEMPLATE/feature.yaml index d29d0178c39..85c44eba697 100644 --- a/.github/ISSUE_TEMPLATE/feature.yaml +++ b/.github/ISSUE_TEMPLATE/feature.yaml @@ -50,6 +50,7 @@ body: - ToxiProxy - Trino - Vault + - YugabyteDB - New Module - type: textarea id: problem diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 095257df4c1..121b8ab4b46 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -258,6 +258,11 @@ updates: schedule: interval: "monthly" open-pull-requests-limit: 10 + - package-ecosystem: "gradle" + directory: "/modules/yugabytedb" + schedule: + interval: "monthly" + open-pull-requests-limit: 10 # Examples - package-ecosystem: "gradle" diff --git a/.github/labeler.yml b/.github/labeler.yml index fcbe0744bd8..8da42a738ae 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -87,5 +87,7 @@ - modules/trino/**/* "modules/vault": - modules/vault/**/* +"modules/yugabytedb": + - modules/yugabytedb/* "type/docs": - docs/**/*.md diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java index 1d3a5f18f8e..e1c886ba79c 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java @@ -2,6 +2,8 @@ import java.net.InetSocketAddress; import java.time.Duration; +import java.util.Collections; +import java.util.Set; import com.github.dockerjava.api.command.InspectContainerResponse; import org.testcontainers.containers.delegate.YugabyteDBYCQLDelegate; @@ -10,7 +12,7 @@ import org.testcontainers.utility.DockerImageName; /** - * YugabyteDB YCQL (Cloud Query Language) API container + * Testcontainers implementation for YugabyteDB YCQL API. * * @author srinivasa-vasu * @see YCQL API @@ -55,6 +57,11 @@ public YugabyteDBYCQLContainer(final DockerImageName imageName) { withCommand(ENTRYPOINT); } + @Override + public Set getLivenessCheckPortNumbers() { + return Collections.singleton(getMappedPort(YCQL_PORT)); + } + /** * Configures the environment variables. Setting up these variables would create the * custom objects. Setting {@link #withKeyspaceName(String)}, diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainer.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainer.java index 6f3d83f49b0..cdc1c1ed011 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainer.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainer.java @@ -9,7 +9,7 @@ import java.util.Collections; /** - * YugabyteDB YSQL (Structured Query Language) API container + * Testcontainers implementation for YugabyteDB YSQL API. * * @author srinivasa-vasu * @see YSQL API From 4af7124ee2aff0849e22ee5dd74fd2cee282a560 Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Sun, 23 Oct 2022 12:30:46 +0530 Subject: [PATCH 14/18] update assertj and removed cassandra driver dependency Signed-off-by: Srinivasa Vasu --- modules/yugabytedb/build.gradle | 1 - .../containers/YCQLSessionDelegate.java | 25 ----------- .../containers/YugabyteDBYCQLContainer.java | 2 +- .../containers/YugabyteDBYSQLContainer.java | 2 +- .../YugabyteDBYSQLContainerProvider.java | 2 +- .../delegate/AbstractYCQLDelegate.java | 23 ++++++++++ .../delegate/YugabyteDBYCQLDelegate.java | 44 +++++++++++-------- .../strategy/YugabyteDBYCQLWaitStrategy.java | 33 +++++++++++--- .../junit/yugabytedb/YugabyteDBYCQLTest.java | 30 ++++++------- .../junit/yugabytedb/YugabyteDBYSQLTest.java | 31 +++++++------ .../src/test/resources/init/init_yql.sql | 6 +-- 11 files changed, 111 insertions(+), 88 deletions(-) delete mode 100644 modules/yugabytedb/src/main/java/org/testcontainers/containers/YCQLSessionDelegate.java create mode 100644 modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/AbstractYCQLDelegate.java diff --git a/modules/yugabytedb/build.gradle b/modules/yugabytedb/build.gradle index 68a6f03abc7..8d0ba6ca3d0 100644 --- a/modules/yugabytedb/build.gradle +++ b/modules/yugabytedb/build.gradle @@ -4,7 +4,6 @@ dependencies { api project(':jdbc') testImplementation project(':jdbc-test') // YCQL driver - compileOnly 'com.yugabyte:java-driver-core:4.6.0-yb-11' testImplementation 'com.yugabyte:java-driver-core:4.6.0-yb-11' // YSQL driver testImplementation 'com.yugabyte:jdbc-yugabytedb:42.3.4' diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YCQLSessionDelegate.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YCQLSessionDelegate.java deleted file mode 100644 index 844260e80fe..00000000000 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YCQLSessionDelegate.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.testcontainers.containers; - -import com.datastax.oss.driver.api.core.CqlSession; - -/** - * A builder abstraction to construct {@link CqlSession} instance from - * {@link YugabyteDBYCQLContainer} instance. - * - * @author srinivasa-vasu - */ -public interface YCQLSessionDelegate { - - /** - * Constructs a {@link CqlSession} instance from {@link YugabyteDBYCQLContainer} - * instance. - * @param container YCQL container instance - * @return {@link CqlSession} instance - */ - default CqlSession builder(YugabyteDBYCQLContainer container) { - return CqlSession.builder().withLocalDatacenter(container.getLocalDc()).withKeyspace(container.getKeyspace()) - .withAuthCredentials(container.getUsername(), container.getPassword()) - .addContactPoint(container.getContactPoint()).build(); - } - -} diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java index e1c886ba79c..09ccca9ace4 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java @@ -27,7 +27,7 @@ public class YugabyteDBYCQLContainer extends GenericContainerycqlsh cli within the container to execute the + * statements at one go. It is recommended to use frameworks such as liquibase to manage + * this requirement. This functionality is kept to address the initialization requirements + * from standalone services that can't leverage liquibase or something similar. * * @author srinivasa-vasu * @see YugabyteDBYCQLContainer */ @RequiredArgsConstructor -public final class YugabyteDBYCQLDelegate extends AbstractDatabaseDelegate implements YCQLSessionDelegate { +@Slf4j +public final class YugabyteDBYCQLDelegate extends AbstractYCQLDelegate { - private final YugabyteDBYCQLContainer container; + private static final String BIN_PATH = "/home/yugabyte/tserver/bin/ycqlsh"; - @Override - protected CqlSession createNewConnection() { - return builder(container); - } + private final YugabyteDBYCQLContainer container; @Override - public void execute(String statement, String scriptPath, int lineNumber, boolean continueOnError, + public void execute(Collection statements, String scriptPath, boolean continueOnError, boolean ignoreFailedDrops) { - getConnection().execute(statement); - } - - @Override - protected void closeConnectionQuietly(CqlSession session) { - if (session != null) { - session.close(); + try { + ExecResult result = container.execInContainer(BIN_PATH, "-u", container.getUsername(), "-p", + container.getPassword(), "-k", container.getKeyspace(), "-e", StringUtils.join(statements, ";")); + if (result.getExitCode() != 0) { + throw new RuntimeException(result.getStderr()); + } + } + catch (Exception e) { + log.debug(e.getMessage(), e); + throw new UncategorizedScriptException(e.getMessage(), e); } } diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYCQLWaitStrategy.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYCQLWaitStrategy.java index 73274dfc562..245ca0ae5fa 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYCQLWaitStrategy.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYCQLWaitStrategy.java @@ -1,10 +1,11 @@ package org.testcontainers.containers.strategy; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; -import com.datastax.oss.driver.api.core.CqlSession; import lombok.RequiredArgsConstructor; -import org.testcontainers.containers.YCQLSessionDelegate; +import lombok.extern.slf4j.Slf4j; +import org.testcontainers.containers.Container.ExecResult; import org.testcontainers.containers.YugabyteDBYCQLContainer; import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitStrategyTarget; @@ -25,22 +26,40 @@ * @author srinivasa-vasu */ @RequiredArgsConstructor -public final class YugabyteDBYCQLWaitStrategy extends AbstractWaitStrategy implements YCQLSessionDelegate { +@Slf4j +public final class YugabyteDBYCQLWaitStrategy extends AbstractWaitStrategy { private static final String YCQL_TEST_QUERY = "SELECT release_version FROM system.local"; + private static final String BIN_PATH = "/home/yugabyte/tserver/bin/ycqlsh"; + private final WaitStrategyTarget target; @Override public void waitUntilReady(WaitStrategyTarget target) { YugabyteDBYCQLContainer container = (YugabyteDBYCQLContainer) target; + AtomicBoolean status = new AtomicBoolean(true); retryUntilSuccess((int) startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> { - getRateLimiter().doWhenReady(() -> { - try (CqlSession session = builder(container)) { - session.execute(YCQL_TEST_QUERY); + YugabyteDBYCQLWaitStrategy.this.getRateLimiter().doWhenReady(() -> { + try { + ExecResult result = container.execInContainer(BIN_PATH, "-u", container.getUsername(), "-p", + container.getPassword(), "-k", container.getKeyspace(), "-e", YCQL_TEST_QUERY); + if (result.getExitCode() != 0) { + status.set(false); + log.debug(result.getStderr()); + } + } + catch (Exception e) { + status.set(false); + log.debug(e.getMessage(), e); + } + finally { + if (!status.getAndSet(true)) { + throw new RuntimeException("container hasn't come up yet"); + } } }); - return true; + return status; }); } diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java index 2f097797fe7..9e220f8c8fa 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java @@ -4,11 +4,12 @@ import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.cql.ResultSet; -import org.junit.Assert; import org.junit.Test; import org.testcontainers.containers.YugabyteDBYCQLContainer; import org.testcontainers.utility.DockerImageName; +import static org.assertj.core.api.Assertions.assertThat; + /** * YugabyteDB YCQL API unit test class * @@ -16,7 +17,7 @@ */ public class YugabyteDBYCQLTest { - private static final String IMAGE_NAME = "yugabytedb/yugabyte:2.14.0.0-b94"; + private static final String IMAGE_NAME = "yugabytedb/yugabyte:2.14.3.1-b1"; private static final DockerImageName YBDB_TEST_IMAGE = DockerImageName.parse(IMAGE_NAME); @@ -34,8 +35,8 @@ public void testSmoke() { // startingYCQLContainer { ycqlContainer.start(); // } - Assert.assertNotNull("Smoke test simple query execution fails!", - performQuery(ycqlContainer, "SELECT release_version FROM system.local").one().getString(0)); + assertThat(performQuery(ycqlContainer, "SELECT release_version FROM system.local").wasApplied()) + .as("A sample test query succeeds").isTrue(); } } @@ -45,10 +46,9 @@ public void testCustomKeyspace() throws InterruptedException { try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) .withKeyspaceName(key)) { ycqlContainer.start(); - Assert.assertEquals("Custom keyspace creation fails!", key, - performQuery(ycqlContainer, - "SELECT keyspace_name FROM system_schema.keyspaces where keyspace_name='" + key + "'").one() - .getString(0)); + assertThat(performQuery(ycqlContainer, + "SELECT keyspace_name FROM system_schema.keyspaces where keyspace_name='" + key + "'").one() + .getString(0)).as("Custom keyspace creation succeeds").isEqualTo(key); } } @@ -58,9 +58,8 @@ public void testAuthenticationEnabled() throws InterruptedException { try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) .withUsername(role).withPassword(role)) { ycqlContainer.start(); - Assert.assertEquals("Keyspace login fails with authentication enabled!", role, - performQuery(ycqlContainer, "SELECT role FROM system_auth.roles where role='" + role + "'").one() - .getString(0)); + assertThat(performQuery(ycqlContainer, "SELECT role FROM system_auth.roles where role='" + role + "'").one() + .getString(0)).as("Keyspace login with authentication enabled succeeds").isEqualTo(role); } } @@ -69,8 +68,8 @@ public void testAuthenticationDisabled() { try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE).withPassword("") .withUsername("")) { ycqlContainer.start(); - Assert.assertTrue("Query execution fails!", - performQuery(ycqlContainer, "SELECT release_version FROM system.local").wasApplied()); + assertThat(performQuery(ycqlContainer, "SELECT release_version FROM system.local").wasApplied()) + .as("Keyspace login with authentication disabled succeeds").isTrue(); } } @@ -80,8 +79,9 @@ public void testInitScript() throws InterruptedException { try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) .withKeyspaceName(key).withUsername(key).withPassword(key).withInitScript("init/init_yql.sql")) { ycqlContainer.start(); - Assert.assertTrue("Query execution fails to execute statements from a custom script!", - performQuery(ycqlContainer, "SELECT * FROM random.bar").wasApplied()); + ResultSet output = performQuery(ycqlContainer, "SELECT greet FROM random.dsql"); + assertThat(output.wasApplied()).as("Statements from a custom script execution succeeds").isTrue(); + assertThat(output.one().getString(0)).as("A record match succeeds").isEqualTo("Hello DSQL"); } } diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java index 0480343546c..701af83cb04 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java @@ -2,14 +2,13 @@ import java.sql.SQLException; -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.junit.Assert; import org.junit.Test; import org.testcontainers.containers.YugabyteDBYSQLContainer; import org.testcontainers.db.AbstractContainerDatabaseTest; import org.testcontainers.utility.DockerImageName; +import static org.assertj.core.api.Assertions.assertThat; + /** * YugabyteDB YSQL API unit test class * @@ -17,7 +16,7 @@ */ public class YugabyteDBYSQLTest extends AbstractContainerDatabaseTest { - private static final String IMAGE_NAME = "yugabytedb/yugabyte:2.14.0.0-b94"; + private static final String IMAGE_NAME = "yugabytedb/yugabyte:2.14.3.1-b1"; private static final DockerImageName YBDB_TEST_IMAGE = DockerImageName.parse(IMAGE_NAME); @@ -31,7 +30,8 @@ public void testSmoke() throws SQLException { // startingYSQLContainer { ysqlContainer.start(); // } - Assert.assertEquals("Query execution fails!", 1, performQuery(ysqlContainer, "SELECT 1").getInt(1)); + assertThat(performQuery(ysqlContainer, "SELECT 1").getInt(1)).as("A sample test query succeeds") + .isEqualTo(1); } } @@ -41,18 +41,18 @@ public void testCustomDatabase() throws SQLException { try (final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) .withDatabaseName(key)) { ysqlContainer.start(); - Assert.assertEquals("Query execution on a custom database fails!", 1, - performQuery(ysqlContainer, "SELECT 1").getInt(1)); + assertThat(performQuery(ysqlContainer, "SELECT 1").getInt(1)) + .as("A test query on a custom database succeeds").isEqualTo(1); } } @Test - public void testExplicitInitScript() throws SQLException { + public void testInitScript() throws SQLException { try (final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) .withInitScript("init/init_yql.sql")) { ysqlContainer.start(); - Assert.assertEquals("Value from the init script does not match the real value", "hello world", - performQuery(ysqlContainer, "SELECT foo FROM bar").getString(1)); + assertThat(performQuery(ysqlContainer, "SELECT greet FROM dsql").getString(1)) + .as("A record match succeeds").isEqualTo("Hello DSQL"); } } @@ -62,10 +62,9 @@ public void testWithAdditionalUrlParamInJdbcUrl() { .withUrlParam("sslmode", "disable").withUrlParam("application_name", "yugabyte")) { ysqlContainer.start(); String jdbcUrl = ysqlContainer.getJdbcUrl(); - MatcherAssert.assertThat(jdbcUrl, CoreMatchers.containsString("?")); - MatcherAssert.assertThat(jdbcUrl, CoreMatchers.containsString("&")); - MatcherAssert.assertThat(jdbcUrl, CoreMatchers.containsString("sslmode=disable")); - MatcherAssert.assertThat(jdbcUrl, CoreMatchers.containsString("application_name=yugabyte")); + assertThat(jdbcUrl).contains("?").contains("&").contains("sslmode=disable") + .contains("application_name=yugabyte") + .as("A JDBC connection string with additional parameter validation succeeds"); } } @@ -74,8 +73,8 @@ public void testWithCustomRole() throws SQLException { try (final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) .withDatabaseName("yugabyte").withPassword("yugabyte").withUsername("yugabyte")) { ysqlContainer.start(); - Assert.assertEquals("Query execution with a custom role fails!", 1, - performQuery(ysqlContainer, "SELECT 1").getInt(1)); + assertThat(performQuery(ysqlContainer, "SELECT 1").getInt(1)) + .as("A sample test query with a custom role succeeds").isEqualTo(1); } } diff --git a/modules/yugabytedb/src/test/resources/init/init_yql.sql b/modules/yugabytedb/src/test/resources/init/init_yql.sql index f09647da277..31cbaa6a758 100644 --- a/modules/yugabytedb/src/test/resources/init/init_yql.sql +++ b/modules/yugabytedb/src/test/resources/init/init_yql.sql @@ -1,5 +1,5 @@ -CREATE TABLE bar( - foo text primary key +CREATE TABLE dsql( + greet text primary key ); -INSERT INTO bar (foo) VALUES ('hello world'); +INSERT INTO dsql (greet) VALUES ('Hello DSQL'); From 9329e83581fd37c88dbb8d2616546139cd85343f Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Tue, 25 Oct 2022 07:49:06 +0530 Subject: [PATCH 15/18] cosmetic fix: checkstyleTest and spotlessApply Signed-off-by: Srinivasa Vasu --- .../containers/YugabyteDBYCQLContainer.java | 301 +++++++++--------- .../containers/YugabyteDBYSQLContainer.java | 260 +++++++-------- .../YugabyteDBYSQLContainerProvider.java | 43 ++- .../delegate/AbstractYCQLDelegate.java | 24 +- .../delegate/YugabyteDBYCQLDelegate.java | 51 +-- .../strategy/YugabyteDBYCQLWaitStrategy.java | 87 ++--- .../strategy/YugabyteDBYSQLWaitStrategy.java | 61 ++-- .../YugabyteDBYSQLJDBCDriverTest.java | 22 +- .../junit/yugabytedb/YugabyteDBYCQLTest.java | 168 ++++++---- .../junit/yugabytedb/YugabyteDBYSQLTest.java | 129 ++++---- 10 files changed, 615 insertions(+), 531 deletions(-) diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java index 09ccca9ace4..723eb50ec6d 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java @@ -1,16 +1,16 @@ package org.testcontainers.containers; -import java.net.InetSocketAddress; -import java.time.Duration; -import java.util.Collections; -import java.util.Set; - import com.github.dockerjava.api.command.InspectContainerResponse; import org.testcontainers.containers.delegate.YugabyteDBYCQLDelegate; import org.testcontainers.containers.strategy.YugabyteDBYCQLWaitStrategy; import org.testcontainers.ext.ScriptUtils; import org.testcontainers.utility.DockerImageName; +import java.net.InetSocketAddress; +import java.time.Duration; +import java.util.Collections; +import java.util.Set; + /** * Testcontainers implementation for YugabyteDB YCQL API. * @@ -19,150 +19,149 @@ */ public class YugabyteDBYCQLContainer extends GenericContainer { - private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("yugabytedb/yugabyte"); - - private static final Integer YCQL_PORT = 9042; - - private static final Integer MASTER_DASHBOARD_PORT = 7000; - - private static final Integer TSERVER_DASHBOARD_PORT = 9000; - - private static final String ENTRYPOINT = "bin/yugabyted start --background=false"; - - private static final String LOCAL_DC = "datacenter1"; - - private String keyspace; - - private String username; - - private String password; - - private String initScript; - - /** - * @param imageName image name - */ - public YugabyteDBYCQLContainer(final String imageName) { - this(DockerImageName.parse(imageName)); - } - - /** - * @param imageName image name - */ - public YugabyteDBYCQLContainer(final DockerImageName imageName) { - super(imageName); - imageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); - withExposedPorts(YCQL_PORT, MASTER_DASHBOARD_PORT, TSERVER_DASHBOARD_PORT); - waitingFor(new YugabyteDBYCQLWaitStrategy(this).withStartupTimeout(Duration.ofSeconds(60))); - withCommand(ENTRYPOINT); - } - - @Override - public Set getLivenessCheckPortNumbers() { - return Collections.singleton(getMappedPort(YCQL_PORT)); - } - - /** - * Configures the environment variables. Setting up these variables would create the - * custom objects. Setting {@link #withKeyspaceName(String)}, - * {@link #withUsername(String)}, {@link #withPassword(String)} these parameters will - * initilaize the database with those custom values - */ - @Override - protected void configure() { - addEnv("YCQL_KEYSPACE", keyspace); - addEnv("YCQL_USER", username); - addEnv("YCQL_PASSWORD", password); - } - - /** - * @param initScript path of the initialization script file - * @return {@link YugabyteDBYCQLContainer} instance - */ - public YugabyteDBYCQLContainer withInitScript(String initScript) { - this.initScript = initScript; - return this; - } - - /** - * Setting this would create the keyspace - * @param keyspace keyspace - * @return {@link YugabyteDBYCQLContainer} instance - */ - public YugabyteDBYCQLContainer withKeyspaceName(final String keyspace) { - this.keyspace = keyspace; - return this; - } - - /** - * Setting this would create the custom user role - * @param username user name - * @return {@link YugabyteDBYCQLContainer} instance - */ - public YugabyteDBYCQLContainer withUsername(final String username) { - this.username = username; - return this; - } - - /** - * Setting this along with {@link #withUsername(String)} would enable authentication - * @param password password - * @return {@link YugabyteDBYCQLContainer} instance - */ - public YugabyteDBYCQLContainer withPassword(final String password) { - this.password = password; - return this; - } - - /** - * Executes the initilization script - * @param containerInfo containerInfo - */ - @Override - protected void containerIsStarted(InspectContainerResponse containerInfo) { - if (initScript != null) { - ScriptUtils.runInitScript(new YugabyteDBYCQLDelegate(this), initScript); - } - } - - /** - * Returns a {@link InetSocketAddress} representation of YCQL's contact point info - * @return contactpoint - */ - public InetSocketAddress getContactPoint() { - return new InetSocketAddress(getHost(), getMappedPort(YCQL_PORT)); - } - - /** - * Returns the local datacenter name - * @return localdc name - */ - public String getLocalDc() { - return LOCAL_DC; - } - - /** - * Username getter method - * @return username - */ - public String getUsername() { - return username; - } - - /** - * Password getter method - * @return password - */ - public String getPassword() { - return password; - } - - /** - * Keyspace getter method - * @return keyspace - */ - public String getKeyspace() { - return keyspace; - } - + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("yugabytedb/yugabyte"); + + private static final Integer YCQL_PORT = 9042; + + private static final Integer MASTER_DASHBOARD_PORT = 7000; + + private static final Integer TSERVER_DASHBOARD_PORT = 9000; + + private static final String ENTRYPOINT = "bin/yugabyted start --background=false"; + + private static final String LOCAL_DC = "datacenter1"; + + private String keyspace; + + private String username; + + private String password; + + private String initScript; + + /** + * @param imageName image name + */ + public YugabyteDBYCQLContainer(final String imageName) { + this(DockerImageName.parse(imageName)); + } + + /** + * @param imageName image name + */ + public YugabyteDBYCQLContainer(final DockerImageName imageName) { + super(imageName); + imageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); + withExposedPorts(YCQL_PORT, MASTER_DASHBOARD_PORT, TSERVER_DASHBOARD_PORT); + waitingFor(new YugabyteDBYCQLWaitStrategy(this).withStartupTimeout(Duration.ofSeconds(60))); + withCommand(ENTRYPOINT); + } + + @Override + public Set getLivenessCheckPortNumbers() { + return Collections.singleton(getMappedPort(YCQL_PORT)); + } + + /** + * Configures the environment variables. Setting up these variables would create the + * custom objects. Setting {@link #withKeyspaceName(String)}, + * {@link #withUsername(String)}, {@link #withPassword(String)} these parameters will + * initilaize the database with those custom values + */ + @Override + protected void configure() { + addEnv("YCQL_KEYSPACE", keyspace); + addEnv("YCQL_USER", username); + addEnv("YCQL_PASSWORD", password); + } + + /** + * @param initScript path of the initialization script file + * @return {@link YugabyteDBYCQLContainer} instance + */ + public YugabyteDBYCQLContainer withInitScript(String initScript) { + this.initScript = initScript; + return this; + } + + /** + * Setting this would create the keyspace + * @param keyspace keyspace + * @return {@link YugabyteDBYCQLContainer} instance + */ + public YugabyteDBYCQLContainer withKeyspaceName(final String keyspace) { + this.keyspace = keyspace; + return this; + } + + /** + * Setting this would create the custom user role + * @param username user name + * @return {@link YugabyteDBYCQLContainer} instance + */ + public YugabyteDBYCQLContainer withUsername(final String username) { + this.username = username; + return this; + } + + /** + * Setting this along with {@link #withUsername(String)} would enable authentication + * @param password password + * @return {@link YugabyteDBYCQLContainer} instance + */ + public YugabyteDBYCQLContainer withPassword(final String password) { + this.password = password; + return this; + } + + /** + * Executes the initilization script + * @param containerInfo containerInfo + */ + @Override + protected void containerIsStarted(InspectContainerResponse containerInfo) { + if (initScript != null) { + ScriptUtils.runInitScript(new YugabyteDBYCQLDelegate(this), initScript); + } + } + + /** + * Returns a {@link InetSocketAddress} representation of YCQL's contact point info + * @return contactpoint + */ + public InetSocketAddress getContactPoint() { + return new InetSocketAddress(getHost(), getMappedPort(YCQL_PORT)); + } + + /** + * Returns the local datacenter name + * @return localdc name + */ + public String getLocalDc() { + return LOCAL_DC; + } + + /** + * Username getter method + * @return username + */ + public String getUsername() { + return username; + } + + /** + * Password getter method + * @return password + */ + public String getPassword() { + return password; + } + + /** + * Keyspace getter method + * @return keyspace + */ + public String getKeyspace() { + return keyspace; + } } diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainer.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainer.java index b8d5215a3fc..290269dfe79 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainer.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainer.java @@ -1,12 +1,11 @@ package org.testcontainers.containers; -import java.time.Duration; -import java.util.Set; - import org.testcontainers.containers.strategy.YugabyteDBYSQLWaitStrategy; import org.testcontainers.utility.DockerImageName; +import java.time.Duration; import java.util.Collections; +import java.util.Set; /** * Testcontainers implementation for YugabyteDB YSQL API. @@ -17,128 +16,135 @@ public class YugabyteDBYSQLContainer extends JdbcDatabaseContainer { - private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("yugabytedb/yugabyte"); - - private static final Integer YSQL_PORT = 5433; - - private static final Integer MASTER_DASHBOARD_PORT = 7000; - - private static final Integer TSERVER_DASHBOARD_PORT = 9000; - - private static final String JDBC_DRIVER_CLASS = "com.yugabyte.Driver"; - - private static final String JDBC_CONNECT_PREFIX = "jdbc:yugabytedb"; - - private static final String ENTRYPOINT = "bin/yugabyted start --background=false"; - - private String database = "yugabyte"; - - private String username = "yugabyte"; - - private String password = "yugabyte"; - - /** - * @param imageName image name - */ - public YugabyteDBYSQLContainer(final String imageName) { - this(DockerImageName.parse(imageName)); - } - - /** - * @param imageName image name - */ - public YugabyteDBYSQLContainer(final DockerImageName imageName) { - super(imageName); - imageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); - withExposedPorts(YSQL_PORT, MASTER_DASHBOARD_PORT, TSERVER_DASHBOARD_PORT); - waitingFor(new YugabyteDBYSQLWaitStrategy(this).withStartupTimeout(Duration.ofSeconds(60))); - withCommand(ENTRYPOINT); - } - - @Override - public Set getLivenessCheckPortNumbers() { - return Collections.singleton(getMappedPort(YSQL_PORT)); - } - - /** - * Configures the environment variables. Setting up these variables would create the - * custom objects. Setting {@link #withDatabaseName(String)}, - * {@link #withUsername(String)}, {@link #withPassword(String)} these parameters will - * initilaize the database with those custom values - */ - - @Override - protected void configure() { - addEnv("YSQL_DB", database); - addEnv("YSQL_USER", username); - addEnv("YSQL_PASSWORD", password); - } - - @Override - public String getDriverClassName() { - return JDBC_DRIVER_CLASS; - } - - @Override - public String getJdbcUrl() { - return JDBC_CONNECT_PREFIX + "://" + getHost() + ":" + getMappedPort(YSQL_PORT) + "/" + database - + constructUrlParameters("?", "&"); - } - - @Override - public String getDatabaseName() { - return database; - } - - @Override - public String getUsername() { - return username; - } - - @Override - public String getPassword() { - return password; - } - - @Override - public String getTestQueryString() { - return "SELECT 1"; - } - - /** - * Setting this would create the keyspace - * @param database database name - * @return {@link YugabyteDBYSQLContainer} instance - */ - - @Override - public YugabyteDBYSQLContainer withDatabaseName(final String database) { - this.database = database; - return this; - } - - /** - * Setting this would create the custom user role - * @param username user name - * @return {@link YugabyteDBYSQLContainer} instance - */ - - @Override - public YugabyteDBYSQLContainer withUsername(final String username) { - this.username = username; - return this; - } - - /** - * Setting this along with {@link #withUsername(String)} would enable authentication - * @param password password - * @return {@link YugabyteDBYSQLContainer} instance - */ - - @Override - public YugabyteDBYSQLContainer withPassword(final String password) { - this.password = password; - return this; - } - + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("yugabytedb/yugabyte"); + + private static final Integer YSQL_PORT = 5433; + + private static final Integer MASTER_DASHBOARD_PORT = 7000; + + private static final Integer TSERVER_DASHBOARD_PORT = 9000; + + private static final String JDBC_DRIVER_CLASS = "com.yugabyte.Driver"; + + private static final String JDBC_CONNECT_PREFIX = "jdbc:yugabytedb"; + + private static final String ENTRYPOINT = "bin/yugabyted start --background=false"; + + private String database = "yugabyte"; + + private String username = "yugabyte"; + + private String password = "yugabyte"; + + /** + * @param imageName image name + */ + public YugabyteDBYSQLContainer(final String imageName) { + this(DockerImageName.parse(imageName)); + } + + /** + * @param imageName image name + */ + public YugabyteDBYSQLContainer(final DockerImageName imageName) { + super(imageName); + imageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); + withExposedPorts(YSQL_PORT, MASTER_DASHBOARD_PORT, TSERVER_DASHBOARD_PORT); + waitingFor(new YugabyteDBYSQLWaitStrategy(this).withStartupTimeout(Duration.ofSeconds(60))); + withCommand(ENTRYPOINT); + } + + @Override + public Set getLivenessCheckPortNumbers() { + return Collections.singleton(getMappedPort(YSQL_PORT)); + } + + /** + * Configures the environment variables. Setting up these variables would create the + * custom objects. Setting {@link #withDatabaseName(String)}, + * {@link #withUsername(String)}, {@link #withPassword(String)} these parameters will + * initilaize the database with those custom values + */ + + @Override + protected void configure() { + addEnv("YSQL_DB", database); + addEnv("YSQL_USER", username); + addEnv("YSQL_PASSWORD", password); + } + + @Override + public String getDriverClassName() { + return JDBC_DRIVER_CLASS; + } + + @Override + public String getJdbcUrl() { + return ( + JDBC_CONNECT_PREFIX + + "://" + + getHost() + + ":" + + getMappedPort(YSQL_PORT) + + "/" + + database + + constructUrlParameters("?", "&") + ); + } + + @Override + public String getDatabaseName() { + return database; + } + + @Override + public String getUsername() { + return username; + } + + @Override + public String getPassword() { + return password; + } + + @Override + public String getTestQueryString() { + return "SELECT 1"; + } + + /** + * Setting this would create the keyspace + * @param database database name + * @return {@link YugabyteDBYSQLContainer} instance + */ + + @Override + public YugabyteDBYSQLContainer withDatabaseName(final String database) { + this.database = database; + return this; + } + + /** + * Setting this would create the custom user role + * @param username user name + * @return {@link YugabyteDBYSQLContainer} instance + */ + + @Override + public YugabyteDBYSQLContainer withUsername(final String username) { + this.username = username; + return this; + } + + /** + * Setting this along with {@link #withUsername(String)} would enable authentication + * @param password password + * @return {@link YugabyteDBYSQLContainer} instance + */ + + @Override + public YugabyteDBYSQLContainer withPassword(final String password) { + this.password = password; + return this; + } } diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainerProvider.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainerProvider.java index 294493dadc8..d160ccdd223 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainerProvider.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainerProvider.java @@ -10,34 +10,33 @@ */ public class YugabyteDBYSQLContainerProvider extends JdbcDatabaseContainerProvider { - private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("yugabytedb/yugabyte"); + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("yugabytedb/yugabyte"); - private static final String DEFAULT_TAG = "2.14.3.1-b1"; + private static final String DEFAULT_TAG = "2.14.3.1-b1"; - private static final String NAME = "yugabyte"; + private static final String NAME = "yugabyte"; - private static final String USER_PARAM = "user"; + private static final String USER_PARAM = "user"; - private static final String PASSWORD_PARAM = "password"; + private static final String PASSWORD_PARAM = "password"; - @Override - public boolean supports(String databaseType) { - return databaseType.equals(NAME); - } + @Override + public boolean supports(String databaseType) { + return databaseType.equals(NAME); + } - @Override - public JdbcDatabaseContainer newInstance() { - return newInstance(DEFAULT_TAG); - } + @Override + public JdbcDatabaseContainer newInstance() { + return newInstance(DEFAULT_TAG); + } - @Override - public JdbcDatabaseContainer newInstance(String tag) { - return new YugabyteDBYSQLContainer(DEFAULT_IMAGE_NAME.withTag(tag)); - } - - @Override - public JdbcDatabaseContainer newInstance(ConnectionUrl connectionUrl) { - return newInstanceFromConnectionUrl(connectionUrl, USER_PARAM, PASSWORD_PARAM); - } + @Override + public JdbcDatabaseContainer newInstance(String tag) { + return new YugabyteDBYSQLContainer(DEFAULT_IMAGE_NAME.withTag(tag)); + } + @Override + public JdbcDatabaseContainer newInstance(ConnectionUrl connectionUrl) { + return newInstanceFromConnectionUrl(connectionUrl, USER_PARAM, PASSWORD_PARAM); + } } diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/AbstractYCQLDelegate.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/AbstractYCQLDelegate.java index 77f61e35340..c0e566c7ecf 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/AbstractYCQLDelegate.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/AbstractYCQLDelegate.java @@ -9,15 +9,19 @@ */ public abstract class AbstractYCQLDelegate implements DatabaseDelegate { - @Override - public void execute(String statement, String scriptPath, int lineNumber, boolean continueOnError, - boolean ignoreFailedDrops) { - // do nothing - } - - @Override - public void close() { - // do nothing - } + @Override + public void execute( + String statement, + String scriptPath, + int lineNumber, + boolean continueOnError, + boolean ignoreFailedDrops + ) { + // do nothing + } + @Override + public void close() { + // do nothing + } } diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/YugabyteDBYCQLDelegate.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/YugabyteDBYCQLDelegate.java index ba440a7bbec..e324679713b 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/YugabyteDBYCQLDelegate.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/delegate/YugabyteDBYCQLDelegate.java @@ -1,7 +1,5 @@ package org.testcontainers.containers.delegate; -import java.util.Collection; - import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -9,6 +7,8 @@ import org.testcontainers.containers.YugabyteDBYCQLContainer; import org.testcontainers.ext.ScriptUtils.UncategorizedScriptException; +import java.util.Collection; + /** * Query execution delegate class for YCQL API to delegate init-script statements. This * invokes the in-built ycqlsh cli within the container to execute the @@ -23,24 +23,35 @@ @Slf4j public final class YugabyteDBYCQLDelegate extends AbstractYCQLDelegate { - private static final String BIN_PATH = "/home/yugabyte/tserver/bin/ycqlsh"; - - private final YugabyteDBYCQLContainer container; + private static final String BIN_PATH = "/home/yugabyte/tserver/bin/ycqlsh"; - @Override - public void execute(Collection statements, String scriptPath, boolean continueOnError, - boolean ignoreFailedDrops) { - try { - ExecResult result = container.execInContainer(BIN_PATH, "-u", container.getUsername(), "-p", - container.getPassword(), "-k", container.getKeyspace(), "-e", StringUtils.join(statements, ";")); - if (result.getExitCode() != 0) { - throw new RuntimeException(result.getStderr()); - } - } - catch (Exception e) { - log.debug(e.getMessage(), e); - throw new UncategorizedScriptException(e.getMessage(), e); - } - } + private final YugabyteDBYCQLContainer container; + @Override + public void execute( + Collection statements, + String scriptPath, + boolean continueOnError, + boolean ignoreFailedDrops + ) { + try { + ExecResult result = container.execInContainer( + BIN_PATH, + "-u", + container.getUsername(), + "-p", + container.getPassword(), + "-k", + container.getKeyspace(), + "-e", + StringUtils.join(statements, ";") + ); + if (result.getExitCode() != 0) { + throw new RuntimeException(result.getStderr()); + } + } catch (Exception e) { + log.debug(e.getMessage(), e); + throw new UncategorizedScriptException(e.getMessage(), e); + } + } } diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYCQLWaitStrategy.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYCQLWaitStrategy.java index 245ca0ae5fa..dd775564941 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYCQLWaitStrategy.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYCQLWaitStrategy.java @@ -1,8 +1,5 @@ package org.testcontainers.containers.strategy; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.testcontainers.containers.Container.ExecResult; @@ -10,6 +7,9 @@ import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitStrategyTarget; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + import static org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess; /** @@ -29,43 +29,54 @@ @Slf4j public final class YugabyteDBYCQLWaitStrategy extends AbstractWaitStrategy { - private static final String YCQL_TEST_QUERY = "SELECT release_version FROM system.local"; - - private static final String BIN_PATH = "/home/yugabyte/tserver/bin/ycqlsh"; + private static final String YCQL_TEST_QUERY = "SELECT release_version FROM system.local"; - private final WaitStrategyTarget target; + private static final String BIN_PATH = "/home/yugabyte/tserver/bin/ycqlsh"; - @Override - public void waitUntilReady(WaitStrategyTarget target) { - YugabyteDBYCQLContainer container = (YugabyteDBYCQLContainer) target; - AtomicBoolean status = new AtomicBoolean(true); - retryUntilSuccess((int) startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> { - YugabyteDBYCQLWaitStrategy.this.getRateLimiter().doWhenReady(() -> { - try { - ExecResult result = container.execInContainer(BIN_PATH, "-u", container.getUsername(), "-p", - container.getPassword(), "-k", container.getKeyspace(), "-e", YCQL_TEST_QUERY); - if (result.getExitCode() != 0) { - status.set(false); - log.debug(result.getStderr()); - } - } - catch (Exception e) { - status.set(false); - log.debug(e.getMessage(), e); - } - finally { - if (!status.getAndSet(true)) { - throw new RuntimeException("container hasn't come up yet"); - } - } - }); - return status; - }); - } + private final WaitStrategyTarget target; - @Override - public void waitUntilReady() { - waitUntilReady(target); - } + @Override + public void waitUntilReady(WaitStrategyTarget target) { + YugabyteDBYCQLContainer container = (YugabyteDBYCQLContainer) target; + AtomicBoolean status = new AtomicBoolean(true); + retryUntilSuccess( + (int) startupTimeout.getSeconds(), + TimeUnit.SECONDS, + () -> { + YugabyteDBYCQLWaitStrategy.this.getRateLimiter() + .doWhenReady(() -> { + try { + ExecResult result = container.execInContainer( + BIN_PATH, + "-u", + container.getUsername(), + "-p", + container.getPassword(), + "-k", + container.getKeyspace(), + "-e", + YCQL_TEST_QUERY + ); + if (result.getExitCode() != 0) { + status.set(false); + log.debug(result.getStderr()); + } + } catch (Exception e) { + status.set(false); + log.debug(e.getMessage(), e); + } finally { + if (!status.getAndSet(true)) { + throw new RuntimeException("container hasn't come up yet"); + } + } + }); + return status; + } + ); + } + @Override + public void waitUntilReady() { + waitUntilReady(target); + } } diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYSQLWaitStrategy.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYSQLWaitStrategy.java index 03d6134123f..31fa52a4155 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYSQLWaitStrategy.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/strategy/YugabyteDBYSQLWaitStrategy.java @@ -1,15 +1,15 @@ package org.testcontainers.containers.strategy; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.concurrent.TimeUnit; - import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.testcontainers.containers.YugabyteDBYSQLContainer; import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitStrategyTarget; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.concurrent.TimeUnit; + import static org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess; /** @@ -29,29 +29,32 @@ @Slf4j public final class YugabyteDBYSQLWaitStrategy extends AbstractWaitStrategy { - private static final String YSQL_TEST_QUERY = "SELECT 1"; - - private final WaitStrategyTarget target; - - @Override - public void waitUntilReady(WaitStrategyTarget target) { - YugabyteDBYSQLContainer container = (YugabyteDBYSQLContainer) target; - retryUntilSuccess((int) startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> { - getRateLimiter().doWhenReady(() -> { - try (Connection con = container.createConnection(container.getJdbcUrl())) { - con.createStatement().execute(YSQL_TEST_QUERY); - } - catch (SQLException ex) { - log.error("Error connecting to the database", ex); - } - }); - return true; - }); - } - - @Override - public void waitUntilReady() { - waitUntilReady(target); - } - + private static final String YSQL_TEST_QUERY = "SELECT 1"; + + private final WaitStrategyTarget target; + + @Override + public void waitUntilReady(WaitStrategyTarget target) { + YugabyteDBYSQLContainer container = (YugabyteDBYSQLContainer) target; + retryUntilSuccess( + (int) startupTimeout.getSeconds(), + TimeUnit.SECONDS, + () -> { + getRateLimiter() + .doWhenReady(() -> { + try (Connection con = container.createConnection(container.getJdbcUrl())) { + con.createStatement().execute(YSQL_TEST_QUERY); + } catch (SQLException ex) { + log.error("Error connecting to the database", ex); + } + }); + return true; + } + ); + } + + @Override + public void waitUntilReady() { + waitUntilReady(target); + } } diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/jdbc/yugabytedb/YugabyteDBYSQLJDBCDriverTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/jdbc/yugabytedb/YugabyteDBYSQLJDBCDriverTest.java index 6e3790c92c1..09c0240e7db 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/jdbc/yugabytedb/YugabyteDBYSQLJDBCDriverTest.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/jdbc/yugabytedb/YugabyteDBYSQLJDBCDriverTest.java @@ -1,12 +1,11 @@ package org.testcontainers.jdbc.yugabytedb; -import java.util.EnumSet; - import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.testcontainers.jdbc.AbstractJDBCDriverTest; -import static java.util.Arrays.asList; +import java.util.Arrays; +import java.util.EnumSet; /** * YugabyteDB YSQL API JDBC connectivity driver test class @@ -16,10 +15,15 @@ @RunWith(Parameterized.class) public class YugabyteDBYSQLJDBCDriverTest extends AbstractJDBCDriverTest { - @Parameterized.Parameters(name = "{index} - {0}") - public static Iterable data() { - return asList(new Object[][] { { "jdbc:tc:yugabyte://hostname/yugabyte?user=yugabyte&password=yugabyte", - EnumSet.noneOf(Options.class) }, }); - } - + @Parameterized.Parameters(name = "{index} - {0}") + public static Iterable data() { + return Arrays.asList( + new Object[][] { + { + "jdbc:tc:yugabyte://hostname/yugabyte?user=yugabyte&password=yugabyte", + EnumSet.noneOf(Options.class), + }, + } + ); + } } diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java index 9e220f8c8fa..021d9a31989 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java @@ -1,13 +1,13 @@ package org.testcontainers.junit.yugabytedb; -import java.net.InetSocketAddress; - 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.YugabyteDBYCQLContainer; import org.testcontainers.utility.DockerImageName; +import java.net.InetSocketAddress; + import static org.assertj.core.api.Assertions.assertThat; /** @@ -17,82 +17,112 @@ */ public class YugabyteDBYCQLTest { - private static final String IMAGE_NAME = "yugabytedb/yugabyte:2.14.3.1-b1"; + private static final String IMAGE_NAME = "yugabytedb/yugabyte:2.14.3.1-b1"; - private static final DockerImageName YBDB_TEST_IMAGE = DockerImageName.parse(IMAGE_NAME); + private static final DockerImageName YBDB_TEST_IMAGE = DockerImageName.parse(IMAGE_NAME); - private static final String LOCAL_DC = "datacenter1"; + private static final String LOCAL_DC = "datacenter1"; - private static final int YCQL_PORT = 9042; + private static final int YCQL_PORT = 9042; - @Test - public void testSmoke() { - try ( + @Test + public void testSmoke() { + try ( // creatingYCQLContainer { final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(IMAGE_NAME) - // } - ) { - // startingYCQLContainer { - ycqlContainer.start(); - // } - assertThat(performQuery(ycqlContainer, "SELECT release_version FROM system.local").wasApplied()) - .as("A sample test query succeeds").isTrue(); - } - } - - @Test - public void testCustomKeyspace() throws InterruptedException { - String key = "random"; - try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) - .withKeyspaceName(key)) { - ycqlContainer.start(); - assertThat(performQuery(ycqlContainer, - "SELECT keyspace_name FROM system_schema.keyspaces where keyspace_name='" + key + "'").one() - .getString(0)).as("Custom keyspace creation succeeds").isEqualTo(key); - } - } + // } + ) { + // startingYCQLContainer { + ycqlContainer.start(); + // } + assertThat(performQuery(ycqlContainer, "SELECT release_version FROM system.local").wasApplied()) + .as("A sample test query succeeds") + .isTrue(); + } + } - @Test - public void testAuthenticationEnabled() throws InterruptedException { - String role = "random"; - try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) - .withUsername(role).withPassword(role)) { - ycqlContainer.start(); - assertThat(performQuery(ycqlContainer, "SELECT role FROM system_auth.roles where role='" + role + "'").one() - .getString(0)).as("Keyspace login with authentication enabled succeeds").isEqualTo(role); - } - } + @Test + public void testCustomKeyspace() throws InterruptedException { + String key = "random"; + try ( + final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) + .withKeyspaceName(key) + ) { + ycqlContainer.start(); + assertThat( + performQuery( + ycqlContainer, + "SELECT keyspace_name FROM system_schema.keyspaces where keyspace_name='" + key + "'" + ) + .one() + .getString(0) + ) + .as("Custom keyspace creation succeeds") + .isEqualTo(key); + } + } - @Test - public void testAuthenticationDisabled() { - try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE).withPassword("") - .withUsername("")) { - ycqlContainer.start(); - assertThat(performQuery(ycqlContainer, "SELECT release_version FROM system.local").wasApplied()) - .as("Keyspace login with authentication disabled succeeds").isTrue(); - } - } + @Test + public void testAuthenticationEnabled() throws InterruptedException { + String role = "random"; + try ( + final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) + .withUsername(role) + .withPassword(role) + ) { + ycqlContainer.start(); + assertThat( + performQuery(ycqlContainer, "SELECT role FROM system_auth.roles where role='" + role + "'") + .one() + .getString(0) + ) + .as("Keyspace login with authentication enabled succeeds") + .isEqualTo(role); + } + } - @Test - public void testInitScript() throws InterruptedException { - String key = "random"; - try (final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) - .withKeyspaceName(key).withUsername(key).withPassword(key).withInitScript("init/init_yql.sql")) { - ycqlContainer.start(); - ResultSet output = performQuery(ycqlContainer, "SELECT greet FROM random.dsql"); - assertThat(output.wasApplied()).as("Statements from a custom script execution succeeds").isTrue(); - assertThat(output.one().getString(0)).as("A record match succeeds").isEqualTo("Hello DSQL"); - } - } + @Test + public void testAuthenticationDisabled() { + try ( + final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) + .withPassword("") + .withUsername("") + ) { + ycqlContainer.start(); + assertThat(performQuery(ycqlContainer, "SELECT release_version FROM system.local").wasApplied()) + .as("Keyspace login with authentication disabled succeeds") + .isTrue(); + } + } - private ResultSet performQuery(YugabyteDBYCQLContainer ycqlContainer, String cql) { - try (CqlSession session = CqlSession.builder().withKeyspace(ycqlContainer.getKeyspace()) - .withAuthCredentials(ycqlContainer.getUsername(), ycqlContainer.getPassword()) - .withLocalDatacenter(LOCAL_DC) - .addContactPoint(new InetSocketAddress(ycqlContainer.getHost(), ycqlContainer.getMappedPort(YCQL_PORT))) - .build()) { - return session.execute(cql); - } - } + @Test + public void testInitScript() throws InterruptedException { + String key = "random"; + try ( + final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) + .withKeyspaceName(key) + .withUsername(key) + .withPassword(key) + .withInitScript("init/init_yql.sql") + ) { + ycqlContainer.start(); + ResultSet output = performQuery(ycqlContainer, "SELECT greet FROM random.dsql"); + assertThat(output.wasApplied()).as("Statements from a custom script execution succeeds").isTrue(); + assertThat(output.one().getString(0)).as("A record match succeeds").isEqualTo("Hello DSQL"); + } + } + private ResultSet performQuery(YugabyteDBYCQLContainer ycqlContainer, String cql) { + try ( + CqlSession session = CqlSession + .builder() + .withKeyspace(ycqlContainer.getKeyspace()) + .withAuthCredentials(ycqlContainer.getUsername(), ycqlContainer.getPassword()) + .withLocalDatacenter(LOCAL_DC) + .addContactPoint(new InetSocketAddress(ycqlContainer.getHost(), ycqlContainer.getMappedPort(YCQL_PORT))) + .build() + ) { + return session.execute(cql); + } + } } diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java index 701af83cb04..0ea7be6846e 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java @@ -1,12 +1,12 @@ package org.testcontainers.junit.yugabytedb; -import java.sql.SQLException; - import org.junit.Test; import org.testcontainers.containers.YugabyteDBYSQLContainer; import org.testcontainers.db.AbstractContainerDatabaseTest; import org.testcontainers.utility.DockerImageName; +import java.sql.SQLException; + import static org.assertj.core.api.Assertions.assertThat; /** @@ -16,66 +16,83 @@ */ public class YugabyteDBYSQLTest extends AbstractContainerDatabaseTest { - private static final String IMAGE_NAME = "yugabytedb/yugabyte:2.14.3.1-b1"; + private static final String IMAGE_NAME = "yugabytedb/yugabyte:2.14.3.1-b1"; - private static final DockerImageName YBDB_TEST_IMAGE = DockerImageName.parse(IMAGE_NAME); + private static final DockerImageName YBDB_TEST_IMAGE = DockerImageName.parse(IMAGE_NAME); - @Test - public void testSmoke() throws SQLException { - try ( + @Test + public void testSmoke() throws SQLException { + try ( // creatingYSQLContainer { final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(IMAGE_NAME) - // } - ) { - // startingYSQLContainer { - ysqlContainer.start(); - // } - assertThat(performQuery(ysqlContainer, "SELECT 1").getInt(1)).as("A sample test query succeeds") - .isEqualTo(1); - } - } - - @Test - public void testCustomDatabase() throws SQLException { - String key = "random"; - try (final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) - .withDatabaseName(key)) { - ysqlContainer.start(); - assertThat(performQuery(ysqlContainer, "SELECT 1").getInt(1)) - .as("A test query on a custom database succeeds").isEqualTo(1); - } - } + // } + ) { + // startingYSQLContainer { + ysqlContainer.start(); + // } + assertThat(performQuery(ysqlContainer, "SELECT 1").getInt(1)) + .as("A sample test query succeeds") + .isEqualTo(1); + } + } - @Test - public void testInitScript() throws SQLException { - try (final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) - .withInitScript("init/init_yql.sql")) { - ysqlContainer.start(); - assertThat(performQuery(ysqlContainer, "SELECT greet FROM dsql").getString(1)) - .as("A record match succeeds").isEqualTo("Hello DSQL"); - } - } + @Test + public void testCustomDatabase() throws SQLException { + String key = "random"; + try ( + final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) + .withDatabaseName(key) + ) { + ysqlContainer.start(); + assertThat(performQuery(ysqlContainer, "SELECT 1").getInt(1)) + .as("A test query on a custom database succeeds") + .isEqualTo(1); + } + } - @Test - public void testWithAdditionalUrlParamInJdbcUrl() { - try (final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) - .withUrlParam("sslmode", "disable").withUrlParam("application_name", "yugabyte")) { - ysqlContainer.start(); - String jdbcUrl = ysqlContainer.getJdbcUrl(); - assertThat(jdbcUrl).contains("?").contains("&").contains("sslmode=disable") - .contains("application_name=yugabyte") - .as("A JDBC connection string with additional parameter validation succeeds"); - } - } + @Test + public void testInitScript() throws SQLException { + try ( + final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) + .withInitScript("init/init_yql.sql") + ) { + ysqlContainer.start(); + assertThat(performQuery(ysqlContainer, "SELECT greet FROM dsql").getString(1)) + .as("A record match succeeds") + .isEqualTo("Hello DSQL"); + } + } - @Test - public void testWithCustomRole() throws SQLException { - try (final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) - .withDatabaseName("yugabyte").withPassword("yugabyte").withUsername("yugabyte")) { - ysqlContainer.start(); - assertThat(performQuery(ysqlContainer, "SELECT 1").getInt(1)) - .as("A sample test query with a custom role succeeds").isEqualTo(1); - } - } + @Test + public void testWithAdditionalUrlParamInJdbcUrl() { + try ( + final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) + .withUrlParam("sslmode", "disable") + .withUrlParam("application_name", "yugabyte") + ) { + ysqlContainer.start(); + String jdbcUrl = ysqlContainer.getJdbcUrl(); + assertThat(jdbcUrl) + .contains("?") + .contains("&") + .contains("sslmode=disable") + .contains("application_name=yugabyte") + .as("A JDBC connection string with additional parameter validation succeeds"); + } + } + @Test + public void testWithCustomRole() throws SQLException { + try ( + final YugabyteDBYSQLContainer ysqlContainer = new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) + .withDatabaseName("yugabyte") + .withPassword("yugabyte") + .withUsername("yugabyte") + ) { + ysqlContainer.start(); + assertThat(performQuery(ysqlContainer, "SELECT 1").getInt(1)) + .as("A sample test query with a custom role succeeds") + .isEqualTo(1); + } + } } From 57d170c7dae947e8048561c0e33077cdc1d24475 Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Fri, 11 Nov 2022 12:16:17 +0530 Subject: [PATCH 16/18] update yugabytedb labeler Signed-off-by: Srinivasa Vasu --- .github/labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index 8da42a738ae..2aff606e27b 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -88,6 +88,6 @@ "modules/vault": - modules/vault/**/* "modules/yugabytedb": - - modules/yugabytedb/* + - modules/yugabytedb/**/* "type/docs": - docs/**/*.md From 1bc628e083d830cd23bb50c01a0e6ccca54a99a1 Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Fri, 11 Nov 2022 16:15:36 +0530 Subject: [PATCH 17/18] update yugabytedb tag Signed-off-by: Srinivasa Vasu --- .../containers/YugabyteDBYSQLContainerProvider.java | 2 +- .../org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java | 2 +- .../org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainerProvider.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainerProvider.java index d160ccdd223..71d8b583448 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainerProvider.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYSQLContainerProvider.java @@ -12,7 +12,7 @@ public class YugabyteDBYSQLContainerProvider extends JdbcDatabaseContainerProvid private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("yugabytedb/yugabyte"); - private static final String DEFAULT_TAG = "2.14.3.1-b1"; + private static final String DEFAULT_TAG = "2.14.4.0-b26"; private static final String NAME = "yugabyte"; diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java index 021d9a31989..065679d17cd 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java @@ -17,7 +17,7 @@ */ public class YugabyteDBYCQLTest { - private static final String IMAGE_NAME = "yugabytedb/yugabyte:2.14.3.1-b1"; + private static final String IMAGE_NAME = "yugabytedb/yugabyte:2.14.4.0-b26"; private static final DockerImageName YBDB_TEST_IMAGE = DockerImageName.parse(IMAGE_NAME); diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java index 0ea7be6846e..cb98fcdc922 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYSQLTest.java @@ -16,7 +16,7 @@ */ public class YugabyteDBYSQLTest extends AbstractContainerDatabaseTest { - private static final String IMAGE_NAME = "yugabytedb/yugabyte:2.14.3.1-b1"; + private static final String IMAGE_NAME = "yugabytedb/yugabyte:2.14.4.0-b26"; private static final DockerImageName YBDB_TEST_IMAGE = DockerImageName.parse(IMAGE_NAME); From 4cee74e8b7622b6d13dd015eb67ec47df552b8b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Tue, 15 Nov 2022 10:09:10 -0800 Subject: [PATCH 18/18] Polish --- .../containers/YugabyteDBYCQLContainer.java | 8 ++++---- .../junit/yugabytedb/YugabyteDBYCQLTest.java | 16 +++++----------- .../src/test/resources/logback-test.xml | 16 ++++++++++++++++ 3 files changed, 25 insertions(+), 15 deletions(-) create mode 100644 modules/yugabytedb/src/test/resources/logback-test.xml diff --git a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java index 723eb50ec6d..af20ef9e157 100644 --- a/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java +++ b/modules/yugabytedb/src/main/java/org/testcontainers/containers/YugabyteDBYCQLContainer.java @@ -120,7 +120,7 @@ public YugabyteDBYCQLContainer withPassword(final String password) { */ @Override protected void containerIsStarted(InspectContainerResponse containerInfo) { - if (initScript != null) { + if (this.initScript != null) { ScriptUtils.runInitScript(new YugabyteDBYCQLDelegate(this), initScript); } } @@ -146,7 +146,7 @@ public String getLocalDc() { * @return username */ public String getUsername() { - return username; + return this.username; } /** @@ -154,7 +154,7 @@ public String getUsername() { * @return password */ public String getPassword() { - return password; + return this.password; } /** @@ -162,6 +162,6 @@ public String getPassword() { * @return keyspace */ public String getKeyspace() { - return keyspace; + return this.keyspace; } } diff --git a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java index 065679d17cd..3616b87850b 100644 --- a/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java +++ b/modules/yugabytedb/src/test/java/org/testcontainers/junit/yugabytedb/YugabyteDBYCQLTest.java @@ -6,8 +6,6 @@ import org.testcontainers.containers.YugabyteDBYCQLContainer; import org.testcontainers.utility.DockerImageName; -import java.net.InetSocketAddress; - import static org.assertj.core.api.Assertions.assertThat; /** @@ -21,10 +19,6 @@ public class YugabyteDBYCQLTest { private static final DockerImageName YBDB_TEST_IMAGE = DockerImageName.parse(IMAGE_NAME); - private static final String LOCAL_DC = "datacenter1"; - - private static final int YCQL_PORT = 9042; - @Test public void testSmoke() { try ( @@ -42,7 +36,7 @@ public void testSmoke() { } @Test - public void testCustomKeyspace() throws InterruptedException { + public void testCustomKeyspace() { String key = "random"; try ( final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) @@ -63,7 +57,7 @@ public void testCustomKeyspace() throws InterruptedException { } @Test - public void testAuthenticationEnabled() throws InterruptedException { + public void testAuthenticationEnabled() { String role = "random"; try ( final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) @@ -96,7 +90,7 @@ public void testAuthenticationDisabled() { } @Test - public void testInitScript() throws InterruptedException { + public void testInitScript() { String key = "random"; try ( final YugabyteDBYCQLContainer ycqlContainer = new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) @@ -118,8 +112,8 @@ private ResultSet performQuery(YugabyteDBYCQLContainer ycqlContainer, String cql .builder() .withKeyspace(ycqlContainer.getKeyspace()) .withAuthCredentials(ycqlContainer.getUsername(), ycqlContainer.getPassword()) - .withLocalDatacenter(LOCAL_DC) - .addContactPoint(new InetSocketAddress(ycqlContainer.getHost(), ycqlContainer.getMappedPort(YCQL_PORT))) + .withLocalDatacenter(ycqlContainer.getLocalDc()) + .addContactPoint(ycqlContainer.getContactPoint()) .build() ) { return session.execute(cql); diff --git a/modules/yugabytedb/src/test/resources/logback-test.xml b/modules/yugabytedb/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..83ef7a1a3ef --- /dev/null +++ b/modules/yugabytedb/src/test/resources/logback-test.xml @@ -0,0 +1,16 @@ + + + + + + %d{HH:mm:ss.SSS} %-5level %logger - %msg%n + + + + + + + + +