Skip to content

Commit

Permalink
feat: add oceanbase-ce module
Browse files Browse the repository at this point in the history
  • Loading branch information
whhe committed Jan 16, 2024
1 parent 4ff8d1d commit d2a6a21
Show file tree
Hide file tree
Showing 17 changed files with 411 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yaml
Expand Up @@ -38,6 +38,7 @@ body:
- MySQL
- Neo4j
- NGINX
- OceanBase CE
- Oracle Free
- Oracle XE
- OrientDB
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/enhancement.yaml
Expand Up @@ -38,6 +38,7 @@ body:
- MySQL
- Neo4j
- NGINX
- OceanBase CE
- Oracle Free
- Oracle XE
- OrientDB
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/feature.yaml
Expand Up @@ -38,6 +38,7 @@ body:
- MySQL
- Neo4j
- NGINX
- OceanBase CE
- Oracle Free
- Oracle XE
- OrientDB
Expand Down
5 changes: 5 additions & 0 deletions .github/dependabot.yml
Expand Up @@ -194,6 +194,11 @@ updates:
schedule:
interval: "weekly"
open-pull-requests-limit: 10
- package-ecosystem: "gradle"
directory: "/modules/oceanbase-ce"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
- package-ecosystem: "gradle"
directory: "/modules/oracle-free"
schedule:
Expand Down
4 changes: 4 additions & 0 deletions .github/labeler.yml
Expand Up @@ -119,6 +119,10 @@
- changed-files:
- any-glob-to-any-file:
- modules/nginx/**/*
"modules/oceanbase-ce":
- changed-files:
- any-glob-to-any-file:
- modules/oceanbase-ce/**/*
"modules/oracle":
- changed-files:
- any-glob-to-any-file:
Expand Down
4 changes: 4 additions & 0 deletions docs/modules/databases/jdbc.md
Expand Up @@ -55,6 +55,10 @@ Insert `tc:` after `jdbc:` as follows. Note that the hostname, port and database

`jdbc:tc:sqlserver:2017-CU12:///databasename`

#### Using OceanBase

`jdbc:tc:oceanbase:4.2.1_bp3:///databasename`

#### Using Oracle

`jdbc:tc:oracle:21-slim-faststart:///databasename`
Expand Down
25 changes: 25 additions & 0 deletions docs/modules/databases/oceanbasece.md
@@ -0,0 +1,25 @@
# OceanBase-CE Module

See [Database containers](./index.md) for documentation and usage that is common to all relational database container types.

## Adding this module to your project dependencies

Add the following dependency to your `pom.xml`/`build.gradle` file:

=== "Gradle"
```groovy
testImplementation "org.testcontainers:oceanbase-ce:{{latest_version}}"
```

=== "Maven"
```xml
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>oceanbase-ce</artifactId>
<version>{{latest_version}}</version>
<scope>test</scope>
</dependency>
```

!!! hint
Adding this Testcontainers library JAR will not automatically add a database driver JAR to your project. You should ensure that your project also has a suitable database driver as a dependency.
1 change: 1 addition & 0 deletions mkdocs.yml
Expand Up @@ -64,6 +64,7 @@ nav:
- modules/databases/mssqlserver.md
- modules/databases/mysql.md
- modules/databases/neo4j.md
- modules/databases/oceanbasece.md
- modules/databases/oraclefree.md
- modules/databases/oraclexe.md
- modules/databases/orientdb.md
Expand Down
8 changes: 8 additions & 0 deletions modules/oceanbase-ce/build.gradle
@@ -0,0 +1,8 @@
description = "Testcontainers :: JDBC :: OceanBase CE"

dependencies {
api project(':jdbc')

testImplementation project(':jdbc-test')
testRuntimeOnly 'mysql:mysql-connector-java:8.0.33'
}
@@ -0,0 +1,163 @@
package org.testcontainers.containers;

import org.apache.commons.lang3.StringUtils;
import org.testcontainers.utility.DockerImageName;

/**
* Testcontainers implementation for OceanBase.
* <p>
* Supported image: {@code oceanbase/oceanbase-ce}
* <p>
* Exposed ports:
* <ul>
* <li>SQL: 2881</li>
* <li>RPC: 2882</li>
* </ul>
*/
public class OceanBaseContainer extends JdbcDatabaseContainer<OceanBaseContainer> {

static final String NAME = "oceanbase";

static final String DOCKER_IMAGE_NAME = "oceanbase/oceanbase-ce";

private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse(DOCKER_IMAGE_NAME);

private static final Integer SQL_PORT = 2881;
private static final Integer RPC_PORT = 2882;

private static final String SYSTEM_TENANT_NAME = "sys";
private static final String DEFAULT_TEST_TENANT_NAME = "test";
private static final String DEFAULT_USERNAME = "root";
private static final String DEFAULT_PASSWORD = "";
private static final String DEFAULT_DATABASE_NAME = "test";

private boolean enableFastboot;
private String mode;
private String tenantName = DEFAULT_TEST_TENANT_NAME;
private String driverClassName = "com.mysql.cj.jdbc.Driver";

public OceanBaseContainer(String dockerImageName) {
this(DockerImageName.parse(dockerImageName));
}

public OceanBaseContainer(DockerImageName dockerImageName) {
super(dockerImageName);
dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);

addExposedPorts(SQL_PORT, RPC_PORT);
}

@Override
public Integer getMappedPort(int originalPort) {
return "host".equals(getNetworkMode()) ? originalPort : super.getMappedPort(originalPort);
}

@Override
public String getDriverClassName() {
return driverClassName;
}

@Override
public String getJdbcUrl() {
return getJdbcUrl(DEFAULT_DATABASE_NAME);
}

public String getJdbcUrl(String databaseName) {
String additionalUrlParams = constructUrlParameters("?", "&");
String prefix = driverClassName.contains("mysql") ? "jdbc:mysql://" : "jdbc:oceanbase://";
return prefix + getHost() + ":" + getMappedPort(SQL_PORT) + "/" + databaseName + additionalUrlParams;
}

@Override
public String getDatabaseName() {
return DEFAULT_DATABASE_NAME;
}

@Override
public String getUsername() {
return DEFAULT_USERNAME + "@" + tenantName;
}

@Override
public String getPassword() {
return DEFAULT_PASSWORD;
}

@Override
protected String getTestQueryString() {
return "SELECT 1";
}

/**
* Enable fastboot.
*
* @return this
*/
public OceanBaseContainer enableFastboot() {
this.enableFastboot = true;
return self();
}

/**
* Set the deployment mode, see <a href="https://hub.docker.com/r/oceanbase/oceanbase-ce">Docker Hub</a> for more details.
*
* @param mode the deployment mode
* @return this
*/
public OceanBaseContainer withMode(String mode) {
this.mode = mode;
return self();
}

/**
* Set the non-system tenant to be created for testing.
*
* @param tenantName the name of tenant to be created
* @return this
*/
public OceanBaseContainer withTenant(String tenantName) {
if (StringUtils.isEmpty(tenantName)) {
throw new IllegalArgumentException("Tenant name cannot be null or empty");
}
if (SYSTEM_TENANT_NAME.equals(tenantName)) {
throw new IllegalArgumentException("Tenant name cannot be " + SYSTEM_TENANT_NAME);
}
this.tenantName = tenantName;
return self();
}

/**
* Set the driver class name.
*
* @param driverClassName the driver class name
* @return this
*/
public OceanBaseContainer withDriverClassName(String driverClassName) {
if (StringUtils.isEmpty(driverClassName)) {
throw new IllegalArgumentException("Driver class name cannot be null or empty");
}
if (!driverClassName.contains("mysql") && !driverClassName.contains("oceanbase")) {
throw new IllegalArgumentException("Driver class name should contains 'mysql' or 'oceanbase'");
}
try {
Class.forName(driverClassName);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Driver class not found", e);
}
this.driverClassName = driverClassName;
return self();
}

@Override
protected void configure() {
if (StringUtils.isNotBlank(mode)) {
withEnv("MODE", mode);
}
if (enableFastboot) {
withEnv("FASTBOOT", "true");
}
if (!DEFAULT_TEST_TENANT_NAME.equals(tenantName)) {
withEnv("OB_TENANT_NAME", tenantName);
}
}
}
@@ -0,0 +1,30 @@
package org.testcontainers.containers;

import org.testcontainers.utility.DockerImageName;

/**
* Factory for OceanBase containers.
*/
public class OceanBaseContainerProvider extends JdbcDatabaseContainerProvider {

private static final String DEFAULT_TAG = "4.2.1_bp3";

@Override
public boolean supports(String databaseType) {
return databaseType.equals(OceanBaseContainer.NAME);
}

@Override
public JdbcDatabaseContainer newInstance() {
return newInstance(DEFAULT_TAG);
}

@Override
public JdbcDatabaseContainer newInstance(String tag) {
if (tag != null) {
return new OceanBaseContainer(DockerImageName.parse(OceanBaseContainer.DOCKER_IMAGE_NAME).withTag(tag));
} else {
return newInstance();
}
}
}
@@ -0,0 +1 @@
org.testcontainers.containers.OceanBaseContainerProvider
@@ -0,0 +1,8 @@
package org.testcontainers;

import org.testcontainers.utility.DockerImageName;

public class OceanBaseTestImages {

public static final DockerImageName OCEANBASE_CE_IMAGE = DockerImageName.parse("oceanbase/oceanbase-ce:4.2.1_bp3");
}
@@ -0,0 +1,19 @@
package org.testcontainers.jdbc.oceanbase;

import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.testcontainers.jdbc.AbstractJDBCDriverTest;

import java.util.Arrays;
import java.util.EnumSet;

@RunWith(Parameterized.class)
public class OceanBaseJdbcDriverTest extends AbstractJDBCDriverTest {

@Parameterized.Parameters(name = "{index} - {0}")
public static Iterable<Object[]> data() {
return Arrays.asList(
new Object[][] { { "jdbc:tc:oceanbase://hostname/databasename", EnumSet.noneOf(Options.class) } }
);
}
}

0 comments on commit d2a6a21

Please sign in to comment.